summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/CMakeLists.txt476
-rw-r--r--src/gui/accessible/linux/atspiadaptor.cpp1379
-rw-r--r--src/gui/accessible/linux/atspiadaptor_p.h56
-rw-r--r--src/gui/accessible/linux/dbusconnection.cpp75
-rw-r--r--src/gui/accessible/linux/dbusconnection_p.h42
-rw-r--r--src/gui/accessible/linux/dbusxml/Socket.xml2
-rw-r--r--src/gui/accessible/linux/qspi_constant_mappings.cpp58
-rw-r--r--src/gui/accessible/linux/qspi_constant_mappings_p.h40
-rw-r--r--src/gui/accessible/linux/qspi_struct_marshallers.cpp62
-rw-r--r--src/gui/accessible/linux/qspi_struct_marshallers_p.h74
-rw-r--r--src/gui/accessible/linux/qspiaccessiblebridge.cpp66
-rw-r--r--src/gui/accessible/linux/qspiaccessiblebridge_p.h40
-rw-r--r--src/gui/accessible/linux/qspiapplicationadaptor.cpp77
-rw-r--r--src/gui/accessible/linux/qspiapplicationadaptor_p.h41
-rw-r--r--src/gui/accessible/linux/qspidbuscache.cpp50
-rw-r--r--src/gui/accessible/linux/qspidbuscache_p.h40
-rw-r--r--src/gui/accessible/qaccessible.cpp389
-rw-r--r--src/gui/accessible/qaccessible.h482
-rw-r--r--src/gui/accessible/qaccessible_base.h420
-rw-r--r--src/gui/accessible/qaccessiblebridge.cpp46
-rw-r--r--src/gui/accessible/qaccessiblebridge.h44
-rw-r--r--src/gui/accessible/qaccessiblebridgeutils.cpp40
-rw-r--r--src/gui/accessible/qaccessiblebridgeutils_p.h40
-rw-r--r--src/gui/accessible/qaccessiblecache.cpp58
-rw-r--r--src/gui/accessible/qaccessiblecache_mac.mm40
-rw-r--r--src/gui/accessible/qaccessiblecache_p.h44
-rw-r--r--src/gui/accessible/qaccessibleobject.cpp50
-rw-r--r--src/gui/accessible/qaccessibleobject.h44
-rw-r--r--src/gui/accessible/qaccessibleplugin.cpp53
-rw-r--r--src/gui/accessible/qaccessibleplugin.h44
-rw-r--r--src/gui/accessible/qplatformaccessibility.cpp52
-rw-r--r--src/gui/accessible/qplatformaccessibility.h44
-rw-r--r--src/gui/accessible/windows/apisupport/qwindowsuiawrapper.cpp125
-rw-r--r--src/gui/accessible/windows/apisupport/qwindowsuiawrapper_p.h103
-rw-r--r--src/gui/accessible/windows/apisupport/uiaattributeids_p.h99
-rw-r--r--src/gui/accessible/windows/apisupport/uiaclientinterfaces_p.h266
-rw-r--r--src/gui/accessible/windows/apisupport/uiacontroltypeids_p.h96
-rw-r--r--src/gui/accessible/windows/apisupport/uiaerrorids_p.h62
-rw-r--r--src/gui/accessible/windows/apisupport/uiaeventids_p.h90
-rw-r--r--src/gui/accessible/windows/apisupport/uiageneralids_p.h57
-rw-r--r--src/gui/accessible/windows/apisupport/uiapatternids_p.h89
-rw-r--r--src/gui/accessible/windows/apisupport/uiapropertyids_p.h224
-rw-r--r--src/gui/accessible/windows/apisupport/uiaserverinterfaces_p.h403
-rw-r--r--src/gui/accessible/windows/apisupport/uiatypes_p.h193
-rw-r--r--src/gui/animation/qguivariantanimation.cpp40
-rw-r--r--src/gui/compat/removed_api.cpp33
-rw-r--r--src/gui/configure.cmake155
-rw-r--r--src/gui/doc/images/qpainter-concentriccircles.pngbin31294 -> 95529 bytes
-rw-r--r--src/gui/doc/includes/QtGuiDoc6
-rw-r--r--src/gui/doc/includes/windows.h42
-rw-r--r--src/gui/doc/qtgui.qdocconf14
-rw-r--r--src/gui/doc/snippets/brush/brush.cpp51
-rw-r--r--src/gui/doc/snippets/brush/gradientcreationsnippet.cpp51
-rw-r--r--src/gui/doc/snippets/clipboard/clipwindow.cpp51
-rw-r--r--src/gui/doc/snippets/clipboard/clipwindow.h51
-rw-r--r--src/gui/doc/snippets/clipboard/main.cpp51
-rw-r--r--src/gui/doc/snippets/code/doc_src_coordsys.cpp51
-rw-r--r--src/gui/doc/snippets/code/doc_src_richtext.cpp51
-rw-r--r--src/gui/doc/snippets/code/doc_src_richtext.qdoc51
-rw-r--r--src/gui/doc/snippets/code/src_gui_accessible_qaccessible.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_image_qicon.cpp79
-rw-r--r--src/gui/doc/snippets/code/src_gui_image_qimage.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_image_qimagereader.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_image_qimagewriter.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_image_qmovie.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_image_qpixmap.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_image_qpixmapcache.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qaction.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qapplication.cpp134
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qevent.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp73
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qguiapplication_x11.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qkeysequence.cpp53
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qshortcut.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qshortcutmap.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_math3d_qquaternion.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_opengl_qopenglfunctions.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_painting_qbrush.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_painting_qcolor.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp84
-rw-r--r--src/gui/doc/snippets/code/src_gui_painting_qpainterpath.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_painting_qpen.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_painting_qregion.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_painting_qregion_unix.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_painting_qtransform.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_text_qfont.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_text_qfontmetrics.cpp55
-rw-r--r--src/gui/doc/snippets/code/src_gui_text_qsyntaxhighlighter.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_text_qtextcursor.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_text_qtextdocument.cpp59
-rw-r--r--src/gui/doc/snippets/code/src_gui_text_qtextdocumentwriter.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_text_qtextlayout.cpp91
-rw-r--r--src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp88
-rw-r--r--src/gui/doc/snippets/code/src_gui_util_qundostack.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_util_qvalidator.cpp70
-rw-r--r--src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp61
-rw-r--r--src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp51
-rw-r--r--src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp51
-rw-r--r--src/gui/doc/snippets/draganddrop/dragwidget.cpp51
-rw-r--r--src/gui/doc/snippets/draganddrop/dragwidget.h51
-rw-r--r--src/gui/doc/snippets/draganddrop/main.cpp51
-rw-r--r--src/gui/doc/snippets/draganddrop/mainwindow.cpp51
-rw-r--r--src/gui/doc/snippets/draganddrop/mainwindow.h51
-rw-r--r--src/gui/doc/snippets/dragging/main.cpp51
-rw-r--r--src/gui/doc/snippets/dragging/mainwindow.cpp51
-rw-r--r--src/gui/doc/snippets/dragging/mainwindow.h51
-rw-r--r--src/gui/doc/snippets/droparea/droparea.cpp51
-rw-r--r--src/gui/doc/snippets/dropevents/window.cpp51
-rw-r--r--src/gui/doc/snippets/droprectangle/window.cpp51
-rw-r--r--src/gui/doc/snippets/image/image.cpp58
-rw-r--r--src/gui/doc/snippets/image/supportedformat.cpp51
-rw-r--r--src/gui/doc/snippets/overview/using-qt-gui.cmake2
-rw-r--r--src/gui/doc/snippets/picture/picture.cpp51
-rw-r--r--src/gui/doc/snippets/plaintextlayout/window.cpp51
-rw-r--r--src/gui/doc/snippets/polygon/polygon.cpp51
-rw-r--r--src/gui/doc/snippets/qfileopenevent/Info.plist51
-rw-r--r--src/gui/doc/snippets/qfileopenevent/main.cpp61
-rw-r--r--src/gui/doc/snippets/qfontdatabase/qfontdatabase_snippets.cpp51
-rw-r--r--src/gui/doc/snippets/qimagewriter/main.cpp51
-rw-r--r--src/gui/doc/snippets/qstatustipevent/main.cpp51
-rw-r--r--src/gui/doc/snippets/qtextobject/textobjectinterface.h51
-rw-r--r--src/gui/doc/snippets/rhioffscreen/color.frag16
-rw-r--r--src/gui/doc/snippets/rhioffscreen/color.vert18
-rw-r--r--src/gui/doc/snippets/rhioffscreen/main.cpp151
-rw-r--r--src/gui/doc/snippets/scribe-overview/main.cpp51
-rw-r--r--src/gui/doc/snippets/separations/finalwidget.cpp54
-rw-r--r--src/gui/doc/snippets/separations/finalwidget.h51
-rw-r--r--src/gui/doc/snippets/separations/main.cpp51
-rw-r--r--src/gui/doc/snippets/separations/screenwidget.cpp54
-rw-r--r--src/gui/doc/snippets/separations/screenwidget.h51
-rw-r--r--src/gui/doc/snippets/separations/separations.qdoc51
-rw-r--r--src/gui/doc/snippets/separations/viewer.cpp51
-rw-r--r--src/gui/doc/snippets/separations/viewer.h51
-rw-r--r--src/gui/doc/snippets/textblock-formats/main.cpp51
-rw-r--r--src/gui/doc/snippets/textblock-fragments/xmlwriter.cpp51
-rw-r--r--src/gui/doc/snippets/textblock-fragments/xmlwriter.h51
-rw-r--r--src/gui/doc/snippets/textdocument-blocks/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-blocks/mainwindow.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-blocks/mainwindow.h51
-rw-r--r--src/gui/doc/snippets/textdocument-charformats/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-css/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-cursors/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-end/textdocumentendsnippet.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-find/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-frames/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-frames/mainwindow.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-frames/mainwindow.h51
-rw-r--r--src/gui/doc/snippets/textdocument-imagedrop/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-imagedrop/textedit.h51
-rw-r--r--src/gui/doc/snippets/textdocument-imageformat/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-images/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-listitems/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-listitems/mainwindow.cpp59
-rw-r--r--src/gui/doc/snippets/textdocument-listitems/mainwindow.h51
-rw-r--r--src/gui/doc/snippets/textdocument-listitemstyles/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-listitemstyles/mainwindow.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-listitemstyles/mainwindow.h51
-rw-r--r--src/gui/doc/snippets/textdocument-lists/mainwindow.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-printing/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-printing/mainwindow.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-printing/mainwindow.h51
-rw-r--r--src/gui/doc/snippets/textdocument-resources/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-selections/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-selections/mainwindow.cpp69
-rw-r--r--src/gui/doc/snippets/textdocument-selections/mainwindow.h51
-rw-r--r--src/gui/doc/snippets/textdocument-tables/main.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-tables/mainwindow.cpp51
-rw-r--r--src/gui/doc/snippets/textdocument-tables/mainwindow.h51
-rw-r--r--src/gui/doc/snippets/textdocument-texttable/main.cpp51
-rw-r--r--src/gui/doc/snippets/transform/main.cpp56
-rw-r--r--src/gui/doc/src/coordsys.qdoc67
-rw-r--r--src/gui/doc/src/dnd.qdoc56
-rw-r--r--src/gui/doc/src/dontdocument.qdoc28
-rw-r--r--src/gui/doc/src/external-resources.qdoc55
-rw-r--r--src/gui/doc/src/includes/qt-colors.qdocinc21
-rw-r--r--src/gui/doc/src/includes/svg-colors.qdocinc148
-rw-r--r--src/gui/doc/src/paintsystem.qdoc28
-rw-r--r--src/gui/doc/src/qt6-changes.qdoc64
-rw-r--r--src/gui/doc/src/qtgui-overview.qdoc187
-rw-r--r--src/gui/doc/src/qtgui.qdoc201
-rw-r--r--src/gui/doc/src/richtext.qdoc37
-rw-r--r--src/gui/image/qabstractfileiconengine.cpp48
-rw-r--r--src/gui/image/qabstractfileiconengine_p.h41
-rw-r--r--src/gui/image/qabstractfileiconprovider.cpp78
-rw-r--r--src/gui/image/qabstractfileiconprovider.h40
-rw-r--r--src/gui/image/qabstractfileiconprovider_p.h41
-rw-r--r--src/gui/image/qbitmap.cpp69
-rw-r--r--src/gui/image/qbitmap.h41
-rw-r--r--src/gui/image/qbmphandler.cpp178
-rw-r--r--src/gui/image/qbmphandler_p.h40
-rw-r--r--src/gui/image/qicon.cpp774
-rw-r--r--src/gui/image/qicon.h207
-rw-r--r--src/gui/image/qicon_p.h44
-rw-r--r--src/gui/image/qiconengine.cpp115
-rw-r--r--src/gui/image/qiconengine.h40
-rw-r--r--src/gui/image/qiconengine_p.h59
-rw-r--r--src/gui/image/qiconengineplugin.cpp42
-rw-r--r--src/gui/image/qiconengineplugin.h40
-rw-r--r--src/gui/image/qiconloader.cpp481
-rw-r--r--src/gui/image/qiconloader_p.h94
-rw-r--r--src/gui/image/qimage.cpp1106
-rw-r--r--src/gui/image/qimage.h62
-rw-r--r--src/gui/image/qimage_conversions.cpp124
-rw-r--r--src/gui/image/qimage_darwin.mm42
-rw-r--r--src/gui/image/qimage_mips_dspr2.cpp40
-rw-r--r--src/gui/image/qimage_mips_dspr2_asm.S40
-rw-r--r--src/gui/image/qimage_neon.cpp42
-rw-r--r--src/gui/image/qimage_p.h221
-rw-r--r--src/gui/image/qimage_ssse3.cpp40
-rw-r--r--src/gui/image/qimageiohandler.cpp55
-rw-r--r--src/gui/image/qimageiohandler.h40
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks.cpp40
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks_p.h40
-rw-r--r--src/gui/image/qimagereader.cpp195
-rw-r--r--src/gui/image/qimagereader.h40
-rw-r--r--src/gui/image/qimagereaderwriterhelpers.cpp81
-rw-r--r--src/gui/image/qimagereaderwriterhelpers_p.h42
-rw-r--r--src/gui/image/qimagewriter.cpp53
-rw-r--r--src/gui/image/qimagewriter.h40
-rw-r--r--src/gui/image/qmovie.cpp81
-rw-r--r--src/gui/image/qmovie.h40
-rw-r--r--src/gui/image/qpaintengine_pic.cpp40
-rw-r--r--src/gui/image/qpaintengine_pic_p.h40
-rw-r--r--src/gui/image/qpicture.cpp42
-rw-r--r--src/gui/image/qpicture.h42
-rw-r--r--src/gui/image/qpicture_p.h40
-rw-r--r--src/gui/image/qpixmap.cpp97
-rw-r--r--src/gui/image/qpixmap.h47
-rw-r--r--src/gui/image/qpixmap_blitter.cpp40
-rw-r--r--src/gui/image/qpixmap_blitter_p.h40
-rw-r--r--src/gui/image/qpixmap_raster.cpp40
-rw-r--r--src/gui/image/qpixmap_raster_p.h40
-rw-r--r--src/gui/image/qpixmap_win.cpp62
-rw-r--r--src/gui/image/qpixmap_win_p.h38
-rw-r--r--src/gui/image/qpixmapcache.cpp231
-rw-r--r--src/gui/image/qpixmapcache.h68
-rw-r--r--src/gui/image/qpixmapcache_p.h43
-rw-r--r--src/gui/image/qplatformpixmap.cpp60
-rw-r--r--src/gui/image/qplatformpixmap.h40
-rw-r--r--src/gui/image/qpnghandler.cpp76
-rw-r--r--src/gui/image/qpnghandler_p.h40
-rw-r--r--src/gui/image/qppmhandler.cpp116
-rw-r--r--src/gui/image/qppmhandler_p.h40
-rw-r--r--src/gui/image/qxbmhandler.cpp64
-rw-r--r--src/gui/image/qxbmhandler_p.h40
-rw-r--r--src/gui/image/qxpmhandler.cpp165
-rw-r--r--src/gui/image/qxpmhandler_p.h40
-rw-r--r--src/gui/itemmodels/qfileinfogatherer.cpp193
-rw-r--r--src/gui/itemmodels/qfileinfogatherer_p.h61
-rw-r--r--src/gui/itemmodels/qfilesystemmodel.cpp443
-rw-r--r--src/gui/itemmodels/qfilesystemmodel.h54
-rw-r--r--src/gui/itemmodels/qfilesystemmodel_p.h99
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.cpp182
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.h60
-rw-r--r--src/gui/itemmodels/qstandarditemmodel_p.h52
-rw-r--r--src/gui/kernel/qaction.cpp128
-rw-r--r--src/gui/kernel/qaction.h54
-rw-r--r--src/gui/kernel/qaction_p.h42
-rw-r--r--src/gui/kernel/qactiongroup.cpp46
-rw-r--r--src/gui/kernel/qactiongroup.h40
-rw-r--r--src/gui/kernel/qactiongroup_p.h42
-rw-r--r--src/gui/kernel/qclipboard.cpp63
-rw-r--r--src/gui/kernel/qclipboard.h40
-rw-r--r--src/gui/kernel/qcursor.cpp77
-rw-r--r--src/gui/kernel/qcursor.h46
-rw-r--r--src/gui/kernel/qcursor_p.h40
-rw-r--r--src/gui/kernel/qdnd.cpp42
-rw-r--r--src/gui/kernel/qdnd_p.h42
-rw-r--r--src/gui/kernel/qdrag.cpp46
-rw-r--r--src/gui/kernel/qdrag.h40
-rw-r--r--src/gui/kernel/qevent.cpp653
-rw-r--r--src/gui/kernel/qevent.h274
-rw-r--r--src/gui/kernel/qevent_p.h45
-rw-r--r--src/gui/kernel/qeventpoint.cpp149
-rw-r--r--src/gui/kernel/qeventpoint.h44
-rw-r--r--src/gui/kernel/qeventpoint_p.h136
-rw-r--r--src/gui/kernel/qgenericplugin.cpp42
-rw-r--r--src/gui/kernel/qgenericplugin.h40
-rw-r--r--src/gui/kernel/qgenericpluginfactory.cpp51
-rw-r--r--src/gui/kernel/qgenericpluginfactory.h40
-rw-r--r--src/gui/kernel/qguiapplication.cpp867
-rw-r--r--src/gui/kernel/qguiapplication.h44
-rw-r--r--src/gui/kernel/qguiapplication_p.h118
-rw-r--r--src/gui/kernel/qguiapplication_platform.h68
-rw-r--r--src/gui/kernel/qguivariant.cpp54
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp102
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h56
-rw-r--r--src/gui/kernel/qinputdevice.cpp111
-rw-r--r--src/gui/kernel/qinputdevice.h42
-rw-r--r--src/gui/kernel/qinputdevice_p.h41
-rw-r--r--src/gui/kernel/qinputdevicemanager.cpp46
-rw-r--r--src/gui/kernel/qinputdevicemanager_p.h48
-rw-r--r--src/gui/kernel/qinputdevicemanager_p_p.h40
-rw-r--r--src/gui/kernel/qinputmethod.cpp62
-rw-r--r--src/gui/kernel/qinputmethod.h40
-rw-r--r--src/gui/kernel/qinputmethod_p.h40
-rw-r--r--src/gui/kernel/qinternalmimedata.cpp72
-rw-r--r--src/gui/kernel/qinternalmimedata_p.h40
-rw-r--r--src/gui/kernel/qkeymapper.cpp116
-rw-r--r--src/gui/kernel/qkeymapper_p.h66
-rw-r--r--src/gui/kernel/qkeysequence.cpp344
-rw-r--r--src/gui/kernel/qkeysequence.h52
-rw-r--r--src/gui/kernel/qkeysequence_p.h53
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp48
-rw-r--r--src/gui/kernel/qoffscreensurface.h42
-rw-r--r--src/gui/kernel/qoffscreensurface_p.h40
-rw-r--r--src/gui/kernel/qoffscreensurface_platform.h51
-rw-r--r--src/gui/kernel/qopenglcontext.cpp120
-rw-r--r--src/gui/kernel/qopenglcontext.h45
-rw-r--r--src/gui/kernel/qopenglcontext_p.h52
-rw-r--r--src/gui/kernel/qopenglcontext_platform.h64
-rw-r--r--src/gui/kernel/qpaintdevicewindow.cpp50
-rw-r--r--src/gui/kernel/qpaintdevicewindow.h40
-rw-r--r--src/gui/kernel/qpaintdevicewindow_p.h47
-rw-r--r--src/gui/kernel/qpalette.cpp282
-rw-r--r--src/gui/kernel/qpalette.h51
-rw-r--r--src/gui/kernel/qpalette_p.h77
-rw-r--r--src/gui/kernel/qpixelformat.cpp42
-rw-r--r--src/gui/kernel/qpixelformat.h40
-rw-r--r--src/gui/kernel/qplatformclipboard.cpp40
-rw-r--r--src/gui/kernel/qplatformclipboard.h40
-rw-r--r--src/gui/kernel/qplatformcursor.cpp46
-rw-r--r--src/gui/kernel/qplatformcursor.h40
-rw-r--r--src/gui/kernel/qplatformdialoghelper.cpp152
-rw-r--r--src/gui/kernel/qplatformdialoghelper.h95
-rw-r--r--src/gui/kernel/qplatformdrag.cpp40
-rw-r--r--src/gui/kernel/qplatformdrag.h40
-rw-r--r--src/gui/kernel/qplatformgraphicsbuffer.cpp42
-rw-r--r--src/gui/kernel/qplatformgraphicsbuffer.h40
-rw-r--r--src/gui/kernel/qplatformgraphicsbufferhelper.cpp44
-rw-r--r--src/gui/kernel/qplatformgraphicsbufferhelper.h40
-rw-r--r--src/gui/kernel/qplatforminputcontext.cpp60
-rw-r--r--src/gui/kernel/qplatforminputcontext.h42
-rw-r--r--src/gui/kernel/qplatforminputcontext_p.h40
-rw-r--r--src/gui/kernel/qplatforminputcontextfactory.cpp81
-rw-r--r--src/gui/kernel/qplatforminputcontextfactory_p.h43
-rw-r--r--src/gui/kernel/qplatforminputcontextplugin.cpp42
-rw-r--r--src/gui/kernel/qplatforminputcontextplugin_p.h40
-rw-r--r--src/gui/kernel/qplatformintegration.cpp103
-rw-r--r--src/gui/kernel/qplatformintegration.h61
-rw-r--r--src/gui/kernel/qplatformintegrationfactory.cpp83
-rw-r--r--src/gui/kernel/qplatformintegrationfactory_p.h40
-rw-r--r--src/gui/kernel/qplatformintegrationplugin.cpp42
-rw-r--r--src/gui/kernel/qplatformintegrationplugin.h40
-rw-r--r--src/gui/kernel/qplatformkeymapper.cpp38
-rw-r--r--src/gui/kernel/qplatformkeymapper.h36
-rw-r--r--src/gui/kernel/qplatformmenu.cpp44
-rw-r--r--src/gui/kernel/qplatformmenu.h49
-rw-r--r--src/gui/kernel/qplatformmenu_p.h44
-rw-r--r--src/gui/kernel/qplatformnativeinterface.cpp44
-rw-r--r--src/gui/kernel/qplatformnativeinterface.h40
-rw-r--r--src/gui/kernel/qplatformoffscreensurface.cpp40
-rw-r--r--src/gui/kernel/qplatformoffscreensurface.h40
-rw-r--r--src/gui/kernel/qplatformopenglcontext.cpp56
-rw-r--r--src/gui/kernel/qplatformopenglcontext.h43
-rw-r--r--src/gui/kernel/qplatformscreen.cpp58
-rw-r--r--src/gui/kernel/qplatformscreen.h46
-rw-r--r--src/gui/kernel/qplatformscreen_p.h47
-rw-r--r--src/gui/kernel/qplatformservices.cpp66
-rw-r--r--src/gui/kernel/qplatformservices.h60
-rw-r--r--src/gui/kernel/qplatformsessionmanager.cpp44
-rw-r--r--src/gui/kernel/qplatformsessionmanager.h44
-rw-r--r--src/gui/kernel/qplatformsharedgraphicscache.cpp42
-rw-r--r--src/gui/kernel/qplatformsharedgraphicscache.h40
-rw-r--r--src/gui/kernel/qplatformsurface.cpp51
-rw-r--r--src/gui/kernel/qplatformsurface.h42
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon.cpp42
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon.h45
-rw-r--r--src/gui/kernel/qplatformtheme.cpp213
-rw-r--r--src/gui/kernel/qplatformtheme.h77
-rw-r--r--src/gui/kernel/qplatformtheme_p.h42
-rw-r--r--src/gui/kernel/qplatformthemefactory.cpp91
-rw-r--r--src/gui/kernel/qplatformthemefactory_p.h40
-rw-r--r--src/gui/kernel/qplatformthemeplugin.cpp42
-rw-r--r--src/gui/kernel/qplatformthemeplugin.h40
-rw-r--r--src/gui/kernel/qplatformwindow.cpp84
-rw-r--r--src/gui/kernel/qplatformwindow.h41
-rw-r--r--src/gui/kernel/qplatformwindow_p.h92
-rw-r--r--src/gui/kernel/qpointingdevice.cpp139
-rw-r--r--src/gui/kernel/qpointingdevice.h48
-rw-r--r--src/gui/kernel/qpointingdevice_p.h45
-rw-r--r--src/gui/kernel/qrasterwindow.cpp58
-rw-r--r--src/gui/kernel/qrasterwindow.h41
-rw-r--r--src/gui/kernel/qscreen.cpp252
-rw-r--r--src/gui/kernel/qscreen.h42
-rw-r--r--src/gui/kernel/qscreen_p.h74
-rw-r--r--src/gui/kernel/qscreen_platform.h61
-rw-r--r--src/gui/kernel/qsessionmanager.cpp50
-rw-r--r--src/gui/kernel/qsessionmanager.h40
-rw-r--r--src/gui/kernel/qsessionmanager_p.h44
-rw-r--r--src/gui/kernel/qshapedpixmapdndwindow.cpp48
-rw-r--r--src/gui/kernel/qshapedpixmapdndwindow_p.h40
-rw-r--r--src/gui/kernel/qshortcut.cpp52
-rw-r--r--src/gui/kernel/qshortcut.h47
-rw-r--r--src/gui/kernel/qshortcut_p.h42
-rw-r--r--src/gui/kernel/qshortcutmap.cpp238
-rw-r--r--src/gui/kernel/qshortcutmap_p.h41
-rw-r--r--src/gui/kernel/qsimpledrag.cpp52
-rw-r--r--src/gui/kernel/qsimpledrag_p.h40
-rw-r--r--src/gui/kernel/qstylehints.cpp128
-rw-r--r--src/gui/kernel/qstylehints.h50
-rw-r--r--src/gui/kernel/qstylehints_p.h54
-rw-r--r--src/gui/kernel/qsurface.cpp53
-rw-r--r--src/gui/kernel/qsurface.h42
-rw-r--r--src/gui/kernel/qsurfaceformat.cpp47
-rw-r--r--src/gui/kernel/qsurfaceformat.h40
-rw-r--r--src/gui/kernel/qt_gui_pch.h40
-rw-r--r--src/gui/kernel/qtestsupport_gui.cpp122
-rw-r--r--src/gui/kernel/qtestsupport_gui.h49
-rw-r--r--src/gui/kernel/qtguiglobal.h40
-rw-r--r--src/gui/kernel/qtguiglobal_p.h40
-rw-r--r--src/gui/kernel/qwindow.cpp498
-rw-r--r--src/gui/kernel/qwindow.h44
-rw-r--r--src/gui/kernel/qwindow_p.h77
-rw-r--r--src/gui/kernel/qwindowdefs.h40
-rw-r--r--src/gui/kernel/qwindowdefs_win.h40
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp557
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h81
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h74
-rw-r--r--src/gui/math3d/qgenericmatrix.cpp49
-rw-r--r--src/gui/math3d/qgenericmatrix.h60
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp105
-rw-r--r--src/gui/math3d/qmatrix4x4.h70
-rw-r--r--src/gui/math3d/qquaternion.cpp163
-rw-r--r--src/gui/math3d/qquaternion.h237
-rw-r--r--src/gui/math3d/qvector2d.h42
-rw-r--r--src/gui/math3d/qvector3d.h42
-rw-r--r--src/gui/math3d/qvector4d.h42
-rw-r--r--src/gui/math3d/qvectornd.cpp48
-rw-r--r--src/gui/math3d/qvectornd.h74
-rw-r--r--src/gui/opengl/platform/egl/qeglconvenience.cpp56
-rw-r--r--src/gui/opengl/platform/egl/qeglconvenience_p.h40
-rw-r--r--src/gui/opengl/platform/egl/qeglpbuffer.cpp49
-rw-r--r--src/gui/opengl/platform/egl/qeglpbuffer_p.h40
-rw-r--r--src/gui/opengl/platform/egl/qeglplatformcontext.cpp42
-rw-r--r--src/gui/opengl/platform/egl/qeglplatformcontext_p.h48
-rw-r--r--src/gui/opengl/platform/egl/qeglstreamconvenience.cpp40
-rw-r--r--src/gui/opengl/platform/egl/qeglstreamconvenience_p.h44
-rw-r--r--src/gui/opengl/platform/egl/qt_egl_p.h47
-rw-r--r--src/gui/opengl/platform/egl/qxlibeglintegration.cpp166
-rw-r--r--src/gui/opengl/platform/egl/qxlibeglintegration_p.h69
-rw-r--r--src/gui/opengl/platform/unix/qglxconvenience.cpp42
-rw-r--r--src/gui/opengl/platform/unix/qglxconvenience_p.h41
-rw-r--r--src/gui/opengl/qopengl.cpp119
-rw-r--r--src/gui/opengl/qopengl.h86
-rw-r--r--src/gui/opengl/qopengl_p.h40
-rw-r--r--src/gui/opengl/qopenglextensions_p.h55
-rw-r--r--src/gui/opengl/qopenglextrafunctions.h40
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp89
-rw-r--r--src/gui/opengl/qopenglfunctions.h42
-rw-r--r--src/gui/opengl/qopenglprogrambinarycache.cpp105
-rw-r--r--src/gui/opengl/qopenglprogrambinarycache_p.h48
-rw-r--r--src/gui/opengl/qt_attribution.json4
-rw-r--r--src/gui/painting/qbackingstore.cpp148
-rw-r--r--src/gui/painting/qbackingstore.h40
-rw-r--r--src/gui/painting/qbackingstoredefaultcompositor.cpp676
-rw-r--r--src/gui/painting/qbackingstoredefaultcompositor_p.h110
-rw-r--r--src/gui/painting/qbackingstorerhisupport.cpp327
-rw-r--r--src/gui/painting/qbackingstorerhisupport_p.h77
-rw-r--r--src/gui/painting/qbezier.cpp40
-rw-r--r--src/gui/painting/qbezier_p.h41
-rw-r--r--src/gui/painting/qblendfunctions.cpp44
-rw-r--r--src/gui/painting/qblendfunctions_p.h97
-rw-r--r--src/gui/painting/qblittable.cpp40
-rw-r--r--src/gui/painting/qblittable_p.h40
-rw-r--r--src/gui/painting/qbrush.cpp59
-rw-r--r--src/gui/painting/qbrush.h42
-rw-r--r--src/gui/painting/qcmyk_p.h88
-rw-r--r--src/gui/painting/qcolor.cpp273
-rw-r--r--src/gui/painting/qcolor.h82
-rw-r--r--src/gui/painting/qcolor_p.h44
-rw-r--r--src/gui/painting/qcolorclut_p.h127
-rw-r--r--src/gui/painting/qcolormatrix_p.h293
-rw-r--r--src/gui/painting/qcolorspace.cpp566
-rw-r--r--src/gui/painting/qcolorspace.h61
-rw-r--r--src/gui/painting/qcolorspace_p.h68
-rw-r--r--src/gui/painting/qcolortransferfunction_p.h116
-rw-r--r--src/gui/painting/qcolortransfertable_p.h100
-rw-r--r--src/gui/painting/qcolortransform.cpp1447
-rw-r--r--src/gui/painting/qcolortransform.h59
-rw-r--r--src/gui/painting/qcolortransform_p.h69
-rw-r--r--src/gui/painting/qcolortrc_p.h59
-rw-r--r--src/gui/painting/qcolortrclut.cpp117
-rw-r--r--src/gui/painting/qcolortrclut_p.h126
-rw-r--r--src/gui/painting/qcompositionfunctions.cpp78
-rw-r--r--src/gui/painting/qcoregraphics.mm93
-rw-r--r--src/gui/painting/qcoregraphics_p.h64
-rw-r--r--src/gui/painting/qcosmeticstroker.cpp46
-rw-r--r--src/gui/painting/qcosmeticstroker_p.h40
-rw-r--r--src/gui/painting/qcssutil.cpp63
-rw-r--r--src/gui/painting/qcssutil_p.h40
-rw-r--r--src/gui/painting/qdatabuffer_p.h61
-rw-r--r--src/gui/painting/qdrawhelper.cpp1420
-rw-r--r--src/gui/painting/qdrawhelper_avx2.cpp77
-rw-r--r--src/gui/painting/qdrawhelper_mips_dsp.cpp44
-rw-r--r--src/gui/painting/qdrawhelper_mips_dsp_asm.S42
-rw-r--r--src/gui/painting/qdrawhelper_mips_dsp_p.h40
-rw-r--r--src/gui/painting/qdrawhelper_mips_dspr2_asm.S40
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp46
-rw-r--r--src/gui/painting/qdrawhelper_neon_asm.S42
-rw-r--r--src/gui/painting/qdrawhelper_neon_p.h40
-rw-r--r--src/gui/painting/qdrawhelper_p.h76
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp121
-rw-r--r--src/gui/painting/qdrawhelper_sse4.cpp48
-rw-r--r--src/gui/painting/qdrawhelper_ssse3.cpp44
-rw-r--r--src/gui/painting/qdrawhelper_x86_p.h40
-rw-r--r--src/gui/painting/qdrawingprimitive_sse2_p.h44
-rw-r--r--src/gui/painting/qemulationpaintengine.cpp40
-rw-r--r--src/gui/painting/qemulationpaintengine_p.h40
-rw-r--r--src/gui/painting/qfixed_p.h129
-rw-r--r--src/gui/painting/qgrayraster.c40
-rw-r--r--src/gui/painting/qgrayraster_p.h40
-rw-r--r--src/gui/painting/qicc.cpp1013
-rw-r--r--src/gui/painting/qicc_p.h41
-rw-r--r--src/gui/painting/qimageeffects.cpp327
-rw-r--r--src/gui/painting/qimagescale.cpp47
-rw-r--r--src/gui/painting/qimagescale_neon.cpp47
-rw-r--r--src/gui/painting/qimagescale_p.h41
-rw-r--r--src/gui/painting/qimagescale_sse4.cpp47
-rw-r--r--src/gui/painting/qmath_p.h56
-rw-r--r--src/gui/painting/qmemrotate.cpp40
-rw-r--r--src/gui/painting/qmemrotate_p.h40
-rw-r--r--src/gui/painting/qoutlinemapper.cpp72
-rw-r--r--src/gui/painting/qoutlinemapper_p.h45
-rw-r--r--src/gui/painting/qpagedpaintdevice.cpp40
-rw-r--r--src/gui/painting/qpagedpaintdevice.h40
-rw-r--r--src/gui/painting/qpagedpaintdevice_p.h40
-rw-r--r--src/gui/painting/qpagelayout.cpp98
-rw-r--r--src/gui/painting/qpagelayout.h50
-rw-r--r--src/gui/painting/qpageranges.cpp55
-rw-r--r--src/gui/painting/qpageranges.h44
-rw-r--r--src/gui/painting/qpageranges_p.h40
-rw-r--r--src/gui/painting/qpagesize.cpp69
-rw-r--r--src/gui/painting/qpagesize.h48
-rw-r--r--src/gui/painting/qpaintdevice.cpp40
-rw-r--r--src/gui/painting/qpaintdevice.h40
-rw-r--r--src/gui/painting/qpaintdevice.qdoc28
-rw-r--r--src/gui/painting/qpaintengine.cpp53
-rw-r--r--src/gui/painting/qpaintengine.h46
-rw-r--r--src/gui/painting/qpaintengine_blitter.cpp40
-rw-r--r--src/gui/painting/qpaintengine_blitter_p.h40
-rw-r--r--src/gui/painting/qpaintengine_p.h40
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp351
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h61
-rw-r--r--src/gui/painting/qpaintengineex.cpp58
-rw-r--r--src/gui/painting/qpaintengineex_p.h40
-rw-r--r--src/gui/painting/qpainter.cpp270
-rw-r--r--src/gui/painting/qpainter.h48
-rw-r--r--src/gui/painting/qpainter_p.h42
-rw-r--r--src/gui/painting/qpainterpath.cpp69
-rw-r--r--src/gui/painting/qpainterpath.h40
-rw-r--r--src/gui/painting/qpainterpath_p.h55
-rw-r--r--src/gui/painting/qpathclipper.cpp44
-rw-r--r--src/gui/painting/qpathclipper_p.h52
-rw-r--r--src/gui/painting/qpathsimplifier.cpp54
-rw-r--r--src/gui/painting/qpathsimplifier_p.h40
-rw-r--r--src/gui/painting/qpdf.cpp688
-rw-r--r--src/gui/painting/qpdf.qrc7
-rw-r--r--src/gui/painting/qpdf_p.h107
-rw-r--r--src/gui/painting/qpdfwriter.cpp89
-rw-r--r--src/gui/painting/qpdfwriter.h52
-rw-r--r--src/gui/painting/qpen.cpp172
-rw-r--r--src/gui/painting/qpen.h56
-rw-r--r--src/gui/painting/qpen_p.h47
-rw-r--r--src/gui/painting/qpixellayout.cpp176
-rw-r--r--src/gui/painting/qpixellayout_p.h49
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp241
-rw-r--r--src/gui/painting/qplatformbackingstore.h163
-rw-r--r--src/gui/painting/qpolygon.cpp91
-rw-r--r--src/gui/painting/qpolygon.h57
-rw-r--r--src/gui/painting/qrasterbackingstore.cpp48
-rw-r--r--src/gui/painting/qrasterbackingstore_p.h41
-rw-r--r--src/gui/painting/qrasterdefs_p.h40
-rw-r--r--src/gui/painting/qrasterizer.cpp154
-rw-r--r--src/gui/painting/qrasterizer_p.h40
-rw-r--r--src/gui/painting/qrbtree_p.h40
-rw-r--r--src/gui/painting/qregion.cpp56
-rw-r--r--src/gui/painting/qregion.h46
-rw-r--r--src/gui/painting/qrgb.h40
-rw-r--r--src/gui/painting/qrgba64.h44
-rw-r--r--src/gui/painting/qrgba64.qdoc28
-rw-r--r--src/gui/painting/qrgba64_p.h48
-rw-r--r--src/gui/painting/qrgbafloat.h136
-rw-r--r--src/gui/painting/qrgbafloat.qdoc42
-rw-r--r--src/gui/painting/qrhibackingstore.cpp68
-rw-r--r--src/gui/painting/qrhibackingstore_p.h34
-rw-r--r--src/gui/painting/qstroker.cpp102
-rw-r--r--src/gui/painting/qstroker_p.h41
-rw-r--r--src/gui/painting/qt_attribution.json16
-rw-r--r--src/gui/painting/qt_mips_asm_dsp_p.h46
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp58
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h45
-rw-r--r--src/gui/painting/qtransform.cpp332
-rw-r--r--src/gui/painting/qtransform.h49
-rw-r--r--src/gui/painting/qtriangulatingstroker.cpp40
-rw-r--r--src/gui/painting/qtriangulatingstroker_p.h40
-rw-r--r--src/gui/painting/qtriangulator.cpp42
-rw-r--r--src/gui/painting/qtriangulator_p.h40
-rw-r--r--src/gui/painting/qvectorpath_p.h40
-rw-r--r--src/gui/painting/shaders/backingstorecompose.frag25
-rw-r--r--src/gui/painting/shaders/backingstorecompose.frag.qsbbin0 -> 1657 bytes
-rw-r--r--src/gui/painting/shaders/backingstorecompose.vert19
-rw-r--r--src/gui/painting/shaders/backingstorecompose.vert.qsbbin0 -> 1408 bytes
-rw-r--r--src/gui/painting/webgradients.cpp43
-rw-r--r--src/gui/platform/android/qandroidnativeinterface.cpp58
-rw-r--r--src/gui/platform/darwin/qappleiconengine.mm464
-rw-r--r--src/gui/platform/darwin/qappleiconengine_p.h64
-rw-r--r--src/gui/platform/darwin/qapplekeymapper.mm283
-rw-r--r--src/gui/platform/darwin/qapplekeymapper_p.h56
-rw-r--r--src/gui/platform/darwin/qmacmime.mm1048
-rw-r--r--src/gui/platform/darwin/qmacmime_p.h99
-rw-r--r--src/gui/platform/darwin/qmacmimeregistry.mm118
-rw-r--r--src/gui/platform/darwin/qmacmimeregistry_p.h42
-rw-r--r--src/gui/platform/darwin/qutimimeconverter.h62
-rw-r--r--src/gui/platform/darwin/qutimimeconverter.mm823
-rw-r--r--src/gui/platform/ios/PrivacyInfo.xcprivacy23
-rw-r--r--src/gui/platform/macos/qcocoanativeinterface.mm48
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenuadaptor.cpp56
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenuadaptor_p.h40
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenubar.cpp48
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenubar_p.h40
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenuconnection.cpp64
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenuconnection_p.h45
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenuregistrarproxy.cpp42
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenuregistrarproxy_p.h43
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenutypes.cpp102
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusmenutypes_p.h59
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusplatformmenu.cpp42
-rw-r--r--src/gui/platform/unix/dbusmenu/qdbusplatformmenu_p.h40
-rw-r--r--src/gui/platform/unix/dbustray/qdbustrayicon.cpp69
-rw-r--r--src/gui/platform/unix/dbustray/qdbustrayicon_p.h40
-rw-r--r--src/gui/platform/unix/dbustray/qdbustraytypes.cpp52
-rw-r--r--src/gui/platform/unix/dbustray/qdbustraytypes_p.h48
-rw-r--r--src/gui/platform/unix/dbustray/qstatusnotifieritemadaptor.cpp48
-rw-r--r--src/gui/platform/unix/dbustray/qstatusnotifieritemadaptor_p.h44
-rw-r--r--src/gui/platform/unix/dbustray/qxdgnotificationproxy.cpp42
-rw-r--r--src/gui/platform/unix/dbustray/qxdgnotificationproxy_p.h43
-rw-r--r--src/gui/platform/unix/qeventdispatcher_glib.cpp42
-rw-r--r--src/gui/platform/unix/qeventdispatcher_glib_p.h40
-rw-r--r--src/gui/platform/unix/qgenericunixeventdispatcher.cpp45
-rw-r--r--src/gui/platform/unix/qgenericunixeventdispatcher_p.h41
-rw-r--r--src/gui/platform/unix/qgenericunixservices.cpp465
-rw-r--r--src/gui/platform/unix/qgenericunixservices_p.h51
-rw-r--r--src/gui/platform/unix/qgenericunixthemes.cpp609
-rw-r--r--src/gui/platform/unix/qgenericunixthemes_p.h43
-rw-r--r--src/gui/platform/unix/qtx11extras.cpp62
-rw-r--r--src/gui/platform/unix/qtx11extras_p.h41
-rw-r--r--src/gui/platform/unix/qunixeventdispatcher.cpp40
-rw-r--r--src/gui/platform/unix/qunixeventdispatcher_qpa_p.h40
-rw-r--r--src/gui/platform/unix/qunixnativeinterface.cpp182
-rw-r--r--src/gui/platform/unix/qxkbcommon.cpp108
-rw-r--r--src/gui/platform/unix/qxkbcommon_3rdparty.cpp40
-rw-r--r--src/gui/platform/unix/qxkbcommon_p.h100
-rw-r--r--src/gui/platform/wasm/qlocalfileapi.cpp211
-rw-r--r--src/gui/platform/wasm/qlocalfileapi_p.h94
-rw-r--r--src/gui/platform/wasm/qwasmlocalfileaccess.cpp335
-rw-r--r--src/gui/platform/wasm/qwasmlocalfileaccess_p.h55
-rw-r--r--src/gui/platform/wasm/qwasmnativeinterface.cpp17
-rw-r--r--src/gui/platform/windows/qwindowsguieventdispatcher.cpp50
-rw-r--r--src/gui/platform/windows/qwindowsguieventdispatcher_p.h40
-rw-r--r--src/gui/platform/windows/qwindowsmime_p.h85
-rw-r--r--src/gui/platform/windows/qwindowsmimeconverter.cpp170
-rw-r--r--src/gui/platform/windows/qwindowsmimeconverter.h43
-rw-r--r--src/gui/platform/windows/qwindowsnativeinterface.cpp66
-rw-r--r--src/gui/platform/windows/qwindowsthemecache.cpp79
-rw-r--r--src/gui/platform/windows/qwindowsthemecache_p.h35
-rw-r--r--src/gui/qt_cmdline.cmake3
-rw-r--r--src/gui/qtgui.tracepoints41
-rw-r--r--src/gui/rhi/MiniEngine_LICENSE.txt22
-rw-r--r--src/gui/rhi/cs_mipmap_p.h939
-rw-r--r--src/gui/rhi/cs_tdr_p.h228
-rw-r--r--src/gui/rhi/mipmap.hlsl117
-rw-r--r--src/gui/rhi/qrhi.cpp5728
-rw-r--r--src/gui/rhi/qrhi.h2026
-rw-r--r--src/gui/rhi/qrhi_p.h2244
-rw-r--r--src/gui/rhi/qrhi_p_p.h713
-rw-r--r--src/gui/rhi/qrhi_platform.h175
-rw-r--r--src/gui/rhi/qrhid3d11.cpp2540
-rw-r--r--src/gui/rhi/qrhid3d11_p.h895
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h788
-rw-r--r--src/gui/rhi/qrhid3d12.cpp6569
-rw-r--r--src/gui/rhi/qrhid3d12_p.h1248
-rw-r--r--src/gui/rhi/qrhid3dhelpers.cpp172
-rw-r--r--src/gui/rhi/qrhid3dhelpers_p.h53
-rw-r--r--src/gui/rhi/qrhigles2.cpp2533
-rw-r--r--src/gui/rhi/qrhigles2_p.h1163
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h1045
-rw-r--r--src/gui/rhi/qrhimetal.mm3730
-rw-r--r--src/gui/rhi/qrhimetal_p.h537
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h486
-rw-r--r--src/gui/rhi/qrhinull.cpp280
-rw-r--r--src/gui/rhi/qrhinull_p.h315
-rw-r--r--src/gui/rhi/qrhinull_p_p.h320
-rw-r--r--src/gui/rhi/qrhiprofiler.cpp611
-rw-r--r--src/gui/rhi/qrhiprofiler_p.h123
-rw-r--r--src/gui/rhi/qrhiprofiler_p_p.h124
-rw-r--r--src/gui/rhi/qrhivulkan.cpp2736
-rw-r--r--src/gui/rhi/qrhivulkan_p.h1071
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h1018
-rw-r--r--src/gui/rhi/qrhivulkanext_p.h84
-rw-r--r--src/gui/rhi/qshader.cpp699
-rw-r--r--src/gui/rhi/qshader.h241
-rw-r--r--src/gui/rhi/qshader_p.h281
-rw-r--r--src/gui/rhi/qshader_p_p.h97
-rw-r--r--src/gui/rhi/qshaderdescription.cpp1398
-rw-r--r--src/gui/rhi/qshaderdescription.h386
-rw-r--r--src/gui/rhi/qshaderdescription_p.h360
-rw-r--r--src/gui/rhi/qshaderdescription_p_p.h102
-rw-r--r--src/gui/rhi/qt_attribution.json16
-rw-r--r--src/gui/rhi/tdr.hlsl9
-rw-r--r--src/gui/rhi/test.hlsl24
-rw-r--r--src/gui/rhi/vs_test_p.h237
-rw-r--r--src/gui/text/coretext/qcoretextfontdatabase.mm434
-rw-r--r--src/gui/text/coretext/qcoretextfontdatabase_p.h62
-rw-r--r--src/gui/text/coretext/qfontengine_coretext.mm100
-rw-r--r--src/gui/text/coretext/qfontengine_coretext_p.h43
-rw-r--r--src/gui/text/freetype/qfontengine_ft.cpp361
-rw-r--r--src/gui/text/freetype/qfontengine_ft_p.h50
-rw-r--r--src/gui/text/freetype/qfreetypefontdatabase.cpp239
-rw-r--r--src/gui/text/freetype/qfreetypefontdatabase_p.h55
-rw-r--r--src/gui/text/qabstracttextdocumentlayout.cpp50
-rw-r--r--src/gui/text/qabstracttextdocumentlayout.h43
-rw-r--r--src/gui/text/qabstracttextdocumentlayout_p.h53
-rw-r--r--src/gui/text/qcssparser.cpp363
-rw-r--r--src/gui/text/qcssparser_p.h73
-rw-r--r--src/gui/text/qcssscanner.cpp42
-rw-r--r--src/gui/text/qdistancefield.cpp52
-rw-r--r--src/gui/text/qdistancefield_p.h40
-rw-r--r--src/gui/text/qfont.cpp732
-rw-r--r--src/gui/text/qfont.h122
-rw-r--r--src/gui/text/qfont_p.h71
-rw-r--r--src/gui/text/qfontdatabase.cpp775
-rw-r--r--src/gui/text/qfontdatabase.h47
-rw-r--r--src/gui/text/qfontdatabase_p.h91
-rw-r--r--src/gui/text/qfontengine.cpp253
-rw-r--r--src/gui/text/qfontengine_p.h71
-rw-r--r--src/gui/text/qfontengineglyphcache.cpp40
-rw-r--r--src/gui/text/qfontengineglyphcache_p.h42
-rw-r--r--src/gui/text/qfontinfo.h45
-rw-r--r--src/gui/text/qfontmetrics.cpp302
-rw-r--r--src/gui/text/qfontmetrics.h54
-rw-r--r--src/gui/text/qfontsubset.cpp148
-rw-r--r--src/gui/text/qfontsubset_agl.cpp40
-rw-r--r--src/gui/text/qfontsubset_p.h45
-rw-r--r--src/gui/text/qfragmentmap.cpp40
-rw-r--r--src/gui/text/qfragmentmap_p.h40
-rw-r--r--src/gui/text/qglyphrun.cpp119
-rw-r--r--src/gui/text/qglyphrun.h50
-rw-r--r--src/gui/text/qglyphrun_p.h45
-rw-r--r--src/gui/text/qharfbuzzng.cpp66
-rw-r--r--src/gui/text/qharfbuzzng_p.h42
-rw-r--r--src/gui/text/qinputcontrol.cpp46
-rw-r--r--src/gui/text/qinputcontrol_p.h41
-rw-r--r--src/gui/text/qplatformfontdatabase.cpp118
-rw-r--r--src/gui/text/qplatformfontdatabase.h52
-rw-r--r--src/gui/text/qrawfont.cpp72
-rw-r--r--src/gui/text/qrawfont.h45
-rw-r--r--src/gui/text/qrawfont_p.h40
-rw-r--r--src/gui/text/qstatictext.cpp42
-rw-r--r--src/gui/text/qstatictext.h44
-rw-r--r--src/gui/text/qstatictext_p.h40
-rw-r--r--src/gui/text/qsyntaxhighlighter.cpp60
-rw-r--r--src/gui/text/qsyntaxhighlighter.h40
-rw-r--r--src/gui/text/qt_attribution.json2
-rw-r--r--src/gui/text/qtextcursor.cpp86
-rw-r--r--src/gui/text/qtextcursor.h49
-rw-r--r--src/gui/text/qtextcursor_p.h40
-rw-r--r--src/gui/text/qtextdocument.cpp860
-rw-r--r--src/gui/text/qtextdocument.h53
-rw-r--r--src/gui/text/qtextdocument_p.cpp86
-rw-r--r--src/gui/text/qtextdocument_p.h55
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp178
-rw-r--r--src/gui/text/qtextdocumentfragment.h50
-rw-r--r--src/gui/text/qtextdocumentfragment_p.h40
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp157
-rw-r--r--src/gui/text/qtextdocumentlayout_p.h40
-rw-r--r--src/gui/text/qtextdocumentwriter.cpp41
-rw-r--r--src/gui/text/qtextdocumentwriter.h40
-rw-r--r--src/gui/text/qtextengine.cpp544
-rw-r--r--src/gui/text/qtextengine_p.h75
-rw-r--r--src/gui/text/qtextformat.cpp217
-rw-r--r--src/gui/text/qtextformat.h86
-rw-r--r--src/gui/text/qtextformat_p.h43
-rw-r--r--src/gui/text/qtexthtmlparser.cpp488
-rw-r--r--src/gui/text/qtexthtmlparser_p.h53
-rw-r--r--src/gui/text/qtextimagehandler.cpp198
-rw-r--r--src/gui/text/qtextimagehandler_p.h40
-rw-r--r--src/gui/text/qtextlayout.cpp911
-rw-r--r--src/gui/text/qtextlayout.h68
-rw-r--r--src/gui/text/qtextlist.cpp87
-rw-r--r--src/gui/text/qtextlist.h40
-rw-r--r--src/gui/text/qtextmarkdownimporter.cpp234
-rw-r--r--src/gui/text/qtextmarkdownimporter_p.h51
-rw-r--r--src/gui/text/qtextmarkdownwriter.cpp412
-rw-r--r--src/gui/text/qtextmarkdownwriter_p.h43
-rw-r--r--src/gui/text/qtextobject.cpp60
-rw-r--r--src/gui/text/qtextobject.h40
-rw-r--r--src/gui/text/qtextobject_p.h40
-rw-r--r--src/gui/text/qtextodfwriter.cpp105
-rw-r--r--src/gui/text/qtextodfwriter_p.h40
-rw-r--r--src/gui/text/qtextoption.cpp50
-rw-r--r--src/gui/text/qtextoption.h46
-rw-r--r--src/gui/text/qtexttable.cpp50
-rw-r--r--src/gui/text/qtexttable.h40
-rw-r--r--src/gui/text/qtexttable_p.h40
-rw-r--r--src/gui/text/qzip.cpp1366
-rw-r--r--src/gui/text/qzipreader_p.h127
-rw-r--r--src/gui/text/qzipwriter_p.h117
-rw-r--r--src/gui/text/unix/qfontconfigdatabase.cpp284
-rw-r--r--src/gui/text/unix/qfontconfigdatabase_p.h41
-rw-r--r--src/gui/text/unix/qfontenginemultifontconfig.cpp42
-rw-r--r--src/gui/text/unix/qfontenginemultifontconfig_p.h40
-rw-r--r--src/gui/text/unix/qgenericunixfontdatabase_p.h47
-rw-r--r--src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp741
-rw-r--r--src/gui/text/windows/qwindowsdirectwritefontdatabase_p.h64
-rw-r--r--src/gui/text/windows/qwindowsfontdatabase.cpp339
-rw-r--r--src/gui/text/windows/qwindowsfontdatabase_ft.cpp84
-rw-r--r--src/gui/text/windows/qwindowsfontdatabase_ft_p.h43
-rw-r--r--src/gui/text/windows/qwindowsfontdatabase_p.h57
-rw-r--r--src/gui/text/windows/qwindowsfontdatabasebase.cpp347
-rw-r--r--src/gui/text/windows/qwindowsfontdatabasebase_p.h58
-rw-r--r--src/gui/text/windows/qwindowsfontengine.cpp83
-rw-r--r--src/gui/text/windows/qwindowsfontengine_p.h45
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite.cpp345
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite_p.h58
-rw-r--r--src/gui/text/windows/qwindowsnativeimage.cpp40
-rw-r--r--src/gui/text/windows/qwindowsnativeimage_p.h41
-rw-r--r--src/gui/util/qabstractlayoutstyleinfo.cpp40
-rw-r--r--src/gui/util/qabstractlayoutstyleinfo_p.h40
-rw-r--r--src/gui/util/qastchandler.cpp50
-rw-r--r--src/gui/util/qastchandler_p.h41
-rw-r--r--src/gui/util/qdesktopservices.cpp132
-rw-r--r--src/gui/util/qdesktopservices.h40
-rw-r--r--src/gui/util/qedidparser.cpp67
-rw-r--r--src/gui/util/qedidparser_p.h43
-rw-r--r--src/gui/util/qedidvendortable_p.h42
-rw-r--r--src/gui/util/qgraphicsframecapture.cpp123
-rw-r--r--src/gui/util/qgraphicsframecapture_p.h55
-rw-r--r--src/gui/util/qgraphicsframecapture_p_p.h67
-rw-r--r--src/gui/util/qgraphicsframecapturemetal.mm169
-rw-r--r--src/gui/util/qgraphicsframecapturemetal_p_p.h57
-rw-r--r--src/gui/util/qgraphicsframecapturerenderdoc.cpp310
-rw-r--r--src/gui/util/qgraphicsframecapturerenderdoc_p_p.h53
-rw-r--r--src/gui/util/qgridlayoutengine.cpp146
-rw-r--r--src/gui/util/qgridlayoutengine_p.h53
-rw-r--r--src/gui/util/qhexstring_p.h40
-rw-r--r--src/gui/util/qktxhandler.cpp278
-rw-r--r--src/gui/util/qktxhandler_p.h45
-rw-r--r--src/gui/util/qlayoutpolicy.cpp42
-rw-r--r--src/gui/util/qlayoutpolicy_p.h70
-rw-r--r--src/gui/util/qpkmhandler.cpp50
-rw-r--r--src/gui/util/qpkmhandler_p.h41
-rw-r--r--src/gui/util/qshaderformat.cpp145
-rw-r--r--src/gui/util/qshaderformat_p.h123
-rw-r--r--src/gui/util/qshadergenerator.cpp638
-rw-r--r--src/gui/util/qshadergenerator_p.h79
-rw-r--r--src/gui/util/qshadergraph.cpp316
-rw-r--r--src/gui/util/qshadergraph_p.h124
-rw-r--r--src/gui/util/qshadergraphloader.cpp269
-rw-r--r--src/gui/util/qshadergraphloader_p.h99
-rw-r--r--src/gui/util/qshaderlanguage.cpp54
-rw-r--r--src/gui/util/qshaderlanguage_p.h164
-rw-r--r--src/gui/util/qshadernode.cpp172
-rw-r--r--src/gui/util/qshadernode_p.h128
-rw-r--r--src/gui/util/qshadernodeport.cpp55
-rw-r--r--src/gui/util/qshadernodeport_p.h88
-rw-r--r--src/gui/util/qshadernodesloader.cpp290
-rw-r--r--src/gui/util/qshadernodesloader_p.h96
-rw-r--r--src/gui/util/qtexturefiledata.cpp114
-rw-r--r--src/gui/util/qtexturefiledata_p.h47
-rw-r--r--src/gui/util/qtexturefilehandler_p.h42
-rw-r--r--src/gui/util/qtexturefilereader.cpp42
-rw-r--r--src/gui/util/qtexturefilereader_p.h40
-rw-r--r--src/gui/util/qundogroup.cpp40
-rw-r--r--src/gui/util/qundogroup.h40
-rw-r--r--src/gui/util/qundostack.cpp56
-rw-r--r--src/gui/util/qundostack.h40
-rw-r--r--src/gui/util/qundostack_p.h40
-rw-r--r--src/gui/util/qvalidator.cpp306
-rw-r--r--src/gui/util/qvalidator.h46
-rw-r--r--src/gui/vulkan/LICENSE.txt64
-rw-r--r--src/gui/vulkan/generated_header.txt38
-rw-r--r--src/gui/vulkan/licenseheader.h.in2
-rw-r--r--src/gui/vulkan/qbasicvulkanplatforminstance.cpp216
-rw-r--r--src/gui/vulkan/qbasicvulkanplatforminstance_p.h62
-rw-r--r--src/gui/vulkan/qplatformvulkaninstance.cpp56
-rw-r--r--src/gui/vulkan/qplatformvulkaninstance.h53
-rw-r--r--src/gui/vulkan/qt_attribution.json8
-rw-r--r--src/gui/vulkan/qvulkandefaultinstance.cpp85
-rw-r--r--src/gui/vulkan/qvulkandefaultinstance_p.h46
-rw-r--r--src/gui/vulkan/qvulkanfunctions.cpp64
-rw-r--r--src/gui/vulkan/qvulkaninstance.cpp208
-rw-r--r--src/gui/vulkan/qvulkaninstance.h76
-rw-r--r--src/gui/vulkan/qvulkaninstance_p.h60
-rw-r--r--src/gui/vulkan/qvulkanwindow.cpp231
-rw-r--r--src/gui/vulkan/qvulkanwindow.h57
-rw-r--r--src/gui/vulkan/qvulkanwindow_p.h45
-rw-r--r--src/gui/vulkan/vk.xml9072
900 files changed, 73588 insertions, 63713 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 1befa1612d..cef71318d8 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -1,10 +1,6 @@
-# Generated from gui.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
-#####################################################################
-## Gui Module:
-#####################################################################
-
-# special case begin
qt_find_package(X11_XCB)
qt_find_package(WrapHarfbuzz PROVIDED_TARGETS WrapHarfbuzz::WrapHarfbuzz)
qt_find_package(WrapPNG PROVIDED_TARGETS WrapPNG::WrapPNG)
@@ -17,7 +13,7 @@ if (QT_FEATURE_gui)
set(_default_platform "android")
elseif(MACOS)
set(_default_platform "cocoa")
- elseif(TVOS OR IOS)
+ elseif(UIKIT)
set(_default_platform "ios")
elseif(WATCHOS)
set(_default_platform "minimal")
@@ -43,25 +39,30 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}
set_source_files_properties(../3rdparty/md4c/md4c.c PROPERTIES COMPILE_FLAGS "-Wno-unused-parameter -Wno-sign-compare -Wno-missing-field-initializers -Wno-missing-braces")
endif()
+# Silence AUTOMOC warning 'No relevant classes found. No output generated.'
+if (NOT UNIX)
+ set_source_files_properties(kernel/qplatformwindow_p.h
+ PROPERTIES SKIP_AUTOMOC TRUE)
+endif()
+
unset(qmake_module_config)
if(QT_FEATURE_opengl)
list(APPEND qmake_module_config opengl)
endif()
-# special case end
-
qt_internal_add_module(Gui
PLUGIN_TYPES accessiblebridge platforms platforms/darwin xcbglintegrations platformthemes platforminputcontexts generic iconengines imageformats egldeviceintegrations
- FEATURE_DEPENDENCIES # special case:
- Qt::Network # special case:
- QMAKE_MODULE_CONFIG "${qmake_module_config}" # special case
+ FEATURE_DEPENDENCIES
+ Qt::Network
+ QMAKE_MODULE_CONFIG "${qmake_module_config}"
SOURCES
+ compat/removed_api.cpp
image/qabstractfileiconengine.cpp image/qabstractfileiconengine_p.h
image/qabstractfileiconprovider.cpp image/qabstractfileiconprovider.h image/qabstractfileiconprovider_p.h
image/qbitmap.cpp image/qbitmap.h
image/qbmphandler.cpp image/qbmphandler_p.h
image/qicon.cpp image/qicon.h image/qicon_p.h
- image/qiconengine.cpp image/qiconengine.h
+ image/qiconengine.cpp image/qiconengine.h image/qiconengine_p.h
image/qiconengineplugin.cpp image/qiconengineplugin.h
image/qiconloader.cpp image/qiconloader_p.h
image/qimage.cpp image/qimage.h image/qimage_p.h
@@ -87,7 +88,7 @@ qt_internal_add_module(Gui
kernel/qevent.cpp kernel/qevent.h kernel/qevent_p.h
kernel/qgenericplugin.cpp kernel/qgenericplugin.h
kernel/qgenericpluginfactory.cpp kernel/qgenericpluginfactory.h
- kernel/qguiapplication.cpp kernel/qguiapplication.h kernel/qguiapplication_p.h
+ kernel/qguiapplication.cpp kernel/qguiapplication.h kernel/qguiapplication_p.h kernel/qguiapplication_platform.h
kernel/qguivariant.cpp
kernel/qhighdpiscaling.cpp kernel/qhighdpiscaling_p.h
kernel/qinputdevice.cpp kernel/qinputdevice.h kernel/qinputdevice_p.h
@@ -98,8 +99,9 @@ qt_internal_add_module(Gui
kernel/qkeymapper.cpp kernel/qkeymapper_p.h
kernel/qoffscreensurface.cpp kernel/qoffscreensurface.h kernel/qoffscreensurface_p.h
kernel/qoffscreensurface_platform.h
+ kernel/qopenglcontext.h
kernel/qpaintdevicewindow.cpp kernel/qpaintdevicewindow.h kernel/qpaintdevicewindow_p.h
- kernel/qpalette.cpp kernel/qpalette.h
+ kernel/qpalette.cpp kernel/qpalette.h kernel/qpalette_p.h
kernel/qpixelformat.cpp kernel/qpixelformat.h
kernel/qplatformclipboard.cpp kernel/qplatformclipboard.h
kernel/qplatformcursor.cpp kernel/qplatformcursor.h
@@ -112,9 +114,11 @@ qt_internal_add_module(Gui
kernel/qplatformintegration.cpp kernel/qplatformintegration.h
kernel/qplatformintegrationfactory.cpp kernel/qplatformintegrationfactory_p.h
kernel/qplatformintegrationplugin.cpp kernel/qplatformintegrationplugin.h
+ kernel/qplatformkeymapper.cpp kernel/qplatformkeymapper.h
kernel/qplatformmenu.cpp kernel/qplatformmenu.h kernel/qplatformmenu_p.h
kernel/qplatformnativeinterface.cpp kernel/qplatformnativeinterface.h
kernel/qplatformoffscreensurface.cpp kernel/qplatformoffscreensurface.h
+ kernel/qplatformopenglcontext.h
kernel/qplatformscreen.cpp kernel/qplatformscreen.h kernel/qplatformscreen_p.h
kernel/qplatformservices.cpp kernel/qplatformservices.h
kernel/qplatformsessionmanager.cpp kernel/qplatformsessionmanager.h
@@ -127,9 +131,9 @@ qt_internal_add_module(Gui
kernel/qplatformwindow.cpp kernel/qplatformwindow.h kernel/qplatformwindow_p.h
kernel/qpointingdevice.cpp kernel/qpointingdevice.h kernel/qpointingdevice_p.h
kernel/qrasterwindow.cpp kernel/qrasterwindow.h
- kernel/qscreen.cpp kernel/qscreen.h kernel/qscreen_p.h
+ kernel/qscreen.cpp kernel/qscreen.h kernel/qscreen_p.h kernel/qscreen_platform.h
kernel/qsessionmanager.cpp kernel/qsessionmanager.h kernel/qsessionmanager_p.h
- kernel/qstylehints.cpp kernel/qstylehints.h
+ kernel/qstylehints.cpp kernel/qstylehints.h kernel/qstylehints_p.h
kernel/qsurface.cpp kernel/qsurface.h
kernel/qsurfaceformat.cpp kernel/qsurfaceformat.h
kernel/qtestsupport_gui.cpp kernel/qtestsupport_gui.h
@@ -144,12 +148,19 @@ qt_internal_add_module(Gui
math3d/qvector3d.h
math3d/qvector4d.h
math3d/qvectornd.cpp math3d/qvectornd.h
+ opengl/qopengl.h
+ opengl/qopenglext.h
+ opengl/qopenglfunctions.h
+ opengl/qopenglextrafunctions.h
painting/qbackingstore.cpp painting/qbackingstore.h
+ painting/qbackingstoredefaultcompositor.cpp painting/qbackingstoredefaultcompositor_p.h
+ painting/qbackingstorerhisupport.cpp painting/qbackingstorerhisupport_p.h
painting/qbezier.cpp painting/qbezier_p.h
painting/qblendfunctions.cpp painting/qblendfunctions_p.h
painting/qblittable.cpp painting/qblittable_p.h
painting/qbrush.cpp painting/qbrush.h
painting/qcolor.cpp painting/qcolor.h painting/qcolor_p.h
+ painting/qcolorclut_p.h
painting/qcolormatrix_p.h
painting/qcolorspace.cpp painting/qcolorspace.h painting/qcolorspace_p.h
painting/qcolortransferfunction_p.h
@@ -159,6 +170,7 @@ qt_internal_add_module(Gui
painting/qcolortrclut.cpp painting/qcolortrclut_p.h
painting/qcompositionfunctions.cpp
painting/qcosmeticstroker.cpp painting/qcosmeticstroker_p.h
+ painting/qcmyk_p.h
painting/qdatabuffer_p.h
painting/qdrawhelper_p.h
painting/qdrawhelper_x86_p.h
@@ -167,7 +179,9 @@ qt_internal_add_module(Gui
painting/qfixed_p.h
painting/qgrayraster.c painting/qgrayraster_p.h
painting/qicc.cpp painting/qicc_p.h
- painting/qimagescale.cpp
+ painting/qimageeffects.cpp
+ painting/qimagescale.cpp painting/qimagescale_p.h
+ painting/qmath_p.h
painting/qmemrotate.cpp painting/qmemrotate_p.h
painting/qoutlinemapper.cpp painting/qoutlinemapper_p.h
painting/qpagedpaintdevice.cpp painting/qpagedpaintdevice.h painting/qpagedpaintdevice_p.h
@@ -185,7 +199,7 @@ qt_internal_add_module(Gui
painting/qpathsimplifier.cpp painting/qpathsimplifier_p.h
painting/qpdf.cpp painting/qpdf_p.h
painting/qpdfwriter.cpp painting/qpdfwriter.h
- painting/qpen.cpp painting/qpen.h
+ painting/qpen.cpp painting/qpen.h painting/qpen_p.h
painting/qpixellayout.cpp painting/qpixellayout_p.h
painting/qplatformbackingstore.cpp painting/qplatformbackingstore.h
painting/qpolygon.cpp painting/qpolygon.h
@@ -202,16 +216,10 @@ qt_internal_add_module(Gui
painting/qtriangulatingstroker.cpp painting/qtriangulatingstroker_p.h
painting/qtriangulator.cpp painting/qtriangulator_p.h
painting/qvectorpath_p.h
- rhi/qrhi.cpp rhi/qrhi_p.h
- rhi/qrhi_p_p.h
+ rhi/qrhi.cpp rhi/qrhi.h rhi/qrhi_platform.h rhi/qrhi_p.h
rhi/qrhinull.cpp rhi/qrhinull_p.h
- rhi/qrhinull_p_p.h
- rhi/qrhiprofiler.cpp rhi/qrhiprofiler_p.h
- rhi/qrhiprofiler_p_p.h
- rhi/qshader.cpp rhi/qshader_p.h
- rhi/qshader_p_p.h
- rhi/qshaderdescription.cpp rhi/qshaderdescription_p.h
- rhi/qshaderdescription_p_p.h
+ rhi/qshader.cpp rhi/qshader.h rhi/qshader_p.h
+ rhi/qshaderdescription.cpp rhi/qshaderdescription.h rhi/qshaderdescription_p.h
text/qabstracttextdocumentlayout.cpp text/qabstracttextdocumentlayout.h text/qabstracttextdocumentlayout_p.h
text/qdistancefield.cpp text/qdistancefield_p.h
text/qfont.cpp text/qfont.h text/qfont_p.h
@@ -250,52 +258,66 @@ qt_internal_add_module(Gui
util/qktxhandler.cpp util/qktxhandler_p.h
util/qlayoutpolicy.cpp util/qlayoutpolicy_p.h
util/qpkmhandler.cpp util/qpkmhandler_p.h
- util/qshaderformat.cpp util/qshaderformat_p.h
- util/qshadergraph.cpp util/qshadergraph_p.h
- util/qshadergraphloader.cpp util/qshadergraphloader_p.h
- util/qshaderlanguage.cpp util/qshaderlanguage_p.h
- util/qshadernode.cpp util/qshadernode_p.h
- util/qshadernodeport.cpp util/qshadernodeport_p.h
- util/qshadernodesloader.cpp util/qshadernodesloader_p.h
util/qtexturefiledata.cpp util/qtexturefiledata_p.h
util/qtexturefilehandler_p.h
util/qtexturefilereader.cpp util/qtexturefilereader_p.h
util/qvalidator.cpp util/qvalidator.h
DEFINES
+ QT_NO_CONTEXTLESS_CONNECT
QT_NO_FOREACH
QT_NO_USING_NAMESPACE
- QT_QPA_DEFAULT_PLATFORM_NAME="${QT_QPA_DEFAULT_PLATFORM}" # special case
+ QT_USE_NODISCARD_FILE_OPEN
+ QT_QPA_DEFAULT_PLATFORM_NAME="${QT_QPA_DEFAULT_PLATFORM}"
INCLUDE_DIRECTORIES
../3rdparty/VulkanMemoryAllocator
+ ../3rdparty/D3D12MemoryAllocator
LIBRARIES
Qt::CorePrivate
PUBLIC_LIBRARIES
Qt::Core
PRIVATE_MODULE_INTERFACE
Qt::CorePrivate
- NO_PCH_SOURCES # special case
- "painting/qdrawhelper.cpp" # special case
+ NO_PCH_SOURCES
+ compat/removed_api.cpp
+ painting/qdrawhelper.cpp
PRECOMPILED_HEADER
"kernel/qt_gui_pch.h"
GENERATE_CPP_EXPORTS
+ QPA_HEADER_FILTERS
+ "(^|/)qplatform.+\\.h$|(^|/)qwindowsystem.+\\.h$"
+ RHI_HEADER_FILTERS
+ "(^|/)qrhi\\.h$|(^|/)qrhi_platform\\.h$|(^|/)qshader\\.h$|(^|/)qshaderdescription\\.h$"
)
# Resources:
-set_source_files_properties("../3rdparty/icc/sRGB2014.icc"
- PROPERTIES QT_RESOURCE_ALIAS "sRGB2014.icc"
-)
-set(qpdf_resource_files
- "../3rdparty/icc/sRGB2014.icc"
- "painting/qpdfa_metadata.xml"
-)
+if(QT_FEATURE_pdf)
+ set_source_files_properties("../3rdparty/icc/sRGB2014.icc"
+ PROPERTIES QT_RESOURCE_ALIAS "sRGB2014.icc"
+ )
+ set(qpdf_resource_files
+ "../3rdparty/icc/sRGB2014.icc"
+ "painting/qpdfa_metadata.xml"
+ )
+ qt_internal_add_resource(Gui "qpdf"
+ PREFIX
+ "/qpdf/"
+ BASE
+ "painting"
+ FILES
+ ${qpdf_resource_files}
+ )
+endif()
+
+if(WIN32 OR (UNIX AND NOT APPLE))
+ set_target_properties(Gui PROPERTIES UNITY_BUILD OFF) # X11 define clashes/Windows oddities.
+endif()
-qt_internal_add_resource(Gui "qpdf"
+qt_internal_add_resource(Gui "gui_shaders"
PREFIX
- "/qpdf/"
- BASE
- "painting"
+ "/qt-project.org/gui"
FILES
- ${qpdf_resource_files}
+ "painting/shaders/backingstorecompose.vert.qsb"
+ "painting/shaders/backingstorecompose.frag.qsb"
)
if(QT_FEATURE_reduce_relocations AND UNIX AND GCC)
@@ -303,21 +325,11 @@ if(QT_FEATURE_reduce_relocations AND UNIX AND GCC)
"LINKER:--dynamic-list=${CMAKE_CURRENT_LIST_DIR}/QtGui.dynlist")
endif()
-# special case begin
qt_internal_extend_target(Gui CONDITION QT_FEATURE_standarditemmodel
SOURCES
itemmodels/qstandarditemmodel.cpp itemmodels/qstandarditemmodel.h itemmodels/qstandarditemmodel_p.h
)
-# special case end
-
-#### Keys ignored in scope 1:.:.:gui.pro:<TRUE>:
-# QMAKE_LIBS = "$$QMAKE_LIBS_GUI"
-
-## Scopes:
-#####################################################################
-
-# special case begin
# With qmake, gui's opengl.pri used CONFIG += opengl, where opengl.prf
# used direct public linkage against either libGLESv2 or libGL, depending
# on the opengl _feature_. This is done by hand now here (where the
@@ -329,29 +341,31 @@ if(QT_FEATURE_opengl)
if(QT_FEATURE_opengles2)
find_package(GLESv2)
target_link_libraries(Gui PUBLIC GLESv2::GLESv2)
+
+ if(INTEGRITY AND _qt_igy_gui_libs)
+ qt_internal_extend_target(Gui
+ LIBRARIES
+ IntegrityPlatformGraphics::IntegrityPlatformGraphics
+ )
+ endif()
+
elseif(NOT QT_FEATURE_opengl_dynamic)
target_link_libraries(Gui PUBLIC WrapOpenGL::WrapOpenGL)
endif()
endif()
-# special case end
qt_internal_extend_target(Gui CONDITION QT_FEATURE_opengl
SOURCES
- kernel/qopenglcontext.cpp kernel/qopenglcontext.h kernel/qopenglcontext_p.h
+ kernel/qopenglcontext.cpp kernel/qopenglcontext_p.h
kernel/qopenglcontext_platform.h
- kernel/qplatformopenglcontext.cpp kernel/qplatformopenglcontext.h
- opengl/qopengl.cpp opengl/qopengl.h opengl/qopengl_p.h
+ kernel/qplatformopenglcontext.cpp
+ opengl/qopengl.cpp opengl/qopengl_p.h
opengl/qopenglextensions_p.h
- opengl/qopenglextrafunctions.h
- opengl/qopenglfunctions.cpp opengl/qopenglfunctions.h
+ opengl/qopenglfunctions.cpp
opengl/qopenglprogrambinarycache.cpp opengl/qopenglprogrambinarycache_p.h
rhi/qrhigles2.cpp rhi/qrhigles2_p.h
- rhi/qrhigles2_p_p.h
)
-#### Keys ignored in scope 2:.:.:gui.pro:QT_FEATURE_opengl:
-# MODULE_CONFIG = "opengl"
-
qt_internal_extend_target(Gui CONDITION MACOS
SOURCES
platform/macos/qcocoanativeinterface.mm
@@ -362,13 +376,21 @@ qt_internal_extend_target(Gui CONDITION MACOS
${FWAppKit}
)
+qt_internal_extend_target(Gui CONDITION WASM
+ SOURCES
+ platform/wasm/qwasmnativeinterface.cpp
+)
+
qt_internal_extend_target(Gui CONDITION APPLE
SOURCES
image/qimage_darwin.mm
painting/qcoregraphics.mm painting/qcoregraphics_p.h
painting/qrasterbackingstore.cpp painting/qrasterbackingstore_p.h
- platform/darwin/qmacmime.mm platform/darwin/qmacmime_p.h
+ painting/qrhibackingstore.cpp painting/qrhibackingstore_p.h
+ platform/darwin/qmacmimeregistry.mm platform/darwin/qmacmimeregistry_p.h
+ platform/darwin/qutimimeconverter.mm platform/darwin/qutimimeconverter.h
platform/darwin/qapplekeymapper.mm platform/darwin/qapplekeymapper_p.h
+ platform/darwin/qappleiconengine.mm platform/darwin/qappleiconengine_p.h
text/coretext/qcoretextfontdatabase.mm text/coretext/qcoretextfontdatabase_p.h
text/coretext/qfontengine_coretext.mm text/coretext/qfontengine_coretext_p.h
LIBRARIES
@@ -387,13 +409,19 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_animation
qt_internal_extend_target(Gui CONDITION WIN32
SOURCES
- image/qpixmap_win.cpp
+ image/qpixmap_win.cpp image/qpixmap_win_p.h
kernel/qwindowdefs_win.h
platform/windows/qwindowsguieventdispatcher.cpp platform/windows/qwindowsguieventdispatcher_p.h
- platform/windows/qwindowsmime_p.h
+ platform/windows/qwindowsmimeconverter.h platform/windows/qwindowsmimeconverter.cpp
platform/windows/qwindowsnativeinterface.cpp
+ platform/windows/qwindowsthemecache.cpp platform/windows/qwindowsthemecache_p.h
rhi/qrhid3d11.cpp rhi/qrhid3d11_p.h
- rhi/qrhid3d11_p_p.h
+ rhi/qrhid3dhelpers.cpp rhi/qrhid3dhelpers_p.h
+ rhi/vs_test_p.h
+ rhi/qrhid3d12.cpp rhi/qrhid3d12_p.h
+ rhi/cs_mipmap_p.h
+ ../3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.h
+ ../3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.cpp
text/windows/qwindowsfontdatabase.cpp text/windows/qwindowsfontdatabase_p.h
text/windows/qwindowsfontdatabasebase.cpp text/windows/qwindowsfontdatabasebase_p.h
text/windows/qwindowsfontengine.cpp text/windows/qwindowsfontengine_p.h
@@ -404,76 +432,66 @@ qt_internal_extend_target(Gui CONDITION WIN32
ole32
shell32
user32
+ uxtheme
PUBLIC_LIBRARIES
d3d11
dxgi
dxguid
+ d3d12
)
-#### Keys ignored in scope 7:.:.:gui.pro:WIN32:
-# CMAKE_WINDOWS_BUILD = "True"
+if(QT_FEATURE_graphicsframecapture)
+ qt_internal_extend_target(Gui
+ SOURCES
+ util/qgraphicsframecapture_p.h util/qgraphicsframecapture.cpp
+ util/qgraphicsframecapture_p_p.h
+ )
+
+ qt_internal_extend_target(Gui CONDITION (WIN32 OR (UNIX AND NOT APPLE)) AND QT_FEATURE_library
+ LIBRARIES
+ RenderDoc::RenderDoc
+ SOURCES
+ util/qgraphicsframecapturerenderdoc_p_p.h util/qgraphicsframecapturerenderdoc.cpp
+ )
+
+ qt_internal_extend_target(Gui CONDITION IOS OR MACOS
+ SOURCES
+ util/qgraphicsframecapturemetal_p_p.h util/qgraphicsframecapturemetal.mm
+ PUBLIC_LIBRARIES
+ ${FWMetal}
+ )
+endif()
-# special case begin
if(QT_FEATURE_egl)
qt_find_package(EGL)
endif()
-# special case end
qt_internal_extend_target(Gui CONDITION QT_FEATURE_egl
SOURCES
opengl/platform/egl/qeglconvenience.cpp opengl/platform/egl/qeglconvenience_p.h
opengl/platform/egl/qeglstreamconvenience.cpp opengl/platform/egl/qeglstreamconvenience_p.h
opengl/platform/egl/qt_egl_p.h
-# special case begin
LIBRARIES
- EGL::EGL # special case
-# special case end
+ EGL::EGL
)
-#### Keys ignored in scope 8:.:.:gui.pro:QT_FEATURE_egl:
-# CMAKE_EGL_LIBS = "$$cmakeProcessLibs($$QMAKE_LIBS_EGL)"
-
-#### Keys ignored in scope 9:.:.:gui.pro:NOT QMAKE_LIBDIR_EGL_ISEMPTY:
-# CMAKE_EGL_LIBDIR = "$$cmakeTargetPath($$QMAKE_LIBDIR_EGL)"
-
-#### Keys ignored in scope 10:.:.:gui.pro:QT_FEATURE_opengles2:
-# CMAKE_GL_HEADER_NAME = "GLES2/gl2.h"
-# CMAKE_OPENGL_INCDIRS = "$$cmakePortablePaths($$QMAKE_INCDIR_OPENGL_ES2)"
-# CMAKE_OPENGL_LIBS = "$$cmakeProcessLibs($$QMAKE_LIBS_OPENGL_ES2)"
-# CMAKE_QT_OPENGL_IMPLEMENTATION = "GLESv2"
-
-#### Keys ignored in scope 11:.:.:gui.pro:NOT QMAKE_INCDIR_OPENGL_ES2_ISEMPTY:
-# CMAKE_GL_INCDIRS = "$$cmakeTargetPaths($$QMAKE_INCDIR_OPENGL_ES2)"
-
-#### Keys ignored in scope 12:.:.:gui.pro:NOT QMAKE_LIBDIR_OPENGL_ES2_ISEMPTY:
-# CMAKE_OPENGL_LIBDIR = "$$cmakePortablePaths($$QMAKE_LIBDIR_OPENGL_ES2)"
-
-#### Keys ignored in scope 14:.:.:gui.pro:QT_FEATURE_opengl:
-# CMAKE_GL_HEADER_NAME = "GL/gl.h"
-# CMAKE_OPENGL_INCDIRS = "$$cmakePortablePaths($$QMAKE_INCDIR_OPENGL)"
-# CMAKE_QT_OPENGL_IMPLEMENTATION = "GL"
-
-#### Keys ignored in scope 15:.:.:gui.pro:NOT QMAKE_INCDIR_OPENGL_ISEMPTY:
-# CMAKE_GL_INCDIRS = "$$cmakeTargetPaths($$QMAKE_INCDIR_OPENGL)"
-
-#### Keys ignored in scope 16:.:.:gui.pro:NOT QT_FEATURE_dynamicgl:
-# CMAKE_OPENGL_LIBS = "$$cmakeProcessLibs($$QMAKE_LIBS_OPENGL)"
-
-#### Keys ignored in scope 17:.:.:gui.pro:NOT QMAKE_LIBDIR_OPENGL_ISEMPTY:
-# CMAKE_OPENGL_LIBDIR = "$$cmakePortablePaths($$QMAKE_LIBDIR_OPENGL)"
-
-#### Keys ignored in scope 18:.:.:gui.pro:APPLE:
-# CMAKE_GL_HEADER_NAME = "gl.h"
+# These two headers are always installed, their contents are guarded with
+# "#if QT_CONFIG(accessibility)", so if QT_FEATURE_accessibility is not
+# enabled, they are just duds.
+qt_internal_extend_target(Gui
+ SOURCES
+ accessible/qaccessible.h accessible/qplatformaccessibility.h
+)
qt_internal_extend_target(Gui CONDITION QT_FEATURE_accessibility
SOURCES
- accessible/qaccessible.cpp accessible/qaccessible.h
+ accessible/qaccessible.cpp accessible/qaccessible_base.h
accessible/qaccessiblebridge.cpp accessible/qaccessiblebridge.h
accessible/qaccessiblebridgeutils.cpp accessible/qaccessiblebridgeutils_p.h
accessible/qaccessiblecache.cpp accessible/qaccessiblecache_p.h
accessible/qaccessibleobject.cpp accessible/qaccessibleobject.h
accessible/qaccessibleplugin.cpp accessible/qaccessibleplugin.h
- accessible/qplatformaccessibility.cpp accessible/qplatformaccessibility.h
+ accessible/qplatformaccessibility.cpp
)
qt_internal_extend_target(Gui CONDITION APPLE AND QT_FEATURE_accessibility
@@ -483,22 +501,13 @@ qt_internal_extend_target(Gui CONDITION APPLE AND QT_FEATURE_accessibility
${FWFoundation}
)
-qt_internal_extend_target(Gui CONDITION QT_FEATURE_accessibility AND WIN32
- SOURCES
- accessible/windows/apisupport/qwindowsuiawrapper.cpp accessible/windows/apisupport/qwindowsuiawrapper_p.h
- accessible/windows/apisupport/uiaattributeids_p.h
- accessible/windows/apisupport/uiaclientinterfaces_p.h
- accessible/windows/apisupport/uiacontroltypeids_p.h
- accessible/windows/apisupport/uiaerrorids_p.h
- accessible/windows/apisupport/uiaeventids_p.h
- accessible/windows/apisupport/uiageneralids_p.h
- accessible/windows/apisupport/uiapatternids_p.h
- accessible/windows/apisupport/uiapropertyids_p.h
- accessible/windows/apisupport/uiaserverinterfaces_p.h
- accessible/windows/apisupport/uiatypes_p.h
-)
-
-qt_internal_extend_target(Gui CONDITION QT_FEATURE_accessibility AND QT_FEATURE_accessibility_atspi_bridge
+if(QT_FEATURE_accessibility AND QT_FEATURE_accessibility_atspi_bridge)
+ set(atspi_accessibility ON)
+else()
+ set(atspi_accessibility OFF)
+endif()
+
+qt_internal_extend_target(Gui CONDITION atspi_accessibility
SOURCES
accessible/linux/atspiadaptor.cpp accessible/linux/atspiadaptor_p.h
accessible/linux/dbusconnection.cpp accessible/linux/dbusconnection_p.h
@@ -507,7 +516,6 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_accessibility AND QT_FEATURE_
accessible/linux/qspiaccessiblebridge.cpp accessible/linux/qspiaccessiblebridge_p.h
accessible/linux/qspiapplicationadaptor.cpp accessible/linux/qspiapplicationadaptor_p.h
accessible/linux/qspidbuscache.cpp accessible/linux/qspidbuscache_p.h
-# special case begin
DBUS_ADAPTOR_SOURCES
accessible/linux/dbusxml/Cache.xml
accessible/linux/dbusxml/DeviceEventController.xml
@@ -518,11 +526,12 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_accessibility AND QT_FEATURE_
accessible/linux/dbusxml/Socket.xml
DBUS_INTERFACE_FLAGS
"-i" "QtGui/private/qspi_struct_marshallers_p.h"
-# special case end
- LIBRARIES
- PkgConfig::ATSPI2_nolink
)
+if(atspi_accessibility)
+ qt_internal_add_target_include_dirs(Gui PkgConfig::ATSPI2)
+endif()
+
qt_internal_extend_target(Gui CONDITION QT_FEATURE_action
SOURCES
kernel/qaction.cpp kernel/qaction.h kernel/qaction_p.h
@@ -557,46 +566,53 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_png
WrapPNG::WrapPNG
)
-#### Keys ignored in scope 40:.:image:image/image.pri:WIN32 AND MINGW:
-# GCC_VERSION = "$${QMAKE_GCC_MAJOR_VERSION}.$${QMAKE_GCC_MINOR_VERSION}.$${QMAKE_GCC_PATCH_VERSION}"
-
-qt_internal_extend_target(Gui CONDITION ((QT_FEATURE_png) AND (WIN32 AND MINGW)) AND (GCC_VERSION___equals___8.1.0)
+qt_internal_extend_target(Gui
+ CONDITION
+ QT_FEATURE_png AND WIN32 AND MINGW AND
+ (CMAKE_CXX_COMPILER_VESION VERSION_EQUAL "8.1.0")
COMPILE_OPTIONS
-fno-reorder-blocks-and-partition
)
-if(NOT ANDROID)
- if(TEST_architecture_arch STREQUAL x86_64)
- qt_internal_extend_target(Gui
- SOURCES
- painting/qdrawhelper_sse2.cpp
- )
- else()
- qt_internal_add_simd_part(Gui SIMD sse2
- SOURCES
- painting/qdrawhelper_sse2.cpp
- )
- endif()
-
- qt_internal_add_simd_part(Gui SIMD ssse3
- SOURCES
- image/qimage_ssse3.cpp
- painting/qdrawhelper_ssse3.cpp
+if(TEST_architecture_arch STREQUAL x86_64)
+ qt_internal_extend_target(Gui
+ SOURCES
+ painting/qdrawhelper_sse2.cpp
)
-
- qt_internal_add_simd_part(Gui SIMD sse4_1
+else()
+ qt_internal_add_simd_part(Gui SIMD sse2
SOURCES
- painting/qdrawhelper_sse4.cpp
- painting/qimagescale_sse4.cpp
+ painting/qdrawhelper_sse2.cpp
)
+endif()
- qt_internal_add_simd_part(Gui SIMD neon
- SOURCES
- image/qimage_neon.cpp
- painting/qdrawhelper_neon.cpp painting/qdrawhelper_neon_p.h
- painting/qimagescale_neon.cpp
- )
+qt_internal_add_simd_part(Gui SIMD ssse3
+ SOURCES
+ image/qimage_ssse3.cpp
+ painting/qdrawhelper_ssse3.cpp
+)
+
+qt_internal_add_simd_part(Gui SIMD sse4_1
+ SOURCES
+ painting/qdrawhelper_sse4.cpp
+ painting/qimagescale_sse4.cpp
+)
+
+qt_internal_add_simd_part(Gui SIMD arch_haswell
+ SOURCES
+ painting/qdrawhelper_avx2.cpp
+ EXCLUDE_OSX_ARCHITECTURES
+ arm64
+)
+
+qt_internal_add_simd_part(Gui SIMD neon
+ SOURCES
+ image/qimage_neon.cpp
+ painting/qdrawhelper_neon.cpp painting/qdrawhelper_neon_p.h
+ painting/qimagescale_neon.cpp
+)
+if(NOT ANDROID)
qt_internal_add_simd_part(Gui SIMD mips_dsp
SOURCES
painting/qdrawhelper_mips_dsp.cpp painting/qdrawhelper_mips_dsp_p.h
@@ -610,21 +626,16 @@ if(NOT ANDROID)
image/qimage_mips_dspr2_asm.S
painting/qdrawhelper_mips_dspr2_asm.S
)
-
- qt_internal_add_simd_part(Gui SIMD arch_haswell
- SOURCES
- painting/qdrawhelper_avx2.cpp
- EXCLUDE_OSX_ARCHITECTURES
- arm64
- )
endif()
qt_internal_extend_target(Gui CONDITION ANDROID
SOURCES
platform/android/qandroidnativeinterface.cpp
+ painting/qrasterbackingstore.cpp painting/qrasterbackingstore_p.h
+ painting/qrhibackingstore.cpp painting/qrhibackingstore_p.h
)
-qt_internal_extend_target(Gui CONDITION ANDROID AND (TEST_architecture_arch STREQUAL arm64 OR TEST_architecture_arch STREQUAL arm) # special case
+qt_internal_extend_target(Gui CONDITION ANDROID AND (TEST_architecture_arch STREQUAL arm64 OR TEST_architecture_arch STREQUAL arm)
SOURCES
image/qimage_neon.cpp
painting/qdrawhelper_neon.cpp painting/qdrawhelper_neon_p.h
@@ -642,14 +653,12 @@ qt_internal_extend_target(Gui CONDITION ANDROID AND (TEST_architecture_arch STRE
QT_COMPILER_SUPPORTS_SSSE3 QT_COMPILER_SUPPORTS_SSSE3
)
-# special case begin
if (MINGW AND CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.1.0)
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86048
set_source_files_properties(image/qpnghandler.cpp
PROPERTIES COMPILE_OPTIONS -fno-reorder-blocks-and-partition
)
endif()
-# special case end
qt_internal_extend_target(Gui CONDITION QT_FEATURE_harfbuzz
SOURCES
@@ -658,22 +667,14 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_harfbuzz
WrapHarfbuzz::WrapHarfbuzz
)
-# special case begin
-# Replicate what src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro does, which is link CoreText
-# when targeting uikit.
-
qt_internal_extend_target(Gui CONDITION QT_FEATURE_harfbuzz AND UIKIT
LIBRARIES
${FWCoreText}
)
-# special case end
qt_internal_extend_target(Gui CONDITION QT_FEATURE_textodfwriter
SOURCES
text/qtextodfwriter.cpp text/qtextodfwriter_p.h
- text/qzip.cpp
- text/qzipreader_p.h
- text/qzipwriter_p.h
)
qt_internal_extend_target(Gui CONDITION QT_FEATURE_textmarkdownreader
@@ -702,7 +703,7 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_textmarkdownwriter
qt_internal_extend_target(Gui CONDITION QT_FEATURE_cssparser
SOURCES
- painting/qcssutil.cpp
+ painting/qcssutil.cpp painting/qcssutil_p.h
text/qcssparser.cpp text/qcssparser_p.h
)
@@ -714,7 +715,7 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_freetype
WrapFreetype::WrapFreetype
)
-qt_internal_extend_target(Gui CONDITION QT_FEATURE_freetype AND UNIX AND NOT APPLE
+qt_internal_extend_target(Gui CONDITION UNIX AND NOT APPLE
SOURCES
text/unix/qgenericunixfontdatabase_p.h
)
@@ -755,12 +756,12 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_direct2d AND QT_FEATURE_direc
SOURCES
text/windows/qwindowsdirectwritefontdatabase.cpp text/windows/qwindowsdirectwritefontdatabase_p.h
LIBRARIES
- dwrite # special case
+ dwrite
)
qt_internal_extend_target(Gui CONDITION QT_FEATURE_direct2d AND QT_FEATURE_directwrite AND WIN32 AND NOT QT_FEATURE_directwrite3
LIBRARIES
- dwrite # special case
+ dwrite
)
qt_internal_extend_target(Gui CONDITION MINGW AND WIN32
@@ -804,11 +805,6 @@ qt_internal_extend_target(Gui CONDITION NOT QT_FEATURE_system_zlib AND NOT no_co
Qt::Core
)
-qt_internal_extend_target(Gui CONDITION QT_FEATURE_regularexpression
- SOURCES
- util/qshadergenerator.cpp util/qshadergenerator_p.h
-)
-
qt_internal_extend_target(Gui CONDITION QT_FEATURE_undocommand
SOURCES
util/qundostack.cpp util/qundostack.h util/qundostack_p.h
@@ -826,17 +822,15 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_opengl AND QT_FEATURE_xlib AN
X11::X11
)
-qt_internal_extend_target(Gui CONDITION QT_FEATURE_egl AND QT_FEATURE_opengl
+qt_internal_extend_target(Gui CONDITION QT_FEATURE_opengles2
SOURCES
- opengl/platform/egl/qeglpbuffer.cpp opengl/platform/egl/qeglpbuffer_p.h
- opengl/platform/egl/qeglplatformcontext.cpp opengl/platform/egl/qeglplatformcontext_p.h
+ opengl/qopengles2ext.h
)
-qt_internal_extend_target(Gui CONDITION QT_FEATURE_egl AND QT_FEATURE_egl_x11
+qt_internal_extend_target(Gui CONDITION QT_FEATURE_egl AND QT_FEATURE_opengl AND NOT WASM
SOURCES
- opengl/platform/egl/qxlibeglintegration.cpp opengl/platform/egl/qxlibeglintegration_p.h
- LIBRARIES
- X11::X11
+ opengl/platform/egl/qeglpbuffer.cpp opengl/platform/egl/qeglpbuffer_p.h
+ opengl/platform/egl/qeglplatformcontext.cpp opengl/platform/egl/qeglplatformcontext_p.h
)
qt_internal_extend_target(Gui CONDITION QT_FEATURE_egl AND NOT QT_FEATURE_egl_x11
@@ -863,18 +857,18 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_filesystemmodel
qt_internal_extend_target(Gui CONDITION QT_FEATURE_vulkan
SOURCES
rhi/qrhivulkan.cpp rhi/qrhivulkan_p.h
- rhi/qrhivulkan_p_p.h
vulkan/qbasicvulkanplatforminstance.cpp vulkan/qbasicvulkanplatforminstance_p.h
vulkan/qplatformvulkaninstance.cpp vulkan/qplatformvulkaninstance.h
+ vulkan/qvulkandefaultinstance.cpp vulkan/qvulkandefaultinstance_p.h
vulkan/qvulkanfunctions.cpp
- vulkan/qvulkaninstance.cpp vulkan/qvulkaninstance.h
+ vulkan/qvulkaninstance.cpp vulkan/qvulkaninstance.h vulkan/qvulkaninstance_p.h
vulkan/qvulkanwindow.cpp vulkan/qvulkanwindow.h vulkan/qvulkanwindow_p.h
- PUBLIC_LIBRARIES
- WrapVulkanHeaders::WrapVulkanHeaders
)
+if(QT_FEATURE_vulkan)
+ qt_internal_add_target_include_dirs_and_optionally_propagate(
+ Gui WrapVulkanHeaders::WrapVulkanHeaders)
+endif()
-#### Keys ignored in scope 111:.:vulkan:vulkan/vulkan.pri:QT_FEATURE_vkgen:
-# special case begin
# We must always generate syncqt-injected header files,
# because we added a custom command earlier for those for framework builds.
set(vulkan_fun "qvulkanfunctions.h")
@@ -886,10 +880,14 @@ if (QT_FEATURE_vulkan)
list(APPEND vulkan_fun_outputs "vulkan/${vulkan_fun_p_cpp}")
if(NOT "${QT_HOST_PATH}" STREQUAL "")
+ set(host_executable_suffix "")
+ if(CMAKE_HOST_WIN32)
+ set(host_executable_suffix ".exe")
+ endif()
qt_path_join(qvkgen
"${QT_HOST_PATH}"
"${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_LIBEXECDIR}"
- "qvkgen")
+ "qvkgen${host_executable_suffix}")
else()
set(qvkgen "${QT_CMAKE_EXPORT_NAMESPACE}::qvkgen")
endif()
@@ -897,9 +895,9 @@ if (QT_FEATURE_vulkan)
list(APPEND vulkan_fun_command_content
COMMAND "${qvkgen}"
"${CMAKE_CURRENT_SOURCE_DIR}/vulkan/vk.xml"
- "${CMAKE_CURRENT_SOURCE_DIR}/vulkan/generated_header.txt"
+ "${CMAKE_CURRENT_SOURCE_DIR}/vulkan/licenseheader.h.in"
"${CMAKE_CURRENT_BINARY_DIR}/vulkan/qvulkanfunctions"
- DEPENDS vulkan/vk.xml
+ DEPENDS vulkan/vk.xml ${qvkgen}
COMMENT "Generating vulkan data"
)
@@ -919,42 +917,25 @@ add_custom_command(
OUTPUT ${vulkan_fun_outputs}
${vulkan_fun_command_content}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ VERBATIM
)
-# special case end
-
-#### Keys ignored in scope 68:.:vulkan:vulkan/vulkan.pri:QT_FEATURE_vkgen:
-# QMAKE_EXTRA_COMPILERS = "qvkgen_h" "qvkgen_ph" "qvkgen_pimpl"
-# QMAKE_QVKGEN_INPUT = "vulkan/vk.xml"
-# QMAKE_QVKGEN_LICENSE_HEADER = "$$QT_SOURCE_TREE/header.LGPL"
-# qvkgen_h.commands = "$$QMAKE_QVKGEN" "${QMAKE_FILE_IN}" "$$shell_quote($$QMAKE_QVKGEN_LICENSE_HEADER)" "${QMAKE_FILE_OUT_PATH}/${QMAKE_FILE_OUT_BASE}"
-# qvkgen_h.input = "QMAKE_QVKGEN_INPUT"
-# qvkgen_h.output = "$$OUT_PWD/vulkan/qvulkanfunctions.h"
-# qvkgen_ph.commands = "$$escape_expand(\\n)"
-# qvkgen_ph.depends = "$$OUT_PWD/vulkan/qvulkanfunctions.h"
-# qvkgen_ph.input = "QMAKE_QVKGEN_INPUT"
-# qvkgen_ph.output = "$$OUT_PWD/vulkan/qvulkanfunctions_p.h"
-# qvkgen_pimpl.commands = "$$escape_expand(\\n)"
-# qvkgen_pimpl.depends = "$$OUT_PWD/vulkan/qvulkanfunctions_p.h"
-# qvkgen_pimpl.input = "QMAKE_QVKGEN_INPUT"
-# qvkgen_pimpl.output = "$$OUT_PWD/vulkan/qvulkanfunctions_p.cpp"
-
-#### Keys ignored in scope 112:.:vulkan:vulkan/vulkan.pri:QT_FEATURE_vulkan:
-# qvkgen_h.variable_out = "HEADERS"
-
-#### Keys ignored in scope 113:.:vulkan:vulkan/vulkan.pri:else:
-# qvkgen_h.CONFIG = "target_predeps" "no_link"
qt_internal_extend_target(Gui CONDITION WASM
SOURCES
+ platform/wasm/qlocalfileapi.cpp platform/wasm/qlocalfileapi_p.h
platform/wasm/qwasmlocalfileaccess.cpp platform/wasm/qwasmlocalfileaccess_p.h
)
qt_internal_extend_target(Gui CONDITION UNIX
SOURCES
+ platform/unix/qunixnativeinterface.cpp
+)
+
+qt_internal_extend_target(Gui CONDITION UNIX AND NOT WASM
+ SOURCES
platform/unix/qgenericunixeventdispatcher.cpp platform/unix/qgenericunixeventdispatcher_p.h
platform/unix/qunixeventdispatcher.cpp
platform/unix/qunixeventdispatcher_qpa_p.h
- platform/unix/qunixnativeinterface.cpp
)
qt_internal_extend_target(Gui CONDITION QT_FEATURE_glib AND UNIX
@@ -1008,39 +989,42 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_xkbcommon AND UNIX
platform/unix/qxkbcommon_3rdparty.cpp
LIBRARIES
XKB::XKB
-# special case begin
PRIVATE_MODULE_INTERFACE
XKB::XKB
-# special case end
)
-qt_internal_extend_target(Gui CONDITION IOS OR MACOS
+qt_internal_extend_target(Gui CONDITION QT_FEATURE_metal
SOURCES
rhi/qrhimetal.mm rhi/qrhimetal_p.h
- rhi/qrhimetal_p_p.h
PUBLIC_LIBRARIES
${FWMetal}
)
-qt_internal_extend_target(Gui # special case CONDITION NOT GCC OR NOT QT_COMPILER_VERSION_MAJOR STREQUAL 5 # source subtraction gone wrong
+qt_internal_extend_target(Gui
SOURCES
- painting/qdrawhelper.cpp
+ painting/qdrawhelper.cpp painting/qdrawhelper_neon_p.h
NO_PCH_SOURCES
"painting/qdrawhelper.cpp"
)
-qt_internal_extend_target(Gui CONDITION (QT_FEATURE_eglfs OR QT_FEATURE_xcb)
+qt_internal_extend_target(Gui CONDITION (QT_FEATURE_eglfs OR QT_FEATURE_xcb OR QT_FEATURE_direct2d OR WIN32)
SOURCES
util/qedidparser.cpp util/qedidparser_p.h
util/qedidvendortable_p.h
)
-
-qt_internal_create_tracepoints(Gui qtgui.tracepoints)
+qt_internal_generate_tracepoints(Gui gui
+ SOURCES
+ image/qimage.cpp image/qimagereader.cpp image/qpixmap.cpp kernel/qguiapplication.cpp
+ text/qfontdatabase.cpp
+)
qt_internal_add_docs(Gui
doc/qtgui.qdocconf
)
-# special case begin
+if(IOS)
+ qt_internal_set_apple_privacy_manifest(Gui
+ "${CMAKE_CURRENT_SOURCE_DIR}/platform/ios/PrivacyInfo.xcprivacy")
+endif()
+
qt_internal_add_optimize_full_flags()
-# special case end
diff --git a/src/gui/accessible/linux/atspiadaptor.cpp b/src/gui/accessible/linux/atspiadaptor.cpp
index 2249e3c121..b3269a2a95 100644
--- a/src/gui/accessible/linux/atspiadaptor.cpp
+++ b/src/gui/accessible/linux/atspiadaptor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "atspiadaptor_p.h"
#include "qspiaccessiblebridge_p.h"
@@ -47,10 +11,12 @@
#include <qclipboard.h>
#include <QtCore/qloggingcategory.h>
+#include <QtCore/qtversion.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "socket_interface.h"
#include "qspi_constant_mappings_p.h"
+#include <QtCore/private/qstringiterator_p.h>
#include <QtGui/private/qaccessiblebridgeutils_p.h>
#include "qspiapplicationadaptor_p.h"
@@ -64,8 +30,15 @@
It sends notifications coming from Qt via dbus and listens to incoming dbus requests.
*/
+// ATSPI_COORD_TYPE_PARENT was added in at-spi 2.30, define here for older versions
+#if ATSPI_COORD_TYPE_COUNT < 3
+#define ATSPI_COORD_TYPE_PARENT 2
+#endif
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcAccessibilityAtspi, "qt.accessibility.atspi")
Q_LOGGING_CATEGORY(lcAccessibilityAtspiCreation, "qt.accessibility.atspi.creation")
@@ -133,11 +106,11 @@ AtSpiAdaptor::AtSpiAdaptor(DBusConnection *connection, QObject *parent)
connect(m_applicationAdaptor, SIGNAL(windowActivated(QObject*,bool)), this, SLOT(windowActivated(QObject*,bool)));
updateEventListeners();
- bool success = m_dbus->connection().connect(QLatin1String("org.a11y.atspi.Registry"), QLatin1String("/org/a11y/atspi/registry"),
- QLatin1String("org.a11y.atspi.Registry"), QLatin1String("EventListenerRegistered"), this,
+ bool success = m_dbus->connection().connect("org.a11y.atspi.Registry"_L1, "/org/a11y/atspi/registry"_L1,
+ "org.a11y.atspi.Registry"_L1, "EventListenerRegistered"_L1, this,
SLOT(eventListenerRegistered(QString,QString)));
- success = success && m_dbus->connection().connect(QLatin1String("org.a11y.atspi.Registry"), QLatin1String("/org/a11y/atspi/registry"),
- QLatin1String("org.a11y.atspi.Registry"), QLatin1String("EventListenerDeregistered"), this,
+ success = success && m_dbus->connection().connect("org.a11y.atspi.Registry"_L1, "/org/a11y/atspi/registry"_L1,
+ "org.a11y.atspi.Registry"_L1, "EventListenerDeregistered"_L1, this,
SLOT(eventListenerDeregistered(QString,QString)));
}
@@ -150,7 +123,7 @@ AtSpiAdaptor::~AtSpiAdaptor()
*/
QString AtSpiAdaptor::introspect(const QString &path) const
{
- static const QLatin1String accessibleIntrospection(
+ static const QLatin1StringView accessibleIntrospection(
" <interface name=\"org.a11y.atspi.Accessible\">\n"
" <property access=\"read\" type=\"s\" name=\"Name\"/>\n"
" <property access=\"read\" type=\"s\" name=\"Description\"/>\n"
@@ -195,10 +168,13 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" <arg direction=\"out\" type=\"(so)\"/>\n"
" <annotation value=\"QSpiObjectReference\" name=\"org.qtproject.QtDBus.QtTypeName.Out0\"/>\n"
" </method>\n"
+ " <method name=\"GetAccessibleId\">\n"
+ " <arg direction=\"out\" type=\"s\"/>\n"
+ " </method>\n"
" </interface>\n"
);
- static const QLatin1String actionIntrospection(
+ static const QLatin1StringView actionIntrospection(
" <interface name=\"org.a11y.atspi.Action\">\n"
" <property access=\"read\" type=\"i\" name=\"NActions\"/>\n"
" <method name=\"GetDescription\">\n"
@@ -224,7 +200,7 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" </interface>\n"
);
- static const QLatin1String applicationIntrospection(
+ static const QLatin1StringView applicationIntrospection(
" <interface name=\"org.a11y.atspi.Application\">\n"
" <property access=\"read\" type=\"s\" name=\"ToolkitName\"/>\n"
" <property access=\"read\" type=\"s\" name=\"Version\"/>\n"
@@ -239,7 +215,7 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" </interface>\n"
);
- static const QLatin1String componentIntrospection(
+ static const QLatin1StringView componentIntrospection(
" <interface name=\"org.a11y.atspi.Component\">\n"
" <method name=\"Contains\">\n"
" <arg direction=\"in\" type=\"i\" name=\"x\"/>\n"
@@ -302,7 +278,7 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" </interface>\n"
);
- static const QLatin1String editableTextIntrospection(
+ static const QLatin1StringView editableTextIntrospection(
" <interface name=\"org.a11y.atspi.EditableText\">\n"
" <method name=\"SetTextContents\">\n"
" <arg direction=\"in\" type=\"s\" name=\"newContents\"/>\n"
@@ -335,7 +311,40 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" </interface>\n"
);
- static const QLatin1String tableIntrospection(
+ static const QLatin1StringView selectionIntrospection(
+ " <interface name=\"org.a11y.atspi.Selection\">\n"
+ " <property name=\"NSelectedChildren\" type=\"i\" access=\"read\"/>\n"
+ " <method name=\"GetSelectedChild\">\n"
+ " <arg direction=\"in\" name=\"selectedChildIndex\" type=\"i\"/>\n"
+ " <arg direction=\"out\" type=\"(so)\"/>\n"
+ " <annotation name=\"org.qtproject.QtDBus.QtTypeName.Out0\" value=\"QSpiObjectReference\"/>\n"
+ " </method>\n"
+ " <method name=\"SelectChild\">\n"
+ " <arg direction=\"in\" name=\"childIndex\" type=\"i\"/>\n"
+ " <arg direction=\"out\" type=\"b\"/>\n"
+ " </method>\n"
+ " <method name=\"DeselectSelectedChild\">\n"
+ " <arg direction=\"in\" name=\"selectedChildIndex\" type=\"i\"/>\n"
+ " <arg direction=\"out\" type=\"b\"/>\n"
+ " </method>\n"
+ " <method name=\"IsChildSelected\">\n"
+ " <arg direction=\"in\" name=\"childIndex\" type=\"i\"/>\n"
+ " <arg direction=\"out\" type=\"b\"/>\n"
+ " </method>\n"
+ " <method name=\"SelectAll\">\n"
+ " <arg direction=\"out\" type=\"b\"/>\n"
+ " </method>\n"
+ " <method name=\"ClearSelection\">\n"
+ " <arg direction=\"out\" type=\"b\"/>\n"
+ " </method>\n"
+ " <method name=\"DeselectChild\">\n"
+ " <arg direction=\"in\" name=\"childIndex\" type=\"i\"/>\n"
+ " <arg direction=\"out\" type=\"b\"/>\n"
+ " </method>\n"
+ " </interface>\n"
+ );
+
+ static const QLatin1StringView tableIntrospection(
" <interface name=\"org.a11y.atspi.Table\">\n"
" <property access=\"read\" type=\"i\" name=\"NRows\"/>\n"
" <property access=\"read\" type=\"i\" name=\"NColumns\"/>\n"
@@ -443,10 +452,45 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" </interface>\n"
);
- static const QLatin1String textIntrospection(
+ static const QLatin1StringView tableCellIntrospection(
+ " <interface name=\"org.a11y.atspi.TableCell\">\n"
+ " <property access=\"read\" name=\"ColumnSpan\" type=\"i\" />\n"
+ " <property access=\"read\" name=\"Position\" type=\"(ii)\">\n"
+ " <annotation name=\"org.qtproject.QtDBus.QtTypeName\" value=\"QPoint\"/>\n"
+ " </property>\n"
+ " <property access=\"read\" name=\"RowSpan\" type=\"i\" />\n"
+ " <property access=\"read\" name=\"Table\" type=\"(so)\" >\n"
+ " <annotation name=\"org.qtproject.QtDBus.QtTypeName\" value=\"QSpiObjectReference\"/>\n"
+ " </property>\n"
+ " <method name=\"GetRowColumnSpan\">\n"
+ " <arg direction=\"out\" type=\"b\" />\n"
+ " <arg direction=\"out\" name=\"row\" type=\"i\" />\n"
+ " <arg direction=\"out\" name=\"col\" type=\"i\" />\n"
+ " <arg direction=\"out\" name=\"row_extents\" type=\"i\" />\n"
+ " <arg direction=\"out\" name=\"col_extents\" type=\"i\" />\n"
+ " </method>\n"
+ " <method name=\"GetColumnHeaderCells\">\n"
+ " <arg direction=\"out\" type=\"a(so)\"/>\n"
+ " <annotation value=\"QSpiObjectReferenceArray\" name=\"org.qtproject.QtDBus.QtTypeName.Out0\"/>\n"
+ " </method>\n"
+ " <method name=\"GetRowHeaderCells\">\n"
+ " <arg direction=\"out\" type=\"a(so)\"/>\n"
+ " <annotation value=\"QSpiObjectReferenceArray\" name=\"org.qtproject.QtDBus.QtTypeName.Out0\"/>\n"
+ " </method>\n"
+ " </interface>\n"
+ );
+
+ static const QLatin1StringView textIntrospection(
" <interface name=\"org.a11y.atspi.Text\">\n"
" <property access=\"read\" type=\"i\" name=\"CharacterCount\"/>\n"
" <property access=\"read\" type=\"i\" name=\"CaretOffset\"/>\n"
+ " <method name=\"GetStringAtOffset\">\n"
+ " <arg direction=\"in\" name=\"offset\" type=\"i\"/>\n"
+ " <arg direction=\"in\" name=\"granularity\" type=\"u\"/>\n"
+ " <arg direction=\"out\" type=\"s\"/>\n"
+ " <arg direction=\"out\" name=\"startOffset\" type=\"i\"/>\n"
+ " <arg direction=\"out\" name=\"endOffset\" type=\"i\"/>\n"
+ " </method>\n"
" <method name=\"GetText\">\n"
" <arg direction=\"in\" type=\"i\" name=\"startOffset\"/>\n"
" <arg direction=\"in\" type=\"i\" name=\"endOffset\"/>\n"
@@ -485,9 +529,6 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" <arg direction=\"in\" type=\"i\" name=\"offset\"/>\n"
" <arg direction=\"in\" type=\"s\" name=\"attributeName\"/>\n"
" <arg direction=\"out\" type=\"s\"/>\n"
- " <arg direction=\"out\" type=\"i\" name=\"startOffset\"/>\n"
- " <arg direction=\"out\" type=\"i\" name=\"endOffset\"/>\n"
- " <arg direction=\"out\" type=\"b\" name=\"defined\"/>\n"
" </method>\n"
" <method name=\"GetAttributes\">\n"
" <arg direction=\"in\" type=\"i\" name=\"offset\"/>\n"
@@ -516,6 +557,7 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" </method>\n"
" <method name=\"GetNSelections\">\n"
" <arg direction=\"out\" type=\"i\"/>\n"
+ " </method>\n"
" <method name=\"GetSelection\">\n"
" <arg direction=\"in\" type=\"i\" name=\"selectionNum\"/>\n"
" <arg direction=\"out\" type=\"i\" name=\"startOffset\"/>\n"
@@ -568,10 +610,16 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" <arg direction=\"out\" type=\"a{ss}\"/>\n"
" <annotation value=\"QSpiAttributeSet\" name=\"org.qtproject.QtDBus.QtTypeName.Out0\"/>\n"
" </method>\n"
+ " <method name=\"ScrollSubstringTo\">\n"
+ " <arg direction=\"in\" name=\"startOffset\" type=\"i\"/>\n"
+ " <arg direction=\"in\" name=\"endOffset\" type=\"i\"/>\n"
+ " <arg direction=\"in\" name=\"type\" type=\"u\"/>\n"
+ " <arg direction=\"out\" type=\"b\"/>\n"
+ " </method>\n"
" </interface>\n"
);
- static const QLatin1String valueIntrospection(
+ static const QLatin1StringView valueIntrospection(
" <interface name=\"org.a11y.atspi.Value\">\n"
" <property access=\"read\" type=\"d\" name=\"MinimumValue\"/>\n"
" <property access=\"read\" type=\"d\" name=\"MaximumValue\"/>\n"
@@ -585,7 +633,7 @@ QString AtSpiAdaptor::introspect(const QString &path) const
QAccessibleInterface * interface = interfaceFromPath(path);
if (!interface) {
- qCDebug(lcAccessibilityAtspi) << "WARNING Qt AtSpiAdaptor: Could not find accessible on path: " << path;
+ qCWarning(lcAccessibilityAtspi) << "Could not find accessible on path:" << path;
return QString();
}
@@ -594,19 +642,23 @@ QString AtSpiAdaptor::introspect(const QString &path) const
QString xml;
xml.append(accessibleIntrospection);
- if (interfaces.contains(QLatin1String(ATSPI_DBUS_INTERFACE_COMPONENT)))
+ if (interfaces.contains(ATSPI_DBUS_INTERFACE_COMPONENT ""_L1))
xml.append(componentIntrospection);
- if (interfaces.contains(QLatin1String(ATSPI_DBUS_INTERFACE_TEXT)))
+ if (interfaces.contains(ATSPI_DBUS_INTERFACE_TEXT ""_L1))
xml.append(textIntrospection);
- if (interfaces.contains(QLatin1String(ATSPI_DBUS_INTERFACE_EDITABLE_TEXT)))
+ if (interfaces.contains(ATSPI_DBUS_INTERFACE_EDITABLE_TEXT ""_L1))
xml.append(editableTextIntrospection);
- if (interfaces.contains(QLatin1String(ATSPI_DBUS_INTERFACE_ACTION)))
+ if (interfaces.contains(ATSPI_DBUS_INTERFACE_ACTION ""_L1))
xml.append(actionIntrospection);
- if (interfaces.contains(QLatin1String(ATSPI_DBUS_INTERFACE_TABLE)))
+ if (interfaces.contains(ATSPI_DBUS_INTERFACE_SELECTION ""_L1))
+ xml.append(selectionIntrospection);
+ if (interfaces.contains(ATSPI_DBUS_INTERFACE_TABLE ""_L1))
xml.append(tableIntrospection);
- if (interfaces.contains(QLatin1String(ATSPI_DBUS_INTERFACE_VALUE)))
+ if (interfaces.contains(ATSPI_DBUS_INTERFACE_TABLE_CELL ""_L1))
+ xml.append(tableCellIntrospection);
+ if (interfaces.contains(ATSPI_DBUS_INTERFACE_VALUE ""_L1))
xml.append(valueIntrospection);
- if (path == QLatin1String(QSPI_OBJECT_PATH_ROOT))
+ if (path == QSPI_OBJECT_PATH_ROOT ""_L1)
xml.append(applicationIntrospection);
return xml;
@@ -624,77 +676,77 @@ void AtSpiAdaptor::setBitFlag(const QString &flag)
} else { // Object:Foo:Bar
QString right = flag.mid(7);
if (false) {
- } else if (right.startsWith(QLatin1String("ActiveDescendantChanged"))) {
+ } else if (right.startsWith("ActiveDescendantChanged"_L1)) {
sendObject_active_descendant_changed = 1;
- } else if (right.startsWith(QLatin1String("AttributesChanged"))) {
+ } else if (right.startsWith("AttributesChanged"_L1)) {
sendObject_attributes_changed = 1;
- } else if (right.startsWith(QLatin1String("BoundsChanged"))) {
+ } else if (right.startsWith("BoundsChanged"_L1)) {
sendObject_bounds_changed = 1;
- } else if (right.startsWith(QLatin1String("ChildrenChanged"))) {
+ } else if (right.startsWith("ChildrenChanged"_L1)) {
sendObject_children_changed = 1;
- } else if (right.startsWith(QLatin1String("ColumnDeleted"))) {
+ } else if (right.startsWith("ColumnDeleted"_L1)) {
sendObject_column_deleted = 1;
- } else if (right.startsWith(QLatin1String("ColumnInserted"))) {
+ } else if (right.startsWith("ColumnInserted"_L1)) {
sendObject_column_inserted = 1;
- } else if (right.startsWith(QLatin1String("ColumnReordered"))) {
+ } else if (right.startsWith("ColumnReordered"_L1)) {
sendObject_column_reordered = 1;
- } else if (right.startsWith(QLatin1String("LinkSelected"))) {
+ } else if (right.startsWith("LinkSelected"_L1)) {
sendObject_link_selected = 1;
- } else if (right.startsWith(QLatin1String("ModelChanged"))) {
+ } else if (right.startsWith("ModelChanged"_L1)) {
sendObject_model_changed = 1;
- } else if (right.startsWith(QLatin1String("PropertyChange"))) {
- if (right == QLatin1String("PropertyChange:AccessibleDescription")) {
+ } else if (right.startsWith("PropertyChange"_L1)) {
+ if (right == "PropertyChange:AccessibleDescription"_L1) {
sendObject_property_change_accessible_description = 1;
- } else if (right == QLatin1String("PropertyChange:AccessibleName")) {
+ } else if (right == "PropertyChange:AccessibleName"_L1) {
sendObject_property_change_accessible_name = 1;
- } else if (right == QLatin1String("PropertyChange:AccessibleParent")) {
+ } else if (right == "PropertyChange:AccessibleParent"_L1) {
sendObject_property_change_accessible_parent = 1;
- } else if (right == QLatin1String("PropertyChange:AccessibleRole")) {
+ } else if (right == "PropertyChange:AccessibleRole"_L1) {
sendObject_property_change_accessible_role = 1;
- } else if (right == QLatin1String("PropertyChange:TableCaption")) {
+ } else if (right == "PropertyChange:TableCaption"_L1) {
sendObject_property_change_accessible_table_caption = 1;
- } else if (right == QLatin1String("PropertyChange:TableColumnDescription")) {
+ } else if (right == "PropertyChange:TableColumnDescription"_L1) {
sendObject_property_change_accessible_table_column_description = 1;
- } else if (right == QLatin1String("PropertyChange:TableColumnHeader")) {
+ } else if (right == "PropertyChange:TableColumnHeader"_L1) {
sendObject_property_change_accessible_table_column_header = 1;
- } else if (right == QLatin1String("PropertyChange:TableRowDescription")) {
+ } else if (right == "PropertyChange:TableRowDescription"_L1) {
sendObject_property_change_accessible_table_row_description = 1;
- } else if (right == QLatin1String("PropertyChange:TableRowHeader")) {
+ } else if (right == "PropertyChange:TableRowHeader"_L1) {
sendObject_property_change_accessible_table_row_header = 1;
- } else if (right == QLatin1String("PropertyChange:TableSummary")) {
+ } else if (right == "PropertyChange:TableSummary"_L1) {
sendObject_property_change_accessible_table_summary = 1;
- } else if (right == QLatin1String("PropertyChange:AccessibleValue")) {
+ } else if (right == "PropertyChange:AccessibleValue"_L1) {
sendObject_property_change_accessible_value = 1;
} else {
sendObject_property_change = 1;
}
- } else if (right.startsWith(QLatin1String("RowDeleted"))) {
+ } else if (right.startsWith("RowDeleted"_L1)) {
sendObject_row_deleted = 1;
- } else if (right.startsWith(QLatin1String("RowInserted"))) {
+ } else if (right.startsWith("RowInserted"_L1)) {
sendObject_row_inserted = 1;
- } else if (right.startsWith(QLatin1String("RowReordered"))) {
+ } else if (right.startsWith("RowReordered"_L1)) {
sendObject_row_reordered = 1;
- } else if (right.startsWith(QLatin1String("SelectionChanged"))) {
+ } else if (right.startsWith("SelectionChanged"_L1)) {
sendObject_selection_changed = 1;
- } else if (right.startsWith(QLatin1String("StateChanged"))) {
+ } else if (right.startsWith("StateChanged"_L1)) {
sendObject_state_changed = 1;
- } else if (right.startsWith(QLatin1String("TextAttributesChanged"))) {
+ } else if (right.startsWith("TextAttributesChanged"_L1)) {
sendObject_text_attributes_changed = 1;
- } else if (right.startsWith(QLatin1String("TextBoundsChanged"))) {
+ } else if (right.startsWith("TextBoundsChanged"_L1)) {
sendObject_text_bounds_changed = 1;
- } else if (right.startsWith(QLatin1String("TextCaretMoved"))) {
+ } else if (right.startsWith("TextCaretMoved"_L1)) {
sendObject_text_caret_moved = 1;
- } else if (right.startsWith(QLatin1String("TextChanged"))) {
+ } else if (right.startsWith("TextChanged"_L1)) {
sendObject_text_changed = 1;
- } else if (right.startsWith(QLatin1String("TextSelectionChanged"))) {
+ } else if (right.startsWith("TextSelectionChanged"_L1)) {
sendObject_text_selection_changed = 1;
- } else if (right.startsWith(QLatin1String("ValueChanged"))) {
+ } else if (right.startsWith("ValueChanged"_L1)) {
sendObject_value_changed = 1;
- } else if (right.startsWith(QLatin1String("VisibleDataChanged"))
- || right.startsWith(QLatin1String("VisibledataChanged"))) { // typo in libatspi
+ } else if (right.startsWith("VisibleDataChanged"_L1)
+ || right.startsWith("VisibledataChanged"_L1)) { // typo in libatspi
sendObject_visible_data_changed = 1;
} else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: subscription string not handled:" << flag;
+ qCWarning(lcAccessibilityAtspi) << "Subscription string not handled:" << flag;
}
}
break;
@@ -705,42 +757,42 @@ void AtSpiAdaptor::setBitFlag(const QString &flag)
} else { // object:Foo:Bar
QString right = flag.mid(7);
if (false) {
- } else if (right.startsWith(QLatin1String("Activate"))) {
+ } else if (right.startsWith("Activate"_L1)) {
sendWindow_activate = 1;
- } else if (right.startsWith(QLatin1String("Close"))) {
+ } else if (right.startsWith("Close"_L1)) {
sendWindow_close= 1;
- } else if (right.startsWith(QLatin1String("Create"))) {
+ } else if (right.startsWith("Create"_L1)) {
sendWindow_create = 1;
- } else if (right.startsWith(QLatin1String("Deactivate"))) {
+ } else if (right.startsWith("Deactivate"_L1)) {
sendWindow_deactivate = 1;
- } else if (right.startsWith(QLatin1String("Lower"))) {
+ } else if (right.startsWith("Lower"_L1)) {
sendWindow_lower = 1;
- } else if (right.startsWith(QLatin1String("Maximize"))) {
+ } else if (right.startsWith("Maximize"_L1)) {
sendWindow_maximize = 1;
- } else if (right.startsWith(QLatin1String("Minimize"))) {
+ } else if (right.startsWith("Minimize"_L1)) {
sendWindow_minimize = 1;
- } else if (right.startsWith(QLatin1String("Move"))) {
+ } else if (right.startsWith("Move"_L1)) {
sendWindow_move = 1;
- } else if (right.startsWith(QLatin1String("Raise"))) {
+ } else if (right.startsWith("Raise"_L1)) {
sendWindow_raise = 1;
- } else if (right.startsWith(QLatin1String("Reparent"))) {
+ } else if (right.startsWith("Reparent"_L1)) {
sendWindow_reparent = 1;
- } else if (right.startsWith(QLatin1String("Resize"))) {
+ } else if (right.startsWith("Resize"_L1)) {
sendWindow_resize = 1;
- } else if (right.startsWith(QLatin1String("Restore"))) {
+ } else if (right.startsWith("Restore"_L1)) {
sendWindow_restore = 1;
- } else if (right.startsWith(QLatin1String("Restyle"))) {
+ } else if (right.startsWith("Restyle"_L1)) {
sendWindow_restyle = 1;
- } else if (right.startsWith(QLatin1String("Shade"))) {
+ } else if (right.startsWith("Shade"_L1)) {
sendWindow_shade = 1;
- } else if (right.startsWith(QLatin1String("Unshade"))) {
+ } else if (right.startsWith("Unshade"_L1)) {
sendWindow_unshade = 1;
- } else if (right.startsWith(QLatin1String("DesktopCreate"))) {
+ } else if (right.startsWith("DesktopCreate"_L1)) {
// ignore this one
- } else if (right.startsWith(QLatin1String("DesktopDestroy"))) {
+ } else if (right.startsWith("DesktopDestroy"_L1)) {
// ignore this one
} else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: subscription string not handled:" << flag;
+ qCWarning(lcAccessibilityAtspi) << "Subscription string not handled:" << flag;
}
}
break;
@@ -759,7 +811,7 @@ void AtSpiAdaptor::setBitFlag(const QString &flag)
break;
}
default:
- qCDebug(lcAccessibilityAtspi) << "WARNING: subscription string not handled:" << flag;
+ qCWarning(lcAccessibilityAtspi) << "Subscription string not handled:" << flag;
}
}
@@ -768,9 +820,9 @@ void AtSpiAdaptor::setBitFlag(const QString &flag)
*/
void AtSpiAdaptor::updateEventListeners()
{
- QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String("org.a11y.atspi.Registry"),
- QLatin1String("/org/a11y/atspi/registry"),
- QLatin1String("org.a11y.atspi.Registry"), QLatin1String("GetRegisteredEvents"));
+ QDBusMessage m = QDBusMessage::createMethodCall("org.a11y.atspi.Registry"_L1,
+ "/org/a11y/atspi/registry"_L1,
+ "org.a11y.atspi.Registry"_L1, "GetRegisteredEvents"_L1);
QDBusReply<QSpiEventListenerArray> listenersReply = m_dbus->connection().call(m);
if (listenersReply.isValid()) {
const QSpiEventListenerArray evList = listenersReply.value();
@@ -819,13 +871,12 @@ void AtSpiAdaptor::windowActivated(QObject* window, bool active)
QVariantList args = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(data));
- QString status = active ? QLatin1String("Activate") : QLatin1String("Deactivate");
+ QString status = active ? "Activate"_L1 : "Deactivate"_L1;
QString path = pathForObject(window);
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_WINDOW), status, args);
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_WINDOW ""_L1, status, args);
- QVariantList stateArgs = packDBusSignalArguments(QLatin1String("active"), active ? 1 : 0, 0, variantForPath(path));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("StateChanged"), stateArgs);
+ QVariantList stateArgs = packDBusSignalArguments("active"_L1, active ? 1 : 0, 0, variantForPath(path));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "StateChanged"_L1, stateArgs);
}
QVariantList AtSpiAdaptor::packDBusSignalArguments(const QString &type, int data1, int data2, const QVariant &variantData) const
@@ -852,10 +903,10 @@ bool AtSpiAdaptor::sendDBusSignal(const QString &path, const QString &interface,
QAccessibleInterface *AtSpiAdaptor::interfaceFromPath(const QString& dbusPath) const
{
- if (dbusPath == QLatin1String(QSPI_OBJECT_PATH_ROOT))
+ if (dbusPath == QSPI_OBJECT_PATH_ROOT ""_L1)
return QAccessible::queryAccessibleInterface(qApp);
- QStringList parts = dbusPath.split(QLatin1Char('/'));
+ QStringList parts = dbusPath.split(u'/');
if (parts.size() != 6) {
qCDebug(lcAccessibilityAtspi) << "invalid path: " << dbusPath;
return nullptr;
@@ -875,8 +926,7 @@ void AtSpiAdaptor::notifyStateChange(QAccessibleInterface *interface, const QStr
{
QString path = pathForInterface(interface);
QVariantList stateArgs = packDBusSignalArguments(state, value, 0, variantForPath(path));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("StateChanged"), stateArgs);
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "StateChanged"_L1, stateArgs);
}
@@ -892,13 +942,13 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
break;
case QAccessible::ObjectShow: {
if (sendObject || sendObject_state_changed) {
- notifyStateChange(event->accessibleInterface(), QLatin1String("showing"), 1);
+ notifyStateChange(event->accessibleInterface(), "showing"_L1, 1);
}
break;
}
case QAccessible::ObjectHide: {
if (sendObject || sendObject_state_changed) {
- notifyStateChange(event->accessibleInterface(), QLatin1String("showing"), 0);
+ notifyStateChange(event->accessibleInterface(), "showing"_L1, 0);
}
break;
}
@@ -914,19 +964,37 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
}
case QAccessible::NameChanged: {
if (sendObject || sendObject_property_change || sendObject_property_change_accessible_name) {
- QString path = pathForInterface(event->accessibleInterface());
- QVariantList args = packDBusSignalArguments(QLatin1String("accessible-name"), 0, 0, variantForPath(path));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("PropertyChange"), args);
+ QAccessibleInterface *iface = event->accessibleInterface();
+ if (!iface) {
+ qCDebug(lcAccessibilityAtspi,
+ "NameChanged event from invalid accessible.");
+ return;
+ }
+
+ QString path = pathForInterface(iface);
+ QVariantList args = packDBusSignalArguments(
+ "accessible-name"_L1, 0, 0,
+ QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Name))));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "PropertyChange"_L1, args);
}
break;
}
case QAccessible::DescriptionChanged: {
if (sendObject || sendObject_property_change || sendObject_property_change_accessible_description) {
- QString path = pathForInterface(event->accessibleInterface());
- QVariantList args = packDBusSignalArguments(QLatin1String("accessible-description"), 0, 0, variantForPath(path));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("PropertyChange"), args);
+ QAccessibleInterface *iface = event->accessibleInterface();
+ if (!iface) {
+ qCDebug(lcAccessibilityAtspi,
+ "DescriptionChanged event from invalid accessible.");
+ return;
+ }
+
+ QString path = pathForInterface(iface);
+ QVariantList args = packDBusSignalArguments(
+ "accessible-description"_L1, 0, 0,
+ QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Description))));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "PropertyChange"_L1, args);
}
break;
}
@@ -941,7 +1009,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
if (sendObject || sendObject_text_changed) {
QAccessibleInterface * iface = event->accessibleInterface();
if (!iface || !iface->textInterface()) {
- qCDebug(lcAccessibilityAtspi) << "Received text event for invalid interface.";
+ qCWarning(lcAccessibilityAtspi) << "Received text event for invalid interface.";
return;
}
QString path = pathForInterface(iface);
@@ -973,16 +1041,16 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
if (!textRemoved.isEmpty()) {
data.setVariant(QVariant::fromValue(textRemoved));
- QVariantList args = packDBusSignalArguments(QLatin1String("delete"), changePosition, textRemoved.length(), QVariant::fromValue(data));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("TextChanged"), args);
+ QVariantList args = packDBusSignalArguments("delete"_L1, changePosition, textRemoved.size(), QVariant::fromValue(data));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "TextChanged"_L1, args);
}
if (!textInserted.isEmpty()) {
data.setVariant(QVariant::fromValue(textInserted));
- QVariantList args = packDBusSignalArguments(QLatin1String("insert"), changePosition, textInserted.length(), QVariant::fromValue(data));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("TextChanged"), args);
+ QVariantList args = packDBusSignalArguments("insert"_L1, changePosition, textInserted.size(), QVariant::fromValue(data));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "TextChanged"_L1, args);
}
// send a cursor update
@@ -990,8 +1058,8 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
// QDBusVariant cursorData;
// cursorData.setVariant(QVariant::fromValue(cursorPosition));
// QVariantList args = packDBusSignalArguments(QString(), cursorPosition, 0, QVariant::fromValue(cursorData));
-// sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
-// QLatin1String("TextCaretMoved"), args);
+// sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+// "TextCaretMoved"_L1, args);
}
break;
}
@@ -1008,8 +1076,8 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
int pos = iface->textInterface()->cursorPosition();
cursorData.setVariant(QVariant::fromValue(pos));
QVariantList args = packDBusSignalArguments(QString(), pos, 0, QVariant::fromValue(cursorData));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("TextCaretMoved"), args);
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "TextCaretMoved"_L1, args);
}
break;
}
@@ -1018,8 +1086,8 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
QAccessibleInterface * iface = event->accessibleInterface();
QString path = pathForInterface(iface);
QVariantList args = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(QDBusVariant(QVariant(QString()))));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("TextSelectionChanged"), args);
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "TextSelectionChanged"_L1, args);
}
break;
}
@@ -1032,19 +1100,21 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
}
if (iface->valueInterface()) {
QString path = pathForInterface(iface);
- QVariantList args = packDBusSignalArguments(QLatin1String("accessible-value"), 0, 0, variantForPath(path));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("PropertyChange"), args);
+ QVariantList args = packDBusSignalArguments("accessible-value"_L1, 0, 0, variantForPath(path));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "PropertyChange"_L1, args);
} else if (iface->role() == QAccessible::ComboBox) {
// Combo Box with AT-SPI likes to be special
// It requires a name-change to update caches and then selection-changed
QString path = pathForInterface(iface);
- QVariantList args1 = packDBusSignalArguments(QLatin1String("accessible-name"), 0, 0, variantForPath(path));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("PropertyChange"), args1);
+ QVariantList args1 = packDBusSignalArguments(
+ "accessible-name"_L1, 0, 0,
+ QVariant::fromValue(QDBusVariant(iface->text(QAccessible::Name))));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "PropertyChange"_L1, args1);
QVariantList args2 = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(QDBusVariant(QVariant(0))));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("SelectionChanged"), args2);
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "SelectionChanged"_L1, args2);
} else {
qCWarning(lcAccessibilityAtspi) << "ValueChanged event and no ValueInterface or ComboBox: " << iface;
}
@@ -1059,14 +1129,37 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
qCWarning(lcAccessibilityAtspi) << "Selection event from invalid accessible.";
return;
}
+ // send event for change of selected state for the interface itself
QString path = pathForInterface(iface);
int selected = iface->state().selected ? 1 : 0;
- QVariantList stateArgs = packDBusSignalArguments(QLatin1String("selected"), selected, 0, variantForPath(path));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("StateChanged"), stateArgs);
+ QVariantList stateArgs = packDBusSignalArguments("selected"_L1, selected, 0, variantForPath(path));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "StateChanged"_L1, stateArgs);
+
+ // send SelectionChanged event for the parent
+ QAccessibleInterface* parent = iface->parent();
+ if (!parent) {
+ qCDebug(lcAccessibilityAtspi) << "No valid parent in selection event.";
+ return;
+ }
+
+ QString parentPath = pathForInterface(parent);
+ QVariantList args = packDBusSignalArguments(QString(), 0, 0, variantForPath(parentPath));
+ sendDBusSignal(parentPath, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
+ QLatin1String("SelectionChanged"), args);
break;
}
+ case QAccessible::SelectionWithin: {
+ QAccessibleInterface * iface = event->accessibleInterface();
+ if (!iface) {
+ qCWarning(lcAccessibilityAtspi) << "SelectionWithin event from invalid accessible.";
+ return;
+ }
+ QString path = pathForInterface(iface);
+ QVariantList args = packDBusSignalArguments(QString(), 0, 0, variantForPath(path));
+ sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), QLatin1String("SelectionChanged"), args);
+ break;
+ }
case QAccessible::StateChanged: {
if (sendObject || sendObject_state_changed || sendWindow || sendWindow_activate) {
QAccessible::State stateChange = static_cast<QAccessibleStateChangeEvent*>(event)->changedStates();
@@ -1077,7 +1170,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
return;
}
int checked = iface->state().checked;
- notifyStateChange(iface, QLatin1String("checked"), checked);
+ notifyStateChange(iface, "checked"_L1, checked);
} else if (stateChange.active) {
QAccessibleInterface * iface = event->accessibleInterface();
if (!iface || !(iface->role() == QAccessible::Window && (sendWindow || sendWindow_activate)))
@@ -1087,26 +1180,91 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
QDBusVariant data;
data.setVariant(windowTitle);
QVariantList args = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(data));
- QString status = isActive ? QLatin1String("Activate") : QLatin1String("Deactivate");
+ QString status = isActive ? "Activate"_L1 : "Deactivate"_L1;
QString path = pathForInterface(iface);
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_WINDOW), status, args);
- notifyStateChange(iface, QLatin1String("active"), isActive);
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_WINDOW ""_L1, status, args);
+ notifyStateChange(iface, "active"_L1, isActive);
} else if (stateChange.disabled) {
QAccessibleInterface *iface = event->accessibleInterface();
QAccessible::State state = iface->state();
bool enabled = !state.disabled;
- notifyStateChange(iface, QLatin1String("enabled"), enabled);
- notifyStateChange(iface, QLatin1String("sensitive"), enabled);
+ notifyStateChange(iface, "enabled"_L1, enabled);
+ notifyStateChange(iface, "sensitive"_L1, enabled);
+ } else if (stateChange.focused) {
+ QAccessibleInterface *iface = event->accessibleInterface();
+ QAccessible::State state = iface->state();
+ bool focused = state.focused;
+ notifyStateChange(iface, "focused"_L1, focused);
}
}
break;
}
+ case QAccessible::TableModelChanged: {
+ QAccessibleInterface *interface = event->accessibleInterface();
+ if (!interface || !interface->isValid()) {
+ qCWarning(lcAccessibilityAtspi) << "TableModelChanged event from invalid accessible.";
+ return;
+ }
+
+ const QString path = pathForInterface(interface);
+ QAccessibleTableModelChangeEvent *tableModelEvent = static_cast<QAccessibleTableModelChangeEvent*>(event);
+ switch (tableModelEvent->modelChangeType()) {
+ case QAccessibleTableModelChangeEvent::ColumnsInserted: {
+ if (sendObject || sendObject_column_inserted) {
+ const int firstColumn = tableModelEvent->firstColumn();
+ const int insertedColumnCount = tableModelEvent->lastColumn() - firstColumn + 1;
+ QVariantList args = packDBusSignalArguments(QString(), firstColumn, insertedColumnCount, QVariant::fromValue(QDBusVariant(QVariant(QString()))));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "ColumnInserted"_L1, args);
+ }
+ break;
+ }
+ case QAccessibleTableModelChangeEvent::ColumnsRemoved: {
+ if (sendObject || sendObject_column_deleted) {
+ const int firstColumn = tableModelEvent->firstColumn();
+ const int removedColumnCount = tableModelEvent->lastColumn() - firstColumn + 1;
+ QVariantList args = packDBusSignalArguments(QString(), firstColumn, removedColumnCount, QVariant::fromValue(QDBusVariant(QVariant(QString()))));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "ColumnDeleted"_L1, args);
+ }
+ break;
+ }
+ case QAccessibleTableModelChangeEvent::RowsInserted: {
+ if (sendObject || sendObject_row_inserted) {
+ const int firstRow = tableModelEvent->firstRow();
+ const int insertedRowCount = tableModelEvent->lastRow() - firstRow + 1;
+ QVariantList args = packDBusSignalArguments(QString(), firstRow, insertedRowCount, QVariant::fromValue(QDBusVariant(QVariant(QString()))));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "RowInserted"_L1, args);
+ }
+ break;
+ }
+ case QAccessibleTableModelChangeEvent::RowsRemoved: {
+ if (sendObject || sendObject_row_deleted) {
+ const int firstRow = tableModelEvent->firstRow();
+ const int removedRowCount = tableModelEvent->lastRow() - firstRow + 1;
+ QVariantList args = packDBusSignalArguments(QString(), firstRow, removedRowCount, QVariant::fromValue(QDBusVariant(QVariant(QString()))));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "RowDeleted"_L1, args);
+ }
+ break;
+ }
+ case QAccessibleTableModelChangeEvent::ModelChangeType::ModelReset: {
+ if (sendObject || sendObject_model_changed) {
+ QVariantList args = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(QDBusVariant(QVariant(QString()))));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "ModelChanged"_L1, args);
+ }
+ break;
+ }
+ case QAccessibleTableModelChangeEvent::DataChanged: {
+ if (sendObject || sendObject_visible_data_changed) {
+ QVariantList args = packDBusSignalArguments(QString(), 0, 0, QVariant::fromValue(QDBusVariant(QVariant(QString()))));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "VisibleDataChanged"_L1, args);
+ }
+ break;
+ }
+ }
+ break;
+ }
+
// For now we ignore these events
- case QAccessible::TableModelChanged:
- // For tables, setting manages_descendants should
- // indicate to the client that it cannot cache these
- // interfaces.
case QAccessible::ParentChanged:
case QAccessible::DialogStart:
case QAccessible::DialogEnd:
@@ -1151,7 +1309,6 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
case QAccessible::TextAttributeChanged:
case QAccessible::TextColumnChanged:
case QAccessible::VisibleDataChanged:
- case QAccessible::SelectionWithin:
case QAccessible::LocationChanged:
case QAccessible::HelpChanged:
case QAccessible::DefaultActionChanged:
@@ -1166,21 +1323,20 @@ void AtSpiAdaptor::sendFocusChanged(QAccessibleInterface *interface) const
static QString lastFocusPath;
// "remove" old focus
if (!lastFocusPath.isEmpty()) {
- QVariantList stateArgs = packDBusSignalArguments(QLatin1String("focused"), 0, 0, variantForPath(lastFocusPath));
- sendDBusSignal(lastFocusPath, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("StateChanged"), stateArgs);
+ QVariantList stateArgs = packDBusSignalArguments("focused"_L1, 0, 0, variantForPath(lastFocusPath));
+ sendDBusSignal(lastFocusPath, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "StateChanged"_L1, stateArgs);
}
// send new focus
{
QString path = pathForInterface(interface);
- QVariantList stateArgs = packDBusSignalArguments(QLatin1String("focused"), 1, 0, variantForPath(path));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
- QLatin1String("StateChanged"), stateArgs);
+ QVariantList stateArgs = packDBusSignalArguments("focused"_L1, 1, 0, variantForPath(path));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1,
+ "StateChanged"_L1, stateArgs);
QVariantList focusArgs = packDBusSignalArguments(QString(), 0, 0, variantForPath(path));
- sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_FOCUS),
- QLatin1String("Focus"), focusArgs);
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_FOCUS ""_L1, "Focus"_L1, focusArgs);
lastFocusPath = path;
}
}
@@ -1191,16 +1347,13 @@ void AtSpiAdaptor::childrenChanged(QAccessibleInterface *interface) const
int childCount = interface->childCount();
for (int i = 0; i < interface->childCount(); ++i) {
QString childPath = pathForInterface(interface->child(i));
- QVariantList args = packDBusSignalArguments(QLatin1String("add"), childCount, 0, childPath);
- sendDBusSignal(parentPath, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), QLatin1String("ChildrenChanged"), args);
+ QVariantList args = packDBusSignalArguments("add"_L1, childCount, 0, childPath);
+ sendDBusSignal(parentPath, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "ChildrenChanged"_L1, args);
}
}
void AtSpiAdaptor::notifyAboutCreation(QAccessibleInterface *interface) const
{
-// // say hello to d-bus
-// cache->emitAddAccessible(accessible->getCacheItem());
-
// notify about the new child of our parent
QAccessibleInterface * parent = interface->parent();
if (!parent) {
@@ -1210,8 +1363,8 @@ void AtSpiAdaptor::notifyAboutCreation(QAccessibleInterface *interface) const
QString path = pathForInterface(interface);
int childCount = parent->childCount();
QString parentPath = pathForInterface(parent);
- QVariantList args = packDBusSignalArguments(QLatin1String("add"), childCount, 0, variantForPath(path));
- sendDBusSignal(parentPath, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), QLatin1String("ChildrenChanged"), args);
+ QVariantList args = packDBusSignalArguments("add"_L1, childCount, 0, variantForPath(path));
+ sendDBusSignal(parentPath, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "ChildrenChanged"_L1, args);
}
void AtSpiAdaptor::notifyAboutDestruction(QAccessibleInterface *interface) const
@@ -1236,8 +1389,8 @@ void AtSpiAdaptor::notifyAboutDestruction(QAccessibleInterface *interface) const
// }
QString parentPath = pathForInterface(parent);
- QVariantList args = packDBusSignalArguments(QLatin1String("remove"), childIndex, 0, variantForPath(path));
- sendDBusSignal(parentPath, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), QLatin1String("ChildrenChanged"), args);
+ QVariantList args = packDBusSignalArguments("remove"_L1, childIndex, 0, variantForPath(path));
+ sendDBusSignal(parentPath, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "ChildrenChanged"_L1, args);
}
/*!
@@ -1249,11 +1402,11 @@ bool AtSpiAdaptor::handleMessage(const QDBusMessage &message, const QDBusConnect
// get accessible interface
QAccessibleInterface * accessible = interfaceFromPath(message.path());
if (!accessible) {
- qCDebug(lcAccessibilityAtspi) << "WARNING Qt AtSpiAdaptor: Could not find accessible on path: " << message.path();
+ qCWarning(lcAccessibilityAtspi) << "Could not find accessible on path:" << message.path();
return false;
}
if (!accessible->isValid()) {
- qCWarning(lcAccessibilityAtspi) << "WARNING Qt AtSpiAdaptor: Accessible invalid: " << accessible << message.path();
+ qCWarning(lcAccessibilityAtspi) << "Accessible invalid:" << accessible << message.path();
return false;
}
@@ -1262,35 +1415,39 @@ bool AtSpiAdaptor::handleMessage(const QDBusMessage &message, const QDBusConnect
// qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::handleMessage: " << interface << function;
- if (function == QLatin1String("Introspect")) {
+ if (function == "Introspect"_L1) {
//introspect(message.path());
return false;
}
// handle properties like regular functions
- if (interface == QLatin1String("org.freedesktop.DBus.Properties")) {
+ if (interface == "org.freedesktop.DBus.Properties"_L1) {
interface = message.arguments().at(0).toString();
// Get/Set + Name
function = message.member() + message.arguments().at(1).toString();
}
// switch interface to call
- if (interface == QLatin1String(ATSPI_DBUS_INTERFACE_ACCESSIBLE))
+ if (interface == ATSPI_DBUS_INTERFACE_ACCESSIBLE ""_L1)
return accessibleInterface(accessible, function, message, connection);
- if (interface == QLatin1String(ATSPI_DBUS_INTERFACE_APPLICATION))
+ if (interface == ATSPI_DBUS_INTERFACE_APPLICATION ""_L1)
return applicationInterface(accessible, function, message, connection);
- if (interface == QLatin1String(ATSPI_DBUS_INTERFACE_COMPONENT))
+ if (interface == ATSPI_DBUS_INTERFACE_COMPONENT ""_L1)
return componentInterface(accessible, function, message, connection);
- if (interface == QLatin1String(ATSPI_DBUS_INTERFACE_ACTION))
+ if (interface == ATSPI_DBUS_INTERFACE_ACTION ""_L1)
return actionInterface(accessible, function, message, connection);
- if (interface == QLatin1String(ATSPI_DBUS_INTERFACE_TEXT))
+ if (interface == ATSPI_DBUS_INTERFACE_SELECTION ""_L1)
+ return selectionInterface(accessible, function, message, connection);
+ if (interface == ATSPI_DBUS_INTERFACE_TEXT ""_L1)
return textInterface(accessible, function, message, connection);
- if (interface == QLatin1String(ATSPI_DBUS_INTERFACE_EDITABLE_TEXT))
+ if (interface == ATSPI_DBUS_INTERFACE_EDITABLE_TEXT ""_L1)
return editableTextInterface(accessible, function, message, connection);
- if (interface == QLatin1String(ATSPI_DBUS_INTERFACE_VALUE))
+ if (interface == ATSPI_DBUS_INTERFACE_VALUE ""_L1)
return valueInterface(accessible, function, message, connection);
- if (interface == QLatin1String(ATSPI_DBUS_INTERFACE_TABLE))
+ if (interface == ATSPI_DBUS_INTERFACE_TABLE ""_L1)
return tableInterface(accessible, function, message, connection);
+ if (interface == ATSPI_DBUS_INTERFACE_TABLE_CELL ""_L1)
+ return tableCellInterface(accessible, function, message, connection);
qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::handleMessage with unknown interface: " << message.path() << interface << function;
return false;
@@ -1299,35 +1456,35 @@ bool AtSpiAdaptor::handleMessage(const QDBusMessage &message, const QDBusConnect
// Application
bool AtSpiAdaptor::applicationInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
{
- if (message.path() != QLatin1String(ATSPI_DBUS_PATH_ROOT)) {
- qCDebug(lcAccessibilityAtspi) << "WARNING Qt AtSpiAdaptor: Could not find application interface for: " << message.path() << interface;
+ if (message.path() != ATSPI_DBUS_PATH_ROOT ""_L1) {
+ qCWarning(lcAccessibilityAtspi) << "Could not find application interface for:" << message.path() << interface;
return false;
}
- if (function == QLatin1String("SetId")) {
- Q_ASSERT(message.signature() == QLatin1String("ssv"));
+ if (function == "SetId"_L1) {
+ Q_ASSERT(message.signature() == "ssv"_L1);
QVariant value = qvariant_cast<QDBusVariant>(message.arguments().at(2)).variant();
m_applicationId = value.toInt();
return true;
}
- if (function == QLatin1String("GetId")) {
- Q_ASSERT(message.signature() == QLatin1String("ss"));
+ if (function == "GetId"_L1) {
+ Q_ASSERT(message.signature() == "ss"_L1);
QDBusMessage reply = message.createReply(QVariant::fromValue(QDBusVariant(m_applicationId)));
return connection.send(reply);
}
- if (function == QLatin1String("GetToolkitName")) {
- Q_ASSERT(message.signature() == QLatin1String("ss"));
- QDBusMessage reply = message.createReply(QVariant::fromValue(QDBusVariant(QLatin1String("Qt"))));
+ if (function == "GetToolkitName"_L1) {
+ Q_ASSERT(message.signature() == "ss"_L1);
+ QDBusMessage reply = message.createReply(QVariant::fromValue(QDBusVariant("Qt"_L1)));
return connection.send(reply);
}
- if (function == QLatin1String("GetVersion")) {
- Q_ASSERT(message.signature() == QLatin1String("ss"));
- QDBusMessage reply = message.createReply(QVariant::fromValue(QDBusVariant(QLatin1String(qVersion()))));
+ if (function == "GetVersion"_L1) {
+ Q_ASSERT(message.signature() == "ss"_L1);
+ QDBusMessage reply = message.createReply(QVariant::fromValue(QDBusVariant(QLatin1StringView(qVersion()))));
return connection.send(reply);
}
- if (function == QLatin1String("GetLocale")) {
- Q_ASSERT(message.signature() == QLatin1String("u"));
+ if (function == "GetLocale"_L1) {
+ Q_ASSERT(message.signature() == "u"_L1);
QDBusMessage reply = message.createReply(QVariant::fromValue(QLocale().name()));
return connection.send(reply);
}
@@ -1341,8 +1498,8 @@ bool AtSpiAdaptor::applicationInterface(QAccessibleInterface *interface, const Q
void AtSpiAdaptor::registerApplication()
{
OrgA11yAtspiSocketInterface *registry;
- registry = new OrgA11yAtspiSocketInterface(QLatin1String(QSPI_REGISTRY_NAME),
- QLatin1String(QSPI_OBJECT_PATH_ROOT), m_dbus->connection());
+ registry = new OrgA11yAtspiSocketInterface(QSPI_REGISTRY_NAME ""_L1,
+ QSPI_OBJECT_PATH_ROOT ""_L1, m_dbus->connection());
QDBusPendingReply<QSpiObjectReference> reply;
QSpiObjectReference ref = QSpiObjectReference(m_dbus->connection(), QDBusObjectPath(QSPI_OBJECT_PATH_ROOT));
@@ -1352,27 +1509,47 @@ void AtSpiAdaptor::registerApplication()
const QSpiObjectReference &socket = reply.value();
accessibilityRegistry = QSpiObjectReference(socket);
} else {
- qCDebug(lcAccessibilityAtspi) << "Error in contacting registry: "
+ qCWarning(lcAccessibilityAtspi) << "Error in contacting registry:"
<< reply.error().name()
<< reply.error().message();
}
delete registry;
}
+namespace {
+QString accessibleIdForAccessible(QAccessibleInterface *accessible)
+{
+ QString result;
+ while (accessible) {
+ if (!result.isEmpty())
+ result.prepend(u'.');
+ if (auto obj = accessible->object()) {
+ const QString name = obj->objectName();
+ if (!name.isEmpty())
+ result.prepend(name);
+ else
+ result.prepend(QString::fromUtf8(obj->metaObject()->className()));
+ }
+ accessible = accessible->parent();
+ }
+ return result;
+}
+} // namespace
+
// Accessible
bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
{
- if (function == QLatin1String("GetRole")) {
+ if (function == "GetRole"_L1) {
sendReply(connection, message, (uint) getRole(interface));
- } else if (function == QLatin1String("GetName")) {
+ } else if (function == "GetName"_L1) {
sendReply(connection, message, QVariant::fromValue(QDBusVariant(interface->text(QAccessible::Name))));
- } else if (function == QLatin1String("GetRoleName")) {
+ } else if (function == "GetRoleName"_L1) {
sendReply(connection, message, QSpiAccessibleBridge::namesForRole(interface->role()).name());
- } else if (function == QLatin1String("GetLocalizedRoleName")) {
+ } else if (function == "GetLocalizedRoleName"_L1) {
sendReply(connection, message, QVariant::fromValue(QSpiAccessibleBridge::namesForRole(interface->role()).localizedName()));
- } else if (function == QLatin1String("GetChildCount")) {
+ } else if (function == "GetChildCount"_L1) {
sendReply(connection, message, QVariant::fromValue(QDBusVariant(interface->childCount())));
- } else if (function == QLatin1String("GetIndexInParent")) {
+ } else if (function == "GetIndexInParent"_L1) {
int childIndex = -1;
QAccessibleInterface * parent = interface->parent();
if (parent) {
@@ -1382,20 +1559,20 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
}
}
sendReply(connection, message, childIndex);
- } else if (function == QLatin1String("GetParent")) {
+ } else if (function == "GetParent"_L1) {
QString path;
QAccessibleInterface * parent = interface->parent();
if (!parent) {
- path = QLatin1String(ATSPI_DBUS_PATH_NULL);
+ path = ATSPI_DBUS_PATH_NULL ""_L1;
} else if (parent->role() == QAccessible::Application) {
- path = QLatin1String(ATSPI_DBUS_PATH_ROOT);
+ path = ATSPI_DBUS_PATH_ROOT ""_L1;
} else {
path = pathForInterface(parent);
}
// Parent is a property, so it needs to be wrapped inside an extra variant.
sendReply(connection, message, QVariant::fromValue(
QDBusVariant(QVariant::fromValue(QSpiObjectReference(connection, QDBusObjectPath(path))))));
- } else if (function == QLatin1String("GetChildAtIndex")) {
+ } else if (function == "GetChildAtIndex"_L1) {
const int index = message.arguments().at(0).toInt();
if (index < 0) {
sendReply(connection, message, QVariant::fromValue(
@@ -1405,13 +1582,16 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
sendReply(connection, message, QVariant::fromValue(
QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(childInterface)))));
}
- } else if (function == QLatin1String("GetInterfaces")) {
+ } else if (function == "GetInterfaces"_L1) {
sendReply(connection, message, accessibleInterfaces(interface));
- } else if (function == QLatin1String("GetDescription")) {
+ } else if (function == "GetDescription"_L1) {
sendReply(connection, message, QVariant::fromValue(QDBusVariant(interface->text(QAccessible::Description))));
- } else if (function == QLatin1String("GetState")) {
+ } else if (function == "GetState"_L1) {
quint64 spiState = spiStatesFromQState(interface->state());
if (interface->tableInterface()) {
+ // For tables, setting manages_descendants should
+ // indicate to the client that it cannot cache these
+ // interfaces.
setSpiStateBit(&spiState, ATSPI_STATE_MANAGES_DESCENDANTS);
}
QAccessible::Role role = interface->role();
@@ -1425,14 +1605,14 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
}
sendReply(connection, message,
QVariant::fromValue(spiStateSetFromSpiStates(spiState)));
- } else if (function == QLatin1String("GetAttributes")) {
+ } else if (function == "GetAttributes"_L1) {
sendReply(connection, message, QVariant::fromValue(QSpiAttributeSet()));
- } else if (function == QLatin1String("GetRelationSet")) {
+ } else if (function == "GetRelationSet"_L1) {
sendReply(connection, message, QVariant::fromValue(relationSet(interface, connection)));
- } else if (function == QLatin1String("GetApplication")) {
+ } else if (function == "GetApplication"_L1) {
sendReply(connection, message, QVariant::fromValue(
QSpiObjectReference(connection, QDBusObjectPath(QSPI_OBJECT_PATH_ROOT))));
- } else if (function == QLatin1String("GetChildren")) {
+ } else if (function == "GetChildren"_L1) {
QSpiObjectReferenceArray children;
const int numChildren = interface->childCount();
children.reserve(numChildren);
@@ -1442,8 +1622,11 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
children << ref;
}
connection.send(message.createReply(QVariant::fromValue(children)));
+ } else if (function == "GetAccessibleId"_L1) {
+ sendReply(connection, message,
+ QVariant::fromValue(QDBusVariant(accessibleIdForAccessible(interface))));
} else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::accessibleInterface does not implement " << function << message.path();
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::accessibleInterface does not implement" << function << message.path();
return false;
}
return true;
@@ -1460,7 +1643,7 @@ QStringList AtSpiAdaptor::accessibleInterfaces(QAccessibleInterface *interface)
{
QStringList ifaces;
qCDebug(lcAccessibilityAtspiCreation) << "AtSpiAdaptor::accessibleInterfaces create: " << interface->object();
- ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_ACCESSIBLE);
+ ifaces << u"" ATSPI_DBUS_INTERFACE_ACCESSIBLE ""_s;
if ( (!interface->rect().isEmpty()) ||
(interface->object() && interface->object()->isWidgetType()) ||
@@ -1470,27 +1653,33 @@ QStringList AtSpiAdaptor::accessibleInterfaces(QAccessibleInterface *interface)
(interface->role() == QAccessible::Row) ||
(interface->object() && interface->object()->inherits("QSGItem"))
) {
- ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_COMPONENT);
+ ifaces << u"" ATSPI_DBUS_INTERFACE_COMPONENT ""_s;
} else {
qCDebug(lcAccessibilityAtspiCreation) << " IS NOT a component";
}
if (interface->role() == QAccessible::Application)
- ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_APPLICATION);
+ ifaces << u"" ATSPI_DBUS_INTERFACE_APPLICATION ""_s;
if (interface->actionInterface() || interface->valueInterface())
- ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_ACTION);
+ ifaces << u"" ATSPI_DBUS_INTERFACE_ACTION ""_s;
+
+ if (interface->selectionInterface())
+ ifaces << ATSPI_DBUS_INTERFACE_SELECTION ""_L1;
if (interface->textInterface())
- ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_TEXT);
+ ifaces << u"" ATSPI_DBUS_INTERFACE_TEXT ""_s;
if (interface->editableTextInterface())
- ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_EDITABLE_TEXT);
+ ifaces << u"" ATSPI_DBUS_INTERFACE_EDITABLE_TEXT ""_s;
if (interface->valueInterface())
- ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_VALUE);
+ ifaces << u"" ATSPI_DBUS_INTERFACE_VALUE ""_s;
if (interface->tableInterface())
- ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_TABLE);
+ ifaces << u"" ATSPI_DBUS_INTERFACE_TABLE ""_s;
+
+ if (interface->tableCellInterface())
+ ifaces << u"" ATSPI_DBUS_INTERFACE_TABLE_CELL ""_s;
return ifaces;
}
@@ -1527,7 +1716,7 @@ QString AtSpiAdaptor::pathForObject(QObject *object) const
Q_ASSERT(object);
if (inheritsQAction(object)) {
- qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::pathForObject: warning: creating path with QAction as object.";
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::pathForObject: Creating path with QAction as object.";
}
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(object);
@@ -1537,21 +1726,21 @@ QString AtSpiAdaptor::pathForObject(QObject *object) const
QString AtSpiAdaptor::pathForInterface(QAccessibleInterface *interface) const
{
if (!interface || !interface->isValid())
- return QLatin1String(ATSPI_DBUS_PATH_NULL);
+ return u"" ATSPI_DBUS_PATH_NULL ""_s;
if (interface->role() == QAccessible::Application)
- return QLatin1String(QSPI_OBJECT_PATH_ROOT);
+ return u"" QSPI_OBJECT_PATH_ROOT ""_s;
QAccessible::Id id = QAccessible::uniqueId(interface);
Q_ASSERT((int)id < 0);
- return QLatin1String(QSPI_OBJECT_PATH_PREFIX) + QString::number(id);
+ return QSPI_OBJECT_PATH_PREFIX ""_L1 + QString::number(id);
}
bool AtSpiAdaptor::inheritsQAction(QObject *object)
{
const QMetaObject *mo = object->metaObject();
while (mo) {
- const QLatin1String cn(mo->className());
- if (cn == QLatin1String("QAction"))
+ const QLatin1StringView cn(mo->className());
+ if (cn == "QAction"_L1)
return true;
mo = mo->superClass();
}
@@ -1561,62 +1750,39 @@ bool AtSpiAdaptor::inheritsQAction(QObject *object)
// Component
static QAccessibleInterface * getWindow(QAccessibleInterface * interface)
{
- if (interface->role() == QAccessible::Window)
- return interface;
-
- QAccessibleInterface * parent = interface->parent();
- while (parent && parent->role() != QAccessible::Window)
- parent = parent->parent();
-
- return parent;
-}
-
-static QRect getRelativeRect(QAccessibleInterface *interface)
-{
- QAccessibleInterface * window;
- QRect wr, cr;
-
- cr = interface->rect();
-
- window = getWindow(interface);
- if (window) {
- wr = window->rect();
-
- cr.setX(cr.x() - wr.x());
- cr.setY(cr.x() - wr.y());
- }
- return cr;
+ // find top-level window in a11y hierarchy (either has a
+ // corresponding role or is a direct child of the application object)
+ QAccessibleInterface* app = QAccessible::queryAccessibleInterface(qApp);
+ while (interface && interface->role() != QAccessible::Dialog
+ && interface->role() != QAccessible::Window && interface->parent() != app)
+ interface = interface->parent();
+
+ return interface;
}
bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
{
- if (function == QLatin1String("Contains")) {
+ if (function == "Contains"_L1) {
bool ret = false;
int x = message.arguments().at(0).toInt();
int y = message.arguments().at(1).toInt();
uint coordType = message.arguments().at(2).toUInt();
- if (coordType == ATSPI_COORD_TYPE_SCREEN)
- ret = interface->rect().contains(x, y);
- else
- ret = getRelativeRect(interface).contains(x, y);
+ if (!isValidCoordType(coordType))
+ return false;
+ ret = getExtents(interface, coordType).contains(x, y);
sendReply(connection, message, ret);
- } else if (function == QLatin1String("GetAccessibleAtPoint")) {
- int x = message.arguments().at(0).toInt();
- int y = message.arguments().at(1).toInt();
+ } else if (function == "GetAccessibleAtPoint"_L1) {
+ QPoint point(message.arguments().at(0).toInt(), message.arguments().at(1).toInt());
uint coordType = message.arguments().at(2).toUInt();
- if (coordType == ATSPI_COORD_TYPE_WINDOW) {
- QWindow * window = interface->window();
- if (window) {
- x += window->position().x();
- y += window->position().y();
- }
- }
+ if (!isValidCoordType(coordType))
+ return false;
+ QPoint screenPos = translateToScreenCoordinates(interface, point, coordType);
- QAccessibleInterface * childInterface(interface->childAt(x, y));
+ QAccessibleInterface * childInterface(interface->childAt(screenPos.x(), screenPos.y()));
QAccessibleInterface * iface = nullptr;
while (childInterface) {
iface = childInterface;
- childInterface = iface->childAt(x, y);
+ childInterface = iface->childAt(screenPos.x(), screenPos.y());
}
if (iface) {
QString path = pathForInterface(iface);
@@ -1626,31 +1792,31 @@ bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QSt
sendReply(connection, message, QVariant::fromValue(
QSpiObjectReference(connection, QDBusObjectPath(ATSPI_DBUS_PATH_NULL))));
}
- } else if (function == QLatin1String("GetAlpha")) {
+ } else if (function == "GetAlpha"_L1) {
sendReply(connection, message, (double) 1.0);
- } else if (function == QLatin1String("GetExtents")) {
+ } else if (function == "GetExtents"_L1) {
uint coordType = message.arguments().at(0).toUInt();
+ if (!isValidCoordType(coordType))
+ return false;
sendReply(connection, message, QVariant::fromValue(getExtents(interface, coordType)));
- } else if (function == QLatin1String("GetLayer")) {
+ } else if (function == "GetLayer"_L1) {
sendReply(connection, message, QVariant::fromValue((uint)1));
- } else if (function == QLatin1String("GetMDIZOrder")) {
+ } else if (function == "GetMDIZOrder"_L1) {
sendReply(connection, message, QVariant::fromValue((short)0));
- } else if (function == QLatin1String("GetPosition")) {
+ } else if (function == "GetPosition"_L1) {
uint coordType = message.arguments().at(0).toUInt();
- QRect rect;
- if (coordType == ATSPI_COORD_TYPE_SCREEN)
- rect = interface->rect();
- else
- rect = getRelativeRect(interface);
+ if (!isValidCoordType(coordType))
+ return false;
+ QRect rect = getExtents(interface, coordType);
QVariantList pos;
pos << rect.x() << rect.y();
connection.send(message.createReply(pos));
- } else if (function == QLatin1String("GetSize")) {
+ } else if (function == "GetSize"_L1) {
QRect rect = interface->rect();
QVariantList size;
size << rect.width() << rect.height();
connection.send(message.createReply(size));
- } else if (function == QLatin1String("GrabFocus")) {
+ } else if (function == "GrabFocus"_L1) {
QAccessibleActionInterface *actionIface = interface->actionInterface();
if (actionIface && actionIface->actionNames().contains(QAccessibleActionInterface::setFocusAction())) {
actionIface->doAction(QAccessibleActionInterface::setFocusAction());
@@ -1658,7 +1824,7 @@ bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QSt
} else {
sendReply(connection, message, false);
}
- } else if (function == QLatin1String("SetExtents")) {
+ } else if (function == "SetExtents"_L1) {
// int x = message.arguments().at(0).toInt();
// int y = message.arguments().at(1).toInt();
// int width = message.arguments().at(2).toInt();
@@ -1666,19 +1832,19 @@ bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QSt
// uint coordinateType = message.arguments().at(4).toUInt();
qCDebug(lcAccessibilityAtspi) << "SetExtents is not implemented.";
sendReply(connection, message, false);
- } else if (function == QLatin1String("SetPosition")) {
+ } else if (function == "SetPosition"_L1) {
// int x = message.arguments().at(0).toInt();
// int y = message.arguments().at(1).toInt();
// uint coordinateType = message.arguments().at(2).toUInt();
qCDebug(lcAccessibilityAtspi) << "SetPosition is not implemented.";
sendReply(connection, message, false);
- } else if (function == QLatin1String("SetSize")) {
+ } else if (function == "SetSize"_L1) {
// int width = message.arguments().at(0).toInt();
// int height = message.arguments().at(1).toInt();
qCDebug(lcAccessibilityAtspi) << "SetSize is not implemented.";
sendReply(connection, message, false);
} else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::componentInterface does not implement " << function << message.path();
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::componentInterface does not implement" << function << message.path();
return false;
}
return true;
@@ -1686,35 +1852,35 @@ bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QSt
QRect AtSpiAdaptor::getExtents(QAccessibleInterface *interface, uint coordType)
{
- return (coordType == ATSPI_COORD_TYPE_SCREEN) ? interface->rect() : getRelativeRect(interface);
+ return translateFromScreenCoordinates(interface, interface->rect(), coordType);
}
// Action interface
bool AtSpiAdaptor::actionInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
{
- if (function == QLatin1String("GetNActions")) {
- int count = QAccessibleBridgeUtils::effectiveActionNames(interface).count();
+ if (function == "GetNActions"_L1) {
+ int count = QAccessibleBridgeUtils::effectiveActionNames(interface).size();
sendReply(connection, message, QVariant::fromValue(QDBusVariant(QVariant::fromValue(count))));
- } else if (function == QLatin1String("DoAction")) {
+ } else if (function == "DoAction"_L1) {
int index = message.arguments().at(0).toInt();
const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(interface);
- if (index < 0 || index >= actionNames.count())
+ if (index < 0 || index >= actionNames.size())
return false;
const QString actionName = actionNames.at(index);
bool success = QAccessibleBridgeUtils::performEffectiveAction(interface, actionName);
sendReply(connection, message, success);
- } else if (function == QLatin1String("GetActions")) {
+ } else if (function == "GetActions"_L1) {
sendReply(connection, message, QVariant::fromValue(getActions(interface)));
- } else if (function == QLatin1String("GetName")) {
+ } else if (function == "GetName"_L1) {
int index = message.arguments().at(0).toInt();
const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(interface);
- if (index < 0 || index >= actionNames.count())
+ if (index < 0 || index >= actionNames.size())
return false;
sendReply(connection, message, actionNames.at(index));
- } else if (function == QLatin1String("GetDescription")) {
+ } else if (function == "GetDescription"_L1) {
int index = message.arguments().at(0).toInt();
const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(interface);
- if (index < 0 || index >= actionNames.count())
+ if (index < 0 || index >= actionNames.size())
return false;
QString description;
if (QAccessibleActionInterface *actionIface = interface->actionInterface())
@@ -1722,10 +1888,10 @@ bool AtSpiAdaptor::actionInterface(QAccessibleInterface *interface, const QStrin
else
description = qAccessibleLocalizedActionDescription(actionNames.at(index));
sendReply(connection, message, description);
- } else if (function == QLatin1String("GetKeyBinding")) {
+ } else if (function == "GetKeyBinding"_L1) {
int index = message.arguments().at(0).toInt();
const QStringList actionNames = QAccessibleBridgeUtils::effectiveActionNames(interface);
- if (index < 0 || index >= actionNames.count())
+ if (index < 0 || index >= actionNames.size())
return false;
QStringList keyBindings;
if (QAccessibleActionInterface *actionIface = interface->actionInterface())
@@ -1735,12 +1901,12 @@ bool AtSpiAdaptor::actionInterface(QAccessibleInterface *interface, const QStrin
if (!acc.isEmpty())
keyBindings.append(acc);
}
- if (keyBindings.length() > 0)
- sendReply(connection, message, keyBindings.join(QLatin1Char(';')));
+ if (keyBindings.size() > 0)
+ sendReply(connection, message, keyBindings.join(u';'));
else
sendReply(connection, message, QString());
} else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::actionInterface does not implement " << function << message.path();
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::actionInterface does not implement" << function << message.path();
return false;
}
return true;
@@ -1777,31 +1943,31 @@ bool AtSpiAdaptor::textInterface(QAccessibleInterface *interface, const QString
return false;
// properties
- if (function == QLatin1String("GetCaretOffset")) {
+ if (function == "GetCaretOffset"_L1) {
sendReply(connection, message, QVariant::fromValue(QDBusVariant(QVariant::fromValue(interface->textInterface()->cursorPosition()))));
- } else if (function == QLatin1String("GetCharacterCount")) {
+ } else if (function == "GetCharacterCount"_L1) {
sendReply(connection, message, QVariant::fromValue(QDBusVariant(QVariant::fromValue(interface->textInterface()->characterCount()))));
// functions
- } else if (function == QLatin1String("AddSelection")) {
+ } else if (function == "AddSelection"_L1) {
int startOffset = message.arguments().at(0).toInt();
int endOffset = message.arguments().at(1).toInt();
int lastSelection = interface->textInterface()->selectionCount();
interface->textInterface()->setSelection(lastSelection, startOffset, endOffset);
sendReply(connection, message, (interface->textInterface()->selectionCount() > lastSelection));
- } else if (function == QLatin1String("GetAttributeRun")) {
+ } else if (function == "GetAttributeRun"_L1) {
int offset = message.arguments().at(0).toInt();
bool includeDefaults = message.arguments().at(1).toBool();
Q_UNUSED(includeDefaults);
connection.send(message.createReply(getAttributes(interface, offset, includeDefaults)));
- } else if (function == QLatin1String("GetAttributeValue")) {
+ } else if (function == "GetAttributeValue"_L1) {
int offset = message.arguments().at(0).toInt();
QString attributeName = message.arguments().at(1).toString();
- connection.send(message.createReply(getAttributeValue(interface, offset, attributeName)));
- } else if (function == QLatin1String("GetAttributes")) {
+ connection.send(message.createReply(QVariant(getAttributeValue(interface, offset, attributeName))));
+ } else if (function == "GetAttributes"_L1) {
int offset = message.arguments().at(0).toInt();
connection.send(message.createReply(getAttributes(interface, offset, true)));
- } else if (function == QLatin1String("GetBoundedRanges")) {
+ } else if (function == "GetBoundedRanges"_L1) {
int x = message.arguments().at(0).toInt();
int y = message.arguments().at(1).toInt();
int width = message.arguments().at(2).toInt();
@@ -1818,39 +1984,43 @@ bool AtSpiAdaptor::textInterface(QAccessibleInterface *interface, const QString
Q_UNUSED(yClipType);
qCDebug(lcAccessibilityAtspi) << "Not implemented: QSpiAdaptor::GetBoundedRanges";
sendReply(connection, message, QVariant::fromValue(QSpiTextRangeList()));
- } else if (function == QLatin1String("GetCharacterAtOffset")) {
+ } else if (function == "GetCharacterAtOffset"_L1) {
int offset = message.arguments().at(0).toInt();
int start;
int end;
- QString result = interface->textInterface()->textAtOffset(offset, QAccessible::CharBoundary, &start, &end);
- sendReply(connection, message, (int) *(qPrintable (result)));
- } else if (function == QLatin1String("GetCharacterExtents")) {
+ const QString charString = interface->textInterface()
+ ->textAtOffset(offset, QAccessible::CharBoundary, &start, &end);
+ int codePoint = 0;
+ QStringIterator stringIt(charString);
+ if (stringIt.hasNext())
+ codePoint = static_cast<int>(stringIt.peekNext());
+ sendReply(connection, message, codePoint);
+ } else if (function == "GetCharacterExtents"_L1) {
int offset = message.arguments().at(0).toInt();
int coordType = message.arguments().at(1).toUInt();
connection.send(message.createReply(getCharacterExtents(interface, offset, coordType)));
- } else if (function == QLatin1String("GetDefaultAttributeSet") || function == QLatin1String("GetDefaultAttributes")) {
+ } else if (function == "GetDefaultAttributeSet"_L1 || function == "GetDefaultAttributes"_L1) {
// GetDefaultAttributes is deprecated in favour of GetDefaultAttributeSet.
// Empty set seems reasonable. There is no default attribute set.
sendReply(connection, message, QVariant::fromValue(QSpiAttributeSet()));
- } else if (function == QLatin1String("GetNSelections")) {
+ } else if (function == "GetNSelections"_L1) {
sendReply(connection, message, interface->textInterface()->selectionCount());
- } else if (function == QLatin1String("GetOffsetAtPoint")) {
+ } else if (function == "GetOffsetAtPoint"_L1) {
qCDebug(lcAccessibilityAtspi) << message.signature();
Q_ASSERT(!message.signature().isEmpty());
QPoint point(message.arguments().at(0).toInt(), message.arguments().at(1).toInt());
uint coordType = message.arguments().at(2).toUInt();
- if (coordType == ATSPI_COORD_TYPE_WINDOW) {
- QWindow *win = interface->window();
- point -= QPoint(win->x(), win->y());
- }
- int offset = interface->textInterface()->offsetAtPoint(point);
+ if (!isValidCoordType(coordType))
+ return false;
+ QPoint screenPos = translateToScreenCoordinates(interface, point, coordType);
+ int offset = interface->textInterface()->offsetAtPoint(screenPos);
sendReply(connection, message, offset);
- } else if (function == QLatin1String("GetRangeExtents")) {
+ } else if (function == "GetRangeExtents"_L1) {
int startOffset = message.arguments().at(0).toInt();
int endOffset = message.arguments().at(1).toInt();
uint coordType = message.arguments().at(2).toUInt();
connection.send(message.createReply(getRangeExtents(interface, startOffset, endOffset, coordType)));
- } else if (function == QLatin1String("GetSelection")) {
+ } else if (function == "GetSelection"_L1) {
int selectionNum = message.arguments().at(0).toInt();
int start, end;
interface->textInterface()->selection(selectionNum, &start, &end);
@@ -1859,58 +2029,75 @@ bool AtSpiAdaptor::textInterface(QAccessibleInterface *interface, const QString
QVariantList sel;
sel << start << end;
connection.send(message.createReply(sel));
- } else if (function == QLatin1String("GetText")) {
+ } else if (function == "GetStringAtOffset"_L1) {
+ int offset = message.arguments().at(0).toInt();
+ uint granularity = message.arguments().at(1).toUInt();
+ if (!isValidAtspiTextGranularity(granularity))
+ return false;
+ int startOffset, endOffset;
+ QString text = interface->textInterface()->textAtOffset(offset, qAccessibleBoundaryTypeFromAtspiTextGranularity(granularity), &startOffset, &endOffset);
+ QVariantList ret;
+ ret << text << startOffset << endOffset;
+ connection.send(message.createReply(ret));
+ } else if (function == "GetText"_L1) {
int startOffset = message.arguments().at(0).toInt();
int endOffset = message.arguments().at(1).toInt();
if (endOffset == -1) // AT-SPI uses -1 to signal all characters
endOffset = interface->textInterface()->characterCount();
sendReply(connection, message, interface->textInterface()->text(startOffset, endOffset));
- } else if (function == QLatin1String("GetTextAfterOffset")) {
+ } else if (function == "GetTextAfterOffset"_L1) {
int offset = message.arguments().at(0).toInt();
int type = message.arguments().at(1).toUInt();
int startOffset, endOffset;
- QString text = interface->textInterface()->textAfterOffset(offset, qAccessibleBoundaryType(type), &startOffset, &endOffset);
+ QString text = interface->textInterface()->textAfterOffset(offset, qAccessibleBoundaryTypeFromAtspiBoundaryType(type), &startOffset, &endOffset);
QVariantList ret;
ret << text << startOffset << endOffset;
connection.send(message.createReply(ret));
- } else if (function == QLatin1String("GetTextAtOffset")) {
+ } else if (function == "GetTextAtOffset"_L1) {
int offset = message.arguments().at(0).toInt();
int type = message.arguments().at(1).toUInt();
int startOffset, endOffset;
- QString text = interface->textInterface()->textAtOffset(offset, qAccessibleBoundaryType(type), &startOffset, &endOffset);
+ QString text = interface->textInterface()->textAtOffset(offset, qAccessibleBoundaryTypeFromAtspiBoundaryType(type), &startOffset, &endOffset);
QVariantList ret;
ret << text << startOffset << endOffset;
connection.send(message.createReply(ret));
- } else if (function == QLatin1String("GetTextBeforeOffset")) {
+ } else if (function == "GetTextBeforeOffset"_L1) {
int offset = message.arguments().at(0).toInt();
int type = message.arguments().at(1).toUInt();
int startOffset, endOffset;
- QString text = interface->textInterface()->textBeforeOffset(offset, qAccessibleBoundaryType(type), &startOffset, &endOffset);
+ QString text = interface->textInterface()->textBeforeOffset(offset, qAccessibleBoundaryTypeFromAtspiBoundaryType(type), &startOffset, &endOffset);
QVariantList ret;
ret << text << startOffset << endOffset;
connection.send(message.createReply(ret));
- } else if (function == QLatin1String("RemoveSelection")) {
+ } else if (function == "RemoveSelection"_L1) {
int selectionNum = message.arguments().at(0).toInt();
interface->textInterface()->removeSelection(selectionNum);
sendReply(connection, message, true);
- } else if (function == QLatin1String("SetCaretOffset")) {
+ } else if (function == "SetCaretOffset"_L1) {
int offset = message.arguments().at(0).toInt();
interface->textInterface()->setCursorPosition(offset);
sendReply(connection, message, true);
- } else if (function == QLatin1String("SetSelection")) {
+ } else if (function == "ScrollSubstringTo"_L1) {
+ int startOffset = message.arguments().at(0).toInt();
+ int endOffset = message.arguments().at(1).toInt();
+ // ignore third parameter (scroll type), since QAccessibleTextInterface::scrollToSubstring doesn't have that
+ qCInfo(lcAccessibilityAtspi) << "AtSpiAdaptor::ScrollSubstringTo doesn'take take scroll type into account.";
+ interface->textInterface()->scrollToSubstring(startOffset, endOffset);
+ sendReply(connection, message, true);
+ } else if (function == "SetSelection"_L1) {
int selectionNum = message.arguments().at(0).toInt();
int startOffset = message.arguments().at(1).toInt();
int endOffset = message.arguments().at(2).toInt();
interface->textInterface()->setSelection(selectionNum, startOffset, endOffset);
sendReply(connection, message, true);
} else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::textInterface does not implement " << function << message.path();
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::textInterface does not implement" << function << message.path();
return false;
}
return true;
}
-QAccessible::TextBoundaryType AtSpiAdaptor::qAccessibleBoundaryType(int atspiTextBoundaryType) const
+QAccessible::TextBoundaryType AtSpiAdaptor::qAccessibleBoundaryTypeFromAtspiBoundaryType(int atspiTextBoundaryType)
{
switch (atspiTextBoundaryType) {
case ATSPI_TEXT_BOUNDARY_CHAR:
@@ -1929,6 +2116,38 @@ QAccessible::TextBoundaryType AtSpiAdaptor::qAccessibleBoundaryType(int atspiTex
return QAccessible::CharBoundary;
}
+bool AtSpiAdaptor::isValidAtspiTextGranularity(uint atspiTextGranularity)
+{
+ if (atspiTextGranularity == ATSPI_TEXT_GRANULARITY_CHAR
+ || atspiTextGranularity == ATSPI_TEXT_GRANULARITY_WORD
+ || atspiTextGranularity == ATSPI_TEXT_GRANULARITY_SENTENCE
+ || atspiTextGranularity == ATSPI_TEXT_GRANULARITY_LINE
+ || atspiTextGranularity == ATSPI_TEXT_GRANULARITY_PARAGRAPH)
+ return true;
+
+ qCWarning(lcAccessibilityAtspi) << "Unknown value" << atspiTextGranularity << "for AT-SPI text granularity type";
+ return false;
+}
+
+QAccessible::TextBoundaryType AtSpiAdaptor::qAccessibleBoundaryTypeFromAtspiTextGranularity(uint atspiTextGranularity)
+{
+ Q_ASSERT(isValidAtspiTextGranularity(atspiTextGranularity));
+
+ switch (atspiTextGranularity) {
+ case ATSPI_TEXT_GRANULARITY_CHAR:
+ return QAccessible::CharBoundary;
+ case ATSPI_TEXT_GRANULARITY_WORD:
+ return QAccessible::WordBoundary;
+ case ATSPI_TEXT_GRANULARITY_SENTENCE:
+ return QAccessible::SentenceBoundary;
+ case ATSPI_TEXT_GRANULARITY_LINE:
+ return QAccessible::LineBoundary;
+ case ATSPI_TEXT_GRANULARITY_PARAGRAPH:
+ return QAccessible::ParagraphBoundary;
+ }
+ return QAccessible::CharBoundary;
+}
+
namespace
{
struct AtSpiAttribute {
@@ -1941,13 +2160,13 @@ namespace
QString atspiColor(const QString &ia2Color)
{
// "rgb(%u,%u,%u)" -> "%u,%u,%u"
- return ia2Color.mid(4, ia2Color.length() - (4+1));
+ return ia2Color.mid(4, ia2Color.size() - (4+1)).replace(u"\\,"_s, u","_s);
}
QString atspiSize(const QString &ia2Size)
{
// "%fpt" -> "%f"
- return ia2Size.left(ia2Size.length() - 2);
+ return ia2Size.left(ia2Size.size() - 2);
}
AtSpiAttribute atspiTextAttribute(const QString &ia2Name, const QString &ia2Value)
@@ -1955,88 +2174,86 @@ namespace
QString name = ia2Name;
QString value = ia2Value;
- // IAccessible2: http://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2/textattributes
- // ATK attribute names: https://git.gnome.org/browse/orca/tree/src/orca/text_attribute_names.py
- // ATK attribute values: https://developer.gnome.org/atk/unstable/AtkText.html#AtkTextAttribute
+ // IAccessible2: https://wiki.linuxfoundation.org/accessibility/iaccessible2/textattributes
+ // ATK attribute names: https://gitlab.gnome.org/GNOME/orca/-/blob/master/src/orca/text_attribute_names.py
+ // ATK attribute values: https://gnome.pages.gitlab.gnome.org/atk/AtkText.html#AtkTextAttribute
// https://bugzilla.gnome.org/show_bug.cgi?id=744553 "ATK docs provide no guidance for allowed values of some text attributes"
// specifically for "weight", "invalid", "language" and value range for colors
- if (ia2Name == QLatin1String("background-color")) {
+ if (ia2Name == "background-color"_L1) {
name = QStringLiteral("bg-color");
value = atspiColor(value);
- } else if (ia2Name == QLatin1String("font-family")) {
+ } else if (ia2Name == "font-family"_L1) {
name = QStringLiteral("family-name");
- } else if (ia2Name == QLatin1String("color")) {
+ } else if (ia2Name == "color"_L1) {
name = QStringLiteral("fg-color");
value = atspiColor(value);
- } else if (ia2Name == QLatin1String("text-align")) {
+ } else if (ia2Name == "text-align"_L1) {
name = QStringLiteral("justification");
- if (value == QLatin1String("justify")) {
+ if (value == "justify"_L1) {
value = QStringLiteral("fill");
- } else {
- if (value != QLatin1String("left") &&
- value != QLatin1String("right") &&
- value != QLatin1String("center")
- ) {
- value = QString();
- qCDebug(lcAccessibilityAtspi) << "Unknown text-align attribute value \"" << value << "\" cannot be translated to AT-SPI.";
- }
+ } else if (value != "left"_L1 && value != "right"_L1 && value != "center"_L1) {
+ qCDebug(lcAccessibilityAtspi) << "Unknown text-align attribute value \""
+ << value << "\" cannot be translated to AT-SPI.";
+ value = QString();
}
- } else if (ia2Name == QLatin1String("font-size")) {
+ } else if (ia2Name == "font-size"_L1) {
name = QStringLiteral("size");
value = atspiSize(value);
- } else if (ia2Name == QLatin1String("font-style")) {
+ } else if (ia2Name == "font-style"_L1) {
name = QStringLiteral("style");
- if (value != QLatin1String("normal") &&
- value != QLatin1String("italic") &&
- value != QLatin1String("oblique")
- ) {
+ if (value != "normal"_L1 && value != "italic"_L1 && value != "oblique"_L1) {
+ qCDebug(lcAccessibilityAtspi) << "Unknown font-style attribute value \"" << value
+ << "\" cannot be translated to AT-SPI.";
value = QString();
- qCDebug(lcAccessibilityAtspi) << "Unknown font-style attribute value \"" << value << "\" cannot be translated to AT-SPI.";
}
- } else if (ia2Name == QLatin1String("text-underline-type")) {
+ } else if (ia2Name == "text-underline-type"_L1) {
name = QStringLiteral("underline");
- if (value != QLatin1String("none") &&
- value != QLatin1String("single") &&
- value != QLatin1String("double")
- ) {
+ if (value != "none"_L1 && value != "single"_L1 && value != "double"_L1) {
+ qCDebug(lcAccessibilityAtspi) << "Unknown text-underline-type attribute value \""
+ << value << "\" cannot be translated to AT-SPI.";
value = QString();
- qCDebug(lcAccessibilityAtspi) << "Unknown text-underline-type attribute value \"" << value << "\" cannot be translated to AT-SPI.";
}
- } else if (ia2Name == QLatin1String("font-weight")) {
+ } else if (ia2Name == "font-weight"_L1) {
name = QStringLiteral("weight");
- if (value == QLatin1String("normal"))
+ if (value == "normal"_L1)
// Orca seems to accept all IAccessible2 values except for "normal"
// (on which it produces traceback and fails to read any following text attributes),
// but that is the default value, so omit it anyway
value = QString();
- } else if (ia2Name == QLatin1String("text-position")) {
+ } else if (((ia2Name == "text-line-through-style"_L1 || ia2Name == "text-line-through-type"_L1) && (ia2Value != "none"_L1))
+ || (ia2Name == "text-line-through-text"_L1 && !ia2Value.isEmpty())) {
+ // if any of the above is set, set "strikethrough" to true, but don't explicitly set
+ // to false otherwise, since any of the others might still be set to indicate strikethrough
+ // and no strikethrough is assumed anyway when nothing is explicitly set
+ name = QStringLiteral("strikethrough");
+ value = QStringLiteral("true");
+ } else if (ia2Name == "text-position"_L1) {
name = QStringLiteral("vertical-align");
- if (value != QLatin1String("baseline") &&
- value != QLatin1String("super") &&
- value != QLatin1String("sub")
- ) {
+ if (value != "baseline"_L1 && value != "super"_L1 && value != "sub"_L1) {
+ qCDebug(lcAccessibilityAtspi) << "Unknown text-position attribute value \"" << value
+ << "\" cannot be translated to AT-SPI.";
value = QString();
- qCDebug(lcAccessibilityAtspi) << "Unknown text-position attribute value \"" << value << "\" cannot be translated to AT-SPI.";
}
- } else if (ia2Name == QLatin1String("writing-mode")) {
+ } else if (ia2Name == "writing-mode"_L1) {
name = QStringLiteral("direction");
- if (value == QLatin1String("lr"))
+ if (value == "lr"_L1)
value = QStringLiteral("ltr");
- else if (value == QLatin1String("rl"))
+ else if (value == "rl"_L1)
value = QStringLiteral("rtl");
- else if (value == QLatin1String("tb")) {
+ else if (value == "tb"_L1) {
// IAccessible2 docs refer to XSL, which specifies "tb" is shorthand for "tb-rl"; so at least give a hint about the horizontal direction (ATK does not support vertical direction in this attribute (yet))
value = QStringLiteral("rtl");
qCDebug(lcAccessibilityAtspi) << "writing-mode attribute value \"tb\" translated only w.r.t. horizontal direction; vertical direction ignored";
} else {
+ qCDebug(lcAccessibilityAtspi) << "Unknown writing-mode attribute value \"" << value
+ << "\" cannot be translated to AT-SPI.";
value = QString();
- qCDebug(lcAccessibilityAtspi) << "Unknown writing-mode attribute value \"" << value << "\" cannot be translated to AT-SPI.";
}
- } else if (ia2Name == QLatin1String("language")) {
+ } else if (ia2Name == "language"_L1) {
// OK - ATK has no docs on the format of the value, IAccessible2 has reasonable format - leave it at that now
- } else if (ia2Name == QLatin1String("invalid")) {
+ } else if (ia2Name == "invalid"_L1) {
// OK - ATK docs are vague but suggest they support the same range of values as IAccessible2
} else {
// attribute we know nothing about
@@ -2057,13 +2274,15 @@ QVariantList AtSpiAdaptor::getAttributes(QAccessibleInterface *interface, int of
int endOffset;
QString joined = interface->textInterface()->attributes(offset, &startOffset, &endOffset);
- const QStringList attributes = joined.split (QLatin1Char(';'), Qt::SkipEmptyParts, Qt::CaseSensitive);
+ const QStringList attributes = joined.split(u';', Qt::SkipEmptyParts, Qt::CaseSensitive);
for (const QString &attr : attributes) {
- QStringList items;
- items = attr.split(QLatin1Char(':'), Qt::SkipEmptyParts, Qt::CaseSensitive);
- AtSpiAttribute attribute = atspiTextAttribute(items[0], items[1]);
- if (!attribute.isNull())
- set[attribute.name] = attribute.value;
+ QStringList items = attr.split(u':', Qt::SkipEmptyParts, Qt::CaseSensitive);
+ if (items.count() == 2)
+ {
+ AtSpiAttribute attribute = atspiTextAttribute(items[0], items[1]);
+ if (!attribute.isNull())
+ set[attribute.name] = attribute.value;
+ }
}
QVariantList list;
@@ -2072,37 +2291,29 @@ QVariantList AtSpiAdaptor::getAttributes(QAccessibleInterface *interface, int of
return list;
}
-QVariantList AtSpiAdaptor::getAttributeValue(QAccessibleInterface *interface, int offset, const QString &attributeName) const
+QString AtSpiAdaptor::getAttributeValue(QAccessibleInterface *interface, int offset, const QString &attributeName) const
{
- QString mapped;
QString joined;
QSpiAttributeSet map;
int startOffset;
int endOffset;
joined = interface->textInterface()->attributes(offset, &startOffset, &endOffset);
- const QStringList attributes = joined.split (QLatin1Char(';'), Qt::SkipEmptyParts, Qt::CaseSensitive);
+ const QStringList attributes = joined.split (u';', Qt::SkipEmptyParts, Qt::CaseSensitive);
for (const QString& attr : attributes) {
QStringList items;
- items = attr.split(QLatin1Char(':'), Qt::SkipEmptyParts, Qt::CaseSensitive);
+ items = attr.split(u':', Qt::SkipEmptyParts, Qt::CaseSensitive);
AtSpiAttribute attribute = atspiTextAttribute(items[0], items[1]);
if (!attribute.isNull())
map[attribute.name] = attribute.value;
}
- mapped = map[attributeName];
- const bool defined = !mapped.isEmpty();
- QVariantList list;
- list << mapped << startOffset << endOffset << defined;
- return list;
+ return map[attributeName];
}
QList<QVariant> AtSpiAdaptor::getCharacterExtents(QAccessibleInterface *interface, int offset, uint coordType) const
{
QRect rect = interface->textInterface()->characterRect(offset);
-
- if (coordType == ATSPI_COORD_TYPE_WINDOW)
- rect = translateRectToWindowCoordinates(interface, rect);
-
+ rect = translateFromScreenCoordinates(interface, rect, coordType);
return QList<QVariant>() << rect.x() << rect.y() << rect.width() << rect.height();
}
@@ -2120,22 +2331,52 @@ QList<QVariant> AtSpiAdaptor::getRangeExtents(QAccessibleInterface *interface,
for (int i=startOffset + 1; i <= endOffset; i++)
rect = rect | textInterface->characterRect(i);
- // relative to window
- if (coordType == ATSPI_COORD_TYPE_WINDOW)
- rect = translateRectToWindowCoordinates(interface, rect);
-
+ rect = translateFromScreenCoordinates(interface, rect, coordType);
return QList<QVariant>() << rect.x() << rect.y() << rect.width() << rect.height();
}
-QRect AtSpiAdaptor::translateRectToWindowCoordinates(QAccessibleInterface *interface, const QRect &rect)
+bool AtSpiAdaptor::isValidCoordType(uint coordType)
{
- QAccessibleInterface * window = getWindow(interface);
- if (window)
- return rect.translated(-window->rect().x(), -window->rect().y());
+ if (coordType == ATSPI_COORD_TYPE_SCREEN || coordType == ATSPI_COORD_TYPE_WINDOW || coordType == ATSPI_COORD_TYPE_PARENT)
+ return true;
+
+ qCWarning(lcAccessibilityAtspi) << "Unknown value" << coordType << "for AT-SPI coord type";
+ return false;
+}
+
+QRect AtSpiAdaptor::translateFromScreenCoordinates(QAccessibleInterface *interface, const QRect &screenRect, uint targetCoordType)
+{
+ Q_ASSERT(isValidCoordType(targetCoordType));
+
+ QAccessibleInterface *upper = nullptr;
+ if (targetCoordType == ATSPI_COORD_TYPE_WINDOW)
+ upper = getWindow(interface);
+ else if (targetCoordType == ATSPI_COORD_TYPE_PARENT)
+ upper = interface->parent();
+
+ QRect rect = screenRect;
+ if (upper)
+ rect.translate(-upper->rect().x(), -upper->rect().y());
return rect;
}
+QPoint AtSpiAdaptor::translateToScreenCoordinates(QAccessibleInterface *interface, const QPoint &pos, uint fromCoordType)
+{
+ Q_ASSERT(isValidCoordType(fromCoordType));
+
+ QAccessibleInterface *upper = nullptr;
+ if (fromCoordType == ATSPI_COORD_TYPE_WINDOW)
+ upper = getWindow(interface);
+ else if (fromCoordType == ATSPI_COORD_TYPE_PARENT)
+ upper = interface->parent();
+
+ QPoint screenPos = pos;
+ if (upper)
+ screenPos += upper->rect().topLeft();
+
+ return screenPos;
+}
// Editable Text interface
static QString textForRange(QAccessibleInterface *accessible, int startOffset, int endOffset)
@@ -2147,7 +2388,7 @@ static QString textForRange(QAccessibleInterface *accessible, int startOffset, i
}
QString txt = accessible->text(QAccessible::Value);
if (endOffset == -1)
- endOffset = txt.length();
+ endOffset = txt.size();
return txt.mid(startOffset, endOffset - startOffset);
}
@@ -2155,7 +2396,7 @@ static void replaceTextFallback(QAccessibleInterface *accessible, long startOffs
{
QString t = textForRange(accessible, 0, -1);
if (endOffset == -1)
- endOffset = t.length();
+ endOffset = t.size();
if (endOffset - startOffset == 0)
t.insert(startOffset, txt);
else
@@ -2165,7 +2406,7 @@ static void replaceTextFallback(QAccessibleInterface *accessible, long startOffs
bool AtSpiAdaptor::editableTextInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
{
- if (function == QLatin1String("CopyText")) {
+ if (function == "CopyText"_L1) {
#ifndef QT_NO_CLIPBOARD
int startOffset = message.arguments().at(0).toInt();
int endOffset = message.arguments().at(1).toInt();
@@ -2173,7 +2414,7 @@ bool AtSpiAdaptor::editableTextInterface(QAccessibleInterface *interface, const
QGuiApplication::clipboard()->setText(t);
#endif
connection.send(message.createReply(true));
- } else if (function == QLatin1String("CutText")) {
+ } else if (function == "CutText"_L1) {
#ifndef QT_NO_CLIPBOARD
int startOffset = message.arguments().at(0).toInt();
int endOffset = message.arguments().at(1).toInt();
@@ -2185,7 +2426,7 @@ bool AtSpiAdaptor::editableTextInterface(QAccessibleInterface *interface, const
QGuiApplication::clipboard()->setText(t);
#endif
connection.send(message.createReply(true));
- } else if (function == QLatin1String("DeleteText")) {
+ } else if (function == "DeleteText"_L1) {
int startOffset = message.arguments().at(0).toInt();
int endOffset = message.arguments().at(1).toInt();
if (QAccessibleEditableTextInterface *editableTextIface = interface->editableTextInterface())
@@ -2193,7 +2434,7 @@ bool AtSpiAdaptor::editableTextInterface(QAccessibleInterface *interface, const
else
replaceTextFallback(interface, startOffset, endOffset, QString());
connection.send(message.createReply(true));
- } else if (function == QLatin1String("InsertText")) {
+ } else if (function == "InsertText"_L1) {
int position = message.arguments().at(0).toInt();
QString text = message.arguments().at(1).toString();
int length = message.arguments().at(2).toInt();
@@ -2203,7 +2444,7 @@ bool AtSpiAdaptor::editableTextInterface(QAccessibleInterface *interface, const
else
replaceTextFallback(interface, position, position, text);
connection.send(message.createReply(true));
- } else if (function == QLatin1String("PasteText")) {
+ } else if (function == "PasteText"_L1) {
#ifndef QT_NO_CLIPBOARD
int position = message.arguments().at(0).toInt();
const QString txt = QGuiApplication::clipboard()->text();
@@ -2213,17 +2454,17 @@ bool AtSpiAdaptor::editableTextInterface(QAccessibleInterface *interface, const
replaceTextFallback(interface, position, position, txt);
#endif
connection.send(message.createReply(true));
- } else if (function == QLatin1String("SetTextContents")) {
+ } else if (function == "SetTextContents"_L1) {
QString newContents = message.arguments().at(0).toString();
if (QAccessibleEditableTextInterface *editableTextIface = interface->editableTextInterface())
editableTextIface->replaceText(0, interface->textInterface()->characterCount(), newContents);
else
replaceTextFallback(interface, 0, -1, newContents);
connection.send(message.createReply(true));
- } else if (function == QLatin1String("")) {
+ } else if (function.isEmpty()) {
connection.send(message.createReply());
} else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::editableTextInterface does not implement " << function << message.path();
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::editableTextInterface does not implement" << function << message.path();
return false;
}
return true;
@@ -2236,29 +2477,29 @@ bool AtSpiAdaptor::valueInterface(QAccessibleInterface *interface, const QString
if (!valueIface)
return false;
- if (function == QLatin1String("SetCurrentValue")) {
+ if (function == "SetCurrentValue"_L1) {
QDBusVariant v = qvariant_cast<QDBusVariant>(message.arguments().at(2));
double value = v.variant().toDouble();
//Temporary fix
//See https://bugzilla.gnome.org/show_bug.cgi?id=652596
valueIface->setCurrentValue(value);
- connection.send(message.createReply()); // FIXME is the reply needed?
+ connection.send(message.createReply());
} else {
QVariant value;
- if (function == QLatin1String("GetCurrentValue"))
+ if (function == "GetCurrentValue"_L1)
value = valueIface->currentValue();
- else if (function == QLatin1String("GetMaximumValue"))
+ else if (function == "GetMaximumValue"_L1)
value = valueIface->maximumValue();
- else if (function == QLatin1String("GetMinimumIncrement"))
+ else if (function == "GetMinimumIncrement"_L1)
value = valueIface->minimumStepSize();
- else if (function == QLatin1String("GetMinimumValue"))
+ else if (function == "GetMinimumValue"_L1)
value = valueIface->minimumValue();
else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::valueInterface does not implement " << function << message.path();
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::valueInterface does not implement" << function << message.path();
return false;
}
if (!value.canConvert<double>()) {
- qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::valueInterface: Could not convert to double: " << function;
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::valueInterface: Could not convert to double:" << function;
}
// explicitly convert to dbus-variant containing one double since atspi expects that
@@ -2269,49 +2510,104 @@ bool AtSpiAdaptor::valueInterface(QAccessibleInterface *interface, const QString
return true;
}
+// Selection interface
+bool AtSpiAdaptor::selectionInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
+{
+ QAccessibleSelectionInterface* selectionInterface = interface->selectionInterface();
+ if (!selectionInterface) {
+ qCWarning(lcAccessibilityAtspi) << "Could not find selection interface for: " << message.path() << interface;
+ return false;
+ }
+
+ if (function == "ClearSelection"_L1 ) {
+ connection.send(message.createReply(QVariant::fromValue((selectionInterface->clear()))));
+ } else if (function == "DeselectChild"_L1 ) {
+ int childIndex = message.arguments().at(0).toInt();
+ bool ret = false;
+ QAccessibleInterface *child = interface->child(childIndex);
+ if (child)
+ ret = selectionInterface->unselect(child);
+ connection.send(message.createReply(QVariant::fromValue(ret)));
+ } else if (function == "DeselectSelectedChild"_L1 ) {
+ int selectionIndex = message.arguments().at(0).toInt();
+ bool ret = false;
+ QAccessibleInterface *selectedChild = selectionInterface->selectedItem(selectionIndex);
+ if (selectedChild)
+ ret = selectionInterface->unselect(selectedChild);
+ connection.send(message.createReply(QVariant::fromValue(ret)));
+ } else if (function == "GetNSelectedChildren"_L1) {
+ connection.send(message.createReply(QVariant::fromValue(QDBusVariant(
+ QVariant::fromValue(selectionInterface->selectedItemCount())))));
+ } else if (function == "GetSelectedChild"_L1) {
+ int selectionIndex = message.arguments().at(0).toInt();
+ QSpiObjectReference ref(connection, QDBusObjectPath(pathForInterface(selectionInterface->selectedItem(selectionIndex))));
+ connection.send(message.createReply(QVariant::fromValue(ref)));
+ } else if (function == "IsChildSelected"_L1 ) {
+ int childIndex = message.arguments().at(0).toInt();
+ bool ret = false;
+ QAccessibleInterface *child = interface->child(childIndex);
+ if (child)
+ ret = selectionInterface->isSelected(child);
+ connection.send(message.createReply(QVariant::fromValue(ret)));
+ } else if (function == "SelectAll"_L1 ) {
+ connection.send(message.createReply(QVariant::fromValue(selectionInterface->selectAll())));
+ } else if (function == "SelectChild"_L1 ) {
+ int childIndex = message.arguments().at(0).toInt();
+ bool ret = false;
+ QAccessibleInterface *child = interface->child(childIndex);
+ if (child)
+ ret = selectionInterface->select(child);
+ connection.send(message.createReply(QVariant::fromValue(ret)));
+ } else {
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::selectionInterface does not implement " << function << message.path();
+ return false;
+ }
+
+ return true;
+}
+
+
// Table interface
bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
{
if (!(interface->tableInterface() || interface->tableCellInterface())) {
- qCDebug(lcAccessibilityAtspi) << "WARNING Qt AtSpiAdaptor: Could not find table interface for: " << message.path() << interface;
+ qCWarning(lcAccessibilityAtspi) << "Qt AtSpiAdaptor: Could not find table interface for:" << message.path() << interface;
return false;
}
- if (0) {
- // properties
- } else if (function == QLatin1String("GetCaption")) {
+ if (function == "GetCaption"_L1) {
QAccessibleInterface * captionInterface= interface->tableInterface()->caption();
if (captionInterface) {
QSpiObjectReference ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(captionInterface)));
- sendReply(connection, message, QVariant::fromValue(ref));
+ sendReply(connection, message, QVariant::fromValue(QDBusVariant(QVariant::fromValue(ref))));
} else {
- sendReply(connection, message, QVariant::fromValue(
- QSpiObjectReference(connection, QDBusObjectPath(ATSPI_DBUS_PATH_NULL))));
+ sendReply(connection, message, QVariant::fromValue(QDBusVariant(QVariant::fromValue(
+ QSpiObjectReference(connection, QDBusObjectPath(ATSPI_DBUS_PATH_NULL))))));
}
- } else if (function == QLatin1String("GetNColumns")) {
+ } else if (function == "GetNColumns"_L1) {
connection.send(message.createReply(QVariant::fromValue(QDBusVariant(
QVariant::fromValue(interface->tableInterface()->columnCount())))));
- } else if (function == QLatin1String("GetNRows")) {
+ } else if (function == "GetNRows"_L1) {
connection.send(message.createReply(QVariant::fromValue(QDBusVariant(
QVariant::fromValue(interface->tableInterface()->rowCount())))));
- } else if (function == QLatin1String("GetNSelectedColumns")) {
+ } else if (function == "GetNSelectedColumns"_L1) {
connection.send(message.createReply(QVariant::fromValue(QDBusVariant(
QVariant::fromValue(interface->tableInterface()->selectedColumnCount())))));
- } else if (function == QLatin1String("GetNSelectedRows")) {
+ } else if (function == "GetNSelectedRows"_L1) {
connection.send(message.createReply(QVariant::fromValue(QDBusVariant(
QVariant::fromValue(interface->tableInterface()->selectedRowCount())))));
- } else if (function == QLatin1String("GetSummary")) {
+ } else if (function == "GetSummary"_L1) {
QAccessibleInterface *summary = interface->tableInterface() ? interface->tableInterface()->summary() : nullptr;
QSpiObjectReference ref(connection, QDBusObjectPath(pathForInterface(summary)));
connection.send(message.createReply(QVariant::fromValue(QDBusVariant(QVariant::fromValue(ref)))));
- } else if (function == QLatin1String("GetAccessibleAt")) {
+ } else if (function == "GetAccessibleAt"_L1) {
int row = message.arguments().at(0).toInt();
int column = message.arguments().at(1).toInt();
if ((row < 0) ||
(column < 0) ||
(row >= interface->tableInterface()->rowCount()) ||
(column >= interface->tableInterface()->columnCount())) {
- qCDebug(lcAccessibilityAtspi) << "WARNING: invalid index for tableInterface GetAccessibleAt (" << row << ", " << column << ')';
+ qCWarning(lcAccessibilityAtspi) << "Invalid index for tableInterface GetAccessibleAt (" << row << "," << column << ')';
return false;
}
@@ -2320,37 +2616,37 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
if (cell) {
ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(cell)));
} else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: no cell interface returned for " << interface->object() << row << column;
+ qCWarning(lcAccessibilityAtspi) << "No cell interface returned for" << interface->object() << row << column;
ref = QSpiObjectReference();
}
connection.send(message.createReply(QVariant::fromValue(ref)));
- } else if (function == QLatin1String("GetIndexAt")) {
+ } else if (function == "GetIndexAt"_L1) {
int row = message.arguments().at(0).toInt();
int column = message.arguments().at(1).toInt();
QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, column);
if (!cell) {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::GetIndexAt(" << row << ',' << column << ") did not find a cell. " << interface;
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::GetIndexAt(" << row << ',' << column << ") did not find a cell." << interface;
return false;
}
int index = interface->indexOfChild(cell);
qCDebug(lcAccessibilityAtspi) << "QSpiAdaptor::GetIndexAt row:" << row << " col:" << column << " logical index:" << index;
Q_ASSERT(index > 0);
connection.send(message.createReply(index));
- } else if ((function == QLatin1String("GetColumnAtIndex")) || (function == QLatin1String("GetRowAtIndex"))) {
+ } else if ((function == "GetColumnAtIndex"_L1) || (function == "GetRowAtIndex"_L1)) {
int index = message.arguments().at(0).toInt();
int ret = -1;
if (index >= 0) {
QAccessibleInterface * cell = interface->child(index);
if (cell) {
- if (function == QLatin1String("GetColumnAtIndex")) {
+ if (function == "GetColumnAtIndex"_L1) {
if (cell->role() == QAccessible::ColumnHeader) {
ret = index;
} else if (cell->role() == QAccessible::RowHeader) {
ret = -1;
} else {
if (!cell->tableCellInterface()) {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::" << function << " No table cell interface: " << cell;
+ qCWarning(lcAccessibilityAtspi).nospace() << "AtSpiAdaptor::" << function << " No table cell interface: " << cell;
return false;
}
ret = cell->tableCellInterface()->columnIndex();
@@ -2362,29 +2658,29 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
ret = index % interface->tableInterface()->columnCount();
} else {
if (!cell->tableCellInterface()) {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::" << function << " No table cell interface: " << cell;
+ qCWarning(lcAccessibilityAtspi).nospace() << "AtSpiAdaptor::" << function << " No table cell interface: " << cell;
return false;
}
ret = cell->tableCellInterface()->rowIndex();
}
}
} else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::" << function << " No cell at index: " << index << interface;
+ qCWarning(lcAccessibilityAtspi).nospace() << "AtSpiAdaptor::" << function << " No cell at index: " << index << " " << interface;
return false;
}
}
connection.send(message.createReply(ret));
- } else if (function == QLatin1String("GetColumnDescription")) {
+ } else if (function == "GetColumnDescription"_L1) {
int column = message.arguments().at(0).toInt();
connection.send(message.createReply(interface->tableInterface()->columnDescription(column)));
- } else if (function == QLatin1String("GetRowDescription")) {
+ } else if (function == "GetRowDescription"_L1) {
int row = message.arguments().at(0).toInt();
connection.send(message.createReply(interface->tableInterface()->rowDescription(row)));
- } else if (function == QLatin1String("GetRowColumnExtentsAtIndex")) {
+ } else if (function == "GetRowColumnExtentsAtIndex"_L1) {
int index = message.arguments().at(0).toInt();
bool success = false;
@@ -2398,31 +2694,42 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
if (cols > 0) {
row = index / cols;
col = index % cols;
- QAccessibleTableCellInterface *cell = interface->tableInterface()->cellAt(row, col)->tableCellInterface();
- if (cell) {
- row = cell->rowIndex();
- col = cell->columnIndex();
- rowExtents = cell->rowExtent();
- colExtents = cell->columnExtent();
- isSelected = cell->isSelected();
- success = true;
+ if (QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, col)) {
+ if (QAccessibleTableCellInterface *cellIface = cell->tableCellInterface()) {
+ row = cellIface->rowIndex();
+ col = cellIface->columnIndex();
+ rowExtents = cellIface->rowExtent();
+ colExtents = cellIface->columnExtent();
+ isSelected = cellIface->isSelected();
+ success = true;
+ }
}
}
QVariantList list;
list << success << row << col << rowExtents << colExtents << isSelected;
connection.send(message.createReply(list));
- } else if (function == QLatin1String("GetColumnExtentAt")) {
+ } else if (function == "GetColumnExtentAt"_L1) {
int row = message.arguments().at(0).toInt();
int column = message.arguments().at(1).toInt();
- connection.send(message.createReply(interface->tableInterface()->cellAt(row, column)->tableCellInterface()->columnExtent()));
+ int columnExtent = 0;
+ if (QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, column)) {
+ if (QAccessibleTableCellInterface *cellIface = cell->tableCellInterface())
+ columnExtent = cellIface->columnExtent();
+ }
+ connection.send(message.createReply(columnExtent));
- } else if (function == QLatin1String("GetRowExtentAt")) {
+ } else if (function == "GetRowExtentAt"_L1) {
int row = message.arguments().at(0).toInt();
int column = message.arguments().at(1).toInt();
- connection.send(message.createReply(interface->tableInterface()->cellAt(row, column)->tableCellInterface()->rowExtent()));
+ int rowExtent = 0;
+ if (QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, column)) {
+ if (QAccessibleTableCellInterface *cellIface = cell->tableCellInterface())
+ rowExtent = cellIface->rowExtent();
+ }
+ connection.send(message.createReply(rowExtent));
- } else if (function == QLatin1String("GetColumnHeader")) {
+ } else if (function == "GetColumnHeader"_L1) {
int column = message.arguments().at(0).toInt();
QSpiObjectReference ref;
@@ -2435,51 +2742,115 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
}
connection.send(message.createReply(QVariant::fromValue(ref)));
- } else if (function == QLatin1String("GetRowHeader")) {
+ } else if (function == "GetRowHeader"_L1) {
int row = message.arguments().at(0).toInt();
QSpiObjectReference ref;
- QAccessibleTableCellInterface *cell = interface->tableInterface()->cellAt(row, 0)->tableCellInterface();
- if (cell) {
- QList<QAccessibleInterface*> header = cell->rowHeaderCells();
+ QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, 0);
+ if (cell && cell->tableCellInterface()) {
+ QList<QAccessibleInterface*> header = cell->tableCellInterface()->rowHeaderCells();
if (header.size() > 0) {
ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(header.takeAt(0))));
}
}
connection.send(message.createReply(QVariant::fromValue(ref)));
- } else if (function == QLatin1String("GetSelectedColumns")) {
+ } else if (function == "GetSelectedColumns"_L1) {
connection.send(message.createReply(QVariant::fromValue(interface->tableInterface()->selectedColumns())));
- } else if (function == QLatin1String("GetSelectedRows")) {
+ } else if (function == "GetSelectedRows"_L1) {
connection.send(message.createReply(QVariant::fromValue(interface->tableInterface()->selectedRows())));
- } else if (function == QLatin1String("IsColumnSelected")) {
+ } else if (function == "IsColumnSelected"_L1) {
int column = message.arguments().at(0).toInt();
connection.send(message.createReply(interface->tableInterface()->isColumnSelected(column)));
- } else if (function == QLatin1String("IsRowSelected")) {
+ } else if (function == "IsRowSelected"_L1) {
int row = message.arguments().at(0).toInt();
connection.send(message.createReply(interface->tableInterface()->isRowSelected(row)));
- } else if (function == QLatin1String("IsSelected")) {
+ } else if (function == "IsSelected"_L1) {
int row = message.arguments().at(0).toInt();
int column = message.arguments().at(1).toInt();
- QAccessibleTableCellInterface* cell = interface->tableInterface()->cellAt(row, column)->tableCellInterface();
- connection.send(message.createReply(cell->isSelected()));
- } else if (function == QLatin1String("AddColumnSelection")) {
+ bool selected = false;
+ if (QAccessibleInterface* cell = interface->tableInterface()->cellAt(row, column)) {
+ if (QAccessibleTableCellInterface *cellIface = cell->tableCellInterface())
+ selected = cellIface->isSelected();
+ }
+ connection.send(message.createReply(selected));
+ } else if (function == "AddColumnSelection"_L1) {
int column = message.arguments().at(0).toInt();
connection.send(message.createReply(interface->tableInterface()->selectColumn(column)));
- } else if (function == QLatin1String("AddRowSelection")) {
+ } else if (function == "AddRowSelection"_L1) {
int row = message.arguments().at(0).toInt();
connection.send(message.createReply(interface->tableInterface()->selectRow(row)));
- } else if (function == QLatin1String("RemoveColumnSelection")) {
+ } else if (function == "RemoveColumnSelection"_L1) {
int column = message.arguments().at(0).toInt();
connection.send(message.createReply(interface->tableInterface()->unselectColumn(column)));
- } else if (function == QLatin1String("RemoveRowSelection")) {
+ } else if (function == "RemoveRowSelection"_L1) {
int row = message.arguments().at(0).toInt();
connection.send(message.createReply(interface->tableInterface()->unselectRow(row)));
} else {
- qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::tableInterface does not implement " << function << message.path();
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::tableInterface does not implement" << function << message.path();
return false;
}
return true;
}
+// Table cell interface
+bool AtSpiAdaptor::tableCellInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
+{
+ QAccessibleTableCellInterface* cellInterface = interface->tableCellInterface();
+ if (!cellInterface) {
+ qCWarning(lcAccessibilityAtspi) << "Could not find table cell interface for: " << message.path() << interface;
+ return false;
+ }
+
+ if (function == "GetColumnHeaderCells"_L1) {
+ QSpiObjectReferenceArray headerCells;
+ const auto headerCellInterfaces = cellInterface->columnHeaderCells();
+ headerCells.reserve(headerCellInterfaces.size());
+ for (QAccessibleInterface *cell : headerCellInterfaces) {
+ const QString childPath = pathForInterface(cell);
+ const QSpiObjectReference ref(connection, QDBusObjectPath(childPath));
+ headerCells << ref;
+ }
+ connection.send(message.createReply(QVariant::fromValue(headerCells)));
+ } else if (function == "GetColumnSpan"_L1) {
+ connection.send(message.createReply(QVariant::fromValue(QDBusVariant(
+ QVariant::fromValue(cellInterface->columnExtent())))));
+ } else if (function == "GetPosition"_L1) {
+ const int row = cellInterface->rowIndex();
+ const int column = cellInterface->columnIndex();
+ connection.send(message.createReply(QVariant::fromValue(QDBusVariant(
+ QVariant::fromValue(QPoint(row, column))))));
+ } else if (function == "GetRowHeaderCells"_L1) {
+ QSpiObjectReferenceArray headerCells;
+ const auto headerCellInterfaces = cellInterface->rowHeaderCells();
+ headerCells.reserve(headerCellInterfaces.size());
+ for (QAccessibleInterface *cell : headerCellInterfaces) {
+ const QString childPath = pathForInterface(cell);
+ const QSpiObjectReference ref(connection, QDBusObjectPath(childPath));
+ headerCells << ref;
+ }
+ connection.send(message.createReply(QVariant::fromValue(headerCells)));
+ } else if (function == "GetRowSpan"_L1) {
+ connection.send(message.createReply(QVariant::fromValue(QDBusVariant(
+ QVariant::fromValue(cellInterface->rowExtent())))));
+ } else if (function == "GetRowColumnSpan"_L1) {
+ QVariantList list;
+ list << cellInterface->rowIndex() << cellInterface->columnIndex() << cellInterface->rowExtent() << cellInterface->columnExtent();
+ connection.send(message.createReply(list));
+ } else if (function == "GetTable"_L1) {
+ QSpiObjectReference ref;
+ QAccessibleInterface* table = cellInterface->table();
+ if (table && table->tableInterface())
+ ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(table)));
+ connection.send(message.createReply(QVariant::fromValue(QDBusVariant(QVariant::fromValue(ref)))));
+ } else {
+ qCWarning(lcAccessibilityAtspi) << "AtSpiAdaptor::tableCellInterface does not implement" << function << message.path();
+ return false;
+ }
+
+ return true;
+}
+
QT_END_NAMESPACE
-#endif //QT_NO_ACCESSIBILITY
+
+#include "moc_atspiadaptor_p.cpp"
+#endif // QT_CONFIG(accessibility)
diff --git a/src/gui/accessible/linux/atspiadaptor_p.h b/src/gui/accessible/linux/atspiadaptor_p.h
index b9f4011695..3a890f3d7d 100644
--- a/src/gui/accessible/linux/atspiadaptor_p.h
+++ b/src/gui/accessible/linux/atspiadaptor_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef ATSPIADAPTOR_H
@@ -55,7 +19,6 @@
#include <atspi/atspi-constants.h>
#include <QtGui/private/qtguiglobal_p.h>
-#include <QtCore/qsharedpointer.h>
#include <QtDBus/qdbusvirtualobject.h>
#include <QtGui/qaccessible.h>
@@ -67,7 +30,6 @@ QT_REQUIRE_CONFIG(accessibility);
QT_BEGIN_NAMESPACE
class QAccessibleInterface;
-class QSpiAccessibleInterface;
class QSpiApplicationAdaptor;
@@ -84,8 +46,6 @@ public:
bool handleMessage(const QDBusMessage &message, const QDBusConnection &connection) override;
void notify(QAccessibleEvent *event);
- void init();
- void checkInitializedAndEnabled();
public Q_SLOTS:
void eventListenerRegistered(const QString &bus, const QString &path);
void eventListenerDeregistered(const QString &bus, const QString &path);
@@ -113,7 +73,9 @@ private:
bool textInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
bool editableTextInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
bool valueInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
+ bool selectionInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
bool tableInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
+ bool tableCellInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
void sendReply(const QDBusConnection &connection, const QDBusMessage &message, const QVariant &argument) const;
@@ -130,17 +92,21 @@ private:
// component helper functions
static QRect getExtents(QAccessibleInterface *interface, uint coordType);
- static QRect translateRectToWindowCoordinates(QAccessibleInterface *interface, const QRect &rect);
+ static bool isValidCoordType(uint coordType);
+ static QRect translateFromScreenCoordinates(QAccessibleInterface *interface, const QRect &rect, uint targetCoordType);
+ static QPoint translateToScreenCoordinates(QAccessibleInterface *interface, const QPoint &pos, uint fromCoordType);
// action helper functions
QSpiActionArray getActions(QAccessibleInterface *interface) const;
// text helper functions
QVariantList getAttributes(QAccessibleInterface *, int offset, bool includeDefaults) const;
- QVariantList getAttributeValue(QAccessibleInterface *, int offset, const QString &attributeName) const;
+ QString getAttributeValue(QAccessibleInterface *, int offset, const QString &attributeName) const;
QList<QVariant> getCharacterExtents(QAccessibleInterface *, int offset, uint coordType) const;
QList<QVariant> getRangeExtents(QAccessibleInterface *, int startOffset, int endOffset, uint coordType) const;
- QAccessible::TextBoundaryType qAccessibleBoundaryType(int atspiTextBoundaryType) const;
+ static QAccessible::TextBoundaryType qAccessibleBoundaryTypeFromAtspiBoundaryType(int atspiTextBoundaryType);
+ static bool isValidAtspiTextGranularity(uint coordType);
+ static QAccessible::TextBoundaryType qAccessibleBoundaryTypeFromAtspiTextGranularity(uint atspiTextGranularity);
static bool inheritsQAction(QObject *object);
// private vars
diff --git a/src/gui/accessible/linux/dbusconnection.cpp b/src/gui/accessible/linux/dbusconnection.cpp
index 45ddc8e496..10bd10927e 100644
--- a/src/gui/accessible/linux/dbusconnection.cpp
+++ b/src/gui/accessible/linux/dbusconnection.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
@@ -53,11 +17,13 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/* note: do not change these to QStringLiteral;
we are unloaded before QtDBus is done using the strings.
*/
-#define A11Y_SERVICE QLatin1String("org.a11y.Bus")
-#define A11Y_PATH QLatin1String("/org/a11y/bus")
+#define A11Y_SERVICE "org.a11y.Bus"_L1
+#define A11Y_PATH "/org/a11y/bus"_L1
/*!
\class DBusConnection
@@ -69,6 +35,14 @@ QT_BEGIN_NAMESPACE
DBusConnection::DBusConnection(QObject *parent)
: QObject(parent), m_a11yConnection(QString()), m_enabled(false)
{
+ // If the bus is explicitly set via env var it overrides everything else.
+ QByteArray addressEnv = qgetenv("AT_SPI_BUS_ADDRESS");
+ if (!addressEnv.isEmpty()) {
+ m_enabled = true;
+ connectA11yBus(QString::fromLocal8Bit(addressEnv));
+ return;
+ }
+
// Start monitoring if "org.a11y.Bus" is registered as DBus service.
QDBusConnection c = QDBusConnection::sessionBus();
if (!c.isConnected()) {
@@ -82,11 +56,13 @@ DBusConnection::DBusConnection(QObject *parent)
if (c.interface()->isServiceRegistered(A11Y_SERVICE))
serviceRegistered();
- // In addition try if there is an xatom exposing the bus address, this allows applications run as root to work
- QString address = getAddressFromXCB();
- if (!address.isEmpty()) {
- m_enabled = true;
- connectA11yBus(address);
+ if (QGuiApplication::platformName().startsWith("xcb"_L1)) {
+ // In addition try if there is an xatom exposing the bus address, this allows applications run as root to work
+ QString address = getAddressFromXCB();
+ if (!address.isEmpty()) {
+ m_enabled = true;
+ connectA11yBus(address);
+ }
}
}
@@ -128,9 +104,8 @@ void DBusConnection::serviceRegistered()
emit enabledChanged(m_enabled);
} else {
QDBusConnection c = QDBusConnection::sessionBus();
- QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String("org.a11y.Bus"),
- QLatin1String("/org/a11y/bus"),
- QLatin1String("org.a11y.Bus"), QLatin1String("GetAddress"));
+ QDBusMessage m = QDBusMessage::createMethodCall(A11Y_SERVICE, A11Y_PATH, A11Y_SERVICE,
+ "GetAddress"_L1);
c.callWithCallback(m, this, SLOT(connectA11yBus(QString)), SLOT(dbusError(QDBusError)));
}
}
@@ -149,7 +124,7 @@ void DBusConnection::connectA11yBus(const QString &address)
qWarning("Could not find Accessibility DBus address.");
return;
}
- m_a11yConnection = QDBusConnection(QDBusConnection::connectToBus(address, QLatin1String("a11y")));
+ m_a11yConnection = QDBusConnection(QDBusConnection::connectToBus(address, "a11y"_L1));
if (m_enabled)
emit enabledChanged(true);
@@ -170,3 +145,5 @@ QDBusConnection DBusConnection::connection() const
}
QT_END_NAMESPACE
+
+#include "moc_dbusconnection_p.cpp"
diff --git a/src/gui/accessible/linux/dbusconnection_p.h b/src/gui/accessible/linux/dbusconnection_p.h
index 826630fddc..8b231c5ad0 100644
--- a/src/gui/accessible/linux/dbusconnection_p.h
+++ b/src/gui/accessible/linux/dbusconnection_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef DBUSCONNECTION_H
@@ -52,9 +16,11 @@
// We mean it.
//
+#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusVariant>
+#include <QtCore/private/qglobal_p.h>
Q_MOC_INCLUDE(<QtDBus/QDBusError>)
QT_BEGIN_NAMESPACE
diff --git a/src/gui/accessible/linux/dbusxml/Socket.xml b/src/gui/accessible/linux/dbusxml/Socket.xml
index 75ec99f994..f9ac76d2c8 100644
--- a/src/gui/accessible/linux/dbusxml/Socket.xml
+++ b/src/gui/accessible/linux/dbusxml/Socket.xml
@@ -17,7 +17,7 @@
<signal name="Available">
<arg direction="in" name="socket" type="(so)"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
- </method>
+ </signal>
</interface>
</node>
diff --git a/src/gui/accessible/linux/qspi_constant_mappings.cpp b/src/gui/accessible/linux/qspi_constant_mappings.cpp
index f428726138..e5b6e3f634 100644
--- a/src/gui/accessible/linux/qspi_constant_mappings.cpp
+++ b/src/gui/accessible/linux/qspi_constant_mappings.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qspi_constant_mappings_p.h"
@@ -51,7 +15,7 @@
// "ruler" "autocomplete" "edit bar" "embedded component" "entry" "caption"
// "heading" "page" "section" "redundant object" "form" "input method window" "menu"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QT_BEGIN_NAMESPACE
quint64 spiStatesFromQState(QAccessible::State state)
@@ -72,6 +36,8 @@ quint64 spiStatesFromQState(QAccessible::State state)
setSpiStateBit(&spiState, ATSPI_STATE_FOCUSED);
if (state.pressed)
setSpiStateBit(&spiState, ATSPI_STATE_PRESSED);
+ if (state.checkable)
+ setSpiStateBit(&spiState, ATSPI_STATE_CHECKABLE);
if (state.checked)
setSpiStateBit(&spiState, ATSPI_STATE_CHECKED);
if (state.checkStateMixed)
@@ -111,7 +77,8 @@ quint64 spiStatesFromQState(QAccessible::State state)
if (state.extSelectable)
setSpiStateBit(&spiState, ATSPI_STATE_SELECTABLE);
// if (state.Protected)
- // if (state.HasPopup)
+ if (state.hasPopup)
+ setSpiStateBit(&spiState, ATSPI_STATE_HAS_POPUP);
if (state.modal)
setSpiStateBit(&spiState, ATSPI_STATE_MODAL);
if (state.multiLine)
@@ -133,6 +100,7 @@ QSpiUIntList spiStateSetFromSpiStates(quint64 states)
AtspiRelationType qAccessibleRelationToAtSpiRelation(QAccessible::Relation relation)
{
+ // direction of the relation is "inversed" in Qt and AT-SPI
switch (relation) {
case QAccessible::Label:
return ATSPI_RELATION_LABELLED_BY;
@@ -142,6 +110,14 @@ AtspiRelationType qAccessibleRelationToAtSpiRelation(QAccessible::Relation relat
return ATSPI_RELATION_CONTROLLED_BY;
case QAccessible::Controlled:
return ATSPI_RELATION_CONTROLLER_FOR;
+ case QAccessible::DescriptionFor:
+ return ATSPI_RELATION_DESCRIBED_BY;
+ case QAccessible::Described:
+ return ATSPI_RELATION_DESCRIPTION_FOR;
+ case QAccessible::FlowsFrom:
+ return ATSPI_RELATION_FLOWS_TO;
+ case QAccessible::FlowsTo:
+ return ATSPI_RELATION_FLOWS_FROM;
default:
qWarning() << "Cannot return AT-SPI relation for:" << relation;
}
@@ -149,4 +125,4 @@ AtspiRelationType qAccessibleRelationToAtSpiRelation(QAccessible::Relation relat
}
QT_END_NAMESPACE
-#endif //QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/gui/accessible/linux/qspi_constant_mappings_p.h b/src/gui/accessible/linux/qspi_constant_mappings_p.h
index 17e36825f6..ea571181e6 100644
--- a/src/gui/accessible/linux/qspi_constant_mappings_p.h
+++ b/src/gui/accessible/linux/qspi_constant_mappings_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//
// W A R N I N G
diff --git a/src/gui/accessible/linux/qspi_struct_marshallers.cpp b/src/gui/accessible/linux/qspi_struct_marshallers.cpp
index 1f49d8533f..032a9fe8b1 100644
--- a/src/gui/accessible/linux/qspi_struct_marshallers.cpp
+++ b/src/gui/accessible/linux/qspi_struct_marshallers.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qspi_struct_marshallers_p.h"
@@ -46,9 +10,27 @@
#include "qspiaccessiblebridge_p.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QSpiIntList)
+QT_IMPL_METATYPE_EXTERN(QSpiUIntList)
+QT_IMPL_METATYPE_EXTERN(QSpiObjectReference)
+QT_IMPL_METATYPE_EXTERN(QSpiObjectReferenceArray)
+QT_IMPL_METATYPE_EXTERN(QSpiAccessibleCacheItem)
+QT_IMPL_METATYPE_EXTERN(QSpiAccessibleCacheArray)
+QT_IMPL_METATYPE_EXTERN(QSpiAction)
+QT_IMPL_METATYPE_EXTERN(QSpiActionArray)
+QT_IMPL_METATYPE_EXTERN(QSpiEventListener)
+QT_IMPL_METATYPE_EXTERN(QSpiEventListenerArray)
+QT_IMPL_METATYPE_EXTERN(QSpiRelationArrayEntry)
+QT_IMPL_METATYPE_EXTERN(QSpiRelationArray)
+QT_IMPL_METATYPE_EXTERN(QSpiTextRange)
+QT_IMPL_METATYPE_EXTERN(QSpiTextRangeList)
+QT_IMPL_METATYPE_EXTERN(QSpiAttributeSet)
+QT_IMPL_METATYPE_EXTERN(QSpiAppUpdate)
+QT_IMPL_METATYPE_EXTERN(QSpiDeviceEvent)
+
QSpiObjectReference::QSpiObjectReference()
: path(QDBusObjectPath(ATSPI_DBUS_PATH_NULL))
{}
@@ -234,4 +216,4 @@ void qSpiInitializeStructTypes()
}
QT_END_NAMESPACE
-#endif //QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/gui/accessible/linux/qspi_struct_marshallers_p.h b/src/gui/accessible/linux/qspi_struct_marshallers_p.h
index c7a4a97176..4338b49dd2 100644
--- a/src/gui/accessible/linux/qspi_struct_marshallers_p.h
+++ b/src/gui/accessible/linux/qspi_struct_marshallers_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef Q_SPI_STRUCT_MARSHALLERS_H
@@ -176,23 +140,23 @@ void qSpiInitializeStructTypes();
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QSpiIntList)
-Q_DECLARE_METATYPE(QSpiUIntList)
-Q_DECLARE_METATYPE(QSpiObjectReference)
-Q_DECLARE_METATYPE(QSpiObjectReferenceArray)
-Q_DECLARE_METATYPE(QSpiAccessibleCacheItem)
-Q_DECLARE_METATYPE(QSpiAccessibleCacheArray)
-Q_DECLARE_METATYPE(QSpiAction)
-Q_DECLARE_METATYPE(QSpiActionArray)
-Q_DECLARE_METATYPE(QSpiEventListener)
-Q_DECLARE_METATYPE(QSpiEventListenerArray)
-Q_DECLARE_METATYPE(QSpiRelationArrayEntry)
-Q_DECLARE_METATYPE(QSpiRelationArray)
-Q_DECLARE_METATYPE(QSpiTextRange)
-Q_DECLARE_METATYPE(QSpiTextRangeList)
-Q_DECLARE_METATYPE(QSpiAttributeSet)
-Q_DECLARE_METATYPE(QSpiAppUpdate)
-Q_DECLARE_METATYPE(QSpiDeviceEvent)
+QT_DECL_METATYPE_EXTERN(QSpiIntList, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiUIntList, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiObjectReference, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiObjectReferenceArray, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiAccessibleCacheItem, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiAccessibleCacheArray, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiAction, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiActionArray, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiEventListener, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiEventListenerArray, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiRelationArrayEntry, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiRelationArray, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiTextRange, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiTextRangeList, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiAttributeSet, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiAppUpdate, /* not exported */)
+QT_DECL_METATYPE_EXTERN(QSpiDeviceEvent, /* not exported */)
// For qdbusxml2cpp-generated code
QT_USE_NAMESPACE
diff --git a/src/gui/accessible/linux/qspiaccessiblebridge.cpp b/src/gui/accessible/linux/qspiaccessiblebridge.cpp
index 9b9b7a46a5..de2e7d5fc0 100644
--- a/src/gui/accessible/linux/qspiaccessiblebridge.cpp
+++ b/src/gui/accessible/linux/qspiaccessiblebridge.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qspiaccessiblebridge_p.h"
@@ -52,11 +16,13 @@
#include "dbusconnection_p.h"
#include "qspi_struct_marshallers_p.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "deviceeventcontroller_adaptor.h"
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QSpiAccessibleBridge
\internal
@@ -67,6 +33,14 @@ QSpiAccessibleBridge::QSpiAccessibleBridge()
{
dbusConnection = new DBusConnection();
connect(dbusConnection, SIGNAL(enabledChanged(bool)), this, SLOT(enabledChanged(bool)));
+ // Now that we have connected the signal, make sure we didn't miss a change,
+ // e.g. when running as root or when AT_SPI_BUS_ADDRESS is set by hand.
+ // But do that only on next loop, once dbus is really settled.
+ QTimer::singleShot(
+ 0, this, [this]{
+ if (dbusConnection->isEnabled() && dbusConnection->connection().isConnected())
+ enabledChanged(true);
+ });
}
void QSpiAccessibleBridge::enabledChanged(bool enabled)
@@ -95,10 +69,10 @@ void QSpiAccessibleBridge::updateStatus()
cache = new QSpiDBusCache(dbusConnection->connection(), this);
dec = new DeviceEventControllerAdaptor(this);
- dbusConnection->connection().registerObject(QLatin1String(ATSPI_DBUS_PATH_DEC), this, QDBusConnection::ExportAdaptors);
+ dbusConnection->connection().registerObject(ATSPI_DBUS_PATH_DEC ""_L1, this, QDBusConnection::ExportAdaptors);
dbusAdaptor = new AtSpiAdaptor(dbusConnection, this);
- dbusConnection->connection().registerVirtualObject(QLatin1String(QSPI_OBJECT_PATH_ACCESSIBLE), dbusAdaptor, QDBusConnection::SubPath);
+ dbusConnection->connection().registerVirtualObject(QSPI_OBJECT_PATH_ACCESSIBLE ""_L1, dbusAdaptor, QDBusConnection::SubPath);
dbusAdaptor->registerApplication();
}
}
@@ -231,7 +205,11 @@ static RoleMapping map[] = {
//: Role of an accessible object
{ QAccessible::ButtonDropDown, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button with drop down") },
//: Role of an accessible object
+#if ATSPI_ROLE_COUNT > 130
+ { QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON_MENU, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button menu") },
+#else
{ QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button menu") },
+#endif
//: Role of an accessible object - a button that expands a grid.
{ QAccessible::ButtonDropGrid, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button with drop down grid") },
//: Role of an accessible object - blank space between other objects.
@@ -275,7 +253,7 @@ static RoleMapping map[] = {
void QSpiAccessibleBridge::initializeConstantMappings()
{
for (uint i = 0; i < sizeof(map) / sizeof(RoleMapping); ++i)
- m_spiRoleMapping.insert(map[i].role, RoleNames(map[i].spiRole, QLatin1String(map[i].name), tr(map[i].name)));
+ m_spiRoleMapping.insert(map[i].role, RoleNames(map[i].spiRole, QLatin1StringView(map[i].name), tr(map[i].name)));
// -1 because we have button duplicated, as PushButton and Button.
Q_ASSERT_X(m_spiRoleMapping.size() ==
@@ -300,4 +278,6 @@ RoleNames QSpiAccessibleBridge::namesForRole(QAccessible::Role role)
}
QT_END_NAMESPACE
-#endif //QT_NO_ACCESSIBILITY
+
+#include "moc_qspiaccessiblebridge_p.cpp"
+#endif // QT_CONFIG(accessibility)
diff --git a/src/gui/accessible/linux/qspiaccessiblebridge_p.h b/src/gui/accessible/linux/qspiaccessiblebridge_p.h
index ef3eff366d..5ad48c5cc4 100644
--- a/src/gui/accessible/linux/qspiaccessiblebridge_p.h
+++ b/src/gui/accessible/linux/qspiaccessiblebridge_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSPIACCESSIBLEBRIDGE_H
diff --git a/src/gui/accessible/linux/qspiapplicationadaptor.cpp b/src/gui/accessible/linux/qspiapplicationadaptor.cpp
index 430dc13b00..37d7648984 100644
--- a/src/gui/accessible/linux/qspiapplicationadaptor.cpp
+++ b/src/gui/accessible/linux/qspiapplicationadaptor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qspiapplicationadaptor_p.h"
@@ -44,14 +8,20 @@
#include <QtDBus/qdbuspendingreply.h>
#include <qdebug.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "deviceeventcontroller_adaptor.h"
#include "atspi/atspi-constants.h"
+#if __has_include(<xcb/xproto.h>)
+#include <xcb/xproto.h>
+#endif
+
//#define KEYBOARD_DEBUG
QT_BEGIN_NAMESPACE
+using namespace Qt::Literals::StringLiterals;
+
/*!
\class QSpiApplicationAdaptor
\internal
@@ -62,7 +32,7 @@ QT_BEGIN_NAMESPACE
*/
QSpiApplicationAdaptor::QSpiApplicationAdaptor(const QDBusConnection &connection, QObject *parent)
- : QObject(parent), dbusConnection(connection), inCapsLock(false)
+ : QObject(parent), dbusConnection(connection)
{
}
@@ -143,13 +113,9 @@ bool QSpiApplicationAdaptor::eventFilter(QObject *target, QEvent *event)
de.text = QStringLiteral("Escape");
else if (keyEvent->key() == Qt::Key_Space)
de.text = QStringLiteral("space");
- else if (keyEvent->key() == Qt::Key_CapsLock) {
+ else if (keyEvent->key() == Qt::Key_CapsLock)
de.text = QStringLiteral("Caps_Lock");
- if (event->type() == QEvent::KeyPress)
- inCapsLock = true;
- else
- inCapsLock = false;
- } else if (keyEvent->key() == Qt::Key_NumLock)
+ else if (keyEvent->key() == Qt::Key_NumLock)
de.text = QStringLiteral("Num_Lock");
else if (keyEvent->key() == Qt::Key_Insert)
de.text = QStringLiteral("Insert");
@@ -161,10 +127,15 @@ bool QSpiApplicationAdaptor::eventFilter(QObject *target, QEvent *event)
de.isText = !de.text.isEmpty();
de.modifiers = 0;
- if (!inCapsLock && keyEvent->modifiers() & Qt::ShiftModifier)
+ if ((keyEvent->modifiers() & Qt::ShiftModifier) && (keyEvent->key() != Qt::Key_Shift))
de.modifiers |= 1 << ATSPI_MODIFIER_SHIFT;
- if (inCapsLock && (keyEvent->key() != Qt::Key_CapsLock))
- de.modifiers |= 1 << ATSPI_MODIFIER_SHIFTLOCK;
+#ifdef XCB_MOD_MASK_LOCK
+ if (QGuiApplication::platformName().startsWith("xcb"_L1)) {
+ // TODO rather introduce Qt::CapslockModifier into KeyboardModifier
+ if (keyEvent->nativeModifiers() & XCB_MOD_MASK_LOCK )
+ de.modifiers |= 1 << ATSPI_MODIFIER_SHIFTLOCK;
+ }
+#endif
if ((keyEvent->modifiers() & Qt::ControlModifier) && (keyEvent->key() != Qt::Key_Control))
de.modifiers |= 1 << ATSPI_MODIFIER_CONTROL;
if ((keyEvent->modifiers() & Qt::AltModifier) && (keyEvent->key() != Qt::Key_Alt))
@@ -210,11 +181,11 @@ QKeyEvent* QSpiApplicationAdaptor::copyKeyEvent(QKeyEvent* old)
void QSpiApplicationAdaptor::notifyKeyboardListenerCallback(const QDBusMessage& message)
{
- if (!keyEvents.length()) {
+ if (!keyEvents.size()) {
qWarning("QSpiApplication::notifyKeyboardListenerCallback with no queued key called");
return;
}
- Q_ASSERT(message.arguments().length() == 1);
+ Q_ASSERT(message.arguments().size() == 1);
if (message.arguments().at(0).toBool() == true) {
QPair<QPointer<QObject>, QKeyEvent*> event = keyEvents.dequeue();
delete event.second;
@@ -237,4 +208,6 @@ void QSpiApplicationAdaptor::notifyKeyboardListenerError(const QDBusError& error
QT_END_NAMESPACE
-#endif //QT_NO_ACCESSIBILITY
+#include "moc_qspiapplicationadaptor_p.cpp"
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/gui/accessible/linux/qspiapplicationadaptor_p.h b/src/gui/accessible/linux/qspiapplicationadaptor_p.h
index ca206edcd4..b852951385 100644
--- a/src/gui/accessible/linux/qspiapplicationadaptor_p.h
+++ b/src/gui/accessible/linux/qspiapplicationadaptor_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef Q_SPI_APPLICATION_H
#define Q_SPI_APPLICATION_H
@@ -91,7 +55,6 @@ private:
QQueue<QPair<QPointer<QObject>, QKeyEvent*> > keyEvents;
QDBusConnection dbusConnection;
- bool inCapsLock;
};
QT_END_NAMESPACE
diff --git a/src/gui/accessible/linux/qspidbuscache.cpp b/src/gui/accessible/linux/qspidbuscache.cpp
index 189cd2adf8..fc5d87c319 100644
--- a/src/gui/accessible/linux/qspidbuscache.cpp
+++ b/src/gui/accessible/linux/qspidbuscache.cpp
@@ -1,53 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qspidbuscache_p.h"
#include "qspiaccessiblebridge_p.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "cache_adaptor.h"
#define QSPI_OBJECT_PATH_CACHE "/org/a11y/atspi/cache"
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QSpiDBusCache
\internal
@@ -69,7 +35,7 @@ QSpiDBusCache::QSpiDBusCache(QDBusConnection c, QObject* parent)
: QObject(parent)
{
new CacheAdaptor(this);
- c.registerObject(QLatin1String(QSPI_OBJECT_PATH_CACHE), this, QDBusConnection::ExportAdaptors);
+ c.registerObject(QSPI_OBJECT_PATH_CACHE ""_L1, this, QDBusConnection::ExportAdaptors);
}
void QSpiDBusCache::emitAddAccessible(const QSpiAccessibleCacheItem& item)
@@ -88,4 +54,6 @@ QSpiAccessibleCacheArray QSpiDBusCache::GetItems()
}
QT_END_NAMESPACE
-#endif //QT_NO_ACCESSIBILITY
+
+#include "moc_qspidbuscache_p.cpp"
+#endif // QT_CONFIG(accessibility)
diff --git a/src/gui/accessible/linux/qspidbuscache_p.h b/src/gui/accessible/linux/qspidbuscache_p.h
index 89bee59d3a..7a6e111f14 100644
--- a/src/gui/accessible/linux/qspidbuscache_p.h
+++ b/src/gui/accessible/linux/qspidbuscache_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef Q_SPI_CACHE_H
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 1ba206e82a..46bca16dad 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qaccessible.h"
@@ -54,11 +18,14 @@
#include <QtCore/qdebug.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qmetaobject.h>
+#include <QtCore/private/qmetaobject_p.h>
#include <QtCore/qhash.h>
#include <private/qfactoryloader_p.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
/*!
@@ -162,7 +129,6 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\value hasPopup The object opens a popup.
\value hotTracked The object's appearance is sensitive to the mouse cursor position.
\value invalid The object is no longer valid (because it has been deleted).
- \value invalidEntry Input validation current input invalid.
\value invisible The object is not visible to the user.
\value linked The object is linked to another object, e.g. a hyperlink.
\value marqueed The object displays scrolling contents, e.g. a log view.
@@ -252,7 +218,7 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\value ObjectHide An object is hidden; for example, with QWidget::hide().
Any children the object that is hidden has do not send
this event. It is not sent when an object is hidden as
- it is being obcured by others.
+ it is being obscured by others.
\value ObjectReorder A layout or item view has added, removed, or moved an
object (Qt does not use this event).
\value ObjectShow An object is displayed; for example, with
@@ -309,7 +275,7 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\value AlertMessage An object that is used to alert the user.
\value Animation An object that displays an animation.
\value Application The application's main window.
- \value Assistant An object that provids interactive help.
+ \value Assistant An object that provides interactive help.
\value Border An object that represents a border.
\value ButtonDropDown A button that drops down a list of items.
\value ButtonDropGrid A button that drops down a grid.
@@ -388,14 +354,29 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\enum QAccessible::RelationFlag
This enum type defines bit flags that can be combined to indicate
- the relationship between two accessible objects.
-
- \value Label The first object is the label of the second object.
- \value Labelled The first object is labelled by the second object.
- \value Controller The first object controls the second object.
- \value Controlled The first object is controlled by the second object.
- \value AllRelations Used as a mask to specify that we are interesting in information
- about all relations
+ the relationship between two accessible objects. It is used by
+ the relations() function, which returns a list of all the related
+ interfaces of the calling object, together with the relations
+ for each object.
+
+ Each entry in the list is a QPair where the \c second member stores
+ the relation type(s) between the \c returned object represented by the
+ \c first member and the \c origin (the caller) interface/object.
+
+ In the table below, the \c returned object refers to the object in
+ the returned list, and the \c origin object is the one represented
+ by the calling interface.
+
+ \value Label The \c returned object is the label for the \c origin object.
+ \value Labelled The \c returned object is labelled by the \c origin object.
+ \value Controller The \c returned object controls the \c origin object.
+ \value Controlled The \c returned object is controlled by the \c origin object.
+ \value [since 6.6] DescriptionFor The \c returned object provides a description for the \c origin object.
+ \value [since 6.6] Described The \c returned object is described by the \c origin object.
+ \value [since 6.6] FlowsFrom Content logically flows from the \c returned object to the \c origin object.
+ \value [since 6.6] FlowsTo Content logically flows to the \c returned object from the \c origin object.
+ \value AllRelations Used as a mask to specify that we are interesting in information
+ about all relations
Implementations of relations() return a combination of these flags.
Some values are mutually exclusive.
@@ -431,6 +412,43 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\sa QAccessibleTextInterface
*/
+/*! \enum QAccessible::Attribute
+ This enum describes different types of attributes used by the
+ \l QAccessibleAttributesInterface.
+ \since 6.8
+
+ These attributes are comparable to the concept of properties/(object)
+ attributes found in ARIA, AT-SPI2, IAccessible, UIA and NSAccessibility
+ and are mapped to their platform counterpart where applicable.
+
+ Each attribute is handled as a key-value pair, with the values of this
+ enumeration being used as keys.
+
+ Attribute values are represented in a \l QVariant. The type of the value
+ stored in the \l QVariant is fixed and specified below for each of the
+ attribute types.
+
+ \value Custom value type: \a QHash<QString, QString>
+ The \a Custom attribute is special in that
+ it can effectively represent multiple attributes at
+ once, since it itself is a \l QHash used to represent
+ key-value pairs.
+ For platforms supporting custom key-value pairs for
+ attributes, those set in the \a Custom attribute
+ are bridged to the platform layer without applying any
+ translation to platform-specific attributes. In general,
+ the other, more strongly typed attributes should be used.
+ This attribute can e.g. be used for prototyping
+ before officially adding an official new enumeration value
+ for a specific feature.
+ \value Level value type: \a int
+ Defines the hierarchical level of an element within a structure,
+ e.g. the heading level of a heading. This attribute conceptually
+ matches the "aria-level" property in ARIA.
+
+ \sa QAccessibleAttributesInterface
+*/
+
/*!
\enum QAccessible::InterfaceType
@@ -449,11 +467,13 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\value TableInterface For lists, tables and trees.
\value TableCellInterface For cells in a TableInterface object.
\value HyperlinkInterface For hyperlink nodes (usually embedded as children of text nodes)
+ \value [since 6.5] SelectionInterface For non-text objects that support selection of child objects.
+ \value [since 6.8] AttributesInterface For objects that support object-specific attributes.
- \sa QAccessibleInterface::interface_cast(), QAccessibleTextInterface, QAccessibleValueInterface, QAccessibleActionInterface, QAccessibleTableInterface, QAccessibleTableCellInterface
+ \sa QAccessibleInterface::interface_cast(), QAccessibleTextInterface, QAccessibleValueInterface, QAccessibleActionInterface, QAccessibleTableInterface, QAccessibleTableCellInterface, QAccessibleSelectionInterface, QAccessibleAttributesInterface
*/
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
/*!
Destroys the QAccessibleInterface.
@@ -470,8 +490,8 @@ QAccessibleInterface::~QAccessibleInterface()
/* accessible widgets plugin discovery stuff */
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QAccessibleFactoryInterface_iid, QLatin1String("/accessible")))
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, acLoader,
+ (QAccessibleFactoryInterface_iid, "/accessible"_L1))
typedef QHash<QString, QAccessiblePlugin*> QAccessiblePluginsHash;
Q_GLOBAL_STATIC(QAccessiblePluginsHash, qAccessiblePlugins)
@@ -681,11 +701,30 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
// Create a QAccessibleInterface for the object class. Start by the most
// derived class and walk up the class hierarchy.
const QMetaObject *mo = object->metaObject();
+ const auto *objectPriv = QObjectPrivate::get(object);
+ /*
+ We do not want to cache each and every QML metaobject (Button_QMLTYPE_124,
+ Button_QMLTYPE_125, etc.). Those dynamic metaobjects shouldn't have an
+ accessible interface in any case. Instead, we start the whole checking
+ with the first non-dynamic meta-object. To avoid potential regressions
+ in other areas of Qt that also use dynamic metaobjects, we only do this
+ for objects that are QML-related (approximated by checking whether they
+ have ddata set).
+ */
+ const bool qmlRelated = !objectPriv->isDeletingChildren &&
+ objectPriv->declarativeData;
+ while (qmlRelated && mo) {
+ auto mop = QMetaObjectPrivate::get(mo);
+ if (!mop || !(mop->flags & DynamicMetaObject))
+ break;
+
+ mo = mo->superClass();
+ };
while (mo) {
- const QString cn = QLatin1String(mo->className());
+ const QString cn = QLatin1StringView(mo->className());
// Check if the class has a InterfaceFactory installed.
- for (int i = qAccessibleFactories()->count(); i > 0; --i) {
+ for (int i = qAccessibleFactories()->size(); i > 0; --i) {
InterfaceFactory factory = qAccessibleFactories()->at(i - 1);
if (QAccessibleInterface *iface = factory(cn, object)) {
QAccessibleCache::instance()->insert(object, iface);
@@ -696,14 +735,15 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
// Find a QAccessiblePlugin (factory) for the class name. If there's
// no entry in the cache try to create it using the plugin loader.
if (!qAccessiblePlugins()->contains(cn)) {
- const int index = loader()->indexOf(cn);
- if (index != -1) {
- QAccessiblePlugin *factory = qobject_cast<QAccessiblePlugin *>(loader()->instance(index));
- qAccessiblePlugins()->insert(cn, factory);
- }
+ QAccessiblePlugin *factory = nullptr; // 0 means "no plugin found". This is cached as well.
+ const int index = acLoader()->indexOf(cn);
+ if (index != -1)
+ factory = qobject_cast<QAccessiblePlugin *>(acLoader()->instance(index));
+ qAccessiblePlugins()->insert(cn, factory);
}
// At this point the cache should contain a valid factory pointer or 0:
+ Q_ASSERT(qAccessiblePlugins()->contains(cn));
QAccessiblePlugin *factory = qAccessiblePlugins()->value(cn);
if (factory) {
QAccessibleInterface *result = factory->create(cn, object);
@@ -801,7 +841,7 @@ bool QAccessible::isActive()
*/
void QAccessible::setActive(bool active)
{
- for (int i = 0; i < qAccessibleActivationObservers()->count() ;++i)
+ for (int i = 0; i < qAccessibleActivationObservers()->size() ;++i)
qAccessibleActivationObservers()->at(i)->accessibilityActiveChanged(active);
}
@@ -864,11 +904,11 @@ void QAccessible::updateAccessibility(QAccessibleEvent *event)
if (iface->tableInterface())
iface->tableInterface()->modelChange(static_cast<QAccessibleTableModelChangeEvent*>(event));
}
+ }
- if (updateHandler) {
- updateHandler(event);
- return;
- }
+ if (updateHandler) {
+ updateHandler(event);
+ return;
}
if (QPlatformAccessibility *pfAccessibility = platformAccessibility())
@@ -1114,7 +1154,7 @@ QAccessibleInterface *QAccessibleInterface::focusChild() const
If there are no children at this position this function returns \nullptr.
The returned accessible must be a child, but not necessarily a direct child.
- This function is only relyable for visible objects (invisible
+ This function is only reliable for visible objects (invisible
object might not be laid out correctly).
All visual objects provide this information.
@@ -1287,6 +1327,11 @@ QColor QAccessibleInterface::backgroundColor() const
*/
/*!
+ \fn QAccessibleSelectionInterface *QAccessibleInterface::selectionInterface()
+ \since 6.5
+*/
+
+/*!
\class QAccessibleEvent
\ingroup accessibility
\inmodule QtGui
@@ -1648,8 +1693,8 @@ QAccessibleTextRemoveEvent::~QAccessibleTextRemoveEvent()
/*!
\fn QAccessibleTextInsertEvent::QAccessibleTextInsertEvent(QAccessibleInterface *iface, int position, const QString &text)
- Constructs a new QAccessibleTextInsertEvent event for \a iface. The text has been inserted at
- \a position.
+ Constructs a new QAccessibleTextInsertEvent event for \a iface. The \a text has been inserted
+ at \a position.
*/
/*!
@@ -1842,16 +1887,16 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleInterface *iface)
QStringList stateStrings;
QAccessible::State st = iface->state();
if (st.focusable)
- stateStrings << QLatin1String("focusable");
+ stateStrings << u"focusable"_s;
if (st.focused)
- stateStrings << QLatin1String("focused");
+ stateStrings << u"focused"_s;
if (st.selected)
- stateStrings << QLatin1String("selected");
+ stateStrings << u"selected"_s;
if (st.invisible)
- stateStrings << QLatin1String("invisible");
+ stateStrings << u"invisible"_s;
if (!stateStrings.isEmpty())
- d << stateStrings.join(QLatin1Char('|'));
+ d << stateStrings.join(u'|');
if (!st.invisible)
d << "rect=" << iface->rect();
@@ -2022,7 +2067,7 @@ static QString textLineBoundary(int beforeAtAfter, const QString &text, int offs
{
Q_ASSERT(beforeAtAfter >= -1 && beforeAtAfter <= 1);
Q_ASSERT(*startOffset == -1 && *endOffset == -1);
- int length = text.length();
+ int length = text.size();
Q_ASSERT(offset >= 0 && offset <= length);
// move offset into the right range (if asking for line before or after
@@ -2071,10 +2116,10 @@ QString QAccessibleTextInterface::textBeforeOffset(int offset, QAccessible::Text
const QString txt = text(0, characterCount());
if (offset == -1)
- offset = txt.length();
+ offset = txt.size();
*startOffset = *endOffset = -1;
- if (txt.isEmpty() || offset <= 0 || offset > txt.length())
+ if (txt.isEmpty() || offset <= 0 || offset > txt.size())
return QString();
// type initialized just to silence a compiler warning [-Werror=maybe-uninitialized]
@@ -2145,10 +2190,10 @@ QString QAccessibleTextInterface::textAfterOffset(int offset, QAccessible::TextB
const QString txt = text(0, characterCount());
if (offset == -1)
- offset = txt.length();
+ offset = txt.size();
*startOffset = *endOffset = -1;
- if (txt.isEmpty() || offset < 0 || offset >= txt.length())
+ if (txt.isEmpty() || offset < 0 || offset >= txt.size())
return QString();
// type initialized just to silence a compiler warning [-Werror=maybe-uninitialized]
@@ -2183,20 +2228,20 @@ QString QAccessibleTextInterface::textAfterOffset(int offset, QAccessible::TextB
int toNext = boundary.toNextBoundary();
if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem)))
break;
- if (toNext < 0 || toNext >= txt.length())
+ if (toNext < 0 || toNext >= txt.size())
break; // not found, the boundary might not exist
}
- Q_ASSERT(boundary.position() <= txt.length());
+ Q_ASSERT(boundary.position() <= txt.size());
*startOffset = boundary.position();
while (true) {
int toNext = boundary.toNextBoundary();
if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem)))
break;
- if (toNext < 0 || toNext >= txt.length())
+ if (toNext < 0 || toNext >= txt.size())
break; // not found, the boundary might not exist
}
- Q_ASSERT(boundary.position() <= txt.length());
+ Q_ASSERT(boundary.position() <= txt.size());
*endOffset = boundary.position();
if ((*startOffset == -1) || (*endOffset == -1) || (*startOffset == *endOffset)) {
@@ -2230,13 +2275,13 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
const QString txt = text(0, characterCount());
if (offset == -1)
- offset = txt.length();
+ offset = txt.size();
*startOffset = *endOffset = -1;
- if (txt.isEmpty() || offset < 0 || offset > txt.length())
+ if (txt.isEmpty() || offset < 0 || offset > txt.size())
return QString();
- if (offset == txt.length() && boundaryType == QAccessible::CharBoundary)
+ if (offset == txt.size() && boundaryType == QAccessible::CharBoundary)
return QString();
// type initialized just to silence a compiler warning [-Werror=maybe-uninitialized]
@@ -2257,7 +2302,7 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
return textLineBoundary(0, txt, offset, startOffset, endOffset);
case QAccessible::NoBoundary:
*startOffset = 0;
- *endOffset = txt.length();
+ *endOffset = txt.size();
return txt;
default:
Q_UNREACHABLE();
@@ -2275,11 +2320,11 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
Q_ASSERT(boundary.position() >= 0);
*startOffset = boundary.position();
- while (boundary.toNextBoundary() < txt.length()) {
+ while (boundary.toNextBoundary() < txt.size()) {
if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem)))
break;
}
- Q_ASSERT(boundary.position() <= txt.length());
+ Q_ASSERT(boundary.position() <= txt.size());
*endOffset = boundary.position();
return txt.mid(*startOffset, *endOffset - *startOffset);
@@ -2417,8 +2462,8 @@ QAccessibleValueInterface::~QAccessibleValueInterface()
\fn QVariant QAccessibleValueInterface::minimumStepSize() const
Returns the minimum step size for the accessible.
- This is the smalles increment that makes sense when changing the value.
- When programatically changing the value it should always be a multiple
+ This is the smallest increment that makes sense when changing the value.
+ When programmatically changing the value it should always be a multiple
of the minimum step size.
Some tools use this value even when the setCurrentValue does not
@@ -2516,6 +2561,7 @@ QAccessibleTableCellInterface::~QAccessibleTableCellInterface()
/*!
\class QAccessibleTableInterface
+ \inmodule QtGui
\ingroup accessibility
\brief The QAccessibleTableInterface class implements support for
@@ -2601,7 +2647,7 @@ QAccessibleTableInterface::~QAccessibleTableInterface()
/*!
\fn virtual QList<int> QAccessibleTableInterface::selectedRows() const
- Returns the list of currently selected columns.
+ Returns the list of currently selected rows.
*/
/*!
@@ -2662,6 +2708,7 @@ QAccessibleTableInterface::~QAccessibleTableInterface()
/*!
\class QAccessibleActionInterface
+ \inmodule QtGui
\ingroup accessibility
\brief The QAccessibleActionInterface class implements support for
@@ -2686,7 +2733,7 @@ QAccessibleTableInterface::~QAccessibleTableInterface()
\row \li \l toggleAction() \li toggles the item (checkbox, radio button, switch, ...)
\row \li \l decreaseAction() \li decrease the value of the accessible (e.g. spinbox)
\row \li \l increaseAction() \li increase the value of the accessible (e.g. spinbox)
- \row \li \l pressAction() \li press or click or activate the accessible (should correspont to clicking the object with the mouse)
+ \row \li \l pressAction() \li press or click or activate the accessible (should correspond to clicking the object with the mouse)
\row \li \l setFocusAction() \li set the focus to this accessible
\row \li \l showMenuAction() \li show a context menu, corresponds to right-clicks
\endtable
@@ -2953,6 +3000,161 @@ QString QAccessibleActionInterface::nextPageAction()
return accessibleActionStrings()->nextPageAction;
}
+
+/*!
+ \since 6.5
+ \class QAccessibleSelectionInterface
+ \inmodule QtGui
+ \ingroup accessibility
+
+ \brief The QAccessibleSelectionInterface class implements support for
+ selection handling.
+
+ It provides methods for both, retrieving the current selection
+ as well as modifying the selection.
+
+ Only selections of direct children are supported.
+*/
+
+/*!
+
+ Destroys the QAccessibleSelectionInterface.
+*/
+QAccessibleSelectionInterface::~QAccessibleSelectionInterface()
+{
+}
+
+/*!
+ \fn virtual int QAccessibleSelectionInterface::selectedItemCount() const
+
+ Returns the total number of selected accessible items.
+*/
+
+/*!
+ \fn virtual QList<QAccessibleInterface *> QAccessibleSelectionInterface::selectedItems() const
+
+ Returns the list of selected accessible items.
+*/
+
+/*!
+ Returns the selected accessible item at index \a selectionIndex in the selection.
+
+ Note that the index refers to the n-th selected accessible item (i.e. the index in the current selection),
+ which generally differs from the index that would be passed to \l QAccessibleInterface::child()
+ in order to retrieve the same item.
+
+ The default implementation uses \a selectionIndex to retrieve the item from the list
+ of selected items retrieved by \l QAccessibleSelectionInterface::selectedItems().
+
+ In particular for implementations dealing with many selected items, reimplementing
+ this method in a more efficient way may be desirable for performance reasons.
+*/
+QAccessibleInterface* QAccessibleSelectionInterface::selectedItem(int selectionIndex) const
+{
+ QList<QAccessibleInterface*> items = selectedItems();
+ if (selectionIndex < 0 || selectionIndex > items.length() -1) {
+ qCWarning(lcAccessibilityCore) << "Selection index" << selectionIndex << "out of range.";
+ return nullptr;
+ }
+
+ return items.at(selectionIndex);
+}
+
+/*!
+ Returns whether \a childItem is part of the current selection.
+
+ The default implementation checks whether \a childItem is contained
+ in the list of items retrieved by \l QAccessibleSelectionInterface::selectedItems.
+*/
+bool QAccessibleSelectionInterface::isSelected(QAccessibleInterface *childItem) const
+{
+ return selectedItems().contains(childItem);
+}
+
+/*!
+ \fn virtual bool QAccessibleSelectionInterface::select(QAccessibleInterface *childItem)
+
+ Adds \a childItem to the selection.
+ Returns whether \a childItem has actually been added to the selection.
+
+ For implementations that only allow single selections,
+ this may replace the current selection.
+*/
+
+/*!
+ \fn virtual bool QAccessibleSelectionInterface::unselect(QAccessibleInterface *childItem)
+
+ Removes \a childItem from the selection.
+
+ Returns whether the accessible item has actually been removed from the selection.
+*/
+
+/*!
+ \fn virtual bool QAccessibleSelectionInterface::selectAll()
+
+ Selects all accessible child items.
+
+ Returns whether all accessible child items have actually been added to the selection.
+*/
+
+/*!
+ \fn virtual bool QAccessibleSelectionInterface::clear()
+
+ Unselects all accessible child items.
+
+ Returns whether all accessible child items have actually been removed from the selection,
+ i.e. whether the selection is empty after this method has been called.
+*/
+
+
+/*!
+ \since 6.8
+ \class QAccessibleAttributesInterface
+ \inmodule QtGui
+ \ingroup accessibility
+
+ \brief The QAccessibleAttributesInterface class implements support for
+ reporting attributes for an accessible object.
+
+ Attributes are key-value pairs. Values are stored in \l QVariant.
+
+ The \a QAccessible::Attributes enumeration describes the available keys and
+ documents which type to use for the value of each key.
+
+ While the text-specific attributes handled by \l QAccessibleTextInterface::attributes
+ are specific to objects implementing text and are specific to a specific text
+ position/offset, the attributes handled by the \l QAccessibleAttributesInterface
+ can be used for objects of any role and apply for the whole object.
+
+ Classes already implementing \l QAccessibleTextInterface for text-specific attrtibutes
+ may want to implement \l QAccessibleAttributesInterface in addition for object-specific
+ attributes.
+*/
+
+/*!
+
+ Destroys the QAccessibleAttributesInterface.
+*/
+QAccessibleAttributesInterface::~QAccessibleAttributesInterface()
+{
+}
+
+/*!
+ \fn QList<QAccessible::Attribute> QAccessibleAttributesInterface::attributeKeys() const
+
+ Returns the keys of all attributes the object supports. The \l QAccessible::Attribute
+ enumeration describes available keys.
+*/
+
+/*!
+ \fn QVariant QAccessibleAttributesInterface::attributeValue(QAccessible::Attribute key) const
+
+ Returns the value of the attribute \a key of this object.
+
+ If the specificed attribute is not set for this object, an invalid
+ \l QVariant is returned.
+*/
+
/*! \internal */
QString qAccessibleLocalizedActionDescription(const QString &actionName)
{
@@ -2997,7 +3199,8 @@ QAccessibleHyperlinkInterface::~QAccessibleHyperlinkInterface()
}
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
QT_END_NAMESPACE
+#include "moc_qaccessible_base.cpp"
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index d7bb31706e..0a92e76c73 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -1,47 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include <QtGui/qtguiglobal.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if 0
+// keep existing syncqt header working after the move of the class
+// into qaccessible_base
+#pragma qt_class(QAccessible)
+#endif
+
#ifndef QACCESSIBLE_H
#define QACCESSIBLE_H
+#include <QtGui/qtguiglobal.h>
+
+#if QT_CONFIG(accessibility)
#include <QtCore/qcoreapplication.h>
#include <QtCore/qdebug.h>
@@ -53,8 +24,7 @@
#include <QtCore/qvariant.h>
#include <QtGui/qcolor.h>
#include <QtGui/qevent.h>
-
-#include <stdlib.h>
+#include <QtGui/qaccessible_base.h>
QT_BEGIN_NAMESPACE
@@ -63,387 +33,6 @@ class QAccessibleEvent;
class QWindow;
class QTextCursor;
-class Q_GUI_EXPORT QAccessible
-{
- Q_GADGET
-public:
-
- enum Event {
- SoundPlayed = 0x0001,
- Alert = 0x0002,
- ForegroundChanged = 0x0003,
- MenuStart = 0x0004,
- MenuEnd = 0x0005,
- PopupMenuStart = 0x0006,
- PopupMenuEnd = 0x0007,
- ContextHelpStart = 0x000C,
- ContextHelpEnd = 0x000D,
- DragDropStart = 0x000E,
- DragDropEnd = 0x000F,
- DialogStart = 0x0010,
- DialogEnd = 0x0011,
- ScrollingStart = 0x0012,
- ScrollingEnd = 0x0013,
-
- MenuCommand = 0x0018,
-
- // Values from IAccessible2
- ActionChanged = 0x0101,
- ActiveDescendantChanged = 0x0102,
- AttributeChanged = 0x0103,
- DocumentContentChanged = 0x0104,
- DocumentLoadComplete = 0x0105,
- DocumentLoadStopped = 0x0106,
- DocumentReload = 0x0107,
- HyperlinkEndIndexChanged = 0x0108,
- HyperlinkNumberOfAnchorsChanged = 0x0109,
- HyperlinkSelectedLinkChanged = 0x010A,
- HypertextLinkActivated = 0x010B,
- HypertextLinkSelected = 0x010C,
- HyperlinkStartIndexChanged = 0x010D,
- HypertextChanged = 0x010E,
- HypertextNLinksChanged = 0x010F,
- ObjectAttributeChanged = 0x0110,
- PageChanged = 0x0111,
- SectionChanged = 0x0112,
- TableCaptionChanged = 0x0113,
- TableColumnDescriptionChanged = 0x0114,
- TableColumnHeaderChanged = 0x0115,
- TableModelChanged = 0x0116,
- TableRowDescriptionChanged = 0x0117,
- TableRowHeaderChanged = 0x0118,
- TableSummaryChanged = 0x0119,
- TextAttributeChanged = 0x011A,
- TextCaretMoved = 0x011B,
- // TextChanged = 0x011C, is deprecated in IA2, use TextUpdated
- TextColumnChanged = 0x011D,
- TextInserted = 0x011E,
- TextRemoved = 0x011F,
- TextUpdated = 0x0120,
- TextSelectionChanged = 0x0121,
- VisibleDataChanged = 0x0122,
-
- ObjectCreated = 0x8000,
- ObjectDestroyed = 0x8001,
- ObjectShow = 0x8002,
- ObjectHide = 0x8003,
- ObjectReorder = 0x8004,
- Focus = 0x8005,
- Selection = 0x8006,
- SelectionAdd = 0x8007,
- SelectionRemove = 0x8008,
- SelectionWithin = 0x8009,
- StateChanged = 0x800A,
- LocationChanged = 0x800B,
- NameChanged = 0x800C,
- DescriptionChanged = 0x800D,
- ValueChanged = 0x800E,
- ParentChanged = 0x800F,
- HelpChanged = 0x80A0,
- DefaultActionChanged = 0x80B0,
- AcceleratorChanged = 0x80C0,
-
- InvalidEvent
- };
- Q_ENUM(Event)
-
- // 64 bit enums seem hard on some platforms (windows...)
- // which makes using a bit field a sensible alternative
- struct State {
- // http://msdn.microsoft.com/en-us/library/ms697270.aspx
- quint64 disabled : 1; // used to be Unavailable
- quint64 selected : 1;
- quint64 focusable : 1;
- quint64 focused : 1;
- quint64 pressed : 1;
- quint64 checkable : 1;
- quint64 checked : 1;
- quint64 checkStateMixed : 1; // used to be Mixed
- quint64 readOnly : 1;
- quint64 hotTracked : 1;
- quint64 defaultButton : 1;
- quint64 expanded : 1;
- quint64 collapsed : 1;
- quint64 busy : 1;
- quint64 expandable : 1;
- quint64 marqueed : 1;
- quint64 animated : 1;
- quint64 invisible : 1;
- quint64 offscreen : 1;
- quint64 sizeable : 1;
- quint64 movable : 1;
- quint64 selfVoicing : 1;
- quint64 selectable : 1;
- quint64 linked : 1;
- quint64 traversed : 1;
- quint64 multiSelectable : 1;
- quint64 extSelectable : 1;
- quint64 passwordEdit : 1; // used to be Protected
- quint64 hasPopup : 1;
- quint64 modal : 1;
-
- // IA2 - we chose to not add some IA2 states for now
- // Below the ones that seem helpful
- quint64 active : 1;
- quint64 invalid : 1; // = defunct
- quint64 editable : 1;
- quint64 multiLine : 1;
- quint64 selectableText : 1;
- quint64 supportsAutoCompletion : 1;
-
- quint64 searchEdit : 1;
-
- // quint64 horizontal : 1;
- // quint64 vertical : 1;
- // quint64 invalidEntry : 1;
- // quint64 managesDescendants : 1;
- // quint64 singleLine : 1; // we have multi line, this is redundant.
- // quint64 stale : 1;
- // quint64 transient : 1;
- // quint64 pinned : 1;
-
- // Apple - see http://mattgemmell.com/2010/12/19/accessibility-for-iphone-and-ipad-apps/
- // quint64 playsSound : 1;
- // quint64 summaryElement : 1;
- // quint64 updatesFrequently : 1;
- // quint64 adjustable : 1;
- // more and not included here: http://developer.apple.com/library/mac/#documentation/UserExperience/Reference/Accessibility_RoleAttribute_Ref/Attributes.html
-
- // MSAA
- // quint64 alertLow : 1;
- // quint64 alertMedium : 1;
- // quint64 alertHigh : 1;
-
- State() {
- memset(this, 0, sizeof(State));
- }
- friend inline bool operator==(const QAccessible::State &first, const QAccessible::State &second)
- {
- return memcmp(&first, &second, sizeof(QAccessible::State)) == 0;
- }
- };
-
-
-
-
-
- enum Role {
- NoRole = 0x00000000,
- TitleBar = 0x00000001,
- MenuBar = 0x00000002,
- ScrollBar = 0x00000003,
- Grip = 0x00000004,
- Sound = 0x00000005,
- Cursor = 0x00000006,
- Caret = 0x00000007,
- AlertMessage = 0x00000008,
- Window = 0x00000009,
- Client = 0x0000000A,
- PopupMenu = 0x0000000B,
- MenuItem = 0x0000000C,
- ToolTip = 0x0000000D,
- Application = 0x0000000E,
- Document = 0x0000000F,
- Pane = 0x00000010,
- Chart = 0x00000011,
- Dialog = 0x00000012,
- Border = 0x00000013,
- Grouping = 0x00000014,
- Separator = 0x00000015,
- ToolBar = 0x00000016,
- StatusBar = 0x00000017,
- Table = 0x00000018,
- ColumnHeader = 0x00000019,
- RowHeader = 0x0000001A,
- Column = 0x0000001B,
- Row = 0x0000001C,
- Cell = 0x0000001D,
- Link = 0x0000001E,
- HelpBalloon = 0x0000001F,
- Assistant = 0x00000020,
- List = 0x00000021,
- ListItem = 0x00000022,
- Tree = 0x00000023,
- TreeItem = 0x00000024,
- PageTab = 0x00000025,
- PropertyPage = 0x00000026,
- Indicator = 0x00000027,
- Graphic = 0x00000028,
- StaticText = 0x00000029,
- EditableText = 0x0000002A, // Editable, selectable, etc.
- Button = 0x0000002B,
-#ifndef Q_QDOC
- PushButton = Button, // deprecated
-#endif
- CheckBox = 0x0000002C,
- RadioButton = 0x0000002D,
- ComboBox = 0x0000002E,
- // DropList = 0x0000002F,
- ProgressBar = 0x00000030,
- Dial = 0x00000031,
- HotkeyField = 0x00000032,
- Slider = 0x00000033,
- SpinBox = 0x00000034,
- Canvas = 0x00000035, // MSAA: ROLE_SYSTEM_DIAGRAM - The object represents a graphical image that is used to diagram data.
- Animation = 0x00000036,
- Equation = 0x00000037,
- ButtonDropDown = 0x00000038, // The object represents a button that expands a grid.
- ButtonMenu = 0x00000039,
- ButtonDropGrid = 0x0000003A,
- Whitespace = 0x0000003B, // The object represents blank space between other objects.
- PageTabList = 0x0000003C,
- Clock = 0x0000003D,
- Splitter = 0x0000003E,
- // Reserved space in case MSAA roles needs to be added
-
- // Additional Qt roles where enum value does not map directly to MSAA:
- LayeredPane = 0x00000080,
- Terminal = 0x00000081,
- Desktop = 0x00000082,
- Paragraph = 0x00000083,
- WebDocument = 0x00000084,
- Section = 0x00000085,
- Notification = 0x00000086,
-
- // IAccessible2 roles
- // IA2_ROLE_CANVAS = 0x401, // An object that can be drawn into and to manage events from the objects drawn into it
- // IA2_ROLE_CAPTION = 0x402,
- // IA2_ROLE_CHECK_MENU_ITEM = 0x403,
- ColorChooser = 0x404,
- // IA2_ROLE_DATE_EDITOR = 0x405,
- // IA2_ROLE_DESKTOP_ICON = 0x406,
- // IA2_ROLE_DESKTOP_PANE = 0x407,
- // IA2_ROLE_DIRECTORY_PANE = 0x408,
- // IA2_ROLE_EDITBAR = 0x409,
- // IA2_ROLE_EMBEDDED_OBJECT = 0x40A,
- // IA2_ROLE_ENDNOTE = 0x40B,
- // IA2_ROLE_FILE_CHOOSER = 0x40C,
- // IA2_ROLE_FONT_CHOOSER = 0x40D,
- Footer = 0x40E,
- // IA2_ROLE_FOOTNOTE = 0x40F,
- Form = 0x410,
- // some platforms (windows and at-spi) use Frame for regular windows
- // because window was taken for tool/dock windows by MSAA
- // Frame = 0x411,
- // IA2_ROLE_GLASS_PANE = 0x412,
- // IA2_ROLE_HEADER = 0x413,
- Heading = 0x414,
- // IA2_ROLE_ICON = 0x415,
- // IA2_ROLE_IMAGE_MAP = 0x416,
- // IA2_ROLE_INPUT_METHOD_WINDOW = 0x417,
- // IA2_ROLE_INTERNAL_FRAME = 0x418,
- // IA2_ROLE_LABEL = 0x419,
- // IA2_ROLE_LAYERED_PANE = 0x41A,
- Note = 0x41B,
- // IA2_ROLE_OPTION_PANE = 0x41C,
- // IA2_ROLE_PAGE = 0x41D,
- // IA2_ROLE_PARAGRAPH = 0x42E,
- // IA2_ROLE_RADIO_MENU_ITEM = 0x41F,
- // IA2_ROLE_REDUNDANT_OBJECT = 0x420,
- // IA2_ROLE_ROOT_PANE = 0x421,
- // IA2_ROLE_RULER = 0x422,
- // IA2_ROLE_SCROLL_PANE = 0x423,
- // IA2_ROLE_SECTION = 0x424,
- // IA2_ROLE_SHAPE = 0x425,
- // IA2_ROLE_SPLIT_PANE = 0x426,
- // IA2_ROLE_TEAR_OFF_MENU = 0x427,
- // IA2_ROLE_TERMINAL = 0x428,
- // IA2_ROLE_TEXT_FRAME = 0x429,
- // IA2_ROLE_TOGGLE_BUTTON = 0x42A,
- // IA2_ROLE_VIEW_PORT = 0x42B,
- ComplementaryContent = 0x42C,
-
- UserRole = 0x0000ffff
- };
- Q_ENUM(Role)
-
- enum Text {
- Name = 0,
- Description,
- Value,
- Help,
- Accelerator,
- DebugDescription,
- UserText = 0x0000ffff
- };
-
- enum RelationFlag {
- Label = 0x00000001,
- Labelled = 0x00000002,
- Controller = 0x00000004,
- Controlled = 0x00000008,
- AllRelations = 0xffffffff
- };
- Q_DECLARE_FLAGS(Relation, RelationFlag)
-
- enum InterfaceType
- {
- TextInterface,
- EditableTextInterface,
- ValueInterface,
- ActionInterface,
- ImageInterface,
- TableInterface,
- TableCellInterface,
- HyperlinkInterface
- };
-
- enum TextBoundaryType {
- CharBoundary,
- WordBoundary,
- SentenceBoundary,
- ParagraphBoundary,
- LineBoundary,
- NoBoundary
- };
-
- typedef QAccessibleInterface*(*InterfaceFactory)(const QString &key, QObject*);
- typedef void(*UpdateHandler)(QAccessibleEvent *event);
- typedef void(*RootObjectHandler)(QObject*);
-
- typedef unsigned Id;
-
- static void installFactory(InterfaceFactory);
- static void removeFactory(InterfaceFactory);
- static UpdateHandler installUpdateHandler(UpdateHandler);
- static RootObjectHandler installRootObjectHandler(RootObjectHandler);
-
- class Q_GUI_EXPORT ActivationObserver
- {
- public:
- virtual ~ActivationObserver();
- virtual void accessibilityActiveChanged(bool active) = 0;
- };
- static void installActivationObserver(ActivationObserver *);
- static void removeActivationObserver(ActivationObserver *);
-
- static QAccessibleInterface *queryAccessibleInterface(QObject *);
- static Id uniqueId(QAccessibleInterface *iface);
- static QAccessibleInterface *accessibleInterface(Id uniqueId);
- static Id registerAccessibleInterface(QAccessibleInterface *iface);
- static void deleteAccessibleInterface(Id uniqueId);
-
- static void updateAccessibility(QAccessibleEvent *event);
-
- static bool isActive();
- static void setActive(bool active);
- static void setRootObject(QObject *object);
-
- static void cleanup();
-
- static QPair< int, int > qAccessibleTextBoundaryHelper(const QTextCursor &cursor, TextBoundaryType boundaryType);
-
-private:
- static UpdateHandler updateHandler;
- static RootObjectHandler rootObjectHandler;
-
- QAccessible() {}
-
- friend class QAccessibleCache;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QAccessible::Relation)
-
class QAccessible2Interface;
class QAccessibleTextInterface;
class QAccessibleEditableTextInterface;
@@ -453,6 +42,8 @@ class QAccessibleImageInterface;
class QAccessibleTableInterface;
class QAccessibleTableCellInterface;
class QAccessibleHyperlinkInterface;
+class QAccessibleSelectionInterface;
+class QAccessibleAttributesInterface;
class QAccessibleTableModelChangeEvent;
class Q_GUI_EXPORT QAccessibleInterface
@@ -513,6 +104,12 @@ public:
inline QAccessibleHyperlinkInterface *hyperlinkInterface()
{ return reinterpret_cast<QAccessibleHyperlinkInterface *>(interface_cast(QAccessible::HyperlinkInterface)); }
+ inline QAccessibleSelectionInterface *selectionInterface()
+ { return reinterpret_cast<QAccessibleSelectionInterface *>(interface_cast(QAccessible::SelectionInterface)); }
+
+ inline QAccessibleAttributesInterface *attributesInterface()
+ { return reinterpret_cast<QAccessibleAttributesInterface *>(interface_cast(QAccessible::AttributesInterface)); }
+
virtual void virtual_hook(int id, void *data);
virtual void *interface_cast(QAccessible::InterfaceType)
@@ -676,6 +273,30 @@ public:
virtual bool isValid() const = 0;
};
+class Q_GUI_EXPORT QAccessibleSelectionInterface
+{
+public:
+ virtual ~QAccessibleSelectionInterface();
+
+ virtual int selectedItemCount() const = 0;
+ virtual QList<QAccessibleInterface*> selectedItems() const = 0;
+ virtual QAccessibleInterface* selectedItem(int selectionIndex) const;
+ virtual bool isSelected(QAccessibleInterface *childItem) const;
+ virtual bool select(QAccessibleInterface *childItem) = 0;
+ virtual bool unselect(QAccessibleInterface *childItem) = 0;
+ virtual bool selectAll() = 0;
+ virtual bool clear() = 0;
+};
+
+class Q_GUI_EXPORT QAccessibleAttributesInterface
+{
+public:
+ virtual ~QAccessibleAttributesInterface();
+ virtual QList<QAccessible::Attribute> attributeKeys() const = 0;
+ virtual QVariant attributeValue(QAccessible::Attribute key) const = 0;
+};
+
+
class Q_GUI_EXPORT QAccessibleEvent
{
Q_DISABLE_COPY(QAccessibleEvent)
@@ -698,7 +319,7 @@ public:
}
inline QAccessibleEvent(QAccessibleInterface *iface, QAccessible::Event typ)
- : m_type(typ), m_object(nullptr)
+ : m_type(typ)
{
Q_ASSERT(iface);
Q_ASSERT(m_type != QAccessible::ValueChanged);
@@ -710,6 +331,7 @@ public:
Q_ASSERT(m_type != QAccessible::TextUpdated);
Q_ASSERT(m_type != QAccessible::TableModelChanged);
m_uniqueId = QAccessible::uniqueId(iface);
+ m_object = iface->object();
}
virtual ~QAccessibleEvent();
@@ -819,13 +441,13 @@ class Q_GUI_EXPORT QAccessibleTextInsertEvent : public QAccessibleTextCursorEven
{
public:
inline QAccessibleTextInsertEvent(QObject *obj, int position, const QString &text)
- : QAccessibleTextCursorEvent(obj, position + int(text.length()))
+ : QAccessibleTextCursorEvent(obj, position + int(text.size()))
, m_position(position), m_text(text)
{
m_type = QAccessible::TextInserted;
}
inline QAccessibleTextInsertEvent(QAccessibleInterface *iface, int position, const QString &text)
- : QAccessibleTextCursorEvent(iface, position + int(text.length()))
+ : QAccessibleTextCursorEvent(iface, position + int(text.size()))
, m_position(position), m_text(text)
{
m_type = QAccessible::TextInserted;
@@ -879,13 +501,13 @@ class Q_GUI_EXPORT QAccessibleTextUpdateEvent : public QAccessibleTextCursorEven
{
public:
inline QAccessibleTextUpdateEvent(QObject *obj, int position, const QString &oldText, const QString &text)
- : QAccessibleTextCursorEvent(obj, position + int(text.length()))
+ : QAccessibleTextCursorEvent(obj, position + int(text.size()))
, m_position(position), m_oldText(oldText), m_text(text)
{
m_type = QAccessible::TextUpdated;
}
inline QAccessibleTextUpdateEvent(QAccessibleInterface *iface, int position, const QString &oldText, const QString &text)
- : QAccessibleTextCursorEvent(iface, position + int(text.length()))
+ : QAccessibleTextCursorEvent(iface, position + int(text.size()))
, m_position(position), m_oldText(oldText), m_text(text)
{
m_type = QAccessible::TextUpdated;
@@ -983,7 +605,7 @@ protected:
int m_lastColumn;
};
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
#define QAccessibleInterface_iid "org.qt-project.Qt.QAccessibleInterface"
Q_DECLARE_INTERFACE(QAccessibleInterface, QAccessibleInterface_iid)
#endif
@@ -999,5 +621,5 @@ Q_GUI_EXPORT QDebug operator<<(QDebug d, const QAccessibleEvent &ev);
QT_END_NAMESPACE
+#endif // QT_CONFIG(accessibility)
#endif // QACCESSIBLE_H
-#endif //!QT_NO_ACCESSIBILITY
diff --git a/src/gui/accessible/qaccessible_base.h b/src/gui/accessible/qaccessible_base.h
new file mode 100644
index 0000000000..2d2b1de316
--- /dev/null
+++ b/src/gui/accessible/qaccessible_base.h
@@ -0,0 +1,420 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QACCESSIBLE_BASE_H
+#define QACCESSIBLE_BASE_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#if 0
+// QAccessible class is handled in qaccessible.h
+#pragma qt_sync_stop_processing
+#endif
+
+#include <QtCore/qobjectdefs.h>
+
+#include <cstring> // memset, memcmp
+
+QT_BEGIN_NAMESPACE
+
+class QAccessibleInterface;
+class QAccessibleEvent;
+class QTextCursor;
+
+class Q_GUI_EXPORT QAccessible
+{
+ Q_GADGET
+public:
+
+ enum Event {
+ SoundPlayed = 0x0001,
+ Alert = 0x0002,
+ ForegroundChanged = 0x0003,
+ MenuStart = 0x0004,
+ MenuEnd = 0x0005,
+ PopupMenuStart = 0x0006,
+ PopupMenuEnd = 0x0007,
+ ContextHelpStart = 0x000C,
+ ContextHelpEnd = 0x000D,
+ DragDropStart = 0x000E,
+ DragDropEnd = 0x000F,
+ DialogStart = 0x0010,
+ DialogEnd = 0x0011,
+ ScrollingStart = 0x0012,
+ ScrollingEnd = 0x0013,
+
+ MenuCommand = 0x0018,
+
+ // Values from IAccessible2
+ ActionChanged = 0x0101,
+ ActiveDescendantChanged = 0x0102,
+ AttributeChanged = 0x0103,
+ DocumentContentChanged = 0x0104,
+ DocumentLoadComplete = 0x0105,
+ DocumentLoadStopped = 0x0106,
+ DocumentReload = 0x0107,
+ HyperlinkEndIndexChanged = 0x0108,
+ HyperlinkNumberOfAnchorsChanged = 0x0109,
+ HyperlinkSelectedLinkChanged = 0x010A,
+ HypertextLinkActivated = 0x010B,
+ HypertextLinkSelected = 0x010C,
+ HyperlinkStartIndexChanged = 0x010D,
+ HypertextChanged = 0x010E,
+ HypertextNLinksChanged = 0x010F,
+ ObjectAttributeChanged = 0x0110,
+ PageChanged = 0x0111,
+ SectionChanged = 0x0112,
+ TableCaptionChanged = 0x0113,
+ TableColumnDescriptionChanged = 0x0114,
+ TableColumnHeaderChanged = 0x0115,
+ TableModelChanged = 0x0116,
+ TableRowDescriptionChanged = 0x0117,
+ TableRowHeaderChanged = 0x0118,
+ TableSummaryChanged = 0x0119,
+ TextAttributeChanged = 0x011A,
+ TextCaretMoved = 0x011B,
+ // TextChanged = 0x011C, is deprecated in IA2, use TextUpdated
+ TextColumnChanged = 0x011D,
+ TextInserted = 0x011E,
+ TextRemoved = 0x011F,
+ TextUpdated = 0x0120,
+ TextSelectionChanged = 0x0121,
+ VisibleDataChanged = 0x0122,
+
+ ObjectCreated = 0x8000,
+ ObjectDestroyed = 0x8001,
+ ObjectShow = 0x8002,
+ ObjectHide = 0x8003,
+ ObjectReorder = 0x8004,
+ Focus = 0x8005,
+ Selection = 0x8006,
+ SelectionAdd = 0x8007,
+ SelectionRemove = 0x8008,
+ SelectionWithin = 0x8009,
+ StateChanged = 0x800A,
+ LocationChanged = 0x800B,
+ NameChanged = 0x800C,
+ DescriptionChanged = 0x800D,
+ ValueChanged = 0x800E,
+ ParentChanged = 0x800F,
+ HelpChanged = 0x80A0,
+ DefaultActionChanged = 0x80B0,
+ AcceleratorChanged = 0x80C0,
+
+ InvalidEvent
+ };
+ Q_ENUM(Event)
+
+ // 64 bit enums seem hard on some platforms (windows...)
+ // which makes using a bit field a sensible alternative
+ struct State {
+ // http://msdn.microsoft.com/en-us/library/ms697270.aspx
+ quint64 disabled : 1; // used to be Unavailable
+ quint64 selected : 1;
+ quint64 focusable : 1;
+ quint64 focused : 1;
+ quint64 pressed : 1;
+ quint64 checkable : 1;
+ quint64 checked : 1;
+ quint64 checkStateMixed : 1; // used to be Mixed
+ quint64 readOnly : 1;
+ quint64 hotTracked : 1;
+ quint64 defaultButton : 1;
+ quint64 expanded : 1;
+ quint64 collapsed : 1;
+ quint64 busy : 1;
+ quint64 expandable : 1;
+ quint64 marqueed : 1;
+ quint64 animated : 1;
+ quint64 invisible : 1;
+ quint64 offscreen : 1;
+ quint64 sizeable : 1;
+ quint64 movable : 1;
+ quint64 selfVoicing : 1;
+ quint64 selectable : 1;
+ quint64 linked : 1;
+ quint64 traversed : 1;
+ quint64 multiSelectable : 1;
+ quint64 extSelectable : 1;
+ quint64 passwordEdit : 1; // used to be Protected
+ quint64 hasPopup : 1;
+ quint64 modal : 1;
+
+ // IA2 - we chose to not add some IA2 states for now
+ // Below the ones that seem helpful
+ quint64 active : 1;
+ quint64 invalid : 1; // = defunct
+ quint64 editable : 1;
+ quint64 multiLine : 1;
+ quint64 selectableText : 1;
+ quint64 supportsAutoCompletion : 1;
+
+ quint64 searchEdit : 1;
+
+ // quint64 horizontal : 1;
+ // quint64 vertical : 1;
+ // quint64 invalidEntry : 1;
+ // quint64 managesDescendants : 1;
+ // quint64 singleLine : 1; // we have multi line, this is redundant.
+ // quint64 stale : 1;
+ // quint64 transient : 1;
+ // quint64 pinned : 1;
+
+ // Apple - see http://mattgemmell.com/2010/12/19/accessibility-for-iphone-and-ipad-apps/
+ // quint64 playsSound : 1;
+ // quint64 summaryElement : 1;
+ // quint64 updatesFrequently : 1;
+ // quint64 adjustable : 1;
+ // more and not included here: http://developer.apple.com/library/mac/#documentation/UserExperience/Reference/Accessibility_RoleAttribute_Ref/Attributes.html
+
+ // MSAA
+ // quint64 alertLow : 1;
+ // quint64 alertMedium : 1;
+ // quint64 alertHigh : 1;
+
+ State() {
+ std::memset(this, 0, sizeof(State));
+ }
+ friend inline bool operator==(const QAccessible::State &first, const QAccessible::State &second)
+ {
+ return std::memcmp(&first, &second, sizeof(QAccessible::State)) == 0;
+ }
+ };
+
+
+
+
+
+ enum Role {
+ NoRole = 0x00000000,
+ TitleBar = 0x00000001,
+ MenuBar = 0x00000002,
+ ScrollBar = 0x00000003,
+ Grip = 0x00000004,
+ Sound = 0x00000005,
+ Cursor = 0x00000006,
+ Caret = 0x00000007,
+ AlertMessage = 0x00000008,
+ Window = 0x00000009,
+ Client = 0x0000000A,
+ PopupMenu = 0x0000000B,
+ MenuItem = 0x0000000C,
+ ToolTip = 0x0000000D,
+ Application = 0x0000000E,
+ Document = 0x0000000F,
+ Pane = 0x00000010,
+ Chart = 0x00000011,
+ Dialog = 0x00000012,
+ Border = 0x00000013,
+ Grouping = 0x00000014,
+ Separator = 0x00000015,
+ ToolBar = 0x00000016,
+ StatusBar = 0x00000017,
+ Table = 0x00000018,
+ ColumnHeader = 0x00000019,
+ RowHeader = 0x0000001A,
+ Column = 0x0000001B,
+ Row = 0x0000001C,
+ Cell = 0x0000001D,
+ Link = 0x0000001E,
+ HelpBalloon = 0x0000001F,
+ Assistant = 0x00000020,
+ List = 0x00000021,
+ ListItem = 0x00000022,
+ Tree = 0x00000023,
+ TreeItem = 0x00000024,
+ PageTab = 0x00000025,
+ PropertyPage = 0x00000026,
+ Indicator = 0x00000027,
+ Graphic = 0x00000028,
+ StaticText = 0x00000029,
+ EditableText = 0x0000002A, // Editable, selectable, etc.
+ Button = 0x0000002B,
+#ifndef Q_QDOC
+ PushButton = Button, // deprecated
+#endif
+ CheckBox = 0x0000002C,
+ RadioButton = 0x0000002D,
+ ComboBox = 0x0000002E,
+ // DropList = 0x0000002F,
+ ProgressBar = 0x00000030,
+ Dial = 0x00000031,
+ HotkeyField = 0x00000032,
+ Slider = 0x00000033,
+ SpinBox = 0x00000034,
+ Canvas = 0x00000035, // MSAA: ROLE_SYSTEM_DIAGRAM - The object represents a graphical image that is used to diagram data.
+ Animation = 0x00000036,
+ Equation = 0x00000037,
+ ButtonDropDown = 0x00000038, // The object represents a button that expands a grid.
+ ButtonMenu = 0x00000039,
+ ButtonDropGrid = 0x0000003A,
+ Whitespace = 0x0000003B, // The object represents blank space between other objects.
+ PageTabList = 0x0000003C,
+ Clock = 0x0000003D,
+ Splitter = 0x0000003E,
+ // Reserved space in case MSAA roles needs to be added
+
+ // Additional Qt roles where enum value does not map directly to MSAA:
+ LayeredPane = 0x00000080,
+ Terminal = 0x00000081,
+ Desktop = 0x00000082,
+ Paragraph = 0x00000083,
+ WebDocument = 0x00000084,
+ Section = 0x00000085,
+ Notification = 0x00000086,
+
+ // IAccessible2 roles
+ // IA2_ROLE_CANVAS = 0x401, // An object that can be drawn into and to manage events from the objects drawn into it
+ // IA2_ROLE_CAPTION = 0x402,
+ // IA2_ROLE_CHECK_MENU_ITEM = 0x403,
+ ColorChooser = 0x404,
+ // IA2_ROLE_DATE_EDITOR = 0x405,
+ // IA2_ROLE_DESKTOP_ICON = 0x406,
+ // IA2_ROLE_DESKTOP_PANE = 0x407,
+ // IA2_ROLE_DIRECTORY_PANE = 0x408,
+ // IA2_ROLE_EDITBAR = 0x409,
+ // IA2_ROLE_EMBEDDED_OBJECT = 0x40A,
+ // IA2_ROLE_ENDNOTE = 0x40B,
+ // IA2_ROLE_FILE_CHOOSER = 0x40C,
+ // IA2_ROLE_FONT_CHOOSER = 0x40D,
+ Footer = 0x40E,
+ // IA2_ROLE_FOOTNOTE = 0x40F,
+ Form = 0x410,
+ // some platforms (windows and at-spi) use Frame for regular windows
+ // because window was taken for tool/dock windows by MSAA
+ // Frame = 0x411,
+ // IA2_ROLE_GLASS_PANE = 0x412,
+ // IA2_ROLE_HEADER = 0x413,
+ Heading = 0x414,
+ // IA2_ROLE_ICON = 0x415,
+ // IA2_ROLE_IMAGE_MAP = 0x416,
+ // IA2_ROLE_INPUT_METHOD_WINDOW = 0x417,
+ // IA2_ROLE_INTERNAL_FRAME = 0x418,
+ // IA2_ROLE_LABEL = 0x419,
+ // IA2_ROLE_LAYERED_PANE = 0x41A,
+ Note = 0x41B,
+ // IA2_ROLE_OPTION_PANE = 0x41C,
+ // IA2_ROLE_PAGE = 0x41D,
+ // IA2_ROLE_PARAGRAPH = 0x42E,
+ // IA2_ROLE_RADIO_MENU_ITEM = 0x41F,
+ // IA2_ROLE_REDUNDANT_OBJECT = 0x420,
+ // IA2_ROLE_ROOT_PANE = 0x421,
+ // IA2_ROLE_RULER = 0x422,
+ // IA2_ROLE_SCROLL_PANE = 0x423,
+ // IA2_ROLE_SECTION = 0x424,
+ // IA2_ROLE_SHAPE = 0x425,
+ // IA2_ROLE_SPLIT_PANE = 0x426,
+ // IA2_ROLE_TEAR_OFF_MENU = 0x427,
+ // IA2_ROLE_TERMINAL = 0x428,
+ // IA2_ROLE_TEXT_FRAME = 0x429,
+ // IA2_ROLE_TOGGLE_BUTTON = 0x42A,
+ // IA2_ROLE_VIEW_PORT = 0x42B,
+ ComplementaryContent = 0x42C,
+
+ UserRole = 0x0000ffff
+ };
+ Q_ENUM(Role)
+
+ enum Text {
+ Name = 0,
+ Description,
+ Value,
+ Help,
+ Accelerator,
+ DebugDescription,
+ UserText = 0x0000ffff
+ };
+
+ enum RelationFlag {
+ Label = 0x00000001,
+ Labelled = 0x00000002,
+ Controller = 0x00000004,
+ Controlled = 0x00000008,
+ DescriptionFor = 0x00000010,
+ Described = 0x00000020,
+ FlowsFrom = 0x00000040,
+ FlowsTo = 0x00000080,
+ AllRelations = 0xffffffff
+ };
+ Q_DECLARE_FLAGS(Relation, RelationFlag)
+
+ enum InterfaceType
+ {
+ TextInterface,
+ EditableTextInterface,
+ ValueInterface,
+ ActionInterface,
+ ImageInterface,
+ TableInterface,
+ TableCellInterface,
+ HyperlinkInterface,
+ SelectionInterface,
+ AttributesInterface,
+ };
+
+ enum TextBoundaryType {
+ CharBoundary,
+ WordBoundary,
+ SentenceBoundary,
+ ParagraphBoundary,
+ LineBoundary,
+ NoBoundary
+ };
+
+ enum class Attribute {
+ Custom,
+ Level,
+ };
+
+ typedef QAccessibleInterface*(*InterfaceFactory)(const QString &key, QObject*);
+ typedef void(*UpdateHandler)(QAccessibleEvent *event);
+ typedef void(*RootObjectHandler)(QObject*);
+
+ typedef unsigned Id;
+
+ static void installFactory(InterfaceFactory);
+ static void removeFactory(InterfaceFactory);
+ static UpdateHandler installUpdateHandler(UpdateHandler);
+ static RootObjectHandler installRootObjectHandler(RootObjectHandler);
+
+ class Q_GUI_EXPORT ActivationObserver
+ {
+ public:
+ virtual ~ActivationObserver();
+ virtual void accessibilityActiveChanged(bool active) = 0;
+ };
+ static void installActivationObserver(ActivationObserver *);
+ static void removeActivationObserver(ActivationObserver *);
+
+ static QAccessibleInterface *queryAccessibleInterface(QObject *);
+ static Id uniqueId(QAccessibleInterface *iface);
+ static QAccessibleInterface *accessibleInterface(Id uniqueId);
+ static Id registerAccessibleInterface(QAccessibleInterface *iface);
+ static void deleteAccessibleInterface(Id uniqueId);
+
+ static void updateAccessibility(QAccessibleEvent *event);
+
+ static bool isActive();
+ static void setActive(bool active);
+ static void setRootObject(QObject *object);
+
+ static void cleanup();
+
+ static QPair< int, int > qAccessibleTextBoundaryHelper(const QTextCursor &cursor, TextBoundaryType boundaryType);
+
+private:
+ static UpdateHandler updateHandler;
+ static RootObjectHandler rootObjectHandler;
+
+ QAccessible() {}
+
+ friend class QAccessibleCache;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QAccessible::Relation)
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+#endif // QACCESSIBLE_BASE_H
diff --git a/src/gui/accessible/qaccessiblebridge.cpp b/src/gui/accessible/qaccessiblebridge.cpp
index c6a417e063..a8b54b0c68 100644
--- a/src/gui/accessible/qaccessiblebridge.cpp
+++ b/src/gui/accessible/qaccessiblebridge.cpp
@@ -1,45 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qaccessiblebridge.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QT_BEGIN_NAMESPACE
@@ -138,4 +102,6 @@ QAccessibleBridgePlugin::~QAccessibleBridgePlugin()
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#include "moc_qaccessiblebridge.cpp"
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/gui/accessible/qaccessiblebridge.h b/src/gui/accessible/qaccessiblebridge.h
index 168889135b..4d817c8e58 100644
--- a/src/gui/accessible/qaccessiblebridge.h
+++ b/src/gui/accessible/qaccessiblebridge.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QACCESSIBLEBRIDGE_H
#define QACCESSIBLEBRIDGE_H
@@ -47,7 +11,7 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
class QAccessibleInterface;
class QAccessibleEvent;
@@ -72,7 +36,7 @@ public:
virtual QAccessibleBridge *create(const QString &key) = 0;
};
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
QT_END_NAMESPACE
diff --git a/src/gui/accessible/qaccessiblebridgeutils.cpp b/src/gui/accessible/qaccessiblebridgeutils.cpp
index a15b93e31e..994f95fee9 100644
--- a/src/gui/accessible/qaccessiblebridgeutils.cpp
+++ b/src/gui/accessible/qaccessiblebridgeutils.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qaccessiblebridgeutils_p.h"
#include <QtCore/qmath.h>
diff --git a/src/gui/accessible/qaccessiblebridgeutils_p.h b/src/gui/accessible/qaccessiblebridgeutils_p.h
index f34fcc5816..b65a4d0b6c 100644
--- a/src/gui/accessible/qaccessiblebridgeutils_p.h
+++ b/src/gui/accessible/qaccessiblebridgeutils_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QACCESSIBLEBRIDGEUTILS_H
#define QACCESSIBLEBRIDGEUTILS_H
diff --git a/src/gui/accessible/qaccessiblecache.cpp b/src/gui/accessible/qaccessiblecache.cpp
index 84d0936386..b41a2481f9 100644
--- a/src/gui/accessible/qaccessiblecache.cpp
+++ b/src/gui/accessible/qaccessiblecache.cpp
@@ -1,47 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qaccessiblecache_p.h"
#include <QtCore/qdebug.h>
#include <QtCore/qloggingcategory.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QT_BEGIN_NAMESPACE
@@ -84,18 +48,18 @@ QAccessibleCache *QAccessibleCache::instance()
QAccessible::Id QAccessibleCache::acquireId() const
{
static const QAccessible::Id FirstId = QAccessible::Id(INT_MAX) + 1;
- static QAccessible::Id lastUsedId = FirstId;
+ static QAccessible::Id nextId = FirstId;
- while (idToInterface.contains(lastUsedId)) {
+ while (idToInterface.contains(nextId)) {
// (wrap back when when we reach UINT_MAX - 1)
// -1 because on Android -1 is taken for the "View" so just avoid it completely for consistency
- if (lastUsedId == UINT_MAX - 1)
- lastUsedId = FirstId;
+ if (nextId == UINT_MAX - 1)
+ nextId = FirstId;
else
- ++lastUsedId;
+ ++nextId;
}
- return lastUsedId;
+ return nextId++;
}
QAccessibleInterface *QAccessibleCache::interfaceForId(QAccessible::Id id) const
@@ -166,7 +130,7 @@ void QAccessibleCache::objectDestroyed(QObject* obj)
/*
In some cases we might add a not fully-constructed object to the cache. This might happen with
for instance QWidget subclasses that are in the construction phase. If updateAccessibility() is
- called in the constructor of QWidget (directly or indirectly), it it will end up asking for the
+ called in the constructor of QWidget (directly or indirectly), it will end up asking for the
classname of that widget in order to know which accessibility interface subclass the
accessibility factory should instantiate and return. However, since that requires a virtual
call to metaObject(), it will return the metaObject() of QWidget (not for the subclass), and so
@@ -215,4 +179,6 @@ void QAccessibleCache::deleteInterface(QAccessible::Id id, QObject *obj)
QT_END_NAMESPACE
+#include "moc_qaccessiblecache_p.cpp"
+
#endif
diff --git a/src/gui/accessible/qaccessiblecache_mac.mm b/src/gui/accessible/qaccessiblecache_mac.mm
index 3f49eb98fd..77a9613d38 100644
--- a/src/gui/accessible/qaccessiblecache_mac.mm
+++ b/src/gui/accessible/qaccessiblecache_mac.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qaccessiblecache_p.h"
diff --git a/src/gui/accessible/qaccessiblecache_p.h b/src/gui/accessible/qaccessiblecache_p.h
index 387a54e783..d1abca0f5d 100644
--- a/src/gui/accessible/qaccessiblecache_p.h
+++ b/src/gui/accessible/qaccessiblecache_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QACCESSIBLECACHE_P
#define QACCESSIBLECACHE_P
@@ -57,7 +21,7 @@
#include "qaccessible.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QMacAccessibilityElement));
@@ -103,6 +67,6 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif
diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp
index 771cfda574..61d3a90632 100644
--- a/src/gui/accessible/qaccessibleobject.cpp
+++ b/src/gui/accessible/qaccessibleobject.cpp
@@ -1,45 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qaccessibleobject.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
@@ -160,7 +124,7 @@ static QObjectList topLevelObjects()
{
QObjectList list;
const QWindowList tlw(QGuiApplication::topLevelWindows());
- for (int i = 0; i < tlw.count(); ++i) {
+ for (int i = 0; i < tlw.size(); ++i) {
QWindow *w = tlw.at(i);
if (w->type() != Qt::Popup && w->type() != Qt::Desktop) {
if (QAccessibleInterface *root = w->accessibleRoot()) {
@@ -176,7 +140,7 @@ static QObjectList topLevelObjects()
/*! \reimp */
int QAccessibleApplication::childCount() const
{
- return topLevelObjects().count();
+ return topLevelObjects().size();
}
/*! \reimp */
@@ -196,7 +160,7 @@ QAccessibleInterface *QAccessibleApplication::parent() const
QAccessibleInterface *QAccessibleApplication::child(int index) const
{
const QObjectList tlo(topLevelObjects());
- if (index >= 0 && index < tlo.count())
+ if (index >= 0 && index < tlo.size())
return QAccessible::queryAccessibleInterface(tlo.at(index));
return nullptr;
}
@@ -239,4 +203,4 @@ QAccessible::State QAccessibleApplication::state() const
QT_END_NAMESPACE
-#endif //QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
diff --git a/src/gui/accessible/qaccessibleobject.h b/src/gui/accessible/qaccessibleobject.h
index fd07d33a18..8e7dd1399c 100644
--- a/src/gui/accessible/qaccessibleobject.h
+++ b/src/gui/accessible/qaccessibleobject.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QACCESSIBLEOBJECT_H
#define QACCESSIBLEOBJECT_H
@@ -46,7 +10,7 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
class QAccessibleObjectPrivate;
class QObject;
@@ -93,7 +57,7 @@ public:
QAccessible::State state() const override;
};
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
QT_END_NAMESPACE
diff --git a/src/gui/accessible/qaccessibleplugin.cpp b/src/gui/accessible/qaccessibleplugin.cpp
index 27497858b5..524d67bf35 100644
--- a/src/gui/accessible/qaccessibleplugin.cpp
+++ b/src/gui/accessible/qaccessibleplugin.cpp
@@ -1,45 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qglobal.h>
-
-#ifndef QT_NO_ACCESSIBILITY
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtGui/qtguiglobal.h>
+
+#if QT_CONFIG(accessibility)
#include "qaccessibleplugin.h"
#include "qaccessible.h"
@@ -48,6 +12,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QAccessiblePlugin
+ \inmodule QtGui
\brief The QAccessiblePlugin class provides an abstract base class
for plugins provinding accessibility information for user interface elements.
@@ -89,4 +54,6 @@ QAccessiblePlugin::~QAccessiblePlugin()
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#include "moc_qaccessibleplugin.cpp"
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/gui/accessible/qaccessibleplugin.h b/src/gui/accessible/qaccessibleplugin.h
index 04169fdeac..014f714b09 100644
--- a/src/gui/accessible/qaccessibleplugin.h
+++ b/src/gui/accessible/qaccessibleplugin.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QACCESSIBLEPLUGIN_H
#define QACCESSIBLEPLUGIN_H
@@ -47,7 +11,7 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
class QAccessibleInterface;
@@ -65,7 +29,7 @@ public:
virtual QAccessibleInterface *create(const QString &key, QObject *object) = 0;
};
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
QT_END_NAMESPACE
diff --git a/src/gui/accessible/qplatformaccessibility.cpp b/src/gui/accessible/qplatformaccessibility.cpp
index 75caeec5dc..ae7635ff7c 100644
--- a/src/gui/accessible/qplatformaccessibility.cpp
+++ b/src/gui/accessible/qplatformaccessibility.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformaccessibility.h"
#include <private/qfactoryloader_p.h>
#include "qaccessibleplugin.h"
@@ -47,11 +11,13 @@
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_ACCESSIBILITY
+using namespace Qt::StringLiterals;
+
+#if QT_CONFIG(accessibility)
/* accessiblebridge plugin discovery stuff */
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, bridgeloader,
- (QAccessibleBridgeFactoryInterface_iid, QLatin1String("/accessiblebridge")))
+ (QAccessibleBridgeFactoryInterface_iid, "/accessiblebridge"_L1))
Q_GLOBAL_STATIC(QList<QAccessibleBridge *>, bridges)
@@ -84,7 +50,7 @@ void QPlatformAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
if (!bridges() || bridges()->isEmpty())
return;
- for (int i = 0; i < bridges()->count(); ++i)
+ for (int i = 0; i < bridges()->size(); ++i)
bridges()->at(i)->notifyAccessibilityUpdate(event);
}
@@ -97,7 +63,7 @@ void QPlatformAccessibility::setRootObject(QObject *o)
if (!o)
return;
- for (int i = 0; i < bridges()->count(); ++i) {
+ for (int i = 0; i < bridges()->size(); ++i) {
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(o);
bridges()->at(i)->setRootObject(iface);
}
@@ -139,6 +105,6 @@ void QPlatformAccessibility::setActive(bool active)
QAccessible::setActive(active);
}
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
QT_END_NAMESPACE
diff --git a/src/gui/accessible/qplatformaccessibility.h b/src/gui/accessible/qplatformaccessibility.h
index 5d668c2bd6..004fcfb40f 100644
--- a/src/gui/accessible/qplatformaccessibility.h
+++ b/src/gui/accessible/qplatformaccessibility.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMACCESSIBILITY_H
#define QPLATFORMACCESSIBILITY_H
@@ -50,7 +14,7 @@
#include <QtGui/qtguiglobal.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtCore/qobject.h>
#include <QtGui/qaccessible.h>
@@ -78,6 +42,6 @@ private:
QT_END_NAMESPACE
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
#endif // QPLATFORMACCESSIBILITY_H
diff --git a/src/gui/accessible/windows/apisupport/qwindowsuiawrapper.cpp b/src/gui/accessible/windows/apisupport/qwindowsuiawrapper.cpp
deleted file mode 100644
index 8038e1a3c3..0000000000
--- a/src/gui/accessible/windows/apisupport/qwindowsuiawrapper.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <initguid.h>
-
-#include "qwindowsuiawrapper_p.h"
-#include <QtCore/private/qsystemlibrary_p.h>
-
-QT_BEGIN_NAMESPACE
-
-// private constructor
-QWindowsUiaWrapper::QWindowsUiaWrapper()
-{
- QSystemLibrary uiaLib(QStringLiteral("UIAutomationCore"));
- if (uiaLib.load()) {
- m_pUiaReturnRawElementProvider = reinterpret_cast<PtrUiaReturnRawElementProvider>(uiaLib.resolve("UiaReturnRawElementProvider"));
- m_pUiaHostProviderFromHwnd = reinterpret_cast<PtrUiaHostProviderFromHwnd>(uiaLib.resolve("UiaHostProviderFromHwnd"));
- m_pUiaRaiseAutomationPropertyChangedEvent = reinterpret_cast<PtrUiaRaiseAutomationPropertyChangedEvent>(uiaLib.resolve("UiaRaiseAutomationPropertyChangedEvent"));
- m_pUiaRaiseAutomationEvent = reinterpret_cast<PtrUiaRaiseAutomationEvent>(uiaLib.resolve("UiaRaiseAutomationEvent"));
- m_pUiaRaiseNotificationEvent = reinterpret_cast<PtrUiaRaiseNotificationEvent>(uiaLib.resolve("UiaRaiseNotificationEvent"));
- m_pUiaClientsAreListening = reinterpret_cast<PtrUiaClientsAreListening>(uiaLib.resolve("UiaClientsAreListening"));
- }
-}
-
-QWindowsUiaWrapper::~QWindowsUiaWrapper()
-{
-}
-
-// shared instance
-QWindowsUiaWrapper *QWindowsUiaWrapper::instance()
-{
- static QWindowsUiaWrapper wrapper;
- return &wrapper;
-}
-
-// True if most symbols resolved (UiaRaiseNotificationEvent is optional).
-BOOL QWindowsUiaWrapper::ready()
-{
- return m_pUiaReturnRawElementProvider
- && m_pUiaHostProviderFromHwnd
- && m_pUiaRaiseAutomationPropertyChangedEvent
- && m_pUiaRaiseAutomationEvent
- && m_pUiaClientsAreListening;
-}
-
-BOOL QWindowsUiaWrapper::clientsAreListening()
-{
- if (!m_pUiaClientsAreListening)
- return FALSE;
- return m_pUiaClientsAreListening();
-}
-
-LRESULT QWindowsUiaWrapper::returnRawElementProvider(HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *el)
-{
- if (!m_pUiaReturnRawElementProvider)
- return static_cast<LRESULT>(NULL);
- return m_pUiaReturnRawElementProvider(hwnd, wParam, lParam, el);
-}
-
-HRESULT QWindowsUiaWrapper::hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider)
-{
- if (!m_pUiaHostProviderFromHwnd)
- return UIA_E_NOTSUPPORTED;
- return m_pUiaHostProviderFromHwnd(hwnd, ppProvider);
-}
-
-HRESULT QWindowsUiaWrapper::raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue)
-{
- if (!m_pUiaRaiseAutomationPropertyChangedEvent)
- return UIA_E_NOTSUPPORTED;
- return m_pUiaRaiseAutomationPropertyChangedEvent(pProvider, id, oldValue, newValue);
-}
-
-HRESULT QWindowsUiaWrapper::raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id)
-{
- if (!m_pUiaRaiseAutomationEvent)
- return UIA_E_NOTSUPPORTED;
- return m_pUiaRaiseAutomationEvent(pProvider, id);
-}
-
-HRESULT QWindowsUiaWrapper::raiseNotificationEvent(IRawElementProviderSimple *provider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId)
-{
- if (!m_pUiaRaiseNotificationEvent)
- return UIA_E_NOTSUPPORTED;
- return m_pUiaRaiseNotificationEvent(provider, notificationKind, notificationProcessing, displayString, activityId);
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/gui/accessible/windows/apisupport/qwindowsuiawrapper_p.h b/src/gui/accessible/windows/apisupport/qwindowsuiawrapper_p.h
deleted file mode 100644
index b814295215..0000000000
--- a/src/gui/accessible/windows/apisupport/qwindowsuiawrapper_p.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QWINDOWSUIAWRAPPER_H
-#define QWINDOWSUIAWRAPPER_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#include "uiatypes_p.h"
-#include "uiaattributeids_p.h"
-#include "uiacontroltypeids_p.h"
-#include "uiaerrorids_p.h"
-#include "uiaeventids_p.h"
-#include "uiageneralids_p.h"
-#include "uiapatternids_p.h"
-#include "uiapropertyids_p.h"
-#include "uiaserverinterfaces_p.h"
-#include "uiaclientinterfaces_p.h"
-
-QT_REQUIRE_CONFIG(accessibility);
-
-QT_BEGIN_NAMESPACE
-
-class Q_GUI_EXPORT QWindowsUiaWrapper
-{
- QWindowsUiaWrapper();
- virtual ~QWindowsUiaWrapper();
-public:
- static QWindowsUiaWrapper *instance();
- BOOL ready();
- BOOL clientsAreListening();
- LRESULT returnRawElementProvider(HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *el);
- HRESULT hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider);
- HRESULT raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue);
- HRESULT raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id);
- HRESULT raiseNotificationEvent(IRawElementProviderSimple *provider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId);
-
-private:
- typedef LRESULT (WINAPI *PtrUiaReturnRawElementProvider)(HWND, WPARAM, LPARAM, IRawElementProviderSimple *);
- typedef HRESULT (WINAPI *PtrUiaHostProviderFromHwnd)(HWND, IRawElementProviderSimple **);
- typedef HRESULT (WINAPI *PtrUiaRaiseAutomationPropertyChangedEvent)(IRawElementProviderSimple *, PROPERTYID, VARIANT, VARIANT);
- typedef HRESULT (WINAPI *PtrUiaRaiseAutomationEvent)(IRawElementProviderSimple *, EVENTID);
- typedef HRESULT (WINAPI *PtrUiaRaiseNotificationEvent)(IRawElementProviderSimple *, NotificationKind, NotificationProcessing, BSTR, BSTR);
- typedef BOOL (WINAPI *PtrUiaClientsAreListening)();
- PtrUiaReturnRawElementProvider m_pUiaReturnRawElementProvider = nullptr;
- PtrUiaHostProviderFromHwnd m_pUiaHostProviderFromHwnd = nullptr;
- PtrUiaRaiseAutomationPropertyChangedEvent m_pUiaRaiseAutomationPropertyChangedEvent = nullptr;
- PtrUiaRaiseAutomationEvent m_pUiaRaiseAutomationEvent = nullptr;
- PtrUiaRaiseNotificationEvent m_pUiaRaiseNotificationEvent = nullptr;
- PtrUiaClientsAreListening m_pUiaClientsAreListening = nullptr;
-};
-
-QT_END_NAMESPACE
-
-#endif //QWINDOWSUIAWRAPPER_H
-
diff --git a/src/gui/accessible/windows/apisupport/uiaattributeids_p.h b/src/gui/accessible/windows/apisupport/uiaattributeids_p.h
deleted file mode 100644
index 795cb9e551..0000000000
--- a/src/gui/accessible/windows/apisupport/uiaattributeids_p.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef UIAATTRIBUTEIDS_H
-#define UIAATTRIBUTEIDS_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#define UIA_AnimationStyleAttributeId 40000
-#define UIA_BackgroundColorAttributeId 40001
-#define UIA_BulletStyleAttributeId 40002
-#define UIA_CapStyleAttributeId 40003
-#define UIA_CultureAttributeId 40004
-#define UIA_FontNameAttributeId 40005
-#define UIA_FontSizeAttributeId 40006
-#define UIA_FontWeightAttributeId 40007
-#define UIA_ForegroundColorAttributeId 40008
-#define UIA_HorizontalTextAlignmentAttributeId 40009
-#define UIA_IndentationFirstLineAttributeId 40010
-#define UIA_IndentationLeadingAttributeId 40011
-#define UIA_IndentationTrailingAttributeId 40012
-#define UIA_IsHiddenAttributeId 40013
-#define UIA_IsItalicAttributeId 40014
-#define UIA_IsReadOnlyAttributeId 40015
-#define UIA_IsSubscriptAttributeId 40016
-#define UIA_IsSuperscriptAttributeId 40017
-#define UIA_MarginBottomAttributeId 40018
-#define UIA_MarginLeadingAttributeId 40019
-#define UIA_MarginTopAttributeId 40020
-#define UIA_MarginTrailingAttributeId 40021
-#define UIA_OutlineStylesAttributeId 40022
-#define UIA_OverlineColorAttributeId 40023
-#define UIA_OverlineStyleAttributeId 40024
-#define UIA_StrikethroughColorAttributeId 40025
-#define UIA_StrikethroughStyleAttributeId 40026
-#define UIA_TabsAttributeId 40027
-#define UIA_TextFlowDirectionsAttributeId 40028
-#define UIA_UnderlineColorAttributeId 40029
-#define UIA_UnderlineStyleAttributeId 40030
-#define UIA_AnnotationTypesAttributeId 40031
-#define UIA_AnnotationObjectsAttributeId 40032
-#define UIA_StyleNameAttributeId 40033
-#define UIA_StyleIdAttributeId 40034
-#define UIA_LinkAttributeId 40035
-#define UIA_IsActiveAttributeId 40036
-#define UIA_SelectionActiveEndAttributeId 40037
-#define UIA_CaretPositionAttributeId 40038
-#define UIA_CaretBidiModeAttributeId 40039
-#define UIA_LineSpacingAttributeId 40040
-#define UIA_BeforeParagraphSpacingAttributeId 40041
-#define UIA_AfterParagraphSpacingAttributeId 40042
-#define UIA_SayAsInterpretAsAttributeId 40043
-
-#endif
diff --git a/src/gui/accessible/windows/apisupport/uiaclientinterfaces_p.h b/src/gui/accessible/windows/apisupport/uiaclientinterfaces_p.h
deleted file mode 100644
index a4f3e15baa..0000000000
--- a/src/gui/accessible/windows/apisupport/uiaclientinterfaces_p.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef UIACLIENTINTERFACES_H
-#define UIACLIENTINTERFACES_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <unknwn.h>
-
-#ifndef __IUIAutomationElement_INTERFACE_DEFINED__
-
-struct IUIAutomationCondition;
-struct IUIAutomationCacheRequest;
-struct IUIAutomationElementArray;
-struct IUIAutomationTreeWalker;
-struct IUIAutomationEventHandler;
-struct IUIAutomationPropertyChangedEventHandler;
-struct IUIAutomationStructureChangedEventHandler;
-struct IUIAutomationFocusChangedEventHandler;
-struct IUIAutomationProxyFactory;
-struct IUIAutomationProxyFactoryEntry;
-struct IUIAutomationProxyFactoryMapping;
-#ifndef __IAccessible_FWD_DEFINED__
-#define __IAccessible_FWD_DEFINED__
-struct IAccessible;
-#endif /* __IAccessible_FWD_DEFINED__ */
-
-#define __IUIAutomationElement_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IUIAutomationElement, 0xd22108aa, 0x8ac5, 0x49a5, 0x83,0x7b, 0x37,0xbb,0xb3,0xd7,0x59,0x1e);
-MIDL_INTERFACE("d22108aa-8ac5-49a5-837b-37bbb3d7591e")
-IUIAutomationElement : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE SetFocus() = 0;
- virtual HRESULT STDMETHODCALLTYPE GetRuntimeId(__RPC__deref_out_opt SAFEARRAY **runtimeId) = 0;
- virtual HRESULT STDMETHODCALLTYPE FindFirst(enum TreeScope scope, __RPC__in_opt IUIAutomationCondition *condition, __RPC__deref_out_opt IUIAutomationElement **found) = 0;
- virtual HRESULT STDMETHODCALLTYPE FindAll(enum TreeScope scope, __RPC__in_opt IUIAutomationCondition *condition, __RPC__deref_out_opt IUIAutomationElementArray **found) = 0;
- virtual HRESULT STDMETHODCALLTYPE FindFirstBuildCache(enum TreeScope scope, __RPC__in_opt IUIAutomationCondition *condition, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **found) = 0;
- virtual HRESULT STDMETHODCALLTYPE FindAllBuildCache(enum TreeScope scope, __RPC__in_opt IUIAutomationCondition *condition, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElementArray **found) = 0;
- virtual HRESULT STDMETHODCALLTYPE BuildUpdatedCache(__RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **updatedElement) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCurrentPropertyValue(PROPERTYID propertyId, __RPC__out VARIANT *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCurrentPropertyValueEx(PROPERTYID propertyId, BOOL ignoreDefaultValue, __RPC__out VARIANT *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCachedPropertyValue(PROPERTYID propertyId, __RPC__out VARIANT *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCachedPropertyValueEx(PROPERTYID propertyId, BOOL ignoreDefaultValue, __RPC__out VARIANT *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCurrentPatternAs(PATTERNID patternId, __RPC__in REFIID riid, __RPC__deref_out_opt void **patternObject) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCachedPatternAs(PATTERNID patternId, __RPC__in REFIID riid, __RPC__deref_out_opt void **patternObject) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCurrentPattern(PATTERNID patternId, __RPC__deref_out_opt IUnknown **patternObject) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCachedPattern(PATTERNID patternId, __RPC__deref_out_opt IUnknown **patternObject) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCachedParent(__RPC__deref_out_opt IUIAutomationElement **parent) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCachedChildren(__RPC__deref_out_opt IUIAutomationElementArray **children) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentProcessId(__RPC__out int *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentControlType(__RPC__out CONTROLTYPEID *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentLocalizedControlType(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentName(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentAcceleratorKey(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentAccessKey(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentHasKeyboardFocus(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentIsKeyboardFocusable(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentIsEnabled(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentAutomationId(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentClassName(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentHelpText(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentCulture(__RPC__out int *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentIsControlElement(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentIsContentElement(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentIsPassword(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentNativeWindowHandle(__RPC__deref_out_opt UIA_HWND *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentItemType(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentIsOffscreen(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentOrientation(__RPC__out enum OrientationType *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentFrameworkId(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentIsRequiredForForm(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentItemStatus(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentBoundingRectangle(__RPC__out RECT *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentLabeledBy(__RPC__deref_out_opt IUIAutomationElement **retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentAriaRole(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentAriaProperties(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentIsDataValidForForm(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentControllerFor(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentDescribedBy(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentFlowsTo(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CurrentProviderDescription(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedProcessId(__RPC__out int *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedControlType(__RPC__out CONTROLTYPEID *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedLocalizedControlType(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedName(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedAcceleratorKey(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedAccessKey(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedHasKeyboardFocus(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedIsKeyboardFocusable(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedIsEnabled(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedAutomationId(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedClassName(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedHelpText(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedCulture(__RPC__out int *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedIsControlElement(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedIsContentElement(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedIsPassword(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedNativeWindowHandle(__RPC__deref_out_opt UIA_HWND *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedItemType(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedIsOffscreen(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedOrientation(__RPC__out enum OrientationType *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedFrameworkId(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedIsRequiredForForm(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedItemStatus(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedBoundingRectangle(__RPC__out RECT *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedLabeledBy(__RPC__deref_out_opt IUIAutomationElement **retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedAriaRole(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedAriaProperties(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedIsDataValidForForm(__RPC__out BOOL *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedControllerFor(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedDescribedBy(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedFlowsTo(__RPC__deref_out_opt IUIAutomationElementArray **retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CachedProviderDescription(__RPC__deref_out_opt BSTR *retVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetClickablePoint(__RPC__out POINT *clickable, __RPC__out BOOL *gotClickable) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IUIAutomationElement, 0xd22108aa, 0x8ac5, 0x49a5, 0x83,0x7b, 0x37,0xbb,0xb3,0xd7,0x59,0x1e)
-#endif
-#endif
-
-
-#ifndef __IUIAutomation_INTERFACE_DEFINED__
-#define __IUIAutomation_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IUIAutomation, 0x30cbe57d, 0xd9d0, 0x452a, 0xab,0x13, 0x7a,0xc5,0xac,0x48,0x25,0xee);
-MIDL_INTERFACE("30cbe57d-d9d0-452a-ab13-7ac5ac4825ee")
-IUIAutomation : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE CompareElements(__RPC__in_opt IUIAutomationElement *el1, __RPC__in_opt IUIAutomationElement *el2, __RPC__out BOOL *areSame) = 0;
- virtual HRESULT STDMETHODCALLTYPE CompareRuntimeIds(__RPC__in SAFEARRAY * runtimeId1, __RPC__in SAFEARRAY * runtimeId2, __RPC__out BOOL *areSame) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetRootElement(__RPC__deref_out_opt IUIAutomationElement **root) = 0;
- virtual HRESULT STDMETHODCALLTYPE ElementFromHandle(__RPC__in UIA_HWND hwnd, __RPC__deref_out_opt IUIAutomationElement **element) = 0;
- virtual HRESULT STDMETHODCALLTYPE ElementFromPoint(POINT pt, __RPC__deref_out_opt IUIAutomationElement **element) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetFocusedElement(__RPC__deref_out_opt IUIAutomationElement **element) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetRootElementBuildCache(__RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **root) = 0;
- virtual HRESULT STDMETHODCALLTYPE ElementFromHandleBuildCache(__RPC__in UIA_HWND hwnd, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **element) = 0;
- virtual HRESULT STDMETHODCALLTYPE ElementFromPointBuildCache(POINT pt, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **element) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetFocusedElementBuildCache(__RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **element) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateTreeWalker(__RPC__in_opt IUIAutomationCondition *pCondition, __RPC__deref_out_opt IUIAutomationTreeWalker **walker) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ControlViewWalker(__RPC__deref_out_opt IUIAutomationTreeWalker **walker) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ContentViewWalker(__RPC__deref_out_opt IUIAutomationTreeWalker **walker) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_RawViewWalker(__RPC__deref_out_opt IUIAutomationTreeWalker **walker) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_RawViewCondition(__RPC__deref_out_opt IUIAutomationCondition **condition) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ControlViewCondition(__RPC__deref_out_opt IUIAutomationCondition **condition) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ContentViewCondition(__RPC__deref_out_opt IUIAutomationCondition **condition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateCacheRequest(__RPC__deref_out_opt IUIAutomationCacheRequest **cacheRequest) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateTrueCondition(__RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateFalseCondition(__RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreatePropertyCondition(PROPERTYID propertyId, VARIANT value, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreatePropertyConditionEx(PROPERTYID propertyId, VARIANT value, enum PropertyConditionFlags flags, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateAndCondition(__RPC__in_opt IUIAutomationCondition *condition1, __RPC__in_opt IUIAutomationCondition *condition2, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateAndConditionFromArray(__RPC__in_opt SAFEARRAY * conditions, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateAndConditionFromNativeArray(__RPC__in_ecount_full(conditionCount) IUIAutomationCondition **conditions, int conditionCount, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateOrCondition(__RPC__in_opt IUIAutomationCondition *condition1, __RPC__in_opt IUIAutomationCondition *condition2, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateOrConditionFromArray(__RPC__in_opt SAFEARRAY * conditions, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateOrConditionFromNativeArray(__RPC__in_ecount_full(conditionCount) IUIAutomationCondition **conditions, int conditionCount, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateNotCondition(__RPC__in_opt IUIAutomationCondition *condition, __RPC__deref_out_opt IUIAutomationCondition **newCondition) = 0;
- virtual HRESULT STDMETHODCALLTYPE AddAutomationEventHandler(EVENTID eventId, __RPC__in_opt IUIAutomationElement *element, enum TreeScope scope, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__in_opt IUIAutomationEventHandler *handler) = 0;
- virtual HRESULT STDMETHODCALLTYPE RemoveAutomationEventHandler(EVENTID eventId, __RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationEventHandler *handler) = 0;
- virtual HRESULT STDMETHODCALLTYPE AddPropertyChangedEventHandlerNativeArray(__RPC__in_opt IUIAutomationElement *element, enum TreeScope scope, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__in_opt IUIAutomationPropertyChangedEventHandler *handler, __RPC__in_ecount_full(propertyCount) PROPERTYID *propertyArray, int propertyCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE AddPropertyChangedEventHandler(__RPC__in_opt IUIAutomationElement *element, enum TreeScope scope, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__in_opt IUIAutomationPropertyChangedEventHandler *handler, __RPC__in SAFEARRAY * propertyArray) = 0;
- virtual HRESULT STDMETHODCALLTYPE RemovePropertyChangedEventHandler(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationPropertyChangedEventHandler *handler) = 0;
- virtual HRESULT STDMETHODCALLTYPE AddStructureChangedEventHandler(__RPC__in_opt IUIAutomationElement *element, enum TreeScope scope, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__in_opt IUIAutomationStructureChangedEventHandler *handler) = 0;
- virtual HRESULT STDMETHODCALLTYPE RemoveStructureChangedEventHandler(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationStructureChangedEventHandler *handler) = 0;
- virtual HRESULT STDMETHODCALLTYPE AddFocusChangedEventHandler(__RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__in_opt IUIAutomationFocusChangedEventHandler *handler) = 0;
- virtual HRESULT STDMETHODCALLTYPE RemoveFocusChangedEventHandler(__RPC__in_opt IUIAutomationFocusChangedEventHandler *handler) = 0;
- virtual HRESULT STDMETHODCALLTYPE RemoveAllEventHandlers() = 0;
- virtual HRESULT STDMETHODCALLTYPE IntNativeArrayToSafeArray(__RPC__in_ecount_full(arrayCount) int *array, int arrayCount, __RPC__deref_out_opt SAFEARRAY **safeArray) = 0;
- virtual HRESULT STDMETHODCALLTYPE IntSafeArrayToNativeArray(__RPC__in SAFEARRAY * intArray, __RPC__deref_out_ecount_full_opt(*arrayCount) int **array, __RPC__out int *arrayCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE RectToVariant(RECT rc, __RPC__out VARIANT *var) = 0;
- virtual HRESULT STDMETHODCALLTYPE VariantToRect(VARIANT var, __RPC__out RECT *rc) = 0;
- virtual HRESULT STDMETHODCALLTYPE SafeArrayToRectNativeArray(__RPC__in SAFEARRAY * rects, __RPC__deref_out_ecount_full_opt(*rectArrayCount) RECT **rectArray, __RPC__out int *rectArrayCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE CreateProxyFactoryEntry(__RPC__in_opt IUIAutomationProxyFactory *factory, __RPC__deref_out_opt IUIAutomationProxyFactoryEntry **factoryEntry) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ProxyFactoryMapping(__RPC__deref_out_opt IUIAutomationProxyFactoryMapping **factoryMapping) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetPropertyProgrammaticName(PROPERTYID property, __RPC__deref_out_opt BSTR *name) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetPatternProgrammaticName(PATTERNID pattern, __RPC__deref_out_opt BSTR *name) = 0;
- virtual HRESULT STDMETHODCALLTYPE PollForPotentialSupportedPatterns(__RPC__in_opt IUIAutomationElement *pElement, __RPC__deref_out_opt SAFEARRAY **patternIds, __RPC__deref_out_opt SAFEARRAY **patternNames) = 0;
- virtual HRESULT STDMETHODCALLTYPE PollForPotentialSupportedProperties(__RPC__in_opt IUIAutomationElement *pElement, __RPC__deref_out_opt SAFEARRAY **propertyIds, __RPC__deref_out_opt SAFEARRAY **propertyNames) = 0;
- virtual HRESULT STDMETHODCALLTYPE CheckNotSupported(VARIANT value, __RPC__out BOOL *isNotSupported) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ReservedNotSupportedValue(__RPC__deref_out_opt IUnknown **notSupportedValue) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ReservedMixedAttributeValue(__RPC__deref_out_opt IUnknown **mixedAttributeValue) = 0;
- virtual HRESULT STDMETHODCALLTYPE ElementFromIAccessible(__RPC__in_opt IAccessible *accessible, int childId, __RPC__deref_out_opt IUIAutomationElement **element) = 0;
- virtual HRESULT STDMETHODCALLTYPE ElementFromIAccessibleBuildCache(__RPC__in_opt IAccessible *accessible, int childId, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **element) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IUIAutomation, 0x30cbe57d, 0xd9d0, 0x452a, 0xab,0x13, 0x7a,0xc5,0xac,0x48,0x25,0xee)
-#endif
-#endif
-
-
-#ifndef __IUIAutomationTreeWalker_INTERFACE_DEFINED__
-#define __IUIAutomationTreeWalker_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IUIAutomationTreeWalker, 0x4042c624, 0x389c, 0x4afc, 0xa6,0x30, 0x9d,0xf8,0x54,0xa5,0x41,0xfc);
-MIDL_INTERFACE("4042c624-389c-4afc-a630-9df854a541fc")
-IUIAutomationTreeWalker : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE GetParentElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **parent) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetFirstChildElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **first) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetLastChildElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **last) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetNextSiblingElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **next) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetPreviousSiblingElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **previous) = 0;
- virtual HRESULT STDMETHODCALLTYPE NormalizeElement(__RPC__in_opt IUIAutomationElement *element, __RPC__deref_out_opt IUIAutomationElement **normalized) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetParentElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **parent) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetFirstChildElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **first) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetLastChildElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **last) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetNextSiblingElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **next) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetPreviousSiblingElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **previous) = 0;
- virtual HRESULT STDMETHODCALLTYPE NormalizeElementBuildCache(__RPC__in_opt IUIAutomationElement *element, __RPC__in_opt IUIAutomationCacheRequest *cacheRequest, __RPC__deref_out_opt IUIAutomationElement **normalized) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_Condition(__RPC__deref_out_opt IUIAutomationCondition **condition) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IUIAutomationTreeWalker, 0x4042c624, 0x389c, 0x4afc, 0xa6,0x30, 0x9d,0xf8,0x54,0xa5,0x41,0xfc)
-#endif
-#endif
-
-DEFINE_GUID(CLSID_CUIAutomation, 0xff48dba4, 0x60ef, 0x4201, 0xaa,0x87, 0x54,0x10,0x3e,0xef,0x59,0x4e);
-
-#endif
diff --git a/src/gui/accessible/windows/apisupport/uiacontroltypeids_p.h b/src/gui/accessible/windows/apisupport/uiacontroltypeids_p.h
deleted file mode 100644
index b5c5a0a4ff..0000000000
--- a/src/gui/accessible/windows/apisupport/uiacontroltypeids_p.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef UIACONTROLTYPEIDS_H
-#define UIACONTROLTYPEIDS_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#define UIA_ButtonControlTypeId 50000
-#define UIA_CalendarControlTypeId 50001
-#define UIA_CheckBoxControlTypeId 50002
-#define UIA_ComboBoxControlTypeId 50003
-#define UIA_EditControlTypeId 50004
-#define UIA_HyperlinkControlTypeId 50005
-#define UIA_ImageControlTypeId 50006
-#define UIA_ListItemControlTypeId 50007
-#define UIA_ListControlTypeId 50008
-#define UIA_MenuControlTypeId 50009
-#define UIA_MenuBarControlTypeId 50010
-#define UIA_MenuItemControlTypeId 50011
-#define UIA_ProgressBarControlTypeId 50012
-#define UIA_RadioButtonControlTypeId 50013
-#define UIA_ScrollBarControlTypeId 50014
-#define UIA_SliderControlTypeId 50015
-#define UIA_SpinnerControlTypeId 50016
-#define UIA_StatusBarControlTypeId 50017
-#define UIA_TabControlTypeId 50018
-#define UIA_TabItemControlTypeId 50019
-#define UIA_TextControlTypeId 50020
-#define UIA_ToolBarControlTypeId 50021
-#define UIA_ToolTipControlTypeId 50022
-#define UIA_TreeControlTypeId 50023
-#define UIA_TreeItemControlTypeId 50024
-#define UIA_CustomControlTypeId 50025
-#define UIA_GroupControlTypeId 50026
-#define UIA_ThumbControlTypeId 50027
-#define UIA_DataGridControlTypeId 50028
-#define UIA_DataItemControlTypeId 50029
-#define UIA_DocumentControlTypeId 50030
-#define UIA_SplitButtonControlTypeId 50031
-#define UIA_WindowControlTypeId 50032
-#define UIA_PaneControlTypeId 50033
-#define UIA_HeaderControlTypeId 50034
-#define UIA_HeaderItemControlTypeId 50035
-#define UIA_TableControlTypeId 50036
-#define UIA_TitleBarControlTypeId 50037
-#define UIA_SeparatorControlTypeId 50038
-#define UIA_SemanticZoomControlTypeId 50039
-#define UIA_AppBarControlTypeId 50040
-
-#endif
diff --git a/src/gui/accessible/windows/apisupport/uiaerrorids_p.h b/src/gui/accessible/windows/apisupport/uiaerrorids_p.h
deleted file mode 100644
index 8c2a24dbc7..0000000000
--- a/src/gui/accessible/windows/apisupport/uiaerrorids_p.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef UIAERRORIDS_H
-#define UIAERRORIDS_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#define UIA_E_ELEMENTNOTENABLED 0x80040200
-#define UIA_E_ELEMENTNOTAVAILABLE 0x80040201
-#define UIA_E_NOCLICKABLEPOINT 0x80040202
-#define UIA_E_PROXYASSEMBLYNOTLOADED 0x80040203
-#define UIA_E_NOTSUPPORTED 0x80040204
-#define UIA_E_INVALIDOPERATION 0x80131509
-#define UIA_E_TIMEOUT 0x80131505
-
-#endif
diff --git a/src/gui/accessible/windows/apisupport/uiaeventids_p.h b/src/gui/accessible/windows/apisupport/uiaeventids_p.h
deleted file mode 100644
index ed6c36834e..0000000000
--- a/src/gui/accessible/windows/apisupport/uiaeventids_p.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef UIAEVENTIDS_H
-#define UIAEVENTIDS_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#define UIA_ToolTipOpenedEventId 20000
-#define UIA_ToolTipClosedEventId 20001
-#define UIA_StructureChangedEventId 20002
-#define UIA_MenuOpenedEventId 20003
-#define UIA_AutomationPropertyChangedEventId 20004
-#define UIA_AutomationFocusChangedEventId 20005
-#define UIA_AsyncContentLoadedEventId 20006
-#define UIA_MenuClosedEventId 20007
-#define UIA_LayoutInvalidatedEventId 20008
-#define UIA_Invoke_InvokedEventId 20009
-#define UIA_SelectionItem_ElementAddedToSelectionEventId 20010
-#define UIA_SelectionItem_ElementRemovedFromSelectionEventId 20011
-#define UIA_SelectionItem_ElementSelectedEventId 20012
-#define UIA_Selection_InvalidatedEventId 20013
-#define UIA_Text_TextSelectionChangedEventId 20014
-#define UIA_Text_TextChangedEventId 20015
-#define UIA_Window_WindowOpenedEventId 20016
-#define UIA_Window_WindowClosedEventId 20017
-#define UIA_MenuModeStartEventId 20018
-#define UIA_MenuModeEndEventId 20019
-#define UIA_InputReachedTargetEventId 20020
-#define UIA_InputReachedOtherElementEventId 20021
-#define UIA_InputDiscardedEventId 20022
-#define UIA_SystemAlertEventId 20023
-#define UIA_LiveRegionChangedEventId 20024
-#define UIA_HostedFragmentRootsInvalidatedEventId 20025
-#define UIA_Drag_DragStartEventId 20026
-#define UIA_Drag_DragCancelEventId 20027
-#define UIA_Drag_DragCompleteEventId 20028
-#define UIA_DropTarget_DragEnterEventId 20029
-#define UIA_DropTarget_DragLeaveEventId 20030
-#define UIA_DropTarget_DroppedEventId 20031
-#define UIA_TextEdit_TextChangedEventId 20032
-#define UIA_TextEdit_ConversionTargetChangedEventId 20033
-#define UIA_ChangesEventId 20034
-
-#endif
diff --git a/src/gui/accessible/windows/apisupport/uiageneralids_p.h b/src/gui/accessible/windows/apisupport/uiageneralids_p.h
deleted file mode 100644
index 220554f885..0000000000
--- a/src/gui/accessible/windows/apisupport/uiageneralids_p.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef UIAGENERALIDS_H
-#define UIAGENERALIDS_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#define UiaAppendRuntimeId 3
-#define UiaRootObjectId -25
-
-#endif
diff --git a/src/gui/accessible/windows/apisupport/uiapatternids_p.h b/src/gui/accessible/windows/apisupport/uiapatternids_p.h
deleted file mode 100644
index d3f4c9bd7a..0000000000
--- a/src/gui/accessible/windows/apisupport/uiapatternids_p.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef UIAPATTERNIDS_H
-#define UIAPATTERNIDS_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#define UIA_InvokePatternId 10000
-#define UIA_SelectionPatternId 10001
-#define UIA_ValuePatternId 10002
-#define UIA_RangeValuePatternId 10003
-#define UIA_ScrollPatternId 10004
-#define UIA_ExpandCollapsePatternId 10005
-#define UIA_GridPatternId 10006
-#define UIA_GridItemPatternId 10007
-#define UIA_MultipleViewPatternId 10008
-#define UIA_WindowPatternId 10009
-#define UIA_SelectionItemPatternId 10010
-#define UIA_DockPatternId 10011
-#define UIA_TablePatternId 10012
-#define UIA_TableItemPatternId 10013
-#define UIA_TextPatternId 10014
-#define UIA_TogglePatternId 10015
-#define UIA_TransformPatternId 10016
-#define UIA_ScrollItemPatternId 10017
-#define UIA_LegacyIAccessiblePatternId 10018
-#define UIA_ItemContainerPatternId 10019
-#define UIA_VirtualizedItemPatternId 10020
-#define UIA_SynchronizedInputPatternId 10021
-#define UIA_ObjectModelPatternId 10022
-#define UIA_AnnotationPatternId 10023
-#define UIA_TextPattern2Id 10024
-#define UIA_StylesPatternId 10025
-#define UIA_SpreadsheetPatternId 10026
-#define UIA_SpreadsheetItemPatternId 10027
-#define UIA_TransformPattern2Id 10028
-#define UIA_TextChildPatternId 10029
-#define UIA_DragPatternId 10030
-#define UIA_DropTargetPatternId 10031
-#define UIA_TextEditPatternId 10032
-#define UIA_CustomNavigationPatternId 10033
-
-#endif
diff --git a/src/gui/accessible/windows/apisupport/uiapropertyids_p.h b/src/gui/accessible/windows/apisupport/uiapropertyids_p.h
deleted file mode 100644
index 9c14a35271..0000000000
--- a/src/gui/accessible/windows/apisupport/uiapropertyids_p.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef UIAPROPERTYIDS_H
-#define UIAPROPERTYIDS_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#define UIA_RuntimeIdPropertyId 30000
-#define UIA_BoundingRectanglePropertyId 30001
-#define UIA_ProcessIdPropertyId 30002
-#define UIA_ControlTypePropertyId 30003
-#define UIA_LocalizedControlTypePropertyId 30004
-#define UIA_NamePropertyId 30005
-#define UIA_AcceleratorKeyPropertyId 30006
-#define UIA_AccessKeyPropertyId 30007
-#define UIA_HasKeyboardFocusPropertyId 30008
-#define UIA_IsKeyboardFocusablePropertyId 30009
-#define UIA_IsEnabledPropertyId 30010
-#define UIA_AutomationIdPropertyId 30011
-#define UIA_ClassNamePropertyId 30012
-#define UIA_HelpTextPropertyId 30013
-#define UIA_ClickablePointPropertyId 30014
-#define UIA_CulturePropertyId 30015
-#define UIA_IsControlElementPropertyId 30016
-#define UIA_IsContentElementPropertyId 30017
-#define UIA_LabeledByPropertyId 30018
-#define UIA_IsPasswordPropertyId 30019
-#define UIA_NativeWindowHandlePropertyId 30020
-#define UIA_ItemTypePropertyId 30021
-#define UIA_IsOffscreenPropertyId 30022
-#define UIA_OrientationPropertyId 30023
-#define UIA_FrameworkIdPropertyId 30024
-#define UIA_IsRequiredForFormPropertyId 30025
-#define UIA_ItemStatusPropertyId 30026
-#define UIA_IsDockPatternAvailablePropertyId 30027
-#define UIA_IsExpandCollapsePatternAvailablePropertyId 30028
-#define UIA_IsGridItemPatternAvailablePropertyId 30029
-#define UIA_IsGridPatternAvailablePropertyId 30030
-#define UIA_IsInvokePatternAvailablePropertyId 30031
-#define UIA_IsMultipleViewPatternAvailablePropertyId 30032
-#define UIA_IsRangeValuePatternAvailablePropertyId 30033
-#define UIA_IsScrollPatternAvailablePropertyId 30034
-#define UIA_IsScrollItemPatternAvailablePropertyId 30035
-#define UIA_IsSelectionItemPatternAvailablePropertyId 30036
-#define UIA_IsSelectionPatternAvailablePropertyId 30037
-#define UIA_IsTablePatternAvailablePropertyId 30038
-#define UIA_IsTableItemPatternAvailablePropertyId 30039
-#define UIA_IsTextPatternAvailablePropertyId 30040
-#define UIA_IsTogglePatternAvailablePropertyId 30041
-#define UIA_IsTransformPatternAvailablePropertyId 30042
-#define UIA_IsValuePatternAvailablePropertyId 30043
-#define UIA_IsWindowPatternAvailablePropertyId 30044
-#define UIA_ValueValuePropertyId 30045
-#define UIA_ValueIsReadOnlyPropertyId 30046
-#define UIA_RangeValueValuePropertyId 30047
-#define UIA_RangeValueIsReadOnlyPropertyId 30048
-#define UIA_RangeValueMinimumPropertyId 30049
-#define UIA_RangeValueMaximumPropertyId 30050
-#define UIA_RangeValueLargeChangePropertyId 30051
-#define UIA_RangeValueSmallChangePropertyId 30052
-#define UIA_ScrollHorizontalScrollPercentPropertyId 30053
-#define UIA_ScrollHorizontalViewSizePropertyId 30054
-#define UIA_ScrollVerticalScrollPercentPropertyId 30055
-#define UIA_ScrollVerticalViewSizePropertyId 30056
-#define UIA_ScrollHorizontallyScrollablePropertyId 30057
-#define UIA_ScrollVerticallyScrollablePropertyId 30058
-#define UIA_SelectionSelectionPropertyId 30059
-#define UIA_SelectionCanSelectMultiplePropertyId 30060
-#define UIA_SelectionIsSelectionRequiredPropertyId 30061
-#define UIA_GridRowCountPropertyId 30062
-#define UIA_GridColumnCountPropertyId 30063
-#define UIA_GridItemRowPropertyId 30064
-#define UIA_GridItemColumnPropertyId 30065
-#define UIA_GridItemRowSpanPropertyId 30066
-#define UIA_GridItemColumnSpanPropertyId 30067
-#define UIA_GridItemContainingGridPropertyId 30068
-#define UIA_DockDockPositionPropertyId 30069
-#define UIA_ExpandCollapseExpandCollapseStatePropertyId 30070
-#define UIA_MultipleViewCurrentViewPropertyId 30071
-#define UIA_MultipleViewSupportedViewsPropertyId 30072
-#define UIA_WindowCanMaximizePropertyId 30073
-#define UIA_WindowCanMinimizePropertyId 30074
-#define UIA_WindowWindowVisualStatePropertyId 30075
-#define UIA_WindowWindowInteractionStatePropertyId 30076
-#define UIA_WindowIsModalPropertyId 30077
-#define UIA_WindowIsTopmostPropertyId 30078
-#define UIA_SelectionItemIsSelectedPropertyId 30079
-#define UIA_SelectionItemSelectionContainerPropertyId 30080
-#define UIA_TableRowHeadersPropertyId 30081
-#define UIA_TableColumnHeadersPropertyId 30082
-#define UIA_TableRowOrColumnMajorPropertyId 30083
-#define UIA_TableItemRowHeaderItemsPropertyId 30084
-#define UIA_TableItemColumnHeaderItemsPropertyId 30085
-#define UIA_ToggleToggleStatePropertyId 30086
-#define UIA_TransformCanMovePropertyId 30087
-#define UIA_TransformCanResizePropertyId 30088
-#define UIA_TransformCanRotatePropertyId 30089
-#define UIA_IsLegacyIAccessiblePatternAvailablePropertyId 30090
-#define UIA_LegacyIAccessibleChildIdPropertyId 30091
-#define UIA_LegacyIAccessibleNamePropertyId 30092
-#define UIA_LegacyIAccessibleValuePropertyId 30093
-#define UIA_LegacyIAccessibleDescriptionPropertyId 30094
-#define UIA_LegacyIAccessibleRolePropertyId 30095
-#define UIA_LegacyIAccessibleStatePropertyId 30096
-#define UIA_LegacyIAccessibleHelpPropertyId 30097
-#define UIA_LegacyIAccessibleKeyboardShortcutPropertyId 30098
-#define UIA_LegacyIAccessibleSelectionPropertyId 30099
-#define UIA_LegacyIAccessibleDefaultActionPropertyId 30100
-#define UIA_AriaRolePropertyId 30101
-#define UIA_AriaPropertiesPropertyId 30102
-#define UIA_IsDataValidForFormPropertyId 30103
-#define UIA_ControllerForPropertyId 30104
-#define UIA_DescribedByPropertyId 30105
-#define UIA_FlowsToPropertyId 30106
-#define UIA_ProviderDescriptionPropertyId 30107
-#define UIA_IsItemContainerPatternAvailablePropertyId 30108
-#define UIA_IsVirtualizedItemPatternAvailablePropertyId 30109
-#define UIA_IsSynchronizedInputPatternAvailablePropertyId 30110
-#define UIA_OptimizeForVisualContentPropertyId 30111
-#define UIA_IsObjectModelPatternAvailablePropertyId 30112
-#define UIA_AnnotationAnnotationTypeIdPropertyId 30113
-#define UIA_AnnotationAnnotationTypeNamePropertyId 30114
-#define UIA_AnnotationAuthorPropertyId 30115
-#define UIA_AnnotationDateTimePropertyId 30116
-#define UIA_AnnotationTargetPropertyId 30117
-#define UIA_IsAnnotationPatternAvailablePropertyId 30118
-#define UIA_IsTextPattern2AvailablePropertyId 30119
-#define UIA_StylesStyleIdPropertyId 30120
-#define UIA_StylesStyleNamePropertyId 30121
-#define UIA_StylesFillColorPropertyId 30122
-#define UIA_StylesFillPatternStylePropertyId 30123
-#define UIA_StylesShapePropertyId 30124
-#define UIA_StylesFillPatternColorPropertyId 30125
-#define UIA_StylesExtendedPropertiesPropertyId 30126
-#define UIA_IsStylesPatternAvailablePropertyId 30127
-#define UIA_IsSpreadsheetPatternAvailablePropertyId 30128
-#define UIA_SpreadsheetItemFormulaPropertyId 30129
-#define UIA_SpreadsheetItemAnnotationObjectsPropertyId 30130
-#define UIA_SpreadsheetItemAnnotationTypesPropertyId 30131
-#define UIA_IsSpreadsheetItemPatternAvailablePropertyId 30132
-#define UIA_Transform2CanZoomPropertyId 30133
-#define UIA_IsTransformPattern2AvailablePropertyId 30134
-#define UIA_LiveSettingPropertyId 30135
-#define UIA_IsTextChildPatternAvailablePropertyId 30136
-#define UIA_IsDragPatternAvailablePropertyId 30137
-#define UIA_DragIsGrabbedPropertyId 30138
-#define UIA_DragDropEffectPropertyId 30139
-#define UIA_DragDropEffectsPropertyId 30140
-#define UIA_IsDropTargetPatternAvailablePropertyId 30141
-#define UIA_DropTargetDropTargetEffectPropertyId 30142
-#define UIA_DropTargetDropTargetEffectsPropertyId 30143
-#define UIA_DragGrabbedItemsPropertyId 30144
-#define UIA_Transform2ZoomLevelPropertyId 30145
-#define UIA_Transform2ZoomMinimumPropertyId 30146
-#define UIA_Transform2ZoomMaximumPropertyId 30147
-#define UIA_FlowsFromPropertyId 30148
-#define UIA_IsTextEditPatternAvailablePropertyId 30149
-#define UIA_IsPeripheralPropertyId 30150
-#define UIA_IsCustomNavigationPatternAvailablePropertyId 30151
-#define UIA_PositionInSetPropertyId 30152
-#define UIA_SizeOfSetPropertyId 30153
-#define UIA_LevelPropertyId 30154
-#define UIA_AnnotationTypesPropertyId 30155
-#define UIA_AnnotationObjectsPropertyId 30156
-#define UIA_LandmarkTypePropertyId 30157
-#define UIA_LocalizedLandmarkTypePropertyId 30158
-#define UIA_FullDescriptionPropertyId 30159
-#define UIA_FillColorPropertyId 30160
-#define UIA_OutlineColorPropertyId 30161
-#define UIA_FillTypePropertyId 30162
-#define UIA_VisualEffectsPropertyId 30163
-#define UIA_OutlineThicknessPropertyId 30164
-#define UIA_CenterPointPropertyId 30165
-#define UIA_RotationPropertyId 30166
-#define UIA_SizePropertyId 30167
-#define UIA_IsDialogPropertyId 30174
-
-#endif
diff --git a/src/gui/accessible/windows/apisupport/uiaserverinterfaces_p.h b/src/gui/accessible/windows/apisupport/uiaserverinterfaces_p.h
deleted file mode 100644
index fde16206da..0000000000
--- a/src/gui/accessible/windows/apisupport/uiaserverinterfaces_p.h
+++ /dev/null
@@ -1,403 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef UIASERVERINTERFACES_H
-#define UIASERVERINTERFACES_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <unknwn.h>
-
-#ifndef __IRawElementProviderSimple_INTERFACE_DEFINED__
-#define __IRawElementProviderSimple_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IRawElementProviderSimple, 0xd6dd68d1, 0x86fd, 0x4332, 0x86,0x66, 0x9a,0xbe,0xde,0xa2,0xd2,0x4c);
-MIDL_INTERFACE("d6dd68d1-86fd-4332-8666-9abedea2d24c")
-IRawElementProviderSimple : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE get_ProviderOptions(__RPC__out enum ProviderOptions *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetPatternProvider(PATTERNID patternId, __RPC__deref_out_opt IUnknown **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetPropertyValue(PROPERTYID propertyId, __RPC__out VARIANT *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_HostRawElementProvider(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IRawElementProviderSimple, 0xd6dd68d1, 0x86fd, 0x4332, 0x86,0x66, 0x9a,0xbe,0xde,0xa2,0xd2,0x4c)
-#endif
-#endif
-
-
-#ifndef __IRawElementProviderFragmentRoot_FWD_DEFINED__
-#define __IRawElementProviderFragmentRoot_FWD_DEFINED__
-typedef interface IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot;
-#endif
-
-
-#ifndef __IRawElementProviderFragment_FWD_DEFINED__
-#define __IRawElementProviderFragment_FWD_DEFINED__
-typedef interface IRawElementProviderFragment IRawElementProviderFragment;
-#endif
-
-
-#ifndef __IRawElementProviderFragment_INTERFACE_DEFINED__
-#define __IRawElementProviderFragment_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IRawElementProviderFragment, 0xf7063da8, 0x8359, 0x439c, 0x92,0x97, 0xbb,0xc5,0x29,0x9a,0x7d,0x87);
-MIDL_INTERFACE("f7063da8-8359-439c-9297-bbc5299a7d87")
-IRawElementProviderFragment : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE Navigate(enum NavigateDirection direction, __RPC__deref_out_opt IRawElementProviderFragment **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetRuntimeId(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_BoundingRectangle(__RPC__out struct UiaRect *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetEmbeddedFragmentRoots(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE SetFocus() = 0;
- virtual HRESULT STDMETHODCALLTYPE get_FragmentRoot(__RPC__deref_out_opt IRawElementProviderFragmentRoot **pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IRawElementProviderFragment, 0xf7063da8, 0x8359, 0x439c, 0x92,0x97, 0xbb,0xc5,0x29,0x9a,0x7d,0x87)
-#endif
-#endif
-
-
-#ifndef __IRawElementProviderFragmentRoot_INTERFACE_DEFINED__
-#define __IRawElementProviderFragmentRoot_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IRawElementProviderFragmentRoot, 0x620ce2a5, 0xab8f, 0x40a9, 0x86,0xcb, 0xde,0x3c,0x75,0x59,0x9b,0x58);
-MIDL_INTERFACE("620ce2a5-ab8f-40a9-86cb-de3c75599b58")
-IRawElementProviderFragmentRoot : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE ElementProviderFromPoint(double x, double y, __RPC__deref_out_opt IRawElementProviderFragment **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetFocus(__RPC__deref_out_opt IRawElementProviderFragment **pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IRawElementProviderFragmentRoot, 0x620ce2a5, 0xab8f, 0x40a9, 0x86,0xcb, 0xde,0x3c,0x75,0x59,0x9b,0x58)
-#endif
-#endif
-
-
-#ifndef __IValueProvider_INTERFACE_DEFINED__
-#define __IValueProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IValueProvider, 0xc7935180, 0x6fb3, 0x4201, 0xb1,0x74, 0x7d,0xf7,0x3a,0xdb,0xf6,0x4a);
-MIDL_INTERFACE("c7935180-6fb3-4201-b174-7df73adbf64a")
-IValueProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE SetValue(__RPC__in LPCWSTR val) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_Value(__RPC__deref_out_opt BSTR *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_IsReadOnly(__RPC__out BOOL *pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IValueProvider, 0xc7935180, 0x6fb3, 0x4201, 0xb1,0x74, 0x7d,0xf7,0x3a,0xdb,0xf6,0x4a)
-#endif
-#endif
-
-
-#ifndef __IRangeValueProvider_INTERFACE_DEFINED__
-#define __IRangeValueProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IRangeValueProvider, 0x36dc7aef, 0x33e6, 0x4691, 0xaf,0xe1, 0x2b,0xe7,0x27,0x4b,0x3d,0x33);
-MIDL_INTERFACE("36dc7aef-33e6-4691-afe1-2be7274b3d33")
-IRangeValueProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE SetValue(double val) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_Value(__RPC__out double *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_IsReadOnly(__RPC__out BOOL *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_Maximum(__RPC__out double *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_Minimum(__RPC__out double *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_LargeChange(__RPC__out double *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_SmallChange(__RPC__out double *pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IRangeValueProvider, 0x36dc7aef, 0x33e6, 0x4691, 0xaf,0xe1, 0x2b,0xe7,0x27,0x4b,0x3d,0x33)
-#endif
-#endif
-
-
-#ifndef __ITextRangeProvider_INTERFACE_DEFINED__
-#define __ITextRangeProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_ITextRangeProvider, 0x5347ad7b, 0xc355, 0x46f8, 0xaf,0xf5, 0x90,0x90,0x33,0x58,0x2f,0x63);
-MIDL_INTERFACE("5347ad7b-c355-46f8-aff5-909033582f63")
-ITextRangeProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE Clone(__RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE Compare(__RPC__in_opt ITextRangeProvider *range, __RPC__out BOOL *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE CompareEndpoints(enum TextPatternRangeEndpoint endpoint, __RPC__in_opt ITextRangeProvider *targetRange, enum TextPatternRangeEndpoint targetEndpoint, __RPC__out int *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE ExpandToEnclosingUnit(enum TextUnit unit) = 0;
- virtual HRESULT STDMETHODCALLTYPE FindAttribute(TEXTATTRIBUTEID attributeId, VARIANT val, BOOL backward, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE FindText(__RPC__in BSTR text, BOOL backward, BOOL ignoreCase, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetAttributeValue(TEXTATTRIBUTEID attributeId, __RPC__out VARIANT *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetBoundingRectangles(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetEnclosingElement(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetText(int maxLength, __RPC__deref_out_opt BSTR *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE Move(enum TextUnit unit, int count, __RPC__out int *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE MoveEndpointByUnit(enum TextPatternRangeEndpoint endpoint, enum TextUnit unit, int count, __RPC__out int *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE MoveEndpointByRange(enum TextPatternRangeEndpoint endpoint, __RPC__in_opt ITextRangeProvider *targetRange, enum TextPatternRangeEndpoint targetEndpoint) = 0;
- virtual HRESULT STDMETHODCALLTYPE Select() = 0;
- virtual HRESULT STDMETHODCALLTYPE AddToSelection() = 0;
- virtual HRESULT STDMETHODCALLTYPE RemoveFromSelection() = 0;
- virtual HRESULT STDMETHODCALLTYPE ScrollIntoView(BOOL alignToTop) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetChildren(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(ITextRangeProvider, 0x5347ad7b, 0xc355, 0x46f8, 0xaf,0xf5, 0x90,0x90,0x33,0x58,0x2f,0x63)
-#endif
-#endif
-
-
-#ifndef __ITextProvider_INTERFACE_DEFINED__
-#define __ITextProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_ITextProvider, 0x3589c92c, 0x63f3, 0x4367, 0x99,0xbb, 0xad,0xa6,0x53,0xb7,0x7c,0xf2);
-MIDL_INTERFACE("3589c92c-63f3-4367-99bb-ada653b77cf2")
-ITextProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE GetSelection(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetVisibleRanges(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE RangeFromChild(__RPC__in_opt IRawElementProviderSimple *childElement, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE RangeFromPoint(struct UiaPoint point, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_DocumentRange(__RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_SupportedTextSelection(__RPC__out enum SupportedTextSelection *pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(ITextProvider, 0x3589c92c, 0x63f3, 0x4367, 0x99,0xbb, 0xad,0xa6,0x53,0xb7,0x7c,0xf2)
-#endif
-#endif
-
-
-#ifndef __ITextProvider2_INTERFACE_DEFINED__
-#define __ITextProvider2_INTERFACE_DEFINED__
-DEFINE_GUID(IID_ITextProvider2, 0x0dc5e6ed, 0x3e16, 0x4bf1, 0x8f,0x9a, 0xa9,0x79,0x87,0x8b,0xc1,0x95);
-MIDL_INTERFACE("0dc5e6ed-3e16-4bf1-8f9a-a979878bc195")
-ITextProvider2 : public ITextProvider
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE RangeFromAnnotation(__RPC__in_opt IRawElementProviderSimple *annotationElement, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetCaretRange(__RPC__out BOOL *isActive, __RPC__deref_out_opt ITextRangeProvider **pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(ITextProvider2, 0x0dc5e6ed, 0x3e16, 0x4bf1, 0x8f,0x9a, 0xa9,0x79,0x87,0x8b,0xc1,0x95)
-#endif
-#endif
-
-
-#ifndef __IToggleProvider_INTERFACE_DEFINED__
-#define __IToggleProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IToggleProvider, 0x56d00bd0, 0xc4f4, 0x433c, 0xa8,0x36, 0x1a,0x52,0xa5,0x7e,0x08,0x92);
-MIDL_INTERFACE("56d00bd0-c4f4-433c-a836-1a52a57e0892")
-IToggleProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE Toggle() = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ToggleState(__RPC__out enum ToggleState *pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IToggleProvider, 0x56d00bd0, 0xc4f4, 0x433c, 0xa8,0x36, 0x1a,0x52,0xa5,0x7e,0x08,0x92)
-#endif
-#endif
-
-
-#ifndef __IInvokeProvider_INTERFACE_DEFINED__
-#define __IInvokeProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IInvokeProvider, 0x54fcb24b, 0xe18e, 0x47a2, 0xb4,0xd3, 0xec,0xcb,0xe7,0x75,0x99,0xa2);
-MIDL_INTERFACE("54fcb24b-e18e-47a2-b4d3-eccbe77599a2")
-IInvokeProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE Invoke() = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IInvokeProvider, 0x54fcb24b, 0xe18e, 0x47a2, 0xb4,0xd3, 0xec,0xcb,0xe7,0x75,0x99,0xa2)
-#endif
-#endif
-
-
-#ifndef __ISelectionProvider_INTERFACE_DEFINED__
-#define __ISelectionProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_ISelectionProvider, 0xfb8b03af, 0x3bdf, 0x48d4, 0xbd,0x36, 0x1a,0x65,0x79,0x3b,0xe1,0x68);
-MIDL_INTERFACE("fb8b03af-3bdf-48d4-bd36-1a65793be168")
-ISelectionProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE GetSelection(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CanSelectMultiple(__RPC__out BOOL *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_IsSelectionRequired(__RPC__out BOOL *pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(ISelectionProvider, 0xfb8b03af, 0x3bdf, 0x48d4, 0xbd,0x36, 0x1a,0x65,0x79,0x3b,0xe1,0x68)
-#endif
-#endif
-
-
-#ifndef __ISelectionItemProvider_INTERFACE_DEFINED__
-#define __ISelectionItemProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_ISelectionItemProvider, 0x2acad808, 0xb2d4, 0x452d, 0xa4,0x07, 0x91,0xff,0x1a,0xd1,0x67,0xb2);
-MIDL_INTERFACE("2acad808-b2d4-452d-a407-91ff1ad167b2")
-ISelectionItemProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE Select() = 0;
- virtual HRESULT STDMETHODCALLTYPE AddToSelection() = 0;
- virtual HRESULT STDMETHODCALLTYPE RemoveFromSelection() = 0;
- virtual HRESULT STDMETHODCALLTYPE get_IsSelected(__RPC__out BOOL *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_SelectionContainer(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(ISelectionItemProvider, 0x2acad808, 0xb2d4, 0x452d, 0xa4,0x07, 0x91,0xff,0x1a,0xd1,0x67,0xb2)
-#endif
-#endif
-
-
-#ifndef __ITableProvider_INTERFACE_DEFINED__
-#define __ITableProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_ITableProvider, 0x9c860395, 0x97b3, 0x490a, 0xb5,0x2a, 0x85,0x8c,0xc2,0x2a,0xf1,0x66);
-MIDL_INTERFACE("9c860395-97b3-490a-b52a-858cc22af166")
-ITableProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE GetRowHeaders(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetColumnHeaders(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_RowOrColumnMajor(__RPC__out enum RowOrColumnMajor *pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(ITableProvider, 0x9c860395, 0x97b3, 0x490a, 0xb5,0x2a, 0x85,0x8c,0xc2,0x2a,0xf1,0x66)
-#endif
-#endif
-
-
-#ifndef __ITableItemProvider_INTERFACE_DEFINED__
-#define __ITableItemProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_ITableItemProvider, 0xb9734fa6, 0x771f, 0x4d78, 0x9c,0x90, 0x25,0x17,0x99,0x93,0x49,0xcd);
-MIDL_INTERFACE("b9734fa6-771f-4d78-9c90-2517999349cd")
-ITableItemProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE GetRowHeaderItems(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE GetColumnHeaderItems(__RPC__deref_out_opt SAFEARRAY **pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(ITableItemProvider, 0xb9734fa6, 0x771f, 0x4d78, 0x9c,0x90, 0x25,0x17,0x99,0x93,0x49,0xcd)
-#endif
-#endif
-
-
-#ifndef __IGridProvider_INTERFACE_DEFINED__
-#define __IGridProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IGridProvider, 0xb17d6187, 0x0907, 0x464b, 0xa1,0x68, 0x0e,0xf1,0x7a,0x15,0x72,0xb1);
-MIDL_INTERFACE("b17d6187-0907-464b-a168-0ef17a1572b1")
-IGridProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE GetItem(int row, int column, __RPC__deref_out_opt IRawElementProviderSimple **pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_RowCount(__RPC__out int *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ColumnCount(__RPC__out int *pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IGridProvider, 0xb17d6187, 0x0907, 0x464b, 0xa1,0x68, 0x0e,0xf1,0x7a,0x15,0x72,0xb1)
-#endif
-#endif
-
-
-#ifndef __IGridItemProvider_INTERFACE_DEFINED__
-#define __IGridItemProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IGridItemProvider, 0xd02541f1, 0xfb81, 0x4d64, 0xae,0x32, 0xf5,0x20,0xf8,0xa6,0xdb,0xd1);
-MIDL_INTERFACE("d02541f1-fb81-4d64-ae32-f520f8a6dbd1")
-IGridItemProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE get_Row(__RPC__out int *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_Column(__RPC__out int *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_RowSpan(__RPC__out int *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ColumnSpan(__RPC__out int *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ContainingGrid(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IGridItemProvider, 0xd02541f1, 0xfb81, 0x4d64, 0xae,0x32, 0xf5,0x20,0xf8,0xa6,0xdb,0xd1)
-#endif
-#endif
-
-
-#ifndef __IWindowProvider_INTERFACE_DEFINED__
-#define __IWindowProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IWindowProvider, 0x987df77b, 0xdb06, 0x4d77, 0x8f,0x8a, 0x86,0xa9,0xc3,0xbb,0x90,0xb9);
-MIDL_INTERFACE("987df77b-db06-4d77-8f8a-86a9c3bb90b9")
-IWindowProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE SetVisualState(enum WindowVisualState state) = 0;
- virtual HRESULT STDMETHODCALLTYPE Close( void) = 0;
- virtual HRESULT STDMETHODCALLTYPE WaitForInputIdle(int milliseconds, __RPC__out BOOL *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CanMaximize(__RPC__out BOOL *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_CanMinimize(__RPC__out BOOL *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_IsModal(__RPC__out BOOL *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_WindowVisualState(__RPC__out enum WindowVisualState *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_WindowInteractionState(__RPC__out enum WindowInteractionState *pRetVal) = 0;
- virtual HRESULT STDMETHODCALLTYPE get_IsTopmost(__RPC__out BOOL *pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IWindowProvider, 0x987df77b, 0xdb06, 0x4d77, 0x8f,0x8a, 0x86,0xa9,0xc3,0xbb,0x90,0xb9)
-#endif
-#endif
-
-
-#ifndef __IExpandCollapseProvider_INTERFACE_DEFINED__
-#define __IExpandCollapseProvider_INTERFACE_DEFINED__
-DEFINE_GUID(IID_IExpandCollapseProvider, 0xd847d3a5, 0xcab0, 0x4a98, 0x8c,0x32, 0xec,0xb4,0x5c,0x59,0xad,0x24);
-MIDL_INTERFACE("d847d3a5-cab0-4a98-8c32-ecb45c59ad24")
-IExpandCollapseProvider : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE Expand() = 0;
- virtual HRESULT STDMETHODCALLTYPE Collapse() = 0;
- virtual HRESULT STDMETHODCALLTYPE get_ExpandCollapseState(__RPC__out enum ExpandCollapseState *pRetVal) = 0;
-};
-#ifdef __CRT_UUID_DECL
-__CRT_UUID_DECL(IExpandCollapseProvider, 0xd847d3a5, 0xcab0, 0x4a98, 0x8c,0x32, 0xec,0xb4,0x5c,0x59,0xad,0x24)
-#endif
-#endif
-
-#endif
diff --git a/src/gui/accessible/windows/apisupport/uiatypes_p.h b/src/gui/accessible/windows/apisupport/uiatypes_p.h
deleted file mode 100644
index 0d2e1161e4..0000000000
--- a/src/gui/accessible/windows/apisupport/uiatypes_p.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef UIATYPES_H
-#define UIATYPES_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-typedef int PROPERTYID;
-typedef int PATTERNID;
-typedef int EVENTID;
-typedef int TEXTATTRIBUTEID;
-typedef int CONTROLTYPEID;
-typedef int LANDMARKTYPEID;
-typedef int METADATAID;
-
-typedef void *UIA_HWND;
-
-enum NavigateDirection {
- NavigateDirection_Parent = 0,
- NavigateDirection_NextSibling = 1,
- NavigateDirection_PreviousSibling = 2,
- NavigateDirection_FirstChild = 3,
- NavigateDirection_LastChild = 4
-};
-
-enum ProviderOptions {
- ProviderOptions_ClientSideProvider = 0x1,
- ProviderOptions_ServerSideProvider = 0x2,
- ProviderOptions_NonClientAreaProvider = 0x4,
- ProviderOptions_OverrideProvider = 0x8,
- ProviderOptions_ProviderOwnsSetFocus = 0x10,
- ProviderOptions_UseComThreading = 0x20,
- ProviderOptions_RefuseNonClientSupport = 0x40,
- ProviderOptions_HasNativeIAccessible = 0x80,
- ProviderOptions_UseClientCoordinates = 0x100
-};
-
-enum SupportedTextSelection {
- SupportedTextSelection_None = 0,
- SupportedTextSelection_Single = 1,
- SupportedTextSelection_Multiple = 2
-};
-
-enum TextUnit {
- TextUnit_Character = 0,
- TextUnit_Format = 1,
- TextUnit_Word = 2,
- TextUnit_Line = 3,
- TextUnit_Paragraph = 4,
- TextUnit_Page = 5,
- TextUnit_Document = 6
-};
-
-enum TextPatternRangeEndpoint {
- TextPatternRangeEndpoint_Start = 0,
- TextPatternRangeEndpoint_End = 1
-};
-
-enum CaretPosition {
- CaretPosition_Unknown = 0,
- CaretPosition_EndOfLine = 1,
- CaretPosition_BeginningOfLine = 2
-};
-
-enum ToggleState {
- ToggleState_Off = 0,
- ToggleState_On = 1,
- ToggleState_Indeterminate = 2
-};
-
-enum RowOrColumnMajor {
- RowOrColumnMajor_RowMajor = 0,
- RowOrColumnMajor_ColumnMajor = 1,
- RowOrColumnMajor_Indeterminate = 2
-};
-
-enum TreeScope {
- TreeScope_None = 0,
- TreeScope_Element = 0x1,
- TreeScope_Children = 0x2,
- TreeScope_Descendants = 0x4,
- TreeScope_Parent = 0x8,
- TreeScope_Ancestors = 0x10,
- TreeScope_Subtree = TreeScope_Element | TreeScope_Children | TreeScope_Descendants
-};
-
-enum OrientationType {
- OrientationType_None = 0,
- OrientationType_Horizontal = 1,
- OrientationType_Vertical = 2
-};
-
-enum PropertyConditionFlags {
- PropertyConditionFlags_None = 0,
- PropertyConditionFlags_IgnoreCase = 1
-};
-
-enum WindowVisualState {
- WindowVisualState_Normal = 0,
- WindowVisualState_Maximized = 1,
- WindowVisualState_Minimized = 2
-};
-
-enum WindowInteractionState {
- WindowInteractionState_Running = 0,
- WindowInteractionState_Closing = 1,
- WindowInteractionState_ReadyForUserInteraction = 2,
- WindowInteractionState_BlockedByModalWindow = 3,
- WindowInteractionState_NotResponding = 4
-};
-
-enum ExpandCollapseState {
- ExpandCollapseState_Collapsed = 0,
- ExpandCollapseState_Expanded = 1,
- ExpandCollapseState_PartiallyExpanded = 2,
- ExpandCollapseState_LeafNode = 3
-};
-
-enum NotificationKind {
- NotificationKind_ItemAdded = 0,
- NotificationKind_ItemRemoved = 1,
- NotificationKind_ActionCompleted = 2,
- NotificationKind_ActionAborted = 3,
- NotificationKind_Other = 4
-};
-
-enum NotificationProcessing {
- NotificationProcessing_ImportantAll = 0,
- NotificationProcessing_ImportantMostRecent = 1,
- NotificationProcessing_All = 2,
- NotificationProcessing_MostRecent = 3,
- NotificationProcessing_CurrentThenMostRecent = 4
-};
-
-struct UiaRect {
- double left;
- double top;
- double width;
- double height;
-};
-
-struct UiaPoint {
- double x;
- double y;
-};
-
-#endif
diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp
index 8afe77ed46..2a7f1a6db2 100644
--- a/src/gui/animation/qguivariantanimation.cpp
+++ b/src/gui/animation/qguivariantanimation.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtguiglobal.h>
#include <QtCore/qvariantanimation.h>
diff --git a/src/gui/compat/removed_api.cpp b/src/gui/compat/removed_api.cpp
new file mode 100644
index 0000000000..a64580e9e1
--- /dev/null
+++ b/src/gui/compat/removed_api.cpp
@@ -0,0 +1,33 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#define QT_GUI_BUILD_REMOVED_API
+
+#include "qtguiglobal.h"
+
+QT_USE_NAMESPACE
+
+#if QT_GUI_REMOVED_SINCE(6, 6)
+
+#include "qpixmapcache.h" // inlined API
+
+// #include "qotherheader.h"
+// // implement removed functions from qotherheader.h
+// order sections alphabetically
+
+#endif // QT_GUI_REMOVED_SINCE(6, 6)
+
+#if QT_GUI_REMOVED_SINCE(6, 7)
+
+#include "qtextdocument.h"
+
+bool Qt::mightBeRichText(const QString& text)
+{
+ return Qt::mightBeRichText(qToStringViewIgnoringNull(text));
+}
+
+// #include "qotherheader.h"
+// // implement removed functions from qotherheader.h
+// order sections alphabetically
+
+#endif // QT_GUI_REMOVED_SINCE(6, 7)
diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake
index de05f5e0f1..e1d8efb292 100644
--- a/src/gui/configure.cmake
+++ b/src/gui/configure.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
#### Inputs
@@ -25,13 +28,18 @@ set_property(CACHE INPUT_libpng PROPERTY STRINGS undefined no qt system)
#### Libraries
-qt_set01(X11_SUPPORTED LINUX OR HPUX OR FREEBSD OR NETBSD OR OPENBSD OR SOLARIS) # special case
+qt_set01(X11_SUPPORTED LINUX OR HPUX OR FREEBSD OR NETBSD OR OPENBSD OR SOLARIS OR
+ HURD)
qt_find_package(ATSPI2 PROVIDED_TARGETS PkgConfig::ATSPI2 MODULE_NAME gui QMAKE_LIB atspi)
qt_find_package(DirectFB PROVIDED_TARGETS PkgConfig::DirectFB MODULE_NAME gui QMAKE_LIB directfb)
qt_find_package(Libdrm PROVIDED_TARGETS Libdrm::Libdrm MODULE_NAME gui QMAKE_LIB drm)
qt_find_package(EGL PROVIDED_TARGETS EGL::EGL MODULE_NAME gui QMAKE_LIB egl)
+if(INTEGRITY AND _qt_igy_gui_libs)
+ qt_find_package(IntegrityPlatformGraphics
+ PROVIDED_TARGETS IntegrityPlatformGraphics::IntegrityPlatformGraphics
+ MODULE_NAME gui QMAKE_LIB integrity_platform_graphics)
+endif()
qt_find_package(WrapSystemFreetype 2.2.0 PROVIDED_TARGETS WrapSystemFreetype::WrapSystemFreetype MODULE_NAME gui QMAKE_LIB freetype)
-set_package_properties(WrapFreetype PROPERTIES TYPE REQUIRED)
if(QT_FEATURE_system_zlib)
qt_add_qmake_lib_dependency(freetype zlib)
endif()
@@ -40,7 +48,7 @@ qt_add_qmake_lib_dependency(fontconfig freetype)
qt_find_package(gbm PROVIDED_TARGETS gbm::gbm MODULE_NAME gui QMAKE_LIB gbm)
qt_find_package(WrapSystemHarfbuzz 2.6.0 PROVIDED_TARGETS WrapSystemHarfbuzz::WrapSystemHarfbuzz MODULE_NAME gui QMAKE_LIB harfbuzz)
qt_find_package(Libinput PROVIDED_TARGETS Libinput::Libinput MODULE_NAME gui QMAKE_LIB libinput)
-qt_find_package(JPEG PROVIDED_TARGETS JPEG::JPEG MODULE_NAME gui QMAKE_LIB libjpeg)
+qt_find_package(WrapSystemJpeg PROVIDED_TARGETS WrapSystemJpeg::WrapSystemJpeg MODULE_NAME gui QMAKE_LIB libjpeg)
qt_find_package(WrapSystemMd4c PROVIDED_TARGETS WrapSystemMd4c::WrapSystemMd4c MODULE_NAME gui QMAKE_LIB libmd4c)
qt_find_package(WrapSystemPNG PROVIDED_TARGETS WrapSystemPNG::WrapSystemPNG MODULE_NAME gui QMAKE_LIB libpng)
if(QT_FEATURE_system_zlib)
@@ -50,20 +58,25 @@ qt_find_package(Mtdev PROVIDED_TARGETS PkgConfig::Mtdev MODULE_NAME gui QMAKE_LI
qt_find_package(WrapOpenGL PROVIDED_TARGETS WrapOpenGL::WrapOpenGL MODULE_NAME gui QMAKE_LIB opengl)
qt_find_package(GLESv2 PROVIDED_TARGETS GLESv2::GLESv2 MODULE_NAME gui QMAKE_LIB opengl_es2)
qt_find_package(Tslib PROVIDED_TARGETS PkgConfig::Tslib MODULE_NAME gui QMAKE_LIB tslib)
-qt_find_package(WrapVulkanHeaders PROVIDED_TARGETS WrapVulkanHeaders::WrapVulkanHeaders MODULE_NAME gui QMAKE_LIB vulkan MARK_OPTIONAL) # special case
+qt_find_package(WrapVulkanHeaders PROVIDED_TARGETS WrapVulkanHeaders::WrapVulkanHeaders
+ MODULE_NAME gui QMAKE_LIB vulkan MARK_OPTIONAL)
if((LINUX) OR QT_FIND_ALL_PACKAGES_ALWAYS)
qt_find_package(Wayland PROVIDED_TARGETS Wayland::Server MODULE_NAME gui QMAKE_LIB wayland_server)
+ qt_find_package(Wayland PROVIDED_TARGETS Wayland::Client MODULE_NAME gui QMAKE_LIB wayland_client)
endif()
if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
qt_find_package(X11 PROVIDED_TARGETS X11::X11 MODULE_NAME gui QMAKE_LIB xlib)
endif()
if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
- qt_find_package(X11 PROVIDED_TARGETS ${X11_SM_LIB} ${X11_ICE_LIB} MODULE_NAME gui QMAKE_LIB x11sm)
+ qt_find_package(X11 PROVIDED_TARGETS X11::SM X11::ICE MODULE_NAME gui QMAKE_LIB x11sm)
endif()
if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
qt_find_package(XCB 1.11 PROVIDED_TARGETS XCB::XCB MODULE_NAME gui QMAKE_LIB xcb)
endif()
if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
+ qt_find_package(XCB 0.1.1 COMPONENTS CURSOR PROVIDED_TARGETS XCB::CURSOR MODULE_NAME gui QMAKE_LIB xcb_cursor)
+endif()
+if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
qt_find_package(XCB 0.3.9 COMPONENTS ICCCM PROVIDED_TARGETS XCB::ICCCM MODULE_NAME gui QMAKE_LIB xcb_icccm)
endif()
qt_add_qmake_lib_dependency(xcb_icccm xcb)
@@ -130,6 +143,7 @@ if((X11_SUPPORTED) OR QT_FIND_ALL_PACKAGES_ALWAYS)
endif()
qt_add_qmake_lib_dependency(xrender xlib)
+qt_find_package(RenderDoc PROVIDED_TARGETS RenderDoc::RenderDoc)
#### Tests
@@ -167,6 +181,7 @@ qt_config_compile_test(egl_x11
// has to be disabled in plugins like xcb in this case since the native display,
// window and pixmap types will be different than what an X-based platform
// plugin would expect.
+#define USE_X11
#include <EGL/egl.h>
#include <X11/Xlib.h>
@@ -219,6 +234,7 @@ EGLDeviceEXT device = 0;
EGLStreamKHR stream = 0;
EGLOutputLayerEXT layer = 0;
(void) EGL_DRM_CRTC_EXT;
+(void) EGL_DRM_MASTER_FD_EXT;
/* END TEST: */
return 0;
}
@@ -266,8 +282,8 @@ qt_config_compile_test(egl_viv
LABEL "i.Mx6 EGL"
LIBRARIES
EGL::EGL
- COMPILE_OPTIONS # special case
- "-DEGL_API_FB=1" # special case
+ COMPILE_OPTIONS
+ "-DEGL_API_FB=1"
CODE
"#include <EGL/egl.h>
#include <EGL/eglvivante.h>
@@ -288,11 +304,16 @@ fbGetDisplayByIndex(0);
"# FIXME: qmake: ['DEFINES += EGL_API_FB=1', '!integrity: DEFINES += LINUX=1']
)
+set(test_libs EGL::EGL)
+if(INTEGRITY AND _qt_igy_gui_libs)
+ set(test_libs ${test_libs} IntegrityPlatformGraphics::IntegrityPlatformGraphics)
+endif()
+
# egl-openwfd
qt_config_compile_test(egl_openwfd
LABEL "OpenWFD EGL"
LIBRARIES
- EGL::EGL
+ ${test_libs}
CODE
"#include <wfd.h>
@@ -390,19 +411,20 @@ ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
")
# opengles3
-# special case begin
if(WASM)
set(extra_compiler_options "-s FULL_ES3=1")
endif()
-# special case end
+
+set(test_libs GLESv2::GLESv2)
+if(INTEGRITY AND _qt_igy_gui_libs)
+ set(test_libs ${test_libs} IntegrityPlatformGraphics::IntegrityPlatformGraphics)
+endif()
qt_config_compile_test(opengles3
LABEL "OpenGL ES 3.0"
LIBRARIES
- GLESv2::GLESv2
-# special case begin
+ ${test_libs}
COMPILE_OPTIONS ${extra_compiler_options}
-# special case end
CODE
"#ifdef __APPLE__
# include <OpenGLES/ES3/gl.h>
@@ -424,11 +446,12 @@ glMapBufferRange(GL_ARRAY_BUFFER, 0, 0, GL_MAP_READ_BIT);
}
")
+
# opengles31
qt_config_compile_test(opengles31
LABEL "OpenGL ES 3.1"
LIBRARIES
- GLESv2::GLESv2
+ ${test_libs}
CODE
"#include <GLES3/gl31.h>
@@ -446,7 +469,7 @@ glProgramUniform1i(0, 0, 0);
qt_config_compile_test(opengles32
LABEL "OpenGL ES 3.2"
LIBRARIES
- GLESv2::GLESv2
+ ${test_libs}
CODE
"#include <GLES3/gl32.h>
@@ -463,6 +486,7 @@ glFramebufferTexture(GL_TEXTURE_2D, GL_DEPTH_STENCIL_ATTACHMENT, 1, 0);
qt_config_compile_test(xcb_syslibs
LABEL "XCB (extensions)"
LIBRARIES
+ XCB::CURSOR
XCB::ICCCM
XCB::IMAGE
XCB::KEYSYMS
@@ -481,6 +505,7 @@ qt_config_compile_test(xcb_syslibs
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
#include <xcb/xcb_keysyms.h>
+#include <xcb/xcb_cursor.h>
#include <xcb/randr.h>
#include <xcb/render.h>
#include <xcb/shape.h>
@@ -512,7 +537,23 @@ xcb_xkb_get_kbd_by_name_replies_key_names_value_list_sizeof(nullptr, 0, 0, 0, 0,
}
")
-# special case begin
+# libinput_hires_wheel_support
+qt_config_compile_test(libinput_hires_wheel_support
+ LABEL "libinput hires wheel support"
+ LIBRARIES
+ Libinput::Libinput
+ CODE
+"#include <libinput.h>
+int main(void)
+{
+ /* BEGIN TEST: */
+libinput_event_type type = LIBINPUT_EVENT_POINTER_SCROLL_WHEEL;
+libinput_event_pointer_get_scroll_value_v120(nullptr, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
+ /* END TEST: */
+ return 0;
+}
+")
+
# directwrite (assumes DirectWrite2)
qt_config_compile_test(directwrite
LABEL "WINDOWS directwrite"
@@ -539,7 +580,7 @@ qt_config_compile_test(directwrite3
int main(int, char **)
{
IUnknown *factory = nullptr;
- DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3),
+ DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory6),
&factory);
return 0;
}
@@ -574,14 +615,27 @@ int main(int, char **)
return 0;
}
")
-# special case end
+
+qt_config_compile_test(renderdoc
+ LIBRARIES
+ RenderDoc::RenderDoc
+ LABEL "RenderDoc header check"
+ CODE
+"#include <renderdoc_app.h>
+int main(int, char **)
+{
+ if (RENDERDOC_Version::eRENDERDOC_API_Version_1_6_0)
+ return 0;
+ return 0;
+}
+")
#### Features
qt_feature("accessibility-atspi-bridge" PUBLIC PRIVATE
LABEL "ATSPI Bridge"
- CONDITION QT_FEATURE_accessibility AND QT_FEATURE_xcb AND QT_FEATURE_dbus AND ATSPI2_FOUND
+ CONDITION QT_FEATURE_accessibility AND QT_FEATURE_dbus AND ATSPI2_FOUND
)
qt_feature_definition("accessibility-atspi-bridge" "QT_NO_ACCESSIBILITY_ATSPI_BRIDGE" NEGATE VALUE "1")
qt_feature("directfb" PRIVATE
@@ -592,21 +646,21 @@ qt_feature("directfb" PRIVATE
)
qt_feature("directwrite" PRIVATE
LABEL "DirectWrite"
- CONDITION TEST_directwrite # special case
+ CONDITION TEST_directwrite
EMIT_IF WIN32
)
qt_feature("directwrite3" PRIVATE
LABEL "DirectWrite 3"
- CONDITION QT_FEATURE_directwrite AND TEST_directwrite3 # special case
+ CONDITION QT_FEATURE_directwrite AND TEST_directwrite3
EMIT_IF WIN32
)
qt_feature("direct2d" PRIVATE
LABEL "Direct 2D"
- CONDITION WIN32 AND NOT WINRT AND TEST_d2d1 # special case
+ CONDITION WIN32 AND NOT WINRT AND TEST_d2d1
)
qt_feature("direct2d1_1" PRIVATE
LABEL "Direct 2D 1.1"
- CONDITION QT_FEATURE_direct2d AND TEST_d2d1_1 # special case
+ CONDITION QT_FEATURE_direct2d AND TEST_d2d1_1
)
qt_feature("evdev" PRIVATE
LABEL "evdev"
@@ -628,7 +682,7 @@ qt_feature("system-freetype" PRIVATE
qt_feature("fontconfig" PUBLIC PRIVATE
LABEL "Fontconfig"
AUTODETECT NOT APPLE
- CONDITION NOT WIN32 AND QT_FEATURE_system_freetype AND FONTCONFIG_FOUND
+ CONDITION NOT WIN32 AND QT_FEATURE_system_freetype AND Fontconfig_FOUND
)
qt_feature_definition("fontconfig" "QT_NO_FONTCONFIG" NEGATE VALUE "1")
qt_feature("gbm"
@@ -678,6 +732,10 @@ qt_feature("libinput-axis-api" PRIVATE
LABEL "axis API in libinput"
CONDITION QT_FEATURE_libinput AND ON
)
+qt_feature("libinput-hires-wheel-support" PRIVATE
+ LABEL "HiRes wheel support in libinput"
+ CONDITION QT_FEATURE_libinput AND TEST_libinput_hires_wheel_support
+)
qt_feature("lgmon"
LABEL "lgmon"
CONDITION libs.lgmon OR FIXME
@@ -751,9 +809,12 @@ qt_feature("vkgen" PRIVATE
)
qt_feature("vulkan" PUBLIC
LABEL "Vulkan"
- AUTODETECT NOT QNX # FIXME: CI QNX toolchain is broken and finds host vulkan QTQAINFRA-4502
CONDITION QT_FEATURE_library AND QT_FEATURE_vkgen AND WrapVulkanHeaders_FOUND
)
+qt_feature("metal" PUBLIC
+ LABEL "Metal"
+ CONDITION MACOS OR IOS OR VISIONOS
+)
qt_feature("vkkhrdisplay" PRIVATE
SECTION "Platform plugins"
LABEL "VK_KHR_display"
@@ -775,7 +836,7 @@ qt_feature("egl_x11" PRIVATE
qt_feature("eglfs" PRIVATE
SECTION "Platform plugins"
LABEL "EGLFS"
- CONDITION NOT ANDROID AND NOT APPLE AND NOT WIN32 AND NOT WASM AND QT_FEATURE_egl
+ CONDITION NOT ANDROID AND NOT APPLE AND NOT WIN32 AND NOT WASM AND NOT QNX AND QT_FEATURE_egl
)
qt_feature("eglfs_brcm" PRIVATE
LABEL "EGLFS Raspberry Pi"
@@ -807,7 +868,7 @@ qt_feature("eglfs_rcar" PRIVATE
)
qt_feature("eglfs_viv_wl" PRIVATE
LABEL "EGLFS i.Mx6 Wayland"
- CONDITION QT_FEATURE_eglfs_viv AND Wayland_FOUND
+ CONDITION QT_FEATURE_eglfs_viv AND TARGET Wayland::Server
)
qt_feature("eglfs_openwfd" PRIVATE
LABEL "EGLFS OpenWFD"
@@ -863,14 +924,14 @@ qt_feature("sessionmanager" PUBLIC
qt_feature_definition("sessionmanager" "QT_NO_SESSIONMANAGER" NEGATE VALUE "1")
qt_feature("tslib" PRIVATE
LABEL "tslib"
- CONDITION Tslib_FOUND
+ CONDITION Tslib_FOUND AND NOT INTEGRITY
)
qt_feature("tuiotouch" PRIVATE
LABEL "TuioTouch"
PURPOSE "Provides the TuioTouch input plugin."
CONDITION QT_FEATURE_network AND QT_FEATURE_udpsocket
)
-qt_feature("xcb" PRIVATE
+qt_feature("xcb" PUBLIC
SECTION "Platform plugins"
LABEL "XCB"
AUTODETECT NOT APPLE
@@ -888,7 +949,7 @@ qt_feature("xcb-glx" PRIVATE
)
qt_feature("xcb-egl-plugin" PRIVATE
LABEL "EGL-X11 Plugin"
- CONDITION QT_FEATURE_egl_x11 AND QT_FEATURE_opengl
+ CONDITION QT_FEATURE_egl AND QT_FEATURE_opengl
EMIT_IF QT_FEATURE_xcb
)
qt_feature("xcb-native-painting" PRIVATE
@@ -913,6 +974,7 @@ qt_feature("xcb-sm" PRIVATE
)
qt_feature("system-xcb-xinput" PRIVATE
LABEL "Using system-provided xcb-xinput"
+ AUTODETECT OFF
CONDITION XCB_XINPUT_FOUND
ENABLE INPUT_bundled_xcb_xinput STREQUAL 'no'
DISABLE INPUT_bundled_xcb_xinput STREQUAL 'yes'
@@ -954,7 +1016,8 @@ qt_feature("system-textmarkdownreader" PUBLIC
qt_feature("textmarkdownwriter" PUBLIC
SECTION "Kernel"
LABEL "MarkdownWriter"
- PURPOSE "Provides a Markdown (CommonMark) writer"
+ CONDITION QT_FEATURE_regularexpression
+ PURPOSE "Provides a Markdown (CommonMark and GitHub) writer"
)
qt_feature("textodfwriter" PUBLIC
SECTION "Kernel"
@@ -972,7 +1035,7 @@ qt_feature_definition("cssparser" "QT_NO_CSSPARSER" NEGATE VALUE "1")
qt_feature("draganddrop" PUBLIC
SECTION "Kernel"
LABEL "Drag and Drop"
- PURPOSE "Supports the drag and drop mechansim."
+ PURPOSE "Supports the drag and drop mechanism."
CONDITION QT_FEATURE_imageformat_xpm
)
qt_feature_definition("draganddrop" "QT_NO_DRAGANDDROP" NEGATE VALUE "1")
@@ -1136,7 +1199,6 @@ qt_feature("accessibility" PUBLIC
SECTION "Utilities"
LABEL "Accessibility"
PURPOSE "Provides accessibility support."
- CONDITION QT_FEATURE_properties
)
qt_feature_definition("accessibility" "QT_NO_ACCESSIBILITY" NEGATE VALUE "1")
qt_feature("multiprocess" PRIVATE
@@ -1160,6 +1222,7 @@ qt_feature("raster-fp" PRIVATE
SECTION "Painting"
LABEL "QPainter - floating point raster"
PURPOSE "Internal painting support for floating point rasterization."
+ CONDITION NOT VXWORKS # QTBUG-115777
)
qt_feature("undocommand" PUBLIC
SECTION "Utilities"
@@ -1180,7 +1243,19 @@ qt_feature("undogroup" PUBLIC
PURPOSE "Provides the ability to cluster QUndoCommands."
CONDITION QT_FEATURE_undostack
)
+qt_feature("graphicsframecapture" PRIVATE
+ SECTION "Utilities"
+ LABEL "QGraphicsFrameCapture"
+ PURPOSE "Provides a way to capture 3D graphics API calls for a rendered frame."
+ CONDITION TEST_renderdoc OR (MACOS OR IOS)
+)
qt_feature_definition("undogroup" "QT_NO_UNDOGROUP" NEGATE VALUE "1")
+qt_feature("wayland" PUBLIC
+ SECTION "Platform plugins"
+ LABEL "Wayland"
+ CONDITION TARGET Wayland::Client
+)
+
qt_configure_add_summary_section(NAME "Qt Gui")
qt_configure_add_summary_entry(ARGS "accessibility")
qt_configure_add_summary_entry(ARGS "freetype")
@@ -1218,11 +1293,14 @@ qt_configure_add_summary_entry(ARGS "opengles31")
qt_configure_add_summary_entry(ARGS "opengles32")
qt_configure_end_summary_section() # end of "OpenGL" section
qt_configure_add_summary_entry(ARGS "vulkan")
+qt_configure_add_summary_entry(ARGS "metal")
+qt_configure_add_summary_entry(ARGS "graphicsframecapture")
qt_configure_add_summary_entry(ARGS "sessionmanager")
qt_configure_end_summary_section() # end of "Qt Gui" section
qt_configure_add_summary_section(NAME "Features used by QPA backends")
qt_configure_add_summary_entry(ARGS "evdev")
qt_configure_add_summary_entry(ARGS "libinput")
+qt_configure_add_summary_entry(ARGS "libinput_hires_wheel_support")
qt_configure_add_summary_entry(ARGS "integrityhid")
qt_configure_add_summary_entry(ARGS "mtdev")
qt_configure_add_summary_entry(ARGS "tslib")
@@ -1271,7 +1349,7 @@ qt_configure_end_summary_section() # end of "GL integrations" section
qt_configure_end_summary_section() # end of "XCB" section
qt_configure_add_summary_section(NAME "Windows")
qt_configure_add_summary_entry(ARGS "direct2d")
-qt_configure_add_summary_entry(ARGS "direct2d1_1") ### special case
+qt_configure_add_summary_entry(ARGS "direct2d1_1")
qt_configure_add_summary_entry(ARGS "directwrite")
qt_configure_add_summary_entry(ARGS "directwrite3")
qt_configure_end_summary_section() # end of "Windows" section
@@ -1292,14 +1370,9 @@ qt_configure_add_report_entry(
CONDITION QT_FEATURE_gui AND LINUX AND NOT ANDROID AND NOT QT_FEATURE_xcb AND NOT QT_FEATURE_eglfs AND NOT QT_FEATURE_directfb AND NOT QT_FEATURE_linuxfb
)
qt_configure_add_report_entry(
- TYPE WARNING
- MESSAGE "On OS X, AAT is supported only with -qt-harfbuzz."
- CONDITION APPLE AND QT_FEATURE_system_harfbuzz
-)
-qt_configure_add_report_entry(
TYPE ERROR
- MESSAGE "The OpenGL functionality tests failed! You might need to modify the include and library search paths by editing QMAKE_INCDIR_OPENGL[_ES2], QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your platform."
- CONDITION QT_FEATURE_gui AND NOT WATCHOS AND ( NOT INPUT_opengl STREQUAL 'no' ) AND NOT QT_FEATURE_opengl_desktop AND NOT QT_FEATURE_opengles2 AND NOT QT_FEATURE_opengl_dynamic
+ MESSAGE "The OpenGL functionality tests failed! You might need to modify the OpenGL package search path by setting the OpenGL_DIR CMake variable to the OpenGL library's installation directory."
+ CONDITION QT_FEATURE_gui AND NOT WATCHOS AND NOT VISIONOS AND ( NOT INPUT_opengl STREQUAL 'no' ) AND NOT QT_FEATURE_opengl_desktop AND NOT QT_FEATURE_opengles2 AND NOT QT_FEATURE_opengl_dynamic
)
qt_configure_add_report_entry(
TYPE WARNING
diff --git a/src/gui/doc/images/qpainter-concentriccircles.png b/src/gui/doc/images/qpainter-concentriccircles.png
index 4889dcd76d..d9489a4162 100644
--- a/src/gui/doc/images/qpainter-concentriccircles.png
+++ b/src/gui/doc/images/qpainter-concentriccircles.png
Binary files differ
diff --git a/src/gui/doc/includes/QtGuiDoc b/src/gui/doc/includes/QtGuiDoc
index 00d01afa9c..e8fa73786e 100644
--- a/src/gui/doc/includes/QtGuiDoc
+++ b/src/gui/doc/includes/QtGuiDoc
@@ -16,4 +16,8 @@
#include <QtGui/qpa/qplatformscreen_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qkeymapper_p.h>
-#include <QtGui/private/qwindowsmime_p.h>
+
+// rhi
+#include <QtGui/rhi/qrhi.h>
+#include <QtGui/rhi/qshader.h>
+#include <QtGui/rhi/qshaderdescription.h>
diff --git a/src/gui/doc/includes/windows.h b/src/gui/doc/includes/windows.h
index aa42233e75..b4824c2e93 100644
--- a/src/gui/doc/includes/windows.h
+++ b/src/gui/doc/includes/windows.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#pragma once
@@ -51,7 +15,7 @@
//
// Dummy declarations for generating docs on non-Windows platforms
-#if !defined(Q_OS_WIN) && defined(Q_CLANG_QDOC)
+#if !defined(Q_OS_WIN) && defined(Q_QDOC)
typedef struct _FORMATETC {} FORMATETC;
typedef struct _STGMEDIUM {} STGMEDIUM;
typedef void *IDataObject;
diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf
index e08219fedd..b94f11849c 100644
--- a/src/gui/doc/qtgui.qdocconf
+++ b/src/gui/doc/qtgui.qdocconf
@@ -18,10 +18,6 @@ qhp.QtGui.virtualFolder = qtgui
qhp.QtGui.indexTitle = Qt GUI
qhp.QtGui.indexRoot =
-qhp.QtGui.filterAttributes = qtgui $QT_VERSION qtrefdoc
-qhp.QtGui.customFilters.Qt.name = QtGui $QT_VERSION
-qhp.QtGui.customFilters.Qt.filterAttributes = qtgui $QT_VERSION
-
qhp.QtGui.subprojects = classes
qhp.QtGui.subprojects.classes.title = C++ Classes
qhp.QtGui.subprojects.classes.indexTitle = Qt GUI C++ Classes
@@ -43,8 +39,10 @@ depends += \
qtdoc \
qmake \
qtcmake \
+ qtshadertools \
qttestlib \
- qtplatformintegration
+ qtplatformintegration \
+ qthelp
headerdirs += ..
@@ -65,7 +63,7 @@ imagedirs += images \
excludefiles += ../kernel/qtestsupport_gui.cpp \
../painting/qdrawhelper_ssse3.cpp
-# manifestmeta.highlighted.names = "QtGui/Analog Clock Window Example"
+manifestmeta.highlighted.names = "QtGui/Hello Vulkan Cubes Example"
navigation.landingpage = "Qt GUI"
navigation.cppclassespage = "Qt GUI C++ Classes"
@@ -75,3 +73,7 @@ spurious += "Undocumented enum item '.*' in QGradient::Preset"
# \svgcolor {#ffdead}
macro.svgcolor.HTML = "<div style=\"padding:10px;color:#fff;background:\1;\"></div>"
+macro.svgcolor.DocBook = "<db:phrase role=\"color:\1\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</db:phrase>"
+
+# Enforce zero documentation warnings
+warninglimit = 0
diff --git a/src/gui/doc/snippets/brush/brush.cpp b/src/gui/doc/snippets/brush/brush.cpp
index 947fc1602a..83b5e2108a 100644
--- a/src/gui/doc/snippets/brush/brush.cpp
+++ b/src/gui/doc/snippets/brush/brush.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QLinearGradient>
namespace brush {
diff --git a/src/gui/doc/snippets/brush/gradientcreationsnippet.cpp b/src/gui/doc/snippets/brush/gradientcreationsnippet.cpp
index 4dce793090..5f98df40f0 100644
--- a/src/gui/doc/snippets/brush/gradientcreationsnippet.cpp
+++ b/src/gui/doc/snippets/brush/gradientcreationsnippet.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QBrush>
diff --git a/src/gui/doc/snippets/clipboard/clipwindow.cpp b/src/gui/doc/snippets/clipboard/clipwindow.cpp
index ae31d01383..4ed0c81f7f 100644
--- a/src/gui/doc/snippets/clipboard/clipwindow.cpp
+++ b/src/gui/doc/snippets/clipboard/clipwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include <QMimeData>
diff --git a/src/gui/doc/snippets/clipboard/clipwindow.h b/src/gui/doc/snippets/clipboard/clipwindow.h
index 6e4fa0c73a..d22fd4f744 100644
--- a/src/gui/doc/snippets/clipboard/clipwindow.h
+++ b/src/gui/doc/snippets/clipboard/clipwindow.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef CLIPWINDOW_H
#define CLIPWINDOW_H
diff --git a/src/gui/doc/snippets/clipboard/main.cpp b/src/gui/doc/snippets/clipboard/main.cpp
index 08d41df483..9d68f539d1 100644
--- a/src/gui/doc/snippets/clipboard/main.cpp
+++ b/src/gui/doc/snippets/clipboard/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
diff --git a/src/gui/doc/snippets/code/doc_src_coordsys.cpp b/src/gui/doc/snippets/code/doc_src_coordsys.cpp
index df4a0c8c76..03da9ef31a 100644
--- a/src/gui/doc/snippets/code/doc_src_coordsys.cpp
+++ b/src/gui/doc/snippets/code/doc_src_coordsys.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QPainter>
#include <QWidget>
diff --git a/src/gui/doc/snippets/code/doc_src_richtext.cpp b/src/gui/doc/snippets/code/doc_src_richtext.cpp
index d6c8e3e5d3..8d7e76503a 100644
--- a/src/gui/doc/snippets/code/doc_src_richtext.cpp
+++ b/src/gui/doc/snippets/code/doc_src_richtext.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QTextDocument>
#include <QTextEdit>
diff --git a/src/gui/doc/snippets/code/doc_src_richtext.qdoc b/src/gui/doc/snippets/code/doc_src_richtext.qdoc
index 17faf1ac86..0c69514210 100644
--- a/src/gui/doc/snippets/code/doc_src_richtext.qdoc
+++ b/src/gui/doc/snippets/code/doc_src_richtext.qdoc
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
//! [7]
<meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" />
diff --git a/src/gui/doc/snippets/code/src_gui_accessible_qaccessible.cpp b/src/gui/doc/snippets/code/src_gui_accessible_qaccessible.cpp
index 9bbbbc32a7..621d00a401 100644
--- a/src/gui/doc/snippets/code/src_gui_accessible_qaccessible.cpp
+++ b/src/gui/doc/snippets/code/src_gui_accessible_qaccessible.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QAccessible>
namespace src_gui_accessible_qaccessible {
diff --git a/src/gui/doc/snippets/code/src_gui_image_qicon.cpp b/src/gui/doc/snippets/code/src_gui_image_qicon.cpp
index f70426e5f1..a7f27a7fdd 100644
--- a/src/gui/doc/snippets/code/src_gui_image_qicon.cpp
+++ b/src/gui/doc/snippets/code/src_gui_image_qicon.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QIcon>
#include <QPainter>
#include <QToolButton>
@@ -55,7 +8,7 @@ namespace src_gui_image_qicon {
struct MyWidget : public QWidget
{
- void drawIcon(QPainter *painter, QPoint pos);
+ void drawIcon(QPainter *painter, const QRect &rect);
bool isChecked() { return true; }
QIcon icon;
};
@@ -64,9 +17,13 @@ void wrapper0() {
//! [0]
QToolButton *button = new QToolButton;
-button->setIcon(QIcon("open.xpm"));
+button->setIcon(QIcon("open.png"));
//! [0]
+//! [addFile]
+QIcon openIcon("open.png");
+openIcon.addFile("open-disabled.png", QIcon::Disabled);
+//! [addFile]
//! [1]
button->setIcon(QIcon());
@@ -76,29 +33,27 @@ button->setIcon(QIcon());
//! [2]
-void MyWidget::drawIcon(QPainter *painter, QPoint pos)
+void MyWidget::drawIcon(QPainter *painter, const QRect &rect)
{
- QPixmap pixmap = icon.pixmap(QSize(22, 22),
- isEnabled() ? QIcon::Normal
- : QIcon::Disabled,
- isChecked() ? QIcon::On
- : QIcon::Off);
- painter->drawPixmap(pos, pixmap);
+ icon.paint(painter, rect, Qt::AlignCenter, isEnabled() ? QIcon::Normal
+ : QIcon::Disabled,
+ isChecked() ? QIcon::On
+ : QIcon::Off);
}
//! [2]
void wrapper1() {
-//! [3]
-QIcon undoicon = QIcon::fromTheme("edit-undo");
-//! [3]
+//! [fromTheme]
+QIcon undoicon = QIcon::fromTheme(QIcon::ThemeIcon::EditUndo);
+//! [fromTheme]
} // wrapper1
//! [4]
-QIcon undoicon = QIcon::fromTheme("edit-undo", QIcon(":/undo.png"));
+QIcon undoicon = QIcon::fromTheme(QIcon::ThemeIcon::EditUndo, QIcon(":/undo.png"));
//! [4]
diff --git a/src/gui/doc/snippets/code/src_gui_image_qimage.cpp b/src/gui/doc/snippets/code/src_gui_image_qimage.cpp
index cbc2aaae33..759b085be4 100644
--- a/src/gui/doc/snippets/code/src_gui_image_qimage.cpp
+++ b/src/gui/doc/snippets/code/src_gui_image_qimage.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QImage>
#include <QRgb>
diff --git a/src/gui/doc/snippets/code/src_gui_image_qimagereader.cpp b/src/gui/doc/snippets/code/src_gui_image_qimagereader.cpp
index 88330523b3..c703cc580a 100644
--- a/src/gui/doc/snippets/code/src_gui_image_qimagereader.cpp
+++ b/src/gui/doc/snippets/code/src_gui_image_qimagereader.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QImage>
#include <QImageReader>
diff --git a/src/gui/doc/snippets/code/src_gui_image_qimagewriter.cpp b/src/gui/doc/snippets/code/src_gui_image_qimagewriter.cpp
index 1bf141d8f9..98b1fcdc9d 100644
--- a/src/gui/doc/snippets/code/src_gui_image_qimagewriter.cpp
+++ b/src/gui/doc/snippets/code/src_gui_image_qimagewriter.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QImage>
#include <QImageWriter>
diff --git a/src/gui/doc/snippets/code/src_gui_image_qmovie.cpp b/src/gui/doc/snippets/code/src_gui_image_qmovie.cpp
index c9371ba1b5..390f69a703 100644
--- a/src/gui/doc/snippets/code/src_gui_image_qmovie.cpp
+++ b/src/gui/doc/snippets/code/src_gui_image_qmovie.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QLabel>
#include <QMovie>
diff --git a/src/gui/doc/snippets/code/src_gui_image_qpixmap.cpp b/src/gui/doc/snippets/code/src_gui_image_qpixmap.cpp
index 9c52a5075f..2ef59d8f24 100644
--- a/src/gui/doc/snippets/code/src_gui_image_qpixmap.cpp
+++ b/src/gui/doc/snippets/code/src_gui_image_qpixmap.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QBitmap>
#include <QPixmap>
diff --git a/src/gui/doc/snippets/code/src_gui_image_qpixmapcache.cpp b/src/gui/doc/snippets/code/src_gui_image_qpixmapcache.cpp
index 80be2af9bd..9d2566c540 100644
--- a/src/gui/doc/snippets/code/src_gui_image_qpixmapcache.cpp
+++ b/src/gui/doc/snippets/code/src_gui_image_qpixmapcache.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QPainter>
#include <QPixmap>
#include <QPixmapCache>
diff --git a/src/gui/doc/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp b/src/gui/doc/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp
index fa2e9d1269..a608312424 100644
--- a/src/gui/doc/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp
+++ b/src/gui/doc/snippets/code/src_gui_itemviews_qstandarditemmodel.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QStandardItemModel>
#include <QTreeView>
#include <QWidget>
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qaction.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qaction.cpp
index 763238076c..054b40d7c0 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qaction.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qaction.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
QApplication app(argc, argv);
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qapplication.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qapplication.cpp
index fafffc3d08..9455cacf1c 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qapplication.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qapplication.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QStyleFactory>
#include <QWidget>
@@ -66,70 +19,6 @@ struct MyWidget
int manhattanLength() { return 0; }
};
-
-//! [0]
-QCoreApplication *createApplication(int &argc, char *argv[])
-{
- for (int i = 1; i < argc; ++i)
- if (!qstrcmp(argv[i], "-no-gui"))
- return new QCoreApplication(argc, argv);
- return new QApplication(argc, argv);
-}
-
-int main(int argc, char *argv[])
-{
- QScopedPointer<QCoreApplication> app(createApplication(argc, argv));
-
- if (qobject_cast<QApplication *>(app.data())) {
- // start GUI version...
- } else {
- // start non-GUI version...
- }
-
- return app->exec();
-}
-//! [0]
-
-
-void wrapper0() {
-
-//! [1]
-QApplication::setStyle(QStyleFactory::create("fusion"));
-//! [1]
-
-} // wrapper0
-
-
-//! [3]
-QSize MyWidget::sizeHint() const
-{
- return QSize(80, 25);
-}
-//! [3]
-
-
-//! [4]
-void showAllHiddenTopLevelWidgets()
-{
- const auto topLevelWidgets = QApplication::topLevelWidgets();
- for (QWidget *widget : topLevelWidgets) {
- if (widget->isHidden())
- widget->show();
- }
-}
-//! [4]
-
-
-//! [5]
-void updateAllWidgets()
-{
- const auto topLevelWidgets = QApplication::topLevelWidgets();
- for (QWidget *widget : topLevelWidgets)
- widget->update();
-}
-//! [5]
-
-
void startTheDrag() {};
void wrapper1() {
MyWidget startPos;
@@ -143,25 +32,6 @@ if ((startPos - currentPos).manhattanLength() >=
startTheDrag();
//! [6]
-
-//! [7]
-QWidget *widget = qApp->widgetAt(x, y);
-if (widget)
- widget = widget->window();
-//! [7]
-
} // wrapper1
-
-void wrapper2() {
-QPoint point;
-
-//! [8]
-QWidget *widget = qApp->widgetAt(point);
-if (widget)
- widget = widget->window();
-//! [8]
-
-
-} // wrapper2
} // src_gui_kernel_qapplication
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp
index 55e24c3be3..61792521ca 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QClipboard>
#include <QGuiApplication>
#include <QMimeData>
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qevent.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qevent.cpp
index 7ae0444d06..c24e755e92 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qevent.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qevent.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QWheelEvent>
namespace src_gui_kernel_qevent {
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp
index d26a15f783..347b47403e 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QMessageBox>
#include <QSessionManager>
@@ -121,26 +74,4 @@ appname -session id
*/ // wrap snippet 2
-
-void wrapper0() {
-
-
-//! [3]
-const QStringList commands = mySession.restartCommand();
-for (const QString &command : commands)
- do_something(command);
-//! [3]
-
-} // wrapper0
-
-
-void wrapper1() {
-//! [4]
-const QStringList commands = mySession.discardCommand();
-for (const QString &command : mySession.discardCommand())
- do_something(command);
-//! [4]
-
-
-} // wrapper1
} // src_gui_kernel_qguiapplication
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication_x11.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication_x11.cpp
index 1030cc71e2..b73f887af2 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication_x11.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication_x11.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QCursor>
#include <QGuiApplication>
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qkeysequence.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qkeysequence.cpp
index 6ba5bde2e0..0f335dd0a0 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qkeysequence.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qkeysequence.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QKeySequence>
#include <QMenu>
#include <QTranslator>
@@ -79,7 +32,7 @@ void Wrapper::wrapper() {
//! [2]
QMenu *file = new QMenu(this);
file->addAction(tr("&Open..."), QKeySequence(tr("Ctrl+O", "File|Open")),
- this, SLOT(open()));
+ this, &MainWindow::open);
//! [2]
} // Wrapper::wrapper
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qshortcut.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qshortcut.cpp
index 370afd0679..d67aea1288 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qshortcut.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qshortcut.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
shortcut = new QShortcut(QKeySequence(tr("Ctrl+O", "File|Open")),
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qshortcutmap.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qshortcutmap.cpp
index 06a51ef128..c08b318a4d 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qshortcutmap.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qshortcutmap.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QKeySequence>
namespace src_gui_kernel_qshortcutmap {
diff --git a/src/gui/doc/snippets/code/src_gui_math3d_qquaternion.cpp b/src/gui/doc/snippets/code/src_gui_math3d_qquaternion.cpp
index 47c571c299..6f27ba9db9 100644
--- a/src/gui/doc/snippets/code/src_gui_math3d_qquaternion.cpp
+++ b/src/gui/doc/snippets/code/src_gui_math3d_qquaternion.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QQuaternion>
#include <QVector3D>
diff --git a/src/gui/doc/snippets/code/src_gui_opengl_qopenglfunctions.cpp b/src/gui/doc/snippets/code/src_gui_opengl_qopenglfunctions.cpp
index 946e3caef5..14531446a1 100644
--- a/src/gui/doc/snippets/code/src_gui_opengl_qopenglfunctions.cpp
+++ b/src/gui/doc/snippets/code/src_gui_opengl_qopenglfunctions.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QOpenGLFunctions>
#include <QtOpenGL/QOpenGLWindow>
diff --git a/src/gui/doc/snippets/code/src_gui_painting_qbrush.cpp b/src/gui/doc/snippets/code/src_gui_painting_qbrush.cpp
index 842a547f83..69eedff7d1 100644
--- a/src/gui/doc/snippets/code/src_gui_painting_qbrush.cpp
+++ b/src/gui/doc/snippets/code/src_gui_painting_qbrush.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QPainter>
namespace src_gui_painting_qbrush {
diff --git a/src/gui/doc/snippets/code/src_gui_painting_qcolor.cpp b/src/gui/doc/snippets/code/src_gui_painting_qcolor.cpp
index ecb52d0756..0a2bc832ff 100644
--- a/src/gui/doc/snippets/code/src_gui_painting_qcolor.cpp
+++ b/src/gui/doc/snippets/code/src_gui_painting_qcolor.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QPainter>
namespace src_gui_painting_qcolor {
diff --git a/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp b/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp
index 3a72c2aed8..cfbf3e44a2 100644
--- a/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp
+++ b/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QOpenGLFunctions>
#include <QPaintEvent>
#include <QPainter>
@@ -110,6 +63,7 @@ struct MyWidget : public QWidget
void wrapper13();
void wrapper14();
void wrapper15();
+ void concentricCircles();
};
QLine drawingCode;
@@ -144,15 +98,6 @@ struct QPainter {
void setWorldTransform(QTransform matrix, bool);
};
-//! [4]
-void QPainter::rotate(qreal angle)
-{
- QTransform matrix;
- matrix.rotate(angle);
- setWorldTransform(matrix, true);
-}
-//! [4]
-
} // QPainterWrapper
void MyWidget::wrapper1() {
@@ -170,7 +115,7 @@ painter.drawPath(path);
//! [6]
QLineF line(10.0, 80.0, 90.0, 20.0);
-QPainter(this);
+QPainter painter(this);
painter.drawLine(line);
//! [6]
} // MyWidget::wrapper1()
@@ -307,7 +252,7 @@ QRectF target(10.0, 20.0, 80.0, 60.0);
QRectF source(0.0, 0.0, 70.0, 40.0);
QPixmap pixmap(":myPixmap.png");
-QPainter(this);
+QPainter painter(this);
painter.drawPixmap(target, pixmap, source);
//! [16]
@@ -411,4 +356,21 @@ painter.drawRect(rectangle.adjusted(0, 0, -pen.width(), -pen.width()));
} // MyWidget::wrapper15
-} // src_gui_painting_qpainter2
+
+void MyWidget::concentricCircles()
+{
+//! [renderHint]
+ QPainter painter(this);
+ painter.setRenderHint(QPainter::Antialiasing, true);
+//! [renderHint]
+ int diameter = 50;
+//! [floatBased]
+ painter.drawEllipse(QRectF(-diameter / 2.0, -diameter / 2.0, diameter, diameter));
+//! [floatBased]
+//! [intBased]
+ painter.drawEllipse(QRect(-diameter / 2, -diameter / 2, diameter, diameter));
+//! [intBased]
+
+} // MyWidget::concentricCircles
+
+} // src_gui_painting_qpainter2 \ No newline at end of file
diff --git a/src/gui/doc/snippets/code/src_gui_painting_qpainterpath.cpp b/src/gui/doc/snippets/code/src_gui_painting_qpainterpath.cpp
index f11b6f59c5..cd538b750c 100644
--- a/src/gui/doc/snippets/code/src_gui_painting_qpainterpath.cpp
+++ b/src/gui/doc/snippets/code/src_gui_painting_qpainterpath.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QLinearGradient>
#include <QPainter>
#include <QPainterPath>
diff --git a/src/gui/doc/snippets/code/src_gui_painting_qpen.cpp b/src/gui/doc/snippets/code/src_gui_painting_qpen.cpp
index 973037cf42..a9c21afb9f 100644
--- a/src/gui/doc/snippets/code/src_gui_painting_qpen.cpp
+++ b/src/gui/doc/snippets/code/src_gui_painting_qpen.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QPainter>
#include <QPen>
diff --git a/src/gui/doc/snippets/code/src_gui_painting_qregion.cpp b/src/gui/doc/snippets/code/src_gui_painting_qregion.cpp
index a1123564aa..6401c29de5 100644
--- a/src/gui/doc/snippets/code/src_gui_painting_qregion.cpp
+++ b/src/gui/doc/snippets/code/src_gui_painting_qregion.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QPaintEvent>
#include <QPainter>
diff --git a/src/gui/doc/snippets/code/src_gui_painting_qregion_unix.cpp b/src/gui/doc/snippets/code/src_gui_painting_qregion_unix.cpp
index d45521a791..26a95566d4 100644
--- a/src/gui/doc/snippets/code/src_gui_painting_qregion_unix.cpp
+++ b/src/gui/doc/snippets/code/src_gui_painting_qregion_unix.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QRegion>
namespace src_gui_painting_qregion_unix {
diff --git a/src/gui/doc/snippets/code/src_gui_painting_qtransform.cpp b/src/gui/doc/snippets/code/src_gui_painting_qtransform.cpp
index 97b9ee8af9..fbc6d9add8 100644
--- a/src/gui/doc/snippets/code/src_gui_painting_qtransform.cpp
+++ b/src/gui/doc/snippets/code/src_gui_painting_qtransform.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
namespace src_gui_painting_qtransform {
/* wrap non-code snippets
diff --git a/src/gui/doc/snippets/code/src_gui_text_qfont.cpp b/src/gui/doc/snippets/code/src_gui_text_qfont.cpp
index 5bd5e69009..d62730e918 100644
--- a/src/gui/doc/snippets/code/src_gui_text_qfont.cpp
+++ b/src/gui/doc/snippets/code/src_gui_text_qfont.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QFont>
#include <QFontInfo>
#include <QFontMetrics>
diff --git a/src/gui/doc/snippets/code/src_gui_text_qfontmetrics.cpp b/src/gui/doc/snippets/code/src_gui_text_qfontmetrics.cpp
index 3c0da7691f..4650ad8d8f 100644
--- a/src/gui/doc/snippets/code/src_gui_text_qfontmetrics.cpp
+++ b/src/gui/doc/snippets/code/src_gui_text_qfontmetrics.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QFont>
#include <QFontMetrics>
@@ -56,7 +9,7 @@ void wrapper0() {
//! [0]
QFont font("times", 24);
QFontMetrics fm(font);
-int pixelsWide = fm.horizontalAdvance("What's the width of this text?");
+int pixelsWide = fm.horizontalAdvance("What's the advance width of this text?");
int pixelsHigh = fm.height();
//! [0]
@@ -69,7 +22,7 @@ void wrapper1() {
//! [1]
QFont font("times", 24);
QFontMetricsF fm(font);
-qreal pixelsWide = fm.horizontalAdvance("What's the width of this text?");
+qreal pixelsWide = fm.horizontalAdvance("What's the advance width of this text?");
qreal pixelsHigh = fm.height();
//! [1]
diff --git a/src/gui/doc/snippets/code/src_gui_text_qsyntaxhighlighter.cpp b/src/gui/doc/snippets/code/src_gui_text_qsyntaxhighlighter.cpp
index 063d189e78..fa4798ea04 100644
--- a/src/gui/doc/snippets/code/src_gui_text_qsyntaxhighlighter.cpp
+++ b/src/gui/doc/snippets/code/src_gui_text_qsyntaxhighlighter.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QChar>
#include <QList>
#include <QRegularExpression>
diff --git a/src/gui/doc/snippets/code/src_gui_text_qtextcursor.cpp b/src/gui/doc/snippets/code/src_gui_text_qtextcursor.cpp
index 8e3825cb14..1438474b98 100644
--- a/src/gui/doc/snippets/code/src_gui_text_qtextcursor.cpp
+++ b/src/gui/doc/snippets/code/src_gui_text_qtextcursor.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QImage>
#include <QTextCursor>
#include <QTextDocument>
diff --git a/src/gui/doc/snippets/code/src_gui_text_qtextdocument.cpp b/src/gui/doc/snippets/code/src_gui_text_qtextdocument.cpp
deleted file mode 100644
index 21e1f85ce7..0000000000
--- a/src/gui/doc/snippets/code/src_gui_text_qtextdocument.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-namespace src_gui_text_qtextdocument {
-
-/* wrap non-code snippet
-
-//! [0]
-<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>...
-//! [0]
-
-*/ // wrap non-code snippet
-} // src_gui_text_qtextdocument
diff --git a/src/gui/doc/snippets/code/src_gui_text_qtextdocumentwriter.cpp b/src/gui/doc/snippets/code/src_gui_text_qtextdocumentwriter.cpp
index d05dffcbc4..a55857cb88 100644
--- a/src/gui/doc/snippets/code/src_gui_text_qtextdocumentwriter.cpp
+++ b/src/gui/doc/snippets/code/src_gui_text_qtextdocumentwriter.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QTextDocumentWriter>
namespace src_gui_text_qtextdocumentwriter {
diff --git a/src/gui/doc/snippets/code/src_gui_text_qtextlayout.cpp b/src/gui/doc/snippets/code/src_gui_text_qtextlayout.cpp
index 4a156edac9..70ec6b01ea 100644
--- a/src/gui/doc/snippets/code/src_gui_text_qtextlayout.cpp
+++ b/src/gui/doc/snippets/code/src_gui_text_qtextlayout.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QFont>
#include <QFontMetrics>
#include <QPainter>
@@ -57,6 +10,7 @@ namespace src_gui_text_qtextlayout {
struct Wrapper : public QPaintDevice
{
void wrapper1();
+ void elided();
};
QTextLayout textLayout;
@@ -71,7 +25,7 @@ int leading = fontMetrics.leading();
qreal height = 0;
textLayout.setCacheEnabled(true);
textLayout.beginLayout();
-while (1) {
+while (true) {
QTextLine line = textLayout.createLine();
if (!line.isValid())
break;
@@ -96,4 +50,41 @@ textLayout.draw(&painter, QPoint(0, 0));
} // Wrapper::wrapper1
+void Wrapper::elided() {
+
+QString content;
+
+//! [elided]
+QPainter painter(this);
+QFontMetrics fontMetrics = painter.fontMetrics();
+
+int lineSpacing = fontMetrics.lineSpacing();
+int y = 0;
+
+QTextLayout textLayout(content, painter.font());
+textLayout.beginLayout();
+while (true) {
+ QTextLine line = textLayout.createLine();
+
+ if (!line.isValid())
+ break;
+
+ line.setLineWidth(width());
+ const int nextLineY = y + lineSpacing;
+
+ if (height() >= nextLineY + lineSpacing) {
+ line.draw(&painter, QPoint(0, y));
+ y = nextLineY;
+ } else {
+ const QString lastLine = content.mid(line.textStart());
+ const QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, width());
+ painter.drawText(QPoint(0, y + fontMetrics.ascent()), elidedLastLine);
+ line = textLayout.createLine();
+ break;
+ }
+}
+textLayout.endLayout();
+//! [elided]
+}
+
} // src_gui_text_qtextlayout
diff --git a/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp b/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp
index 0809d62da9..13deb88bc8 100644
--- a/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp
+++ b/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QDesktopServices>
#include <QObject>
#include <QStandardPaths>
@@ -84,7 +37,7 @@ mailto:user@foo.com?subject=Test&body=Just a test
void wrapper1() {
//! [2]
-QDesktopServices::openUrl(QUrl("file:///C:/Documents and Settings/All Users/Desktop", QUrl::TolerantMode));
+QDesktopServices::openUrl(QUrl("file:///C:/Program Files", QUrl::TolerantMode));
//! [2]
}
@@ -112,15 +65,6 @@ QDesktopServices::openUrl(QUrl("file:///C:/Documents and Settings/All Users/Desk
*/ // comment wrapper 2
-
-void wrapper3() {
-//! [6]
-QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
- "/data/organization/application";
-//! [6]
-} // wrapper3
-
-
/* comment wrapper 3
//! [7]
<key>com.apple.developer.associated-domains</key>
@@ -144,7 +88,31 @@ QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
}
//! [8]
-*/ // comment wrapper 3
+//! [9]
+<intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="https" android:host="your.domain.com" android:port="1337" android:path="/help"/>
+</intent-filter>
+//! [9]
+
+//! [10]
+<intent-filter android:autoVerify="true">
+//! [10]
+
+//! [11]
+[{
+ "relation": ["delegate_permission/common.handle_all_urls"],
+ "target": {
+ "namespace": "android_app",
+ "package_name": "com.example.app",
+ "sha256_cert_fingerprints":
+ ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
+ }
+}]
+//! [11]
+*/ // comment wrapper 3
} // src_gui_util_qdesktopservices
diff --git a/src/gui/doc/snippets/code/src_gui_util_qundostack.cpp b/src/gui/doc/snippets/code/src_gui_util_qundostack.cpp
index 8f59fe9cb3..fe3ced1d02 100644
--- a/src/gui/doc/snippets/code/src_gui_util_qundostack.cpp
+++ b/src/gui/doc/snippets/code/src_gui_util_qundostack.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [0]
class AppendText : public QUndoCommand
diff --git a/src/gui/doc/snippets/code/src_gui_util_qvalidator.cpp b/src/gui/doc/snippets/code/src_gui_util_qvalidator.cpp
index 51fc3a6e14..f562126ffd 100644
--- a/src/gui/doc/snippets/code/src_gui_util_qvalidator.cpp
+++ b/src/gui/doc/snippets/code/src_gui_util_qvalidator.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QLineEdit>
#include <QValidator>
#include <QWidget>
@@ -57,6 +10,7 @@ struct Wrapper : public QWidget {
void wrapper0();
void wrapper1();
void wrapper2();
+ void wrapper3();
};
void Wrapper::wrapper0() {
@@ -164,4 +118,22 @@ s = "readm"; v.validate(s, pos); // Returns Intermediate
} // Wrapper::wrapper2
+void Wrapper::wrapper3()
+{
+//! [7]
+QString input = "0.98765e2";
+QDoubleValidator val;
+val.setLocale(QLocale::C);
+val.setNotation(QDoubleValidator::ScientificNotation);
+val.fixup(input); // input == "9.8765e+01"
+//! [7]
+//! [8]
+input = "-1234.6789";
+val.setDecimals(2);
+val.setLocale(QLocale::C);
+val.setNotation(QDoubleValidator::StandardNotation);
+val.fixup(input); // input == "-1234.68"
+//! [8]
+} // Wrapper::wrapper3
+
} // src_gui_util_qvalidator
diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp
index df08418581..700d933f43 100644
--- a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp
+++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QVulkanDeviceFunctions>
#include <QVulkanFunctions>
@@ -55,20 +8,18 @@
namespace src_gui_vulkan_qvulkanfunctions {
struct Window {
- void render();
+ void init();
QVulkanInstance *vulkanInstance() { return nullptr; }
};
-VkDevice_T *device = nullptr;
-VkCommandBufferAllocateInfo cmdBufInfo;
-VkCommandBuffer cmdBuf;
//! [0]
-void Window::render()
+void Window::init()
{
QVulkanInstance *inst = vulkanInstance();
QVulkanFunctions *f = inst->functions();
// ...
- VkResult err = f->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf);
+ uint32_t count = 0;
+ VkResult err = f->vkEnumeratePhysicalDevices(inst->vkInstance(), &count, nullptr);
// ...
}
//! [0]
diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp
index 1dfd43ad10..bfb7c7c3a4 100644
--- a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp
+++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QGuiApplication>
#include <QVulkanFunctions>
diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp
index 1f4988ca35..7f9abb638e 100644
--- a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp
+++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QGuiApplication>
#include <QVulkanDeviceFunctions>
#include <QVulkanWindow>
diff --git a/src/gui/doc/snippets/draganddrop/dragwidget.cpp b/src/gui/doc/snippets/draganddrop/dragwidget.cpp
index ba8a0cc39d..4f592de10b 100644
--- a/src/gui/doc/snippets/draganddrop/dragwidget.cpp
+++ b/src/gui/doc/snippets/draganddrop/dragwidget.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
#include <QLabel>
diff --git a/src/gui/doc/snippets/draganddrop/dragwidget.h b/src/gui/doc/snippets/draganddrop/dragwidget.h
index eb069d73d2..2861104a00 100644
--- a/src/gui/doc/snippets/draganddrop/dragwidget.h
+++ b/src/gui/doc/snippets/draganddrop/dragwidget.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef DRAGWIDGET_H
#define DRAGWIDGET_H
diff --git a/src/gui/doc/snippets/draganddrop/main.cpp b/src/gui/doc/snippets/draganddrop/main.cpp
index 95a6b3ff00..12e3317a25 100644
--- a/src/gui/doc/snippets/draganddrop/main.cpp
+++ b/src/gui/doc/snippets/draganddrop/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
diff --git a/src/gui/doc/snippets/draganddrop/mainwindow.cpp b/src/gui/doc/snippets/draganddrop/mainwindow.cpp
index 003e57c4fd..c6f4454f5e 100644
--- a/src/gui/doc/snippets/draganddrop/mainwindow.cpp
+++ b/src/gui/doc/snippets/draganddrop/mainwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
diff --git a/src/gui/doc/snippets/draganddrop/mainwindow.h b/src/gui/doc/snippets/draganddrop/mainwindow.h
index 85581e7909..7c24115a4d 100644
--- a/src/gui/doc/snippets/draganddrop/mainwindow.h
+++ b/src/gui/doc/snippets/draganddrop/mainwindow.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
diff --git a/src/gui/doc/snippets/dragging/main.cpp b/src/gui/doc/snippets/dragging/main.cpp
index b08a18b894..a266be0fb9 100644
--- a/src/gui/doc/snippets/dragging/main.cpp
+++ b/src/gui/doc/snippets/dragging/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
diff --git a/src/gui/doc/snippets/dragging/mainwindow.cpp b/src/gui/doc/snippets/dragging/mainwindow.cpp
index 5614c9351b..8eecfa53b7 100644
--- a/src/gui/doc/snippets/dragging/mainwindow.cpp
+++ b/src/gui/doc/snippets/dragging/mainwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
diff --git a/src/gui/doc/snippets/dragging/mainwindow.h b/src/gui/doc/snippets/dragging/mainwindow.h
index fd7f659b2d..9d2a18e55e 100644
--- a/src/gui/doc/snippets/dragging/mainwindow.h
+++ b/src/gui/doc/snippets/dragging/mainwindow.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
diff --git a/src/gui/doc/snippets/droparea/droparea.cpp b/src/gui/doc/snippets/droparea/droparea.cpp
index b66cf0c031..6b3583acff 100644
--- a/src/gui/doc/snippets/droparea/droparea.cpp
+++ b/src/gui/doc/snippets/droparea/droparea.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QClipboard>
#include <QMimeData>
diff --git a/src/gui/doc/snippets/dropevents/window.cpp b/src/gui/doc/snippets/dropevents/window.cpp
index a62b656b64..753bb8705f 100644
--- a/src/gui/doc/snippets/dropevents/window.cpp
+++ b/src/gui/doc/snippets/dropevents/window.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QComboBox>
#include <QDragEnterEvent>
#include <QLabel>
diff --git a/src/gui/doc/snippets/droprectangle/window.cpp b/src/gui/doc/snippets/droprectangle/window.cpp
index 7b71d4b508..351f4d12c1 100644
--- a/src/gui/doc/snippets/droprectangle/window.cpp
+++ b/src/gui/doc/snippets/droprectangle/window.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QDragMoveEvent>
#include <QFrame>
#include <QMimeData>
diff --git a/src/gui/doc/snippets/image/image.cpp b/src/gui/doc/snippets/image/image.cpp
index 3f2e7371e0..82703c5c0f 100644
--- a/src/gui/doc/snippets/image/image.cpp
+++ b/src/gui/doc/snippets/image/image.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
namespace image {
void wrapper0() {
@@ -72,13 +25,6 @@ buffer.open(QIODevice::WriteOnly);
pixmap.save(&buffer, "PNG"); // writes pixmap into bytes in PNG format
//! [1]
-
-//! [2]
-QPixmap alpha("image-with-alpha.png");
-QPixmap alphacopy = alpha;
-alphacopy.setMask(alphacopy.mask());
-//! [2]
-
} // wrapper1
} // image
diff --git a/src/gui/doc/snippets/image/supportedformat.cpp b/src/gui/doc/snippets/image/supportedformat.cpp
index c6a9779ac9..61aed40c57 100644
--- a/src/gui/doc/snippets/image/supportedformat.cpp
+++ b/src/gui/doc/snippets/image/supportedformat.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
diff --git a/src/gui/doc/snippets/overview/using-qt-gui.cmake b/src/gui/doc/snippets/overview/using-qt-gui.cmake
index 65a3f9034a..4f774c43ff 100644
--- a/src/gui/doc/snippets/overview/using-qt-gui.cmake
+++ b/src/gui/doc/snippets/overview/using-qt-gui.cmake
@@ -1,2 +1,2 @@
-find_package(Qt6 COMPONENTS Gui REQUIRED)
+find_package(Qt6 REQUIRED COMPONENTS Gui)
target_link_libraries(mytarget PRIVATE Qt6::Gui)
diff --git a/src/gui/doc/snippets/picture/picture.cpp b/src/gui/doc/snippets/picture/picture.cpp
index cdf0dda84b..2faf0dde5f 100644
--- a/src/gui/doc/snippets/picture/picture.cpp
+++ b/src/gui/doc/snippets/picture/picture.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
namespace picture {
diff --git a/src/gui/doc/snippets/plaintextlayout/window.cpp b/src/gui/doc/snippets/plaintextlayout/window.cpp
index 36c061635e..77ed9d4e54 100644
--- a/src/gui/doc/snippets/plaintextlayout/window.cpp
+++ b/src/gui/doc/snippets/plaintextlayout/window.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QPainter>
#include <QTextLayout>
#include <QWidget>
diff --git a/src/gui/doc/snippets/polygon/polygon.cpp b/src/gui/doc/snippets/polygon/polygon.cpp
index 8105ebf491..4afb586135 100644
--- a/src/gui/doc/snippets/polygon/polygon.cpp
+++ b/src/gui/doc/snippets/polygon/polygon.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QPolygon>
namespace polygon {
diff --git a/src/gui/doc/snippets/qfileopenevent/Info.plist b/src/gui/doc/snippets/qfileopenevent/Info.plist
index 85311bb037..98ab05e708 100644
--- a/src/gui/doc/snippets/qfileopenevent/Info.plist
+++ b/src/gui/doc/snippets/qfileopenevent/Info.plist
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2015 Samuel Gaist <samuel.gaist@edeltech.ch>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [Custom Info.plist]
<?xml version="1.0" encoding="UTF-8"?>
diff --git a/src/gui/doc/snippets/qfileopenevent/main.cpp b/src/gui/doc/snippets/qfileopenevent/main.cpp
index f3754c49c5..a94ff58137 100644
--- a/src/gui/doc/snippets/qfileopenevent/main.cpp
+++ b/src/gui/doc/snippets/qfileopenevent/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2023 Samuel Gaist <samuel.gaist@edeltech.ch>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [QApplication subclass]
#include <QApplication>
@@ -66,7 +19,15 @@ public:
{
if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
- qDebug() << "Open file" << openEvent->file();
+ const QUrl url = openEvent->url();
+ if (url.isLocalFile()) {
+ QFile localFile(url.toLocalFile());
+ // read from local file
+ } else if (url.isValid()) {
+ // process according to the URL's schema
+ } else {
+ // parse openEvent->file()
+ }
}
return QApplication::event(event);
diff --git a/src/gui/doc/snippets/qfontdatabase/qfontdatabase_snippets.cpp b/src/gui/doc/snippets/qfontdatabase/qfontdatabase_snippets.cpp
index abcff4211a..5b6bfe14cf 100644
--- a/src/gui/doc/snippets/qfontdatabase/qfontdatabase_snippets.cpp
+++ b/src/gui/doc/snippets/qfontdatabase/qfontdatabase_snippets.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
diff --git a/src/gui/doc/snippets/qimagewriter/main.cpp b/src/gui/doc/snippets/qimagewriter/main.cpp
index 2b8046c332..ffb0b8eda5 100644
--- a/src/gui/doc/snippets/qimagewriter/main.cpp
+++ b/src/gui/doc/snippets/qimagewriter/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Samuel Gaist <samuel.gaist@idiap.ch>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Samuel Gaist <samuel.gaist@idiap.ch>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
void wrapper() {
diff --git a/src/gui/doc/snippets/qstatustipevent/main.cpp b/src/gui/doc/snippets/qstatustipevent/main.cpp
index 3022f85209..c6f2c8da3a 100644
--- a/src/gui/doc/snippets/qstatustipevent/main.cpp
+++ b/src/gui/doc/snippets/qstatustipevent/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
diff --git a/src/gui/doc/snippets/qtextobject/textobjectinterface.h b/src/gui/doc/snippets/qtextobject/textobjectinterface.h
index 08b14a4eef..f17b233cb8 100644
--- a/src/gui/doc/snippets/qtextobject/textobjectinterface.h
+++ b/src/gui/doc/snippets/qtextobject/textobjectinterface.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QObject>
#include <QTextObjectInterface>
diff --git a/src/gui/doc/snippets/rhioffscreen/color.frag b/src/gui/doc/snippets/rhioffscreen/color.frag
new file mode 100644
index 0000000000..ad9d953d02
--- /dev/null
+++ b/src/gui/doc/snippets/rhioffscreen/color.frag
@@ -0,0 +1,16 @@
+//! [0]
+#version 440
+
+layout(location = 0) in vec3 v_color;
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float opacity;
+};
+
+void main()
+{
+ fragColor = vec4(v_color * opacity, opacity);
+}
+//! [0]
diff --git a/src/gui/doc/snippets/rhioffscreen/color.vert b/src/gui/doc/snippets/rhioffscreen/color.vert
new file mode 100644
index 0000000000..0010e55561
--- /dev/null
+++ b/src/gui/doc/snippets/rhioffscreen/color.vert
@@ -0,0 +1,18 @@
+//! [0]
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec3 color;
+layout(location = 0) out vec3 v_color;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float opacity;
+};
+
+void main()
+{
+ v_color = color;
+ gl_Position = mvp * position;
+}
+//! [0]
diff --git a/src/gui/doc/snippets/rhioffscreen/main.cpp b/src/gui/doc/snippets/rhioffscreen/main.cpp
new file mode 100644
index 0000000000..c2c6f74dc1
--- /dev/null
+++ b/src/gui/doc/snippets/rhioffscreen/main.cpp
@@ -0,0 +1,151 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [0]
+#include <QGuiApplication>
+#include <QImage>
+#include <QFile>
+#include <rhi/qrhi.h>
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+#if QT_CONFIG(vulkan)
+ QVulkanInstance inst;
+#endif
+ std::unique_ptr<QRhi> rhi;
+#if defined(Q_OS_WIN)
+ QRhiD3D12InitParams params;
+ rhi.reset(QRhi::create(QRhi::D3D12, &params));
+#elif QT_CONFIG(metal)
+ QRhiMetalInitParams params;
+ rhi.reset(QRhi::create(QRhi::Metal, &params));
+#elif QT_CONFIG(vulkan)
+ inst.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions());
+ if (inst.create()) {
+ QRhiVulkanInitParams params;
+ params.inst = &inst;
+ rhi.reset(QRhi::create(QRhi::Vulkan, &params));
+ } else {
+ qFatal("Failed to create Vulkan instance");
+ }
+#endif
+ if (rhi)
+ qDebug() << rhi->backendName() << rhi->driverInfo();
+ else
+ qFatal("Failed to initialize RHI");
+
+ float rotation = 0.0f;
+ float opacity = 1.0f;
+ int opacityDir = 1;
+
+ std::unique_ptr<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8,
+ QSize(1280, 720),
+ 1,
+ QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
+ tex->create();
+ std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ tex.get() }));
+ std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
+ rt->setRenderPassDescriptor(rp.get());
+ rt->create();
+
+ QMatrix4x4 viewProjection = rhi->clipSpaceCorrMatrix();
+ viewProjection.perspective(45.0f, 1280 / 720.f, 0.01f, 1000.0f);
+ viewProjection.translate(0, 0, -4);
+
+ static float vertexData[] = { // Y up, CCW
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f,
+ };
+
+ std::unique_ptr<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable,
+ QRhiBuffer::VertexBuffer,
+ sizeof(vertexData)));
+ vbuf->create();
+
+ std::unique_ptr<QRhiBuffer> ubuf(rhi->newBuffer(QRhiBuffer::Dynamic,
+ QRhiBuffer::UniformBuffer,
+ 64 + 4));
+ ubuf->create();
+
+ std::unique_ptr<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
+ srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0,
+ QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage,
+ ubuf.get())
+ });
+ srb->create();
+
+ std::unique_ptr<QRhiGraphicsPipeline> ps(rhi->newGraphicsPipeline());
+ QRhiGraphicsPipeline::TargetBlend premulAlphaBlend;
+ premulAlphaBlend.enable = true;
+ ps->setTargetBlends({ premulAlphaBlend });
+ static auto getShader = [](const QString &name) {
+ QFile f(name);
+ return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
+ };
+ ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(QLatin1String("color.vert.qsb")) },
+ { QRhiShaderStage::Fragment, getShader(QLatin1String("color.frag.qsb")) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float2, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
+ });
+ ps->setVertexInputLayout(inputLayout);
+ ps->setShaderResourceBindings(srb.get());
+ ps->setRenderPassDescriptor(rp.get());
+ ps->create();
+
+ QRhiCommandBuffer *cb;
+ for (int frame = 0; frame < 20; ++frame) {
+ rhi->beginOffscreenFrame(&cb);
+
+ QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
+ if (frame == 0)
+ u->uploadStaticBuffer(vbuf.get(), vertexData);
+
+ QMatrix4x4 mvp = viewProjection;
+ mvp.rotate(rotation, 0, 1, 0);
+ u->updateDynamicBuffer(ubuf.get(), 0, 64, mvp.constData());
+ rotation += 5.0f;
+
+ u->updateDynamicBuffer(ubuf.get(), 64, 4, &opacity);
+ opacity += opacityDir * 0.2f;
+ if (opacity < 0.0f || opacity > 1.0f) {
+ opacityDir *= -1;
+ opacity = qBound(0.0f, opacity, 1.0f);
+ }
+
+ cb->beginPass(rt.get(), Qt::green, { 1.0f, 0 }, u);
+ cb->setGraphicsPipeline(ps.get());
+ cb->setViewport({ 0, 0, 1280, 720 });
+ cb->setShaderResources();
+ const QRhiCommandBuffer::VertexInput vbufBinding(vbuf.get(), 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+ cb->draw(3);
+ QRhiReadbackResult readbackResult;
+ u = rhi->nextResourceUpdateBatch();
+ u->readBackTexture({ tex.get() }, &readbackResult);
+ cb->endPass(u);
+
+ rhi->endOffscreenFrame();
+
+ QImage image(reinterpret_cast<const uchar *>(readbackResult.data.constData()),
+ readbackResult.pixelSize.width(),
+ readbackResult.pixelSize.height(),
+ QImage::Format_RGBA8888_Premultiplied);
+ if (rhi->isYUpInFramebuffer())
+ image = image.mirrored();
+ image.save(QString::asprintf("frame%d.png", frame));
+ }
+
+ return 0;
+}
+//! [0]
diff --git a/src/gui/doc/snippets/scribe-overview/main.cpp b/src/gui/doc/snippets/scribe-overview/main.cpp
index 3781123a71..c58c93ec6c 100644
--- a/src/gui/doc/snippets/scribe-overview/main.cpp
+++ b/src/gui/doc/snippets/scribe-overview/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextEdit>
diff --git a/src/gui/doc/snippets/separations/finalwidget.cpp b/src/gui/doc/snippets/separations/finalwidget.cpp
index 25aa6b8d1c..3c308d9df8 100644
--- a/src/gui/doc/snippets/separations/finalwidget.cpp
+++ b/src/gui/doc/snippets/separations/finalwidget.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
/*
finalwidget.cpp
@@ -75,10 +28,9 @@ FinalWidget::FinalWidget(QWidget *parent, const QString &name,
imageLabel->setMinimumSize(labelSize);
nameLabel = new QLabel(name);
- QVBoxLayout *layout = new QVBoxLayout;
+ QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(imageLabel, 1);
layout->addWidget(nameLabel, 0);
- setLayout(layout);
}
/*!
diff --git a/src/gui/doc/snippets/separations/finalwidget.h b/src/gui/doc/snippets/separations/finalwidget.h
index a7c092c92a..da65ca8be2 100644
--- a/src/gui/doc/snippets/separations/finalwidget.h
+++ b/src/gui/doc/snippets/separations/finalwidget.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef FINALWIDGET_H
#define FINALWIDGET_H
diff --git a/src/gui/doc/snippets/separations/main.cpp b/src/gui/doc/snippets/separations/main.cpp
index a730f193a8..d3b63ceeb5 100644
--- a/src/gui/doc/snippets/separations/main.cpp
+++ b/src/gui/doc/snippets/separations/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include "viewer.h"
diff --git a/src/gui/doc/snippets/separations/screenwidget.cpp b/src/gui/doc/snippets/separations/screenwidget.cpp
index d562991d26..223de95962 100644
--- a/src/gui/doc/snippets/separations/screenwidget.cpp
+++ b/src/gui/doc/snippets/separations/screenwidget.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
/*
screenwidget.cpp
@@ -108,12 +61,11 @@ ScreenWidget::ScreenWidget(QWidget *parent, QColor initialColor,
connect(colorButton, &QPushButton::clicked, this, &ScreenWidget::setColor);
connect(invertButton, &QPushButton::clicked, this, &ScreenWidget::invertImage);
- QGridLayout *gridLayout = new QGridLayout;
+ QGridLayout *gridLayout = new QGridLayout(this);
gridLayout->addWidget(imageLabel, 0, 0, 1, 2);
gridLayout->addWidget(nameLabel, 1, 0);
gridLayout->addWidget(colorButton, 1, 1);
gridLayout->addWidget(invertButton, 2, 1, 1, 1);
- setLayout(gridLayout);
}
/*!
diff --git a/src/gui/doc/snippets/separations/screenwidget.h b/src/gui/doc/snippets/separations/screenwidget.h
index 1fc839be65..ae2d736851 100644
--- a/src/gui/doc/snippets/separations/screenwidget.h
+++ b/src/gui/doc/snippets/separations/screenwidget.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef SCREENWIDGET_H
#define SCREENWIDGET_H
diff --git a/src/gui/doc/snippets/separations/separations.qdoc b/src/gui/doc/snippets/separations/separations.qdoc
index ecb35012ee..ee567030bb 100644
--- a/src/gui/doc/snippets/separations/separations.qdoc
+++ b/src/gui/doc/snippets/separations/separations.qdoc
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*
\example painting/separations
diff --git a/src/gui/doc/snippets/separations/viewer.cpp b/src/gui/doc/snippets/separations/viewer.cpp
index c1aca07524..87378a3852 100644
--- a/src/gui/doc/snippets/separations/viewer.cpp
+++ b/src/gui/doc/snippets/separations/viewer.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
/*
viewer.cpp
diff --git a/src/gui/doc/snippets/separations/viewer.h b/src/gui/doc/snippets/separations/viewer.h
index 5dfba3a209..869372cb83 100644
--- a/src/gui/doc/snippets/separations/viewer.h
+++ b/src/gui/doc/snippets/separations/viewer.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef VIEWER_H
#define VIEWER_H
diff --git a/src/gui/doc/snippets/textblock-formats/main.cpp b/src/gui/doc/snippets/textblock-formats/main.cpp
index ec3075c2e3..d9ca3eff35 100644
--- a/src/gui/doc/snippets/textblock-formats/main.cpp
+++ b/src/gui/doc/snippets/textblock-formats/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextEdit>
diff --git a/src/gui/doc/snippets/textblock-fragments/xmlwriter.cpp b/src/gui/doc/snippets/textblock-fragments/xmlwriter.cpp
index 96a2fdfb09..ce9dab80f9 100644
--- a/src/gui/doc/snippets/textblock-fragments/xmlwriter.cpp
+++ b/src/gui/doc/snippets/textblock-fragments/xmlwriter.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "xmlwriter.h"
#include <QTextDocument>
diff --git a/src/gui/doc/snippets/textblock-fragments/xmlwriter.h b/src/gui/doc/snippets/textblock-fragments/xmlwriter.h
index b140aa1c9b..910a87b50e 100644
--- a/src/gui/doc/snippets/textblock-fragments/xmlwriter.h
+++ b/src/gui/doc/snippets/textblock-fragments/xmlwriter.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef XMLWRITER_H
#define XMLWRITER_H
diff --git a/src/gui/doc/snippets/textdocument-blocks/main.cpp b/src/gui/doc/snippets/textdocument-blocks/main.cpp
index fb3bb2b2e9..026cd59961 100644
--- a/src/gui/doc/snippets/textdocument-blocks/main.cpp
+++ b/src/gui/doc/snippets/textdocument-blocks/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
diff --git a/src/gui/doc/snippets/textdocument-blocks/mainwindow.cpp b/src/gui/doc/snippets/textdocument-blocks/mainwindow.cpp
index a62f0f3f89..a55336b01c 100644
--- a/src/gui/doc/snippets/textdocument-blocks/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-blocks/mainwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
diff --git a/src/gui/doc/snippets/textdocument-blocks/mainwindow.h b/src/gui/doc/snippets/textdocument-blocks/mainwindow.h
index 0ce579c158..32fdcfd1c8 100644
--- a/src/gui/doc/snippets/textdocument-blocks/mainwindow.h
+++ b/src/gui/doc/snippets/textdocument-blocks/mainwindow.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
diff --git a/src/gui/doc/snippets/textdocument-charformats/main.cpp b/src/gui/doc/snippets/textdocument-charformats/main.cpp
index 43ad7ffc11..381f204cae 100644
--- a/src/gui/doc/snippets/textdocument-charformats/main.cpp
+++ b/src/gui/doc/snippets/textdocument-charformats/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextEdit>
diff --git a/src/gui/doc/snippets/textdocument-css/main.cpp b/src/gui/doc/snippets/textdocument-css/main.cpp
index 418230c65b..8ac28adbc3 100644
--- a/src/gui/doc/snippets/textdocument-css/main.cpp
+++ b/src/gui/doc/snippets/textdocument-css/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextBrowser>
diff --git a/src/gui/doc/snippets/textdocument-cursors/main.cpp b/src/gui/doc/snippets/textdocument-cursors/main.cpp
index 8d20d66c2e..b71874a889 100644
--- a/src/gui/doc/snippets/textdocument-cursors/main.cpp
+++ b/src/gui/doc/snippets/textdocument-cursors/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextEdit>
diff --git a/src/gui/doc/snippets/textdocument-end/textdocumentendsnippet.cpp b/src/gui/doc/snippets/textdocument-end/textdocumentendsnippet.cpp
index e56ad8d30b..1653fd4d2f 100644
--- a/src/gui/doc/snippets/textdocument-end/textdocumentendsnippet.cpp
+++ b/src/gui/doc/snippets/textdocument-end/textdocumentendsnippet.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
#include <iostream>
diff --git a/src/gui/doc/snippets/textdocument-find/main.cpp b/src/gui/doc/snippets/textdocument-find/main.cpp
index 286b34db3e..4b3948b114 100644
--- a/src/gui/doc/snippets/textdocument-find/main.cpp
+++ b/src/gui/doc/snippets/textdocument-find/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextEdit>
diff --git a/src/gui/doc/snippets/textdocument-frames/main.cpp b/src/gui/doc/snippets/textdocument-frames/main.cpp
index ff3f70192c..71c21ac803 100644
--- a/src/gui/doc/snippets/textdocument-frames/main.cpp
+++ b/src/gui/doc/snippets/textdocument-frames/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
diff --git a/src/gui/doc/snippets/textdocument-frames/mainwindow.cpp b/src/gui/doc/snippets/textdocument-frames/mainwindow.cpp
index 2608fb9f00..5b9adbaf3b 100644
--- a/src/gui/doc/snippets/textdocument-frames/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-frames/mainwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
diff --git a/src/gui/doc/snippets/textdocument-frames/mainwindow.h b/src/gui/doc/snippets/textdocument-frames/mainwindow.h
index 40fa8e41e0..e535d67f32 100644
--- a/src/gui/doc/snippets/textdocument-frames/mainwindow.h
+++ b/src/gui/doc/snippets/textdocument-frames/mainwindow.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
diff --git a/src/gui/doc/snippets/textdocument-imagedrop/main.cpp b/src/gui/doc/snippets/textdocument-imagedrop/main.cpp
index c7f7e2df45..6a451db44a 100644
--- a/src/gui/doc/snippets/textdocument-imagedrop/main.cpp
+++ b/src/gui/doc/snippets/textdocument-imagedrop/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "textedit.h"
#include <QApplication>
diff --git a/src/gui/doc/snippets/textdocument-imagedrop/textedit.h b/src/gui/doc/snippets/textdocument-imagedrop/textedit.h
index 5db7dd0ad7..86f31a0edf 100644
--- a/src/gui/doc/snippets/textdocument-imagedrop/textedit.h
+++ b/src/gui/doc/snippets/textdocument-imagedrop/textedit.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef TEXTEDIT_H
#define TEXTEDIT_H
diff --git a/src/gui/doc/snippets/textdocument-imageformat/main.cpp b/src/gui/doc/snippets/textdocument-imageformat/main.cpp
index b69d75eb0a..f626c6fef4 100644
--- a/src/gui/doc/snippets/textdocument-imageformat/main.cpp
+++ b/src/gui/doc/snippets/textdocument-imageformat/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextBlock>
#include <QTextEdit>
diff --git a/src/gui/doc/snippets/textdocument-images/main.cpp b/src/gui/doc/snippets/textdocument-images/main.cpp
index 0d87b9a671..d9fd232388 100644
--- a/src/gui/doc/snippets/textdocument-images/main.cpp
+++ b/src/gui/doc/snippets/textdocument-images/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextEdit>
diff --git a/src/gui/doc/snippets/textdocument-listitems/main.cpp b/src/gui/doc/snippets/textdocument-listitems/main.cpp
index 020e0fe771..44afd4775f 100644
--- a/src/gui/doc/snippets/textdocument-listitems/main.cpp
+++ b/src/gui/doc/snippets/textdocument-listitems/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
#include <QApplication>
diff --git a/src/gui/doc/snippets/textdocument-listitems/mainwindow.cpp b/src/gui/doc/snippets/textdocument-listitems/mainwindow.cpp
index 119cf1b5f7..324f1937d9 100644
--- a/src/gui/doc/snippets/textdocument-listitems/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-listitems/mainwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QMenu>
@@ -60,17 +13,17 @@ MainWindow::MainWindow()
QMenu *fileMenu = new QMenu(tr("&File"));
fileMenu->addAction(tr("E&xit"), QKeySequence(tr("Ctrl+Q", "File|Exit")),
- this, SLOT(close()));
+ this, &QWidget::close);
QMenu *actionsMenu = new QMenu(tr("&Actions"));
actionsMenu->addAction(tr("&Highlight List Items"),
- this, SLOT(highlightListItems()));
- actionsMenu->addAction(tr("&Show Current List"), this, SLOT(showList()));
+ this, &MainWindow::highlightListItems);
+ actionsMenu->addAction(tr("&Show Current List"), this, &MainWindow::showList);
QMenu *insertMenu = new QMenu(tr("&Insert"));
insertMenu->addAction(tr("&List"), QKeySequence(tr("Ctrl+L", "Insert|List")),
- this, SLOT(insertList()));
+ this, &MainWindow::insertList);
menuBar()->addMenu(fileMenu);
menuBar()->addMenu(insertMenu);
diff --git a/src/gui/doc/snippets/textdocument-listitems/mainwindow.h b/src/gui/doc/snippets/textdocument-listitems/mainwindow.h
index 019897124f..9dd441c2d3 100644
--- a/src/gui/doc/snippets/textdocument-listitems/mainwindow.h
+++ b/src/gui/doc/snippets/textdocument-listitems/mainwindow.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
diff --git a/src/gui/doc/snippets/textdocument-listitemstyles/main.cpp b/src/gui/doc/snippets/textdocument-listitemstyles/main.cpp
index 37ccd8269f..27d478e05c 100644
--- a/src/gui/doc/snippets/textdocument-listitemstyles/main.cpp
+++ b/src/gui/doc/snippets/textdocument-listitemstyles/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
#include <QApplication>
diff --git a/src/gui/doc/snippets/textdocument-listitemstyles/mainwindow.cpp b/src/gui/doc/snippets/textdocument-listitemstyles/mainwindow.cpp
index 49f96bff18..bd692f15b9 100644
--- a/src/gui/doc/snippets/textdocument-listitemstyles/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-listitemstyles/mainwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QMenu>
diff --git a/src/gui/doc/snippets/textdocument-listitemstyles/mainwindow.h b/src/gui/doc/snippets/textdocument-listitemstyles/mainwindow.h
index 6219863e64..ff03d07be7 100644
--- a/src/gui/doc/snippets/textdocument-listitemstyles/mainwindow.h
+++ b/src/gui/doc/snippets/textdocument-listitemstyles/mainwindow.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
diff --git a/src/gui/doc/snippets/textdocument-lists/mainwindow.cpp b/src/gui/doc/snippets/textdocument-lists/mainwindow.cpp
index 5cb81c8721..0a4b076f63 100644
--- a/src/gui/doc/snippets/textdocument-lists/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-lists/mainwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QTextEdit>
#include <QTextList>
diff --git a/src/gui/doc/snippets/textdocument-printing/main.cpp b/src/gui/doc/snippets/textdocument-printing/main.cpp
index cb8158adf9..c0e5d49f7c 100644
--- a/src/gui/doc/snippets/textdocument-printing/main.cpp
+++ b/src/gui/doc/snippets/textdocument-printing/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
diff --git a/src/gui/doc/snippets/textdocument-printing/mainwindow.cpp b/src/gui/doc/snippets/textdocument-printing/mainwindow.cpp
index 60d94a99ba..ff16d6f0da 100644
--- a/src/gui/doc/snippets/textdocument-printing/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-printing/mainwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QMenu>
diff --git a/src/gui/doc/snippets/textdocument-printing/mainwindow.h b/src/gui/doc/snippets/textdocument-printing/mainwindow.h
index 9d1d483f6b..f58d5ec49e 100644
--- a/src/gui/doc/snippets/textdocument-printing/mainwindow.h
+++ b/src/gui/doc/snippets/textdocument-printing/mainwindow.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
diff --git a/src/gui/doc/snippets/textdocument-resources/main.cpp b/src/gui/doc/snippets/textdocument-resources/main.cpp
index f48c726f10..8b9f16098e 100644
--- a/src/gui/doc/snippets/textdocument-resources/main.cpp
+++ b/src/gui/doc/snippets/textdocument-resources/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextEdit>
diff --git a/src/gui/doc/snippets/textdocument-selections/main.cpp b/src/gui/doc/snippets/textdocument-selections/main.cpp
index cb8158adf9..c0e5d49f7c 100644
--- a/src/gui/doc/snippets/textdocument-selections/main.cpp
+++ b/src/gui/doc/snippets/textdocument-selections/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
diff --git a/src/gui/doc/snippets/textdocument-selections/mainwindow.cpp b/src/gui/doc/snippets/textdocument-selections/mainwindow.cpp
index ef25fa9112..6e1d051d4b 100644
--- a/src/gui/doc/snippets/textdocument-selections/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-selections/mainwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QtWidgets>
@@ -56,30 +9,30 @@ MainWindow::MainWindow()
QMenu *fileMenu = new QMenu(tr("&File"));
fileMenu->addAction(tr("&Open..."), QKeySequence(tr("Ctrl+O", "File|Open")),
- this, SLOT(openFile()));
+ this, &MainWindow::openFile);
- QAction *quitAction = fileMenu->addAction(tr("E&xit"), this, SLOT(close()));
+ QAction *quitAction = fileMenu->addAction(tr("E&xit"), this, &MainWindow::close);
quitAction->setShortcut(tr("Ctrl+Q"));
QMenu *editMenu = new QMenu(tr("&Edit"));
- cutAction = editMenu->addAction(tr("Cu&t"), this, SLOT(cutSelection()));
+ cutAction = editMenu->addAction(tr("Cu&t"), this, &MainWindow::cutSelection);
cutAction->setShortcut(tr("Ctrl+X"));
cutAction->setEnabled(false);
- copyAction = editMenu->addAction(tr("&Copy"), this, SLOT(copySelection()));
+ copyAction = editMenu->addAction(tr("&Copy"), this, &MainWindow::copySelection);
copyAction->setShortcut(tr("Ctrl+C"));
copyAction->setEnabled(false);
- pasteAction = editMenu->addAction(tr("&Paste"), this, SLOT(pasteSelection()));
+ pasteAction = editMenu->addAction(tr("&Paste"), this, &MainWindow::pasteSelection);
pasteAction->setShortcut(tr("Ctrl+V"));
pasteAction->setEnabled(false);
QMenu *selectMenu = new QMenu(tr("&Select"));
- selectMenu->addAction(tr("&Word"), this, SLOT(selectWord()));
- selectMenu->addAction(tr("&Line"), this, SLOT(selectLine()));
- selectMenu->addAction(tr("&Block"), this, SLOT(selectBlock()));
- selectMenu->addAction(tr("&Frame"), this, SLOT(selectFrame()));
+ selectMenu->addAction(tr("&Word"), this, &MainWindow::selectWord);
+ selectMenu->addAction(tr("&Line"), this, &MainWindow::selectLine);
+ selectMenu->addAction(tr("&Block"), this, &MainWindow::selectBlock);
+ selectMenu->addAction(tr("&Frame"), this, &MainWindow::selectFrame);
menuBar()->addMenu(fileMenu);
menuBar()->addMenu(editMenu);
diff --git a/src/gui/doc/snippets/textdocument-selections/mainwindow.h b/src/gui/doc/snippets/textdocument-selections/mainwindow.h
index 8327a55877..31bd7a2d64 100644
--- a/src/gui/doc/snippets/textdocument-selections/mainwindow.h
+++ b/src/gui/doc/snippets/textdocument-selections/mainwindow.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
diff --git a/src/gui/doc/snippets/textdocument-tables/main.cpp b/src/gui/doc/snippets/textdocument-tables/main.cpp
index 811aaded9a..87ce7e46da 100644
--- a/src/gui/doc/snippets/textdocument-tables/main.cpp
+++ b/src/gui/doc/snippets/textdocument-tables/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
diff --git a/src/gui/doc/snippets/textdocument-tables/mainwindow.cpp b/src/gui/doc/snippets/textdocument-tables/mainwindow.cpp
index ab00f43c2e..02f31f8807 100644
--- a/src/gui/doc/snippets/textdocument-tables/mainwindow.cpp
+++ b/src/gui/doc/snippets/textdocument-tables/mainwindow.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
diff --git a/src/gui/doc/snippets/textdocument-tables/mainwindow.h b/src/gui/doc/snippets/textdocument-tables/mainwindow.h
index 37a7cc289d..3885478e6c 100644
--- a/src/gui/doc/snippets/textdocument-tables/mainwindow.h
+++ b/src/gui/doc/snippets/textdocument-tables/mainwindow.h
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
diff --git a/src/gui/doc/snippets/textdocument-texttable/main.cpp b/src/gui/doc/snippets/textdocument-texttable/main.cpp
index a61ff7a318..69c7580a7e 100644
--- a/src/gui/doc/snippets/textdocument-texttable/main.cpp
+++ b/src/gui/doc/snippets/textdocument-texttable/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTextEdit>
#include <QTextTable>
diff --git a/src/gui/doc/snippets/transform/main.cpp b/src/gui/doc/snippets/transform/main.cpp
index d15b059020..cedffe218c 100644
--- a/src/gui/doc/snippets/transform/main.cpp
+++ b/src/gui/doc/snippets/transform/main.cpp
@@ -1,54 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
-#include <QMath>
+#include <QtMath>
#include <QPainter>
#include <QVBoxLayout>
#include <QWidget>
@@ -138,11 +91,10 @@ int main(int argc, char **argv)
CombinedTransformation *combinedWidget = new CombinedTransformation;
BasicOperations *basicWidget = new BasicOperations;
- QVBoxLayout *layout = new QVBoxLayout;
+ QVBoxLayout *layout = new QVBoxLayout(&widget);
layout->addWidget(simpleWidget);
layout->addWidget(combinedWidget);
layout->addWidget(basicWidget);
- widget.setLayout(layout);
widget.show();
widget.resize(130, 350);
diff --git a/src/gui/doc/src/coordsys.qdoc b/src/gui/doc/src/coordsys.qdoc
index 4df7151750..087916635b 100644
--- a/src/gui/doc/src/coordsys.qdoc
+++ b/src/gui/doc/src/coordsys.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page coordsys.html
@@ -111,7 +87,7 @@
\endtable
When rendering with a pen with an even number of pixels, the
- pixels will be rendered symetrically around the mathematical
+ pixels will be rendered symmetrically around the mathematical
defined points, while rendering with a pen with an odd number of
pixels, the spare pixel will be rendered to the right and below
the mathematical point as in the one pixel case. See the QRectF
@@ -160,7 +136,7 @@
\section2 Anti-aliased Painting
If you set QPainter's \l {QPainter::Antialiasing}{anti-aliasing}
- render hint, the pixels will be rendered symetrically on both
+ render hint, the pixels will be rendered symmetrically on both
sides of the mathematically defined points:
\table
@@ -237,11 +213,11 @@
\row
\li {2,1}
- \snippet analogclock/main.cpp 1
+ \snippet ../widgets/widgets/analogclock/analogclock.cpp 9
We translate the coordinate system so that point (0, 0) is in the
widget's center, instead of being at the top-left corner. We also
- scale the system by \c side / 100, where \c side is either the
+ scale the system by \c side / 200, where \c side is either the
widget's width or the height, whichever is shortest. We want the
clock to be square, even if the device isn't.
@@ -251,7 +227,7 @@
See also the \l {Window-Viewport Conversion} section.
- \snippet analogclock/main.cpp 2
+ \snippet ../widgets/widgets/analogclock/analogclock.cpp 18
We draw the clock's hour hand by rotating the coordinate system
and calling QPainter::drawConvexPolygon(). Thank's to the
@@ -259,26 +235,35 @@
The polygon is specified as an array of alternating \e x, \e y
values, stored in the \c hourHand static variable (defined at the
- beginning of the function), which corresponds to the four points
- (2, 0), (0, 2), (-2, 0), and (0, -25).
+ beginning of the function), which corresponds to the three points
+ (7, 8), (-7, 8), (0, -40).
The calls to QPainter::save() and QPainter::restore() surrounding
the code guarantees that the code that follows won't be disturbed
by the transformations we've used.
- \snippet analogclock/main.cpp 3
+ \snippet ../widgets/widgets/analogclock/analogclock.cpp 21
+
+ After that, we draw the hour markers for the clock face, which
+ consists of twelve short lines at 30-degree intervals. When that
+ loop is done, the painter has been rotated a full circle back to
+ its original state, so we don't need to save and restore the state.
+
+ \snippet ../widgets/widgets/analogclock/analogclock.cpp 24
We do the same for the clock's minute hand, which is defined by
- the four points (1, 0), (0, 1), (-1, 0), and (0, -40). These
+ the three points (7, 8), (-7, 8), (0, -70). These
coordinates specify a hand that is thinner and longer than the
minute hand.
- \snippet analogclock/main.cpp 4
+ \snippet ../widgets/widgets/analogclock/analogclock.cpp 27
- Finally, we draw the clock face, which consists of twelve short
- lines at 30-degree intervals. At the end of that, the painter is
- rotated in a way which isn't very useful, but we're done with
- painting so that doesn't matter.
+ Finally, we draw the minute markers for the clock face, which
+ consists of sixty short lines at 6-degree intervals. We skip every
+ fifth minute marker because we don't want to draw over the hour
+ markers. At the end of that, the painter is rotated in a way which
+ isn't very useful, but we're done with painting so that doesn't
+ matter.
\endtable
For more information about the transformation matrix, see the
@@ -446,5 +431,5 @@
\endtable
\endomit
- \sa {Analog Clock Window Example}
+ \sa {Analog Clock}
*/
diff --git a/src/gui/doc/src/dnd.qdoc b/src/gui/doc/src/dnd.qdoc
index 35bb47fdb6..7a756b304e 100644
--- a/src/gui/doc/src/dnd.qdoc
+++ b/src/gui/doc/src/dnd.qdoc
@@ -1,31 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
+ \keyword Drag and Drop in Qt
\page dnd.html
\title Drag and Drop
\brief An overview of the drag and drop system provided by Qt.
@@ -358,7 +335,9 @@
For example, we can copy the contents of a QLineEdit to the clipboard
with the following code:
- \snippet ../widgets/widgets/charactermap/mainwindow.cpp 11
+ \code
+ QGuiApplication::clipboard()->setText(lineEdit->text(), QClipboard::Clipboard);
+ \endcode
Data with different MIME types can also be put on the clipboard.
Construct a QMimeData object and set data with setData() function in
@@ -387,23 +366,20 @@
\li \l{draganddrop/draggableicons}{Draggable Icons}
\li \l{draganddrop/draggabletext}{Draggable Text}
\li \l{draganddrop/dropsite}{Drop Site}
- \li \l{draganddrop/fridgemagnets}{Fridge Magnets}
- \li \l{draganddrop/puzzle}{Drag and Drop Puzzle}
\endlist
\section1 Interoperating with Other Applications
- On X11, the public \l{http://www.newplanetsoftware.com/xdnd/}{XDND
- protocol} is used, while on Windows Qt uses the OLE standard, and
- Qt for \macos uses the Cocoa Drag Manager. On X11, XDND uses MIME,
- so no translation is necessary. The Qt API is the same regardless of
- the platform. On Windows, MIME-aware applications can communicate by
- using clipboard format names that are MIME types. Already some
- Windows applications use MIME naming conventions for their
- clipboard formats.
+ On X11, the public
+ \l{https://freedesktop.org/wiki/Specifications/XDND}{XDND protocol} is
+ used, while on Windows Qt uses the OLE standard, and Qt for \macos uses the
+ Cocoa Drag Manager. On X11, XDND uses MIME, so no translation is necessary.
+ The Qt API is the same regardless of the platform. On Windows, MIME-aware
+ applications can communicate by using clipboard format names that are MIME
+ types. Some Windows applications already use MIME naming conventions for
+ their clipboard formats.
Custom classes for translating proprietary clipboard formats can be
- registered by reimplementing QWinMime on Windows or
- QMacPasteboardMime on \macos.
-
+ registered by reimplementing QWindowsMimeConverter on Windows or
+ QUtiMimeConverter on \macos.
*/
diff --git a/src/gui/doc/src/dontdocument.qdoc b/src/gui/doc/src/dontdocument.qdoc
index 6711644359..5f19ea9e73 100644
--- a/src/gui/doc/src/dontdocument.qdoc
+++ b/src/gui/doc/src/dontdocument.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\dontdocument (QTypeInfo QScreenOrientationChangeEvent QApplicationStateChangeEvent
diff --git a/src/gui/doc/src/external-resources.qdoc b/src/gui/doc/src/external-resources.qdoc
index 0addbb21cd..16bca2475d 100644
--- a/src/gui/doc/src/external-resources.qdoc
+++ b/src/gui/doc/src/external-resources.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
@@ -32,13 +8,13 @@
*/
/*!
- \externalpage http://www.linux-foundation.org/en/Accessibility/IAccessible2
+ \externalpage https://accessibility.linuxfoundation.org/a11yspecs/ia2/docs/html/index.html
\title IAccessible2 Specification
*/
/*!
- \externalpage http://czyborra.com/
- \title Roman Czyborra's
+ \externalpage https://www.unicode.org/reports/tr17/
+ \title UTR17
*/
/*!
@@ -53,15 +29,24 @@
/*!
\externalpage https://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
- \title Icon Theme Specification
+ \title Freedesktop Icon Theme Specification
*/
/*!
+ \externalpage https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
+ \title Freedesktop Icon Naming Specification
+*/
+/*!
\externalpage https://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#directory_layout
\title Icon Theme Specification - Directory Layout
*/
/*!
+ \externalpage https://freedesktop.org/
+ \title Freedesktop
+*/
+
+/*!
\externalpage https://www.khronos.org/vulkan/
\title Vulkan
*/
@@ -70,3 +55,13 @@
\externalpage https://www.lunarg.com/vulkan-sdk/
\title LunarG Vulkan SDK
*/
+
+/*!
+ \externalpage https://developer.android.com/reference/androidx/core/content/FileProvider
+ \title Android: FileProvider
+*/
+
+/*!
+ \externalpage https://developer.android.com/training/secure-file-sharing/setup-sharing.html
+ \title Android: Setting up file sharing
+*/
diff --git a/src/gui/doc/src/includes/qt-colors.qdocinc b/src/gui/doc/src/includes/qt-colors.qdocinc
index 4c082323b6..d98c0a908a 100644
--- a/src/gui/doc/src/includes/qt-colors.qdocinc
+++ b/src/gui/doc/src/includes/qt-colors.qdocinc
@@ -3,84 +3,105 @@
\li Name
\li Hex
\li Color
+
\row
\li Color0
\li #000000
\li \svgcolor {#000000}
+
\row
\li Color1
\li #ffffff
\li \svgcolor {#ffffff}
+
\row
\li Black
\li #000000
\li \svgcolor {#000000}
+
\row
\li White
\li #ffffff
\li \svgcolor {#ffffff}
+
\row
\li DarkGray
\li #808080
\li \svgcolor {#808080}
+
\row
\li Gray
\li #a0a0a4
\li \svgcolor {#a0a0a4}
+
\row
\li LightGray
\li #c0c0c0
\li \svgcolor {#c0c0c0}
+
\row
\li Red
\li #ff0000
\li \svgcolor {#ff0000}
+
\row
\li Green
\li #00ff00
\li \svgcolor {#00ff00}
+
\row
\li Blue
\li #0000ff
\li \svgcolor {#0000ff}
+
\row
\li Cyan
\li #00ffff
\li \svgcolor {#00ffff}
+
\row
\li Magenta
\li #ff00ff
\li \svgcolor {#ff00ff}
+
\row
\li Yellow
\li #ffff00
\li \svgcolor {#ffff00}
+
\row
\li DarkRed
\li #800000
\li \svgcolor {#800000}
+
\row
\li DarkGreen
\li #008000
\li \svgcolor {#008000}
+
\row
\li DarkBlue
\li #000080
\li \svgcolor {#000080}
+
\row
\li DarkCyan
\li #008080
\li \svgcolor {#008080}
+
\row
\li DarkMagenta
\li #800080
\li \svgcolor {#800080}
+
\row
\li DarkYellow
\li #808000
\li \svgcolor {#808000}
+
\row
\li Transparent
\li #00000000
\li (transparent)
+
\endtable
diff --git a/src/gui/doc/src/includes/svg-colors.qdocinc b/src/gui/doc/src/includes/svg-colors.qdocinc
index 4e5fb56d5e..c28cbabbf7 100644
--- a/src/gui/doc/src/includes/svg-colors.qdocinc
+++ b/src/gui/doc/src/includes/svg-colors.qdocinc
@@ -3,592 +3,740 @@
\li Name
\li Hex
\li Color
+
\row
\li aliceblue
\li #f0f8ff
\li \svgcolor {#f0f8ff}
+
\row
\li antiquewhite
\li #faebd7
\li \svgcolor {#faebd7}
+
\row
\li aqua
\li #00ffff
\li \svgcolor {#00ffff}
+
\row
\li aquamarine
\li #7fffd4
\li \svgcolor {#7fffd4}
+
\row
\li azure
\li #f0ffff
\li \svgcolor {#f0ffff}
+
\row
\li beige
\li #f5f5dc
\li \svgcolor {#f5f5dc}
+
\row
\li bisque
\li #ffe4c4
\li \svgcolor {#ffe4c4}
+
\row
\li black
\li #000000
\li \svgcolor {#000000}
+
\row
\li blanchedalmond
\li #ffebcd
\li \svgcolor {#ffebcd}
+
\row
\li blue
\li #0000ff
\li \svgcolor {#0000ff}
+
\row
\li blueviolet
\li #8a2be2
\li \svgcolor {#8a2be2}
+
\row
\li brown
\li #a52a2a
\li \svgcolor {#a52a2a}
+
\row
\li burlywood
\li #deb887
\li \svgcolor {#deb887}
+
\row
\li cadetblue
\li #5f9ea0
\li \svgcolor {#5f9ea0}
+
\row
\li chartreuse
\li #7fff00
\li \svgcolor {#7fff00}
+
\row
\li chocolate
\li #d2691e
\li \svgcolor {#d2691e}
+
\row
\li coral
\li #ff7f50
\li \svgcolor {#ff7f50}
+
\row
\li cornflowerblue
\li #6495ed
\li \svgcolor {#6495ed}
+
\row
\li cornsilk
\li #fff8dc
\li \svgcolor {#fff8dc}
+
\row
\li crimson
\li #dc143c
\li \svgcolor {#dc143c}
+
\row
\li cyan
\li #00ffff
\li \svgcolor {#00ffff}
+
\row
\li darkblue
\li #00008b
\li \svgcolor {#00008b}
+
\row
\li darkcyan
\li #008b8b
\li \svgcolor {#008b8b}
+
\row
\li darkgoldenrod
\li #b8860b
\li \svgcolor {#b8860b}
+
\row
\li darkgray
\li #a9a9a9
\li \svgcolor {#a9a9a9}
+
\row
\li darkgreen
\li #006400
\li \svgcolor {#006400}
+
\row
\li darkgrey
\li #a9a9a9
\li \svgcolor {#a9a9a9}
+
\row
\li darkkhaki
\li #bdb76b
\li \svgcolor {#bdb76b}
+
\row
\li darkmagenta
\li #8b008b
\li \svgcolor {#8b008b}
+
\row
\li darkolivegreen
\li #556b2f
\li \svgcolor {#556b2f}
+
\row
\li darkorange
\li #ff8c00
\li \svgcolor {#ff8c00}
+
\row
\li darkorchid
\li #9932cc
\li \svgcolor {#9932cc}
+
\row
\li darkred
\li #8b0000
\li \svgcolor {#8b0000}
+
\row
\li darksalmon
\li #e9967a
\li \svgcolor {#e9967a}
+
\row
\li darkseagreen
\li #8fbc8f
\li \svgcolor {#8fbc8f}
+
\row
\li darkslateblue
\li #483d8b
\li \svgcolor {#483d8b}
+
\row
\li darkslategray
\li #2f4f4f
\li \svgcolor {#2f4f4f}
+
\row
\li darkslategrey
\li #2f4f4f
\li \svgcolor {#2f4f4f}
+
\row
\li darkturquoise
\li #00ced1
\li \svgcolor {#00ced1}
+
\row
\li darkviolet
\li #9400d3
\li \svgcolor {#9400d3}
+
\row
\li deeppink
\li #ff1493
\li \svgcolor {#ff1493}
+
\row
\li deepskyblue
\li #00bfff
\li \svgcolor {#00bfff}
+
\row
\li dimgray
\li #696969
\li \svgcolor {#696969}
+
\row
\li dimgrey
\li #696969
\li \svgcolor {#696969}
+
\row
\li dodgerblue
\li #1e90ff
\li \svgcolor {#1e90ff}
+
\row
\li firebrick
\li #b22222
\li \svgcolor {#b22222}
+
\row
\li floralwhite
\li #fffaf0
\li \svgcolor {#fffaf0}
+
\row
\li forestgreen
\li #228b22
\li \svgcolor {#228b22}
+
\row
\li fuchsia
\li #ff00ff
\li \svgcolor {#ff00ff}
+
\row
\li gainsboro
\li #dcdcdc
\li \svgcolor {#dcdcdc}
+
\row
\li ghostwhite
\li #f8f8ff
\li \svgcolor {#f8f8ff}
+
\row
\li gold
\li #ffd700
\li \svgcolor {#ffd700}
+
\row
\li goldenrod
\li #daa520
\li \svgcolor {#daa520}
+
\row
\li gray
\li #808080
\li \svgcolor {#808080}
+
\row
\li grey
\li #808080
\li \svgcolor {#808080}
+
\row
\li green
\li #008000
\li \svgcolor {#008000}
+
\row
\li greenyellow
\li #adff2f
\li \svgcolor {#adff2f}
+
\row
\li honeydew
\li #f0fff0
\li \svgcolor {#f0fff0}
+
\row
\li hotpink
\li #ff69b4
\li \svgcolor {#ff69b4}
+
\row
\li indianred
\li #cd5c5c
\li \svgcolor {#cd5c5c}
+
\row
\li indigo
\li #4b0082
\li \svgcolor {#4b0082}
+
\row
\li ivory
\li #fffff0
\li \svgcolor {#fffff0}
+
\row
\li khaki
\li #f0e68c
\li \svgcolor {#f0e68c}
+
\row
\li lavender
\li #e6e6fa
\li \svgcolor {#e6e6fa}
+
\row
\li lavenderblush
\li #fff0f5
\li \svgcolor {#fff0f5}
+
\row
\li lawngreen
\li #7cfc00
\li \svgcolor {#7cfc00}
+
\row
\li lemonchiffon
\li #fffacd
\li \svgcolor {#fffacd}
+
\row
\li lightblue
\li #add8e6
\li \svgcolor {#add8e6}
+
\row
\li lightcoral
\li #f08080
\li \svgcolor {#f08080}
+
\row
\li lightcyan
\li #e0ffff
\li \svgcolor {#e0ffff}
+
\row
\li lightgoldenrodyellow
\li #fafad2
\li \svgcolor {#fafad2}
+
\row
\li lightgray
\li #d3d3d3
\li \svgcolor {#d3d3d3}
+
\row
\li lightgreen
\li #90ee90
\li \svgcolor {#90ee90}
+
\row
\li lightgrey
\li #d3d3d3
\li \svgcolor {#d3d3d3}
+
\row
\li lightpink
\li #ffb6c1
\li \svgcolor {#ffb6c1}
+
\row
\li lightsalmon
\li #ffa07a
\li \svgcolor {#ffa07a}
+
\row
\li lightseagreen
\li #20b2aa
\li \svgcolor {#20b2aa}
+
\row
\li lightskyblue
\li #87cefa
\li \svgcolor {#87cefa}
+
\row
\li lightslategray
\li #778899
\li \svgcolor {#778899}
+
\row
\li lightslategrey
\li #778899
\li \svgcolor {#778899}
+
\row
\li lightsteelblue
\li #b0c4de
\li \svgcolor {#b0c4de}
+
\row
\li lightyellow
\li #ffffe0
\li \svgcolor {#ffffe0}
+
\row
\li lime
\li #00ff00
\li \svgcolor {#00ff00}
+
\row
\li limegreen
\li #32cd32
\li \svgcolor {#32cd32}
+
\row
\li linen
\li #faf0e6
\li \svgcolor {#faf0e6}
+
\row
\li magenta
\li #ff00ff
\li \svgcolor {#ff00ff}
+
\row
\li maroon
\li #800000
\li \svgcolor {#800000}
+
\row
\li mediumaquamarine
\li #66cdaa
\li \svgcolor {#66cdaa}
+
\row
\li mediumblue
\li #0000cd
\li \svgcolor {#0000cd}
+
\row
\li mediumorchid
\li #ba55d3
\li \svgcolor {#ba55d3}
+
\row
\li mediumpurple
\li #9370db
\li \svgcolor {#9370db}
+
\row
\li mediumseagreen
\li #3cb371
\li \svgcolor {#3cb371}
+
\row
\li mediumslateblue
\li #7b68ee
\li \svgcolor {#7b68ee}
+
\row
\li mediumspringgreen
\li #00fa9a
\li \svgcolor {#00fa9a}
+
\row
\li mediumturquoise
\li #48d1cc
\li \svgcolor {#48d1cc}
+
\row
\li mediumvioletred
\li #c71585
\li \svgcolor {#c71585}
+
\row
\li midnightblue
\li #191970
\li \svgcolor {#191970}
+
\row
\li mintcream
\li #f5fffa
\li \svgcolor {#f5fffa}
+
\row
\li mistyrose
\li #ffe4e1
\li \svgcolor {#ffe4e1}
+
\row
\li moccasin
\li #ffe4b5
\li \svgcolor {#ffe4b5}
+
\row
\li navajowhite
\li #ffdead
\li \svgcolor {#ffdead}
+
\row
\li navy
\li #000080
\li \svgcolor {#000080}
+
\row
\li oldlace
\li #fdf5e6
\li \svgcolor {#fdf5e6}
+
\row
\li olive
\li #808000
\li \svgcolor {#808000}
+
\row
\li olivedrab
\li #6b8e23
\li \svgcolor {#6b8e23}
+
\row
\li orange
\li #ffa500
\li \svgcolor {#ffa500}
+
\row
\li orangered
\li #ff4500
\li \svgcolor {#ff4500}
+
\row
\li orchid
\li #da70d6
\li \svgcolor {#da70d6}
+
\row
\li palegoldenrod
\li #eee8aa
\li \svgcolor {#eee8aa}
+
\row
\li palegreen
\li #98fb98
\li \svgcolor {#98fb98}
+
\row
\li paleturquoise
\li #afeeee
\li \svgcolor {#afeeee}
+
\row
\li palevioletred
\li #db7093
\li \svgcolor {#db7093}
+
\row
\li papayawhip
\li #ffefd5
\li \svgcolor {#ffefd5}
+
\row
\li peachpuff
\li #ffdab9
\li \svgcolor {#ffdab9}
+
\row
\li peru
\li #cd853f
\li \svgcolor {#cd853f}
+
\row
\li pink
\li #ffc0cb
\li \svgcolor {#ffc0cb}
+
\row
\li plum
\li #dda0dd
\li \svgcolor {#dda0dd}
+
\row
\li powderblue
\li #b0e0e6
\li \svgcolor {#b0e0e6}
+
\row
\li purple
\li #800080
\li \svgcolor {#800080}
+
\row
\li red
\li #ff0000
\li \svgcolor {#ff0000}
+
\row
\li rosybrown
\li #bc8f8f
\li \svgcolor {#bc8f8f}
+
\row
\li royalblue
\li #4169e1
\li \svgcolor {#4169e1}
+
\row
\li saddlebrown
\li #8b4513
\li \svgcolor {#8b4513}
+
\row
\li salmon
\li #fa8072
\li \svgcolor {#fa8072}
+
\row
\li sandybrown
\li #f4a460
\li \svgcolor {#f4a460}
+
\row
\li seagreen
\li #2e8b57
\li \svgcolor {#2e8b57}
+
\row
\li seashell
\li #fff5ee
\li \svgcolor {#fff5ee}
+
\row
\li sienna
\li #a0522d
\li \svgcolor {#a0522d}
+
\row
\li silver
\li #c0c0c0
\li \svgcolor {#c0c0c0}
+
\row
\li skyblue
\li #87ceeb
\li \svgcolor {#87ceeb}
+
\row
\li slateblue
\li #6a5acd
\li \svgcolor {#6a5acd}
+
\row
\li slategray
\li #708090
\li \svgcolor {#708090}
+
\row
\li slategrey
\li #708090
\li \svgcolor {#708090}
+
\row
\li snow
\li #fffafa
\li \svgcolor {#fffafa}
+
\row
\li springgreen
\li #00ff7f
\li \svgcolor {#00ff7f}
+
\row
\li steelblue
\li #4682b4
\li \svgcolor {#4682b4}
+
\row
\li tan
\li #d2b48c
\li \svgcolor {#d2b48c}
+
\row
\li teal
\li #008080
\li \svgcolor {#008080}
+
\row
\li thistle
\li #d8bfd8
\li \svgcolor {#d8bfd8}
+
\row
\li tomato
\li #ff6347
\li \svgcolor {#ff6347}
+
\row
\li turquoise
\li #40e0d0
\li \svgcolor {#40e0d0}
+
\row
\li violet
\li #ee82ee
\li \svgcolor {#ee82ee}
+
\row
\li wheat
\li #f5deb3
\li \svgcolor {#f5deb3}
+
\row
\li white
\li #ffffff
\li \svgcolor {#ffffff}
+
\row
\li whitesmoke
\li #f5f5f5
\li \svgcolor {#f5f5f5}
+
\row
\li yellow
\li #ffff00
\li \svgcolor {#ffff00}
+
\row
\li yellowgreen
\li #9acd32
\li \svgcolor {#9acd32}
+
\endtable
diff --git a/src/gui/doc/src/paintsystem.qdoc b/src/gui/doc/src/paintsystem.qdoc
index 163c0252da..f3a5248db1 100644
--- a/src/gui/doc/src/paintsystem.qdoc
+++ b/src/gui/doc/src/paintsystem.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\group painting
diff --git a/src/gui/doc/src/qt6-changes.qdoc b/src/gui/doc/src/qt6-changes.qdoc
index e66b53c081..60e1bffba8 100644
--- a/src/gui/doc/src/qt6-changes.qdoc
+++ b/src/gui/doc/src/qt6-changes.qdoc
@@ -1,35 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page gui-changes-qt6.html
\title Changes to Qt GUI
\ingroup changes-qt-5-to-6
- \brief Migrate Qt GUI to Qt 6.
+ \brief Kernel, Text, Painting, and Utility classes are modified.
Qt 6 is a result of the conscious effort to make the framework more
efficient and easy to use.
@@ -138,4 +114,38 @@
Metal, in addition to OpenGL. On Windows the default choice is Direct 3D,
therefore the removal of ANGLE is alleviated by having support for graphics
APIs other than OpenGL as well.
+
+ \section2 Native clipboard integration
+
+ Qt 5 provided interfaces for integrating platform specific or custom
+ clipboard formats into Qt through \c QMacPasteboardMime in \c QtMacExtras,
+ and \c QWindowsMime from the Windows QPA API. Since Qt 6.6, the
+ equivalent functionality is provided by the classes QUtiMimeConverter for
+ \macos, and the QWindowsMimeConverter for Windows.
+
+ Porting from QWindowsMime to QWindowsMimeConverter requires practically no
+ changes, as the virtual interface is identical. However, in Qt 6 it is no
+ longer needed to register a QWindowsMimeConverter implementation;
+ instantiating the type implicitly registers the converter.
+
+ Porting a QMacPasteboardMime to QUtiMimeConverter requires renaming some of
+ the virtual functions. Note that the \c{QMacPasteboardMime} API used the
+ outdated term \c{flavor} for the native clipboard format on \macos, whereas
+ the platform now uses \c{Uniform Type Identifiers}, i.e. \c{UTI}s, which Qt
+ has adapted for function and parameter names.
+
+ The \c{mimeFor} and \c{flavorFor} functions are replaced by the
+ \l{QUtiMimeConverter::}{mimeForUti} and \l{QUtiMimeConverter::}{utiForMime}
+ implementations, respectively. Those should return the name of the mime
+ type or \c{UTI} that the converter can convert the input format to, so a
+ port usually just involves renaming existing overrides. The
+ \c{convertToMime}, \c{convertFromMime}, and \c{count} functions in
+ QUtiMimeConverter are identical to their QMacPasteboardMime versions.
+
+ The \c{canConvert}, \c{converterName} functions are no longer needed, they
+ are implied by implementation of the above functions, so overrides of those
+ functions can be removed.
+
+ As with the the QWindowsMimeConverter, registration is done by instantiating
+ the type.
*/
diff --git a/src/gui/doc/src/qtgui-overview.qdoc b/src/gui/doc/src/qtgui-overview.qdoc
new file mode 100644
index 0000000000..446479c9be
--- /dev/null
+++ b/src/gui/doc/src/qtgui-overview.qdoc
@@ -0,0 +1,187 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \page qtgui-overview.html
+ \title Qt GUI Overview
+ \brief An overview of the Qt GUI module.
+
+ The Qt GUI module provides classes for windowing system integration, event
+ handling, OpenGL and OpenGL ES integration, 2D graphics, basic imaging,
+ fonts, and text. These classes are used internally by Qt's user interface
+ technologies but can also be used directly, for example to write
+ applications using low-level OpenGL ES graphics APIs.
+
+ For application developers writing user interfaces, Qt provides higher level
+ APIs, like Qt Quick, that are much more suitable than the enablers found in
+ the Qt GUI module.
+
+ \section1 Application Windows
+
+ The most important classes in the Qt GUI module are QGuiApplication and
+ QWindow. A Qt application that wants to show content on screen has to use
+ these. QGuiApplication contains the main event loop, where all events from
+ the window system and other sources are processed and dispatched. It also
+ handles the application's initialization and finalization.
+
+ The \l QWindow class represents a window in the underlying windowing system.
+ It provides a number of virtual functions to handle events (\l {QEvent})
+ from the windowing system, such as touch-input, exposure, focus, key
+ strokes, and geometry changes.
+
+ \section1 2D Graphics
+
+ The Qt GUI module contains classes for 2D graphics, imaging, fonts,
+ and advanced typography.
+
+ A \l QWindow created with the surface type \l {QSurface::RasterSurface} can
+ be used in combination with \l {QBackingStore} and \l {QPainter}, Qt's
+ highly optimized 2D vector graphics API. QPainter supports drawing lines,
+ polygons, vector paths, images, and text. For more information, see \l{Paint
+ System} and \l {Raster Window Example}.
+
+ Qt can load and save images using the \l QImage and \l QPixmap classes. By
+ default, Qt supports the most common image formats including JPEG and PNG
+ among others. Users can add support for additional formats via the \l
+ QImageIOPlugin class. For more information, see \l {Reading and Writing
+ Image Files}.
+
+ Typography in Qt is done with \l QTextDocument, which uses the \l QPainter
+ API in combination with Qt's font classes, primarily QFont. Applications
+ that prefer more low-level APIs to text and font handling can use classes
+ like QRawFont and QGlyphRun.
+
+ \section1 RHI Graphics
+
+ The Qt Rendering Hardware Interface is an abstraction for hardware accelerated
+ graphics APIs, such as, \l{https://www.khronos.org/opengl/}{OpenGL},
+ \l{https://www.khronos.org/opengles/}{OpenGL ES},
+ \l{https://docs.microsoft.com/en-us/windows/desktop/direct3d}{Direct3D},
+ \l{https://developer.apple.com/metal/}{Metal}, and
+ \l{https://www.khronos.org/vulkan/}{Vulkan}.
+
+ As an alternative to using OpenGL or Vulkan directly to render to a
+ QWindow, \l QRhi and the related classes provide a portable, cross-platform
+ 3D graphics and compute API complemented by a shader conditioning and
+ transpiling pipeline. This way applications can avoid directly depending on
+ a single, and, in some cases, vendor or platform-specific 3D API.
+
+ Below is a list of the main RHI-related classes. These are complemented by
+ a number of additional classes and structs.
+
+ \list
+ \li QRhi
+ \li QShader
+ \li QShaderDescription
+ \li QRhiCommandBuffer
+ \li QRhiResourceUpdateBatch
+ \li QRhiBuffer
+ \li QRhiRenderBuffer
+ \li QRhiTexture
+ \li QRhiSampler
+ \li QRhiTextureRenderTarget
+ \li QRhiShaderResourceBindings
+ \li QRhiGraphicsPipeline
+ \li QRhiComputePipeline
+ \li QRhiSwapChain
+ \endlist
+
+ See the \l{RHI Window Example} for an introductory example of creating a
+ portable, cross-platform application that performs accelerated 3D rendering
+ onto a QWindow using QRhi.
+
+ Working directly with QWindow is the most advanced and often the most
+ flexible way of rendering with the QRhi API. It is the most low-level
+ approach, however, and limited in the sense that Qt's UI technologies,
+ widgets and Qt Quick, are not utilized at all. In many cases applications
+ will rather want to integrate QRhi-based rendering into a widget or Qt
+ Quick-based user interface. QWidget-based applications may choose to embed
+ the window as a native child into the widget hierarchy via
+ QWidget::createWindowContainer(), but in many cases \l QRhiWidget will
+ offer a more convenient enabler to integrate QRhi-based rendering into a
+ widget UI. Qt Quick provides its own set of enablers for extending the
+ 2D/3D scene with QRhi-based custom rendering.
+
+ \note The RHI family of APIs are currently offered with a limited
+ compatibility guarantee, as opposed to regular Qt public APIs. See \l QRhi
+ for details.
+
+ \section1 3D Matrix and Vector Math
+
+ The Qt GUI module also contains a few math classes to aid with the most
+ common mathematical operations related to 3D graphics. These classes
+ include \l {QMatrix4x4}, \l {QVector2D}, \l {QVector3D}, \l {QVector4D},
+ and \l {QQuaternion}.
+
+ \section1 OpenGL and OpenGL ES Integration
+
+ QWindow supports rendering using OpenGL and OpenGL ES, depending on what the
+ platform supports. OpenGL rendering is enabled by setting the QWindow's
+ surface type to QSurface::OpenGLSurface, choosing the format attributes with
+ QSurfaceFormat, and then creating a QOpenGLContext to manage the native
+ OpenGL context. In addition, Qt has QOpenGLPaintDevice, which enables the
+ use of OpenGL accelerated QPainter rendering, as well as convenience classes
+ that simplify the writing of OpenGL code and hides the complexities of
+ extension handling and the differences between OpenGL ES 2 and desktop
+ OpenGL. The convenience classes include QOpenGLFunctions that lets an
+ application use all the OpenGL ES 2 functions on desktop OpenGL without
+ having to manually resolve the OpenGL function pointers. This enables
+ cross-platform development of applications targeting mobile or embedded
+ devices, and provides classes that wrap native OpenGL functionality in a
+ simpler Qt API:
+
+ \list
+ \li QOpenGLBuffer
+ \li QOpenGLFramebufferObject
+ \li QOpenGLShaderProgram
+ \li QOpenGLTexture
+ \li QOpenGLDebugLogger
+ \li QOpenGLTimerQuery
+ \li QOpenGLVertexArrayObject
+ \endlist
+
+ Finally, to provide better support for the newer versions (3.0 and
+ higher) of OpenGL, a versioned function wrapper mechanism is also available:
+ The QOpenGLFunction_N_N family of classes expose all the functions in a
+ given OpenGL version and profile, allowing easy development of desktop
+ applications that rely on modern, desktop-only OpenGL features.
+
+ For more information, see the \l {OpenGL Window Example}.
+
+ A \l {QWindow} created with the \l {QSurface::OpenGLSurface} can be used in
+ combination with \l QPainter and \l QOpenGLPaintDevice to have OpenGL
+ hardware-accelerated 2D graphics by sacrificing some of the visual quality.
+
+ \section1 Vulkan Integration
+
+ Qt GUI has support for the \l {Vulkan} API. Qt applications require the
+ presence of the \l{LunarG Vulkan SDK}.
+
+ On Windows, the SDK sets the environment variable \c {VULKAN_SDK},
+ which will be detected by the \c {configure} script.
+
+ On Android, Vulkan headers were added in API level 24 of the NDK.
+
+ The main relevant classes for low-level Vulkan support are:
+
+ \list
+ \li QVulkanInstance
+ \li QVulkanFunctions
+ \li QVulkanDeviceFunctions
+ \endlist
+
+ In addition, \l QVulkanWindow provides a convenience subclass of QWindow
+ that makes it easier to get started with implementing Vulkan-based
+ rendering targeting a QWindow. Using this helper class is completely
+ optional; applications with more advanced Vulkan-based renderers may
+ instead want to use a QWindow with the \l {QSurface::VulkanSurface} type
+ directly.
+
+ For more information, see the \l{Hello Vulkan Widget Example}
+ and the \l {Hello Vulkan Triangle Example}.
+
+ \section1 Drag and Drop
+
+ Qt GUI includes support for drag and drop. The \l{Drag and Drop} overview
+ has more information.
+*/
diff --git a/src/gui/doc/src/qtgui.qdoc b/src/gui/doc/src/qtgui.qdoc
index efa4295a41..2a1d69d4d3 100644
--- a/src/gui/doc/src/qtgui.qdoc
+++ b/src/gui/doc/src/qtgui.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\module QtGui
@@ -39,26 +15,46 @@
*/
/*!
+ \module QtGuiPrivate
+ \title Qt GUI Private C++ Classes
+ \qtcmakepackage Gui
+ \qtvariable gui-private
+
+ \brief Provides access to private GUI functionality.
+
+ Use the following CMake commands in your \c {CMakeLists.txt} to access
+ private Qt GUI APIs:
+
+ \badcode
+ find_package(Qt6 REQUIRED COMPONENTS Gui)
+ target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate)
+ \endcode
+*/
+
+/*!
\page qtgui-index.html
\title Qt GUI
The Qt GUI module provides classes for windowing system
integration, event handling, OpenGL and OpenGL ES integration, 2D
- graphics, basic imaging, fonts and text. These classes are used
- internally by Qt's user interface technologies and can also be
- used directly, for instance to write applications using low-level
+ graphics, basic imaging, fonts, and text. These classes are used
+ internally by Qt's user interface technologies but can also be
+ used directly, for example to write applications using low-level
OpenGL ES graphics APIs.
For application developers writing user interfaces, Qt provides
- higher level API's, like Qt Quick, that are much more suitable
+ higher level APIs, like Qt Quick, that are much more suitable
than the enablers found in the Qt GUI module.
\if !defined(qtforpython)
- \include module-use.qdocinc using qt module
- \quotefile overview/using-qt-gui.cmake
+ \section1 Using the Module
+
+ \include {module-use.qdocinc} {using the c++ api}
- See also the \l {Build with CMake} overview.
+ \section2 Building with CMake
+
+ \include {module-use.qdocinc} {building with cmake} {Gui}
\section2 Building with qmake
@@ -68,125 +64,34 @@
\snippet code/doc_src_qtgui.pro 1
\endif
- \section1 Application Windows
-
- The most important classes in the Qt GUI module are
- QGuiApplication and QWindow. A Qt application that wants to show
- content on screen, will need to make use of these. QGuiApplication
- contains the main event loop, where all events from the window
- system and other sources are processed and dispatched. It also
- handles the application's initialization and finalization.
-
- The \l QWindow class represents a window in the underlying
- windowing system. It provides a number of virtual functions to
- handle events (\l {QEvent}) from the windowing system, such as
- touch-input, exposure, focus, key strokes and geometry changes.
-
-
-
- \section1 2D Graphics
-
- The Qt GUI module contains classes for 2D graphics, imaging, fonts
- and advanced typography.
-
- A \l QWindow created with the surface type \l
- {QSurface::RasterSurface} can be used in combination with \l
- {QBackingStore} and \l {QPainter}, Qt's highly optimized 2D vector
- graphics API. QPainter supports drawing lines, polygons, vector
- paths, images and text. For more information, see \l{Paint
- System} and \l {Raster Window Example}.
-
- Qt can load and save images using the \l QImage and \l QPixmap
- classes. By default, Qt supports the most common image formats
- including JPEG and PNG among others. Users can add support for
- additional formats via the \l QImageIOPlugin class. For more
- information, see \l {Reading and Writing Image Files}
-
- Typography in Qt is done with \l QTextDocument which uses the \l
- QPainter API in combination with Qt's font classes, primarily
- QFont. Applications that prefer more low-level APIs to text
- and font handling, classes like QRawFont and QGlyphRun can be
- used.
-
- \section1 OpenGL and OpenGL ES Integration
-
- QWindow supports rendering using OpenGL and OpenGL ES, depending
- on what the platform supports. OpenGL rendering is enabled by
- setting the QWindow's surface type to QSurface::OpenGLSurface,
- choosing the format attributes with QSurfaceFormat, and then
- creating a QOpenGLContext to manage the native OpenGL context. In
- addition, Qt has QOpenGLPaintDevice, which enables the use of
- OpenGL accelerated QPainter rendering, as well as convenience
- classes that simplify the writing of OpenGL code and hides the
- complexities of extension handling and the differences between
- OpenGL ES 2 and desktop OpenGL. The convenience classes include
- QOpenGLFunctions that lets an application use all the OpenGL ES 2
- functions on desktop OpenGL without having to manually resolve the
- OpenGL function pointers, thus allowing cross-platform development
- of applications targeting mobile or embedded devices, and some
- classes that wrap native OpenGL functionality in a simpler Qt API:
+ \section1 Articles and Guides
\list
- \li QOpenGLBuffer
- \li QOpenGLFramebufferObject
- \li QOpenGLShaderProgram
- \li QOpenGLTexture
- \li QOpenGLDebugLogger
- \li QOpenGLTimerQuery
- \li QOpenGLVertexArrayObject
+ \li \l {Qt GUI Overview}
+ \list
+ \li \l {Application Windows} {Qt GUI Application Windows}
+ \li \l {2D Graphics} {Qt GUI 2D Graphics}
+ \li \l {RHI Graphics} {Qt GUI Accelerated 2D and 3D Graphics using the Qt RHI}
+ \li \l {3D Matrix and Vector Math} {Qt GUI Matrix and Vector Math}
+ \li \l {OpenGL and OpenGL ES Integration}
+ {Qt GUI OpenGL and OpenGL ES Integration}
+ \li \l {Vulkan Integration} {Qt GUI Vulkan Integration}
+ \endlist
\endlist
- Finally, in order to provide better support for the newer versions
- (3.0 and higher) of OpenGL, a versioned function wrapper mechanism
- is also available: The QOpenGLFunction_N_N family of classes
- expose all the functions in a given OpenGL version and profile,
- allowing easy development of desktop applications relying on
- modern, desktop-only OpenGL features.
-
- For more information, see the \l {OpenGL Window Example}.
-
- The Qt GUI module also contains a few math classes to aid with the
- most common mathmatical operations related to 3D graphics. These
- classes include \l {QMatrix4x4}, \l {QVector4D} and \l {QQuaternion}
-
- A \l {QWindow} created with the \l {QSurface::OpenGLSurface} can
- be used in combination with \l QPainter and \l QOpenGLPaintDevice
- to have OpenGL hardware accelerated 2D graphics, by sacrificing
- some of the visual quality.
-
-
-
- \section1 Vulkan Integration
-
- Qt GUI has support for the \l {Vulkan} API. Qt applications require the
- presence of the \l{LunarG Vulkan SDK}.
-
- On Windows, the SDK sets the environment variable \c {VULKAN_SDK},
- which will be detected by the \c {configure} script.
-
- On Android, Vulkan headers were added in API level 24 of the NDK.
-
- Relevant classes:
+ \section1 Reference
\list
- \li QVulkanDeviceFunctions
- \li QVulkanExtension
- \li QVulkanFunctions
- \li QVulkanInfoVector
- \li QVulkanInstance
- \li QVulkanWindow
- \li QVulkanWindowRenderer
+ \li \l{Qt GUI C++ Classes}
+ \list
+ \li \l{Event Classes}
+ \li \l{Painting Classes}
+ \li \l{Rendering in 3D}
+ \endlist
\endlist
- For more information, see the \l{Hello Vulkan Widget Example}
- and the \l {Hello Vulkan Window Example}.
-
- \section1 Drag and Drop
-
- Qt GUI includes support for drag and drop. The \l{Drag and Drop} overview
- has more information.
-
\section1 Module Evolution
+
\l{Changes to Qt GUI} lists important changes in the module API
and functionality that were done for the Qt 6 series of Qt.
@@ -202,14 +107,4 @@
modules under following permissive licenses:
\generatelist{groupsbymodule attributions-qtgui}
-
- \section1 Reference
- \list
- \li \l{Qt GUI C++ Classes}
- \list
- \li \l{Event Classes}
- \li \l{Painting Classes}
- \li \l{Rendering in 3D}
- \endlist
- \endlist
*/
diff --git a/src/gui/doc/src/richtext.qdoc b/src/gui/doc/src/richtext.qdoc
index 4114067c66..10d9962850 100644
--- a/src/gui/doc/src/richtext.qdoc
+++ b/src/gui/doc/src/richtext.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\group richtext-processing
@@ -35,10 +11,9 @@
\page richtext.html
\title Rich Text Processing
\brief An overview of Qt's rich text processing, editing and display features.
-
+ \ingroup explanations-ui
\ingroup frameworks-technologies
\ingroup qt-basic-concepts
- \ingroup best-practices
\nextpage Rich Text Document Structure
@@ -863,7 +838,11 @@
\section1 Supported Tags
The following table lists the HTML tags supported by Qt's
- \l{Rich Text Processing}{rich text} engine:
+ \l{Rich Text Processing}{rich text} engine.
+
+ \note The functionality implemented for tags listed below is a subset of
+ the full HTML 4 specification. Not all attributes are supported,
+ see comments for each tag.
\table 70%
\header \li Tag
diff --git a/src/gui/image/qabstractfileiconengine.cpp b/src/gui/image/qabstractfileiconengine.cpp
index 8fa29e8227..ffbe088d20 100644
--- a/src/gui/image/qabstractfileiconengine.cpp
+++ b/src/gui/image/qabstractfileiconengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractfileiconengine_p.h"
@@ -43,6 +7,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QAbstractFileIconEngine
\brief Helper base class for retrieving icons for files for usage by QFileIconProvider and related.
@@ -73,7 +39,7 @@ QPixmap QAbstractFileIconEngine::pixmap(const QSize &size, QIcon::Mode mode,
if (key.isEmpty())
return filePixmap(size, mode, state);
- key += QLatin1Char('_') + QString::number(size.width());
+ key += u'_' + QString::number(size.width());
QPixmap result;
if (!QPixmapCache::find(key, &result)) {
@@ -95,7 +61,7 @@ QSize QAbstractFileIconEngine::actualSize(const QSize &size, QIcon::Mode mode,
QIcon::State state)
{
const QList<QSize> &sizes = availableSizes(mode, state);
- const int numberSizes = sizes.length();
+ const int numberSizes = sizes.size();
if (numberSizes == 0)
return QSize();
@@ -128,7 +94,7 @@ QString QAbstractFileIconEngine::cacheKey() const
return QString();
const QString &suffix = m_fileInfo.suffix();
- return QLatin1String("qt_.")
+ return "qt_."_L1
+ (suffix.isEmpty() ? m_fileInfo.fileName() : suffix); // handle "Makefile" ;)
}
diff --git a/src/gui/image/qabstractfileiconengine_p.h b/src/gui/image/qabstractfileiconengine_p.h
index eccc83a4fe..99d16d3224 100644
--- a/src/gui/image/qabstractfileiconengine_p.h
+++ b/src/gui/image/qabstractfileiconengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTFILEICONENGINE_P_H
#define QABSTRACTFILEICONENGINE_P_H
@@ -66,6 +30,7 @@ public:
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State) override;
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State, qreal scale) override;
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+ bool isNull() override { return false; }
QFileInfo fileInfo() const { return m_fileInfo; }
QPlatformTheme::IconOptions options() const { return m_options; }
diff --git a/src/gui/image/qabstractfileiconprovider.cpp b/src/gui/image/qabstractfileiconprovider.cpp
index d79e49832b..71b6a0b03d 100644
--- a/src/gui/image/qabstractfileiconprovider.cpp
+++ b/src/gui/image/qabstractfileiconprovider.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractfileiconprovider.h"
@@ -53,6 +17,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
QAbstractFileIconProviderPrivate::QAbstractFileIconProviderPrivate(QAbstractFileIconProvider *q)
: q_ptr(q)
{}
@@ -114,22 +80,22 @@ QIcon QAbstractFileIconProviderPrivate::getIconThemeIcon(QAbstractFileIconProvid
{
switch (type) {
case QAbstractFileIconProvider::Computer:
- return QIcon::fromTheme(QLatin1String("computer"));
+ return QIcon::fromTheme("computer"_L1);
case QAbstractFileIconProvider::Desktop:
- return QIcon::fromTheme(QLatin1String("user-desktop"));
+ return QIcon::fromTheme("user-desktop"_L1);
case QAbstractFileIconProvider::Trashcan:
- return QIcon::fromTheme(QLatin1String("user-trash"));
+ return QIcon::fromTheme("user-trash"_L1);
case QAbstractFileIconProvider::Network:
- return QIcon::fromTheme(QLatin1String("network-workgroup"));
+ return QIcon::fromTheme("network-workgroup"_L1);
case QAbstractFileIconProvider::Drive:
- return QIcon::fromTheme(QLatin1String("drive-harddisk"));
+ return QIcon::fromTheme("drive-harddisk"_L1);
case QAbstractFileIconProvider::Folder:
- return QIcon::fromTheme(QLatin1String("folder"));
+ return QIcon::fromTheme("folder"_L1);
case QAbstractFileIconProvider::File:
- return QIcon::fromTheme(QLatin1String("text-x-generic"));
+ return QIcon::fromTheme("text-x-generic"_L1);
// no default on purpose; we want warnings when the type enum is extended
}
- return QIcon::fromTheme(QLatin1String("text-x-generic"));
+ return QIcon::fromTheme("text-x-generic"_L1);
}
static inline QPlatformTheme::IconOptions toThemeIconOptions(QAbstractFileIconProvider::Options options)
@@ -156,7 +122,7 @@ QIcon QAbstractFileIconProviderPrivate::getIconThemeIcon(const QFileInfo &info)
#if QT_CONFIG(mimetype)
return QIcon::fromTheme(mimeDatabase.mimeTypeForFile(info).iconName());
#else
- return QIcon::fromTheme(QLatin1String("text-x-generic"));
+ return QIcon::fromTheme("text-x-generic"_L1);
#endif
}
@@ -263,21 +229,16 @@ QIcon QAbstractFileIconProvider::icon(const QFileInfo &info) const
return result.isNull() ? d->getPlatformThemeIcon(info) : result;
}
-/*!
- Returns the type of the file described by \a info.
-*/
-QString QAbstractFileIconProvider::type(const QFileInfo &info) const
+QString QAbstractFileIconProviderPrivate::getFileType(const QFileInfo &info)
{
- Q_D(const QAbstractFileIconProvider);
if (QFileSystemEntry::isRootPath(info.absoluteFilePath()))
return QGuiApplication::translate("QAbstractFileIconProvider", "Drive");
if (info.isFile()) {
#if QT_CONFIG(mimetype)
- const QMimeType mimeType = d->mimeDatabase.mimeTypeForFile(info);
+ const QMimeType mimeType = QMimeDatabase().mimeTypeForFile(info);
return mimeType.comment().isEmpty() ? mimeType.name() : mimeType.comment();
#else
- Q_UNUSED(d);
return QGuiApplication::translate("QAbstractFileIconProvider", "File");
#endif
}
@@ -307,4 +268,13 @@ QString QAbstractFileIconProvider::type(const QFileInfo &info) const
return QGuiApplication::translate("QAbstractFileIconProvider", "Unknown");
}
+/*!
+ Returns the type of the file described by \a info.
+*/
+
+QString QAbstractFileIconProvider::type(const QFileInfo &info) const
+{
+ return QAbstractFileIconProviderPrivate::getFileType(info);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/image/qabstractfileiconprovider.h b/src/gui/image/qabstractfileiconprovider.h
index fc107e0ca3..df5f642521 100644
--- a/src/gui/image/qabstractfileiconprovider.h
+++ b/src/gui/image/qabstractfileiconprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTFILEICONPROVIDER_H
#define QABSTRACTFILEICONPROVIDER_H
diff --git a/src/gui/image/qabstractfileiconprovider_p.h b/src/gui/image/qabstractfileiconprovider_p.h
index c6193fe48a..f53be0f06c 100644
--- a/src/gui/image/qabstractfileiconprovider_p.h
+++ b/src/gui/image/qabstractfileiconprovider_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTFILEICONPROVIDER_P_H
#define QABSTRACTFILEICONPROVIDER_P_H
@@ -73,6 +37,7 @@ public:
QIcon getIconThemeIcon(const QFileInfo &info) const;
static void clearIconTypeCache();
+ static QString getFileType(const QFileInfo &info);
QAbstractFileIconProvider *q_ptr = nullptr;
QAbstractFileIconProvider::Options options = {};
diff --git a/src/gui/image/qbitmap.cpp b/src/gui/image/qbitmap.cpp
index 45620e7181..2208cca1be 100644
--- a/src/gui/image/qbitmap.cpp
+++ b/src/gui/image/qbitmap.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbitmap.h"
#include <qpa/qplatformpixmap.h>
@@ -46,6 +10,8 @@
#include <qpainter.h>
#include <private/qguiapplication_p.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
/*!
@@ -114,25 +80,31 @@ QBitmap::QBitmap()
\sa clear()
*/
-
QBitmap::QBitmap(int w, int h)
: QPixmap(QSize(w, h), QPlatformPixmap::BitmapType)
{
}
/*!
+ \deprecated [6.0] Use fromPixmap instead.
+
Constructs a bitmap with the given \a size. The pixels in the
bitmap are uninitialized.
\sa clear()
*/
-
QBitmap::QBitmap(const QSize &size)
: QPixmap(size, QPlatformPixmap::BitmapType)
{
}
/*!
+ \internal
+ This dtor must stay empty until Qt 7 (was inline until 6.2).
+*/
+QBitmap::~QBitmap() = default;
+
+/*!
\fn QBitmap::clear()
Clears the bitmap, setting all its bits to Qt::color0.
@@ -149,7 +121,6 @@ QBitmap::QBitmap(const QSize &size)
\sa QPixmap::isNull(), QImageReader::imageFormat()
*/
-
QBitmap::QBitmap(const QString& fileName, const char *format)
: QPixmap(QSize(0, 0), QPlatformPixmap::BitmapType)
{
@@ -184,10 +155,10 @@ static QBitmap makeBitmap(QImage &&image, Qt::ImageConversionFlags flags)
image.setColor(1, c0);
}
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::BitmapType));
+ std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::BitmapType));
data->fromImageInPlace(image, flags | Qt::MonoOnly);
- return QBitmap::fromPixmap(QPixmap(data.take()));
+ return QBitmap::fromPixmap(QPixmap(data.release()));
}
/*!
@@ -225,7 +196,7 @@ QBitmap QBitmap::fromImage(QImage &&image, Qt::ImageConversionFlags flags)
Constructs a bitmap with the given \a size, and sets the contents to
the \a bits supplied.
- The bitmap data has to be byte aligned and provided in in the bit
+ The bitmap data has to be byte aligned and provided in the bit
order specified by \a monoFormat. The mono format must be either
QImage::Format_Mono or QImage::Format_MonoLSB. Use
QImage::Format_Mono to specify data on the XBM format.
@@ -241,7 +212,7 @@ QBitmap QBitmap::fromData(const QSize &size, const uchar *bits, QImage::Format m
image.setColor(0, QColor(Qt::color0).rgb());
image.setColor(1, QColor(Qt::color1).rgb());
- // Need to memcpy each line separatly since QImage is 32bit aligned and
+ // Need to memcpy each line separately since QImage is 32bit aligned and
// this data is only byte aligned...
int bytesPerLine = (size.width() + 7) / 8;
for (int y = 0; y < size.height(); ++y)
@@ -255,6 +226,8 @@ QBitmap QBitmap::fromData(const QSize &size, const uchar *bits, QImage::Format m
If the pixmap has a depth greater than 1, the resulting bitmap
will be dithered automatically.
+ \since 6.0
+
\sa QPixmap::depth()
*/
@@ -277,7 +250,7 @@ QBitmap QBitmap::fromPixmap(const QPixmap &pixmap)
#if QT_DEPRECATED_SINCE(6, 0)
/*!
- \deprecated Use fromPixmap instead.
+ \deprecated [6.0] Use fromPixmap instead.
Constructs a bitmap that is a copy of the given \a pixmap.
If the pixmap has a depth greater than 1, the resulting bitmap
@@ -285,14 +258,13 @@ QBitmap QBitmap::fromPixmap(const QPixmap &pixmap)
\sa QPixmap::depth(), fromImage(), fromData()
*/
-
QBitmap::QBitmap(const QPixmap &pixmap)
{
*this = QBitmap::fromPixmap(pixmap);
}
/*!
- \deprecated Use fromPixmap instead.
+ \deprecated [6.0] Use fromPixmap instead.
\overload
Assigns the given \a pixmap to this bitmap and returns a reference
@@ -303,7 +275,6 @@ QBitmap::QBitmap(const QPixmap &pixmap)
\sa QPixmap::depth()
*/
-
QBitmap &QBitmap::operator=(const QPixmap &pixmap)
{
*this = QBitmap::fromPixmap(pixmap);
diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h
index 9052e62db6..77d276ab14 100644
--- a/src/gui/image/qbitmap.h
+++ b/src/gui/image/qbitmap.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBITMAP_H
#define QBITMAP_H
@@ -58,6 +22,7 @@ public:
QBitmap(int w, int h);
explicit QBitmap(const QSize &);
explicit QBitmap(const QString &fileName, const char *format = nullptr);
+ ~QBitmap() override;
#if QT_DEPRECATED_SINCE(6, 0)
QT_DEPRECATED_VERSION_X_6_0("Use fromPixmap instead.") QBitmap &operator=(const QPixmap &);
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index 6d265ded67..798ba7f4b3 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qbmphandler_p.h"
@@ -104,6 +68,7 @@ const int BMP_RGB = 0; // no compression
const int BMP_RLE8 = 1; // run-length encoded, 8 bits
const int BMP_RLE4 = 2; // run-length encoded, 4 bits
const int BMP_BITFIELDS = 3; // RGB values encoded in data as bit-fields
+const int BMP_ALPHABITFIELDS = 4; // RGBA values encoded in data as bit-fields
static QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi)
@@ -170,16 +135,42 @@ static QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi)
return s;
}
-static int calc_shift(uint mask)
+static uint calc_shift(uint mask)
{
- int result = 0;
- while (mask && !(mask & 1)) {
+ uint result = 0;
+ while ((mask >= 0x100) || (!(mask & 1) && mask)) {
result++;
mask >>= 1;
}
return result;
}
+static uint calc_scale(uint low_mask)
+{
+ uint result = 8;
+ while (low_mask && result) {
+ result--;
+ low_mask >>= 1;
+ }
+ return result;
+}
+
+static inline uint apply_scale(uint value, uint scale)
+{
+ if (!(scale & 0x07)) // return immediately if scale == 8 or 0
+ return value;
+
+ uint filled = 8 - scale;
+ uint result = value << scale;
+
+ do {
+ result |= result >> filled;
+ filled <<= 1;
+ } while (filled < 8);
+
+ return result;
+}
+
static bool read_dib_fileheader(QDataStream &s, BMP_FILEHDR &bf)
{
// read BMP file header
@@ -216,13 +207,13 @@ static bool read_dib_infoheader(QDataStream &s, BMP_INFOHDR &bi)
return true;
}
-static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset, qint64 startpos, QImage &image)
+static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 datapos, qint64 startpos, QImage &image)
{
QIODevice* d = s.device();
if (d->atEnd()) // end of stream/file
return false;
#if 0
- qDebug("offset...........%lld", offset);
+ qDebug("offset...........%lld", datapos);
qDebug("startpos.........%lld", startpos);
qDebug("biSize...........%d", bi.biSize);
qDebug("biWidth..........%d", bi.biWidth);
@@ -242,33 +233,36 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
uint green_mask = 0;
uint blue_mask = 0;
uint alpha_mask = 0;
- int red_shift = 0;
- int green_shift = 0;
- int blue_shift = 0;
- int alpha_shift = 0;
- int red_scale = 0;
- int green_scale = 0;
- int blue_scale = 0;
- int alpha_scale = 0;
+ uint red_shift = 0;
+ uint green_shift = 0;
+ uint blue_shift = 0;
+ uint alpha_shift = 0;
+ uint red_scale = 0;
+ uint green_scale = 0;
+ uint blue_scale = 0;
+ uint alpha_scale = 0;
+ bool bitfields = comp == BMP_BITFIELDS || comp == BMP_ALPHABITFIELDS;
if (!d->isSequential())
- d->seek(startpos + BMP_FILEHDR_SIZE + bi.biSize); // goto start of colormap or masks
+ d->seek(startpos + bi.biSize); // goto start of colormap or masks
if (bi.biSize >= BMP_WIN4) {
red_mask = bi.biRedMask;
green_mask = bi.biGreenMask;
blue_mask = bi.biBlueMask;
alpha_mask = bi.biAlphaMask;
- } else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
+ } else if (bitfields && (nbits == 16 || nbits == 32)) {
if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
return false;
if (d->read((char *)&green_mask, sizeof(green_mask)) != sizeof(green_mask))
return false;
if (d->read((char *)&blue_mask, sizeof(blue_mask)) != sizeof(blue_mask))
return false;
+ if (comp == BMP_ALPHABITFIELDS && d->read((char *)&alpha_mask, sizeof(alpha_mask)) != sizeof(alpha_mask))
+ return false;
}
- bool transp = comp == BMP_BITFIELDS || (comp == BMP_RGB && nbits == 32 && alpha_mask == 0xff000000);
+ bool transp = bitfields || (comp == BMP_RGB && nbits == 32 && alpha_mask == 0xff000000);
transp = transp && alpha_mask;
int ncols = 0;
@@ -317,23 +311,23 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
if (d->atEnd()) // truncated file
return false;
}
- } else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
+ } else if (bitfields && (nbits == 16 || nbits == 32)) {
red_shift = calc_shift(red_mask);
if (((red_mask >> red_shift) + 1) == 0)
return false;
- red_scale = 256 / ((red_mask >> red_shift) + 1);
+ red_scale = calc_scale(red_mask >> red_shift);
green_shift = calc_shift(green_mask);
if (((green_mask >> green_shift) + 1) == 0)
return false;
- green_scale = 256 / ((green_mask >> green_shift) + 1);
+ green_scale = calc_scale(green_mask >> green_shift);
blue_shift = calc_shift(blue_mask);
if (((blue_mask >> blue_shift) + 1) == 0)
return false;
- blue_scale = 256 / ((blue_mask >> blue_shift) + 1);
+ blue_scale = calc_scale(blue_mask >> blue_shift);
alpha_shift = calc_shift(alpha_mask);
if (((alpha_mask >> alpha_shift) + 1) == 0)
return false;
- alpha_scale = 256 / ((alpha_mask >> alpha_shift) + 1);
+ alpha_scale = calc_scale(alpha_mask >> alpha_shift);
} else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) {
blue_mask = 0x000000ff;
green_mask = 0x0000ff00;
@@ -341,23 +335,21 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
blue_shift = 0;
green_shift = 8;
red_shift = 16;
- blue_scale = green_scale = red_scale = 1;
+ blue_scale = green_scale = red_scale = 0;
if (transp) {
alpha_shift = calc_shift(alpha_mask);
if (((alpha_mask >> alpha_shift) + 1) == 0)
return false;
- alpha_scale = 256 / ((alpha_mask >> alpha_shift) + 1);
+ alpha_scale = calc_scale(alpha_mask >> alpha_shift);
}
} else if (comp == BMP_RGB && nbits == 16) {
blue_mask = 0x001f;
green_mask = 0x03e0;
red_mask = 0x7c00;
blue_shift = 0;
- green_shift = 2;
- red_shift = 7;
- red_scale = 1;
- green_scale = 1;
- blue_scale = 8;
+ green_shift = 5;
+ red_shift = 10;
+ blue_scale = green_scale = red_scale = 3;
}
image.setDotsPerMeterX(bi.biXPelsPerMeter);
@@ -370,10 +362,9 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
qDebug("Amask: %08x Ashift: %08x Ascale:%08x", alpha_mask, alpha_shift, alpha_scale);
#endif
- // offset can be bogus, be careful
- if (offset>=0 && startpos + offset > d->pos()) {
+ if (datapos >= 0 && datapos > d->pos()) {
if (!d->isSequential())
- d->seek(startpos + offset); // start of image data
+ d->seek(datapos); // start of image data
}
int bpl = image.bytesPerLine();
@@ -566,10 +557,10 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
c |= *(uchar*)(b+2)<<16;
if (nbits > 24)
c |= *(uchar*)(b+3)<<24;
- *p++ = qRgba(((c & red_mask) >> red_shift) * red_scale,
- ((c & green_mask) >> green_shift) * green_scale,
- ((c & blue_mask) >> blue_shift) * blue_scale,
- transp ? ((c & alpha_mask) >> alpha_shift) * alpha_scale : 0xff);
+ *p++ = qRgba(apply_scale((c & red_mask) >> red_shift, red_scale),
+ apply_scale((c & green_mask) >> green_shift, green_scale),
+ apply_scale((c & blue_mask) >> blue_shift, blue_scale),
+ transp ? apply_scale((c & alpha_mask) >> alpha_shift, alpha_scale) : 0xff);
b += nbits/8;
}
}
@@ -591,7 +582,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
return true;
}
-// this is also used in qmime_win.cpp
bool qt_write_dib(QDataStream &s, const QImage &image, int bpl, int bpl_bmp, int nbits)
{
QIODevice* d = s.device();
@@ -618,7 +608,7 @@ bool qt_write_dib(QDataStream &s, const QImage &image, int bpl, int bpl_bmp, int
if (image.depth() != 32) { // write color table
uchar *color_table = new uchar[4*image.colorCount()];
uchar *rgb = color_table;
- QList<QRgb> c = image.colorTable();
+ const QList<QRgb> c = image.colorTable();
for (int i = 0; i < image.colorCount(); i++) {
*rgb++ = qBlue (c[i]);
*rgb++ = qGreen(c[i]);
@@ -678,15 +668,6 @@ bool qt_write_dib(QDataStream &s, const QImage &image, int bpl, int bpl_bmp, int
return true;
}
-// this is also used in qmime_win.cpp
-bool qt_read_dib(QDataStream &s, QImage &image)
-{
- BMP_INFOHDR bi;
- if (!read_dib_infoheader(s, bi))
- return false;
- return read_dib_body(s, bi, -1, -BMP_FILEHDR_SIZE, image);
-}
-
QBmpHandler::QBmpHandler(InternalFormat fmt) :
m_format(fmt), state(Ready)
{
@@ -769,9 +750,32 @@ bool QBmpHandler::read(QImage *image)
s.setByteOrder(QDataStream::LittleEndian);
// read image
+ qint64 datapos = startpos;
+ if (m_format == BmpFormat) {
+ datapos += fileHeader.bfOffBits;
+ } else {
+ // QTBUG-100351: We have no file header when reading dib format so we have to depend on the size of the
+ // buffer and the biSizeImage value to find where the pixel data starts since there's sometimes optional
+ // color mask values after biSize, like for example when pasting from the windows snipping tool.
+ if (infoHeader.biSizeImage > 0 && infoHeader.biSizeImage < d->size()) {
+ datapos = d->size() - infoHeader.biSizeImage;
+ } else {
+ // And sometimes biSizeImage is not filled in like when pasting from Microsoft Edge, so then we just
+ // have to assume the optional color mask values are there.
+ datapos += infoHeader.biSize;
+
+ if (infoHeader.biBitCount == 16 || infoHeader.biBitCount == 32) {
+ if (infoHeader.biCompression == BMP_BITFIELDS) {
+ datapos += 12;
+ } else if (infoHeader.biCompression == BMP_ALPHABITFIELDS) {
+ datapos += 16;
+ }
+ }
+ }
+ }
const bool readSuccess = m_format == BmpFormat ?
- read_dib_body(s, infoHeader, fileHeader.bfOffBits, startpos, *image) :
- read_dib_body(s, infoHeader, -1, startpos - BMP_FILEHDR_SIZE, *image);
+ read_dib_body(s, infoHeader, datapos, startpos + BMP_FILEHDR_SIZE, *image) :
+ read_dib_body(s, infoHeader, datapos, startpos, *image);
if (!readSuccess)
return false;
@@ -875,7 +879,7 @@ QVariant QBmpHandler::option(ImageOption option) const
case 32:
case 24:
case 16:
- if (infoHeader.biCompression == BMP_BITFIELDS && infoHeader.biSize >= BMP_WIN4 && infoHeader.biAlphaMask)
+ if ((infoHeader.biCompression == BMP_BITFIELDS || infoHeader.biCompression == BMP_ALPHABITFIELDS) && infoHeader.biSize >= BMP_WIN4 && infoHeader.biAlphaMask)
format = QImage::Format_ARGB32;
else
format = QImage::Format_RGB32;
diff --git a/src/gui/image/qbmphandler_p.h b/src/gui/image/qbmphandler_p.h
index e1d744e539..0ba0946afe 100644
--- a/src/gui/image/qbmphandler_p.h
+++ b/src/gui/image/qbmphandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBMPHANDLER_P_H
#define QBMPHANDLER_P_H
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index af28c8a0ec..086ac37a07 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qicon.h"
#include "qicon_p.h"
@@ -61,11 +25,14 @@
#include "private/qhexstring_p.h"
#include "private/qguiapplication_p.h"
+#include "private/qoffsetstringarray_p.h"
#include "qpa/qplatformtheme.h"
#ifndef QT_NO_ICON
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\enum QIcon::Mode
@@ -101,7 +68,7 @@ QT_BEGIN_NAMESPACE
static int nextSerialNumCounter()
{
- static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
return 1 + serial.fetchAndAddRelaxed(1);
}
@@ -132,6 +99,11 @@ QIconPrivate::QIconPrivate(QIconEngine *e)
{
}
+void QIconPrivate::clearIconCache()
+{
+ qt_cleanup_icon_cache();
+}
+
/*! \internal
Computes the displayDevicePixelRatio for a pixmap.
@@ -192,12 +164,15 @@ static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale
// scale: we can only differentiate on scale if the scale differs
if (pa->scale != pb->scale) {
- // Score the pixmaps: 0 is an exact scale match, postive
+ // Score the pixmaps: 0 is an exact scale match, positive
// scores have more detail than requested, negative scores
- // have less detail than rquested.
+ // have less detail than requested.
qreal ascore = pa->scale - scale;
qreal bscore = pb->scale - scale;
+ // always prefer positive scores to prevent upscaling
+ if ((ascore < 0) != (bscore < 0))
+ return bscore < 0 ? pa : pb;
// Take the one closest to 0
return (qAbs(ascore) < qAbs(bscore)) ? pa : pb;
}
@@ -226,7 +201,7 @@ static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale
QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state)
{
QPixmapIconEngineEntry *pe = nullptr;
- for (int i = 0; i < pixmaps.count(); ++i)
+ for (int i = 0; i < pixmaps.size(); ++i)
if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
if (pe)
pe = bestSizeScaleMatch(size, scale, &pixmaps[i], pe);
@@ -303,7 +278,7 @@ QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIc
pm = pe->pixmap;
if (pm.isNull()) {
- int idx = pixmaps.count();
+ int idx = pixmaps.size();
while (--idx >= 0) {
if (pe == &pixmaps.at(idx)) {
pixmaps.remove(idx);
@@ -320,7 +295,7 @@ QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIc
if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
actualSize.scale(size, Qt::KeepAspectRatio);
- QString key = QLatin1String("qt_")
+ QString key = "qt_"_L1
% HexString<quint64>(pm.cacheKey())
% HexString<uint>(pe ? pe->mode : QIcon::Normal)
% HexString<quint64>(QGuiApplication::palette().cacheKey())
@@ -358,7 +333,7 @@ QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::
{
QSize actualSize;
- // The returned actiual size is the size in device independent pixels,
+ // The returned actual size is the size in device independent pixels,
// so we limit the search to scale 1 and assume that e.g. @2x versions
// does not proviode extra actual sizes not also provided by the 1x versions.
qreal scale = 1;
@@ -377,15 +352,16 @@ QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::
QList<QSize> QPixmapIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state)
{
QList<QSize> sizes;
- for (int i = 0; i < pixmaps.size(); ++i) {
- QPixmapIconEngineEntry &pe = pixmaps[i];
- if (pe.size == QSize() && pe.pixmap.isNull()) {
+ for (QPixmapIconEngineEntry &pe : pixmaps) {
+ if (pe.mode != mode || pe.state != state)
+ continue;
+ if (pe.size.isEmpty() && pe.pixmap.isNull()) {
pe.pixmap = QPixmap(pe.fileName);
pe.size = pe.pixmap.size();
}
- if (pe.mode == mode && pe.state == state && !pe.size.isEmpty())
+ if (!pe.size.isEmpty() && !sizes.contains(pe.size))
sizes.push_back(pe.size);
- }
+ }
return sizes;
}
@@ -450,7 +426,7 @@ void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIco
{
if (fileName.isEmpty())
return;
- const QString abs = fileName.startsWith(QLatin1Char(':')) ? fileName : QFileInfo(fileName).absoluteFilePath();
+ const QString abs = fileName.startsWith(u':') ? fileName : QFileInfo(fileName).absoluteFilePath();
const bool ignoreSize = !size.isValid();
ImageReader imageReader(abs);
const QByteArray format = imageReader.format();
@@ -485,15 +461,20 @@ void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIco
}
}
}
- for (const QImage &i : qAsConst(icoImages))
+ for (const QImage &i : std::as_const(icoImages))
pixmaps += QPixmapIconEngineEntry(abs, i, mode, state);
if (icoImages.isEmpty() && !ignoreSize) // Add placeholder with the filename and empty pixmap for the size.
pixmaps += QPixmapIconEngineEntry(abs, size, mode, state);
}
+bool QPixmapIconEngine::isNull()
+{
+ return pixmaps.isEmpty();
+}
+
QString QPixmapIconEngine::key() const
{
- return QLatin1String("QPixmapIconEngine");
+ return "QPixmapIconEngine"_L1;
}
QIconEngine *QPixmapIconEngine::clone() const
@@ -549,12 +530,12 @@ bool QPixmapIconEngine::write(QDataStream &out) const
return true;
}
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QIconEngineFactoryInterface_iid, QLatin1String("/iconengines"), Qt::CaseInsensitive))
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, iceLoader,
+ (QIconEngineFactoryInterface_iid, "/iconengines"_L1, Qt::CaseInsensitive))
QFactoryLoader *qt_iconEngineFactoryLoader()
{
- return loader();
+ return iceLoader();
}
@@ -570,15 +551,26 @@ QFactoryLoader *qt_iconEngineFactoryLoader()
A QIcon can generate smaller, larger, active, and disabled pixmaps
from the set of pixmaps it is given. Such pixmaps are used by Qt
- widgets to show an icon representing a particular action.
+ UI components to show an icon representing a particular action.
- The simplest use of QIcon is to create one from a QPixmap file or
- resource, and then use it, allowing Qt to work out all the required
- icon styles and sizes. For example:
+ \section1 Creating an icon from image files
+
+ The simplest way to construct a QIcon is to create one from one or
+ several image files or resources. For example:
\snippet code/src_gui_image_qicon.cpp 0
- To undo a QIcon, simply set a null icon in its place:
+ QIcon can store several images for different states, and Qt will
+ select the image that is the closest match for the action's current
+ state.
+
+ \snippet code/src_gui_image_qicon.cpp addFile
+
+ Qt will generate the required icon styles and sizes when needed,
+ e.g. the pixmap for the QIcon::Disabled state might be generated by
+ graying out one of the provided pixmaps.
+
+ To clear the icon, simply set a null icon in its place:
\snippet code/src_gui_image_qicon.cpp 1
@@ -586,31 +578,54 @@ QFactoryLoader *qt_iconEngineFactoryLoader()
QImageWriter::supportedImageFormats() functions to retrieve a
complete list of the supported file formats.
- When you retrieve a pixmap using pixmap(QSize, Mode, State), and no
- pixmap for this given size, mode and state has been added with
- addFile() or addPixmap(), then QIcon will generate one on the
- fly. This pixmap generation happens in a QIconEngine. The default
- engine scales pixmaps down if required, but never up, and it uses
- the current style to calculate a disabled appearance. By using
- custom icon engines, you can customize every aspect of generated
- icons. With QIconEnginePlugin it is possible to register different
- icon engines for different file suffixes, making it possible for
- third parties to provide additional icon engines to those included
+ \section1 Creating an icon from a theme or icon library
+
+ The most convenient way to construct an icon is by using the
+ \l{QIcon::}{fromTheme()} factory function. Qt implements access to
+ the native icon library on platforms that support the
+ \l {Freedesktop Icon Theme Specification}. Since Qt 6.7, Qt also
+ provides access to the native icon library on macOS, iOS, and
+ Windows 10 and 11. On Android, Qt can access icons from the Material
+ design system as long as the
+ \l{https://github.com/google/material-design-icons/tree/master/font}
+ {MaterialIcons-Regular} font is available on the system, or bundled
+ as a resource at \c{:/qt-project.org/icons/MaterialIcons-Regular.ttf}
+ with the application.
+
+ \snippet code/src_gui_image_qicon.cpp fromTheme
+
+ Applications can use the same theming specification to provide
+ their own icon library. See below for an example theme description
+ and the corresponding directory structure for the image files.
+ Icons from an application-provided theme take precedence over the
+ native icon library.
+
+ In addition, it is possible to provide custom \l {QIconEngine}
+ {icon engines}. This allows applications to customize every aspect
+ of generated icons. With QIconEnginePlugin it is possible to register
+ different icon engines for different file suffixes, making it possible
+ for third parties to provide additional icon engines to those included
with Qt.
- \note Since Qt 4.2, an icon engine that supports SVG is included.
-
\section1 Making Classes that Use QIcon
If you write your own widgets that have an option to set a small
pixmap, consider allowing a QIcon to be set for that pixmap. The
Qt class QToolButton is an example of such a widget.
- Provide a method to set a QIcon, and when you draw the icon, choose
- whichever pixmap is appropriate for the current state of your widget.
- For example:
+ Provide a method to set a QIcon, and paint the QIcon with
+ \l{QIcon::}{paint}, choosing the appropriate parameters based
+ on the current state of your widget. For example:
+
\snippet code/src_gui_image_qicon.cpp 2
+ When you retrieve a pixmap using pixmap(QSize, Mode, State), and no
+ pixmap for this given size, mode and state has been added with
+ addFile() or addPixmap(), then QIcon will generate one on the
+ fly. This pixmap generation happens in a QIconEngine. The default
+ engine scales pixmaps down if required, but never up, and it uses
+ the current style to calculate a disabled appearance.
+
You might also make use of the \c Active mode, perhaps making your
widget \c Active when the mouse is over the widget (see \l
QWidget::enterEvent()), while the mouse is pressed pending the
@@ -624,17 +639,19 @@ QFactoryLoader *qt_iconEngineFactoryLoader()
\section1 High DPI Icons
- There are two ways that QIcon supports \l {High DPI}{high DPI}
- icons: via \l addFile() and \l fromTheme().
+ Icons that are provided by the native icon library are usually based
+ on vector graphics, and will automatically be rendered in the appropriate
+ resolution.
- \l addFile() is useful if you have your own custom directory structure and do
- not need to use the \l {Icon Theme Specification}{freedesktop.org Icon Theme
- Specification}. Icons created via this approach use Qt's \l {High Resolution
- Versions of Images}{"@nx" high DPI syntax}.
+ When providing your own image files via \l addFile(), then QIcon will
+ use Qt's \l {High Resolution Versions of Images}{"@nx" high DPI syntax}.
+ This is useful if you have your own custom directory structure and do not
+ use follow \l {Freedesktop Icon Theme Specification}.
- Using \l fromTheme() is necessary if you plan on following the Icon Theme
- Specification. To make QIcon use the high DPI version of an image, add an
- additional entry to the appropriate \c index.theme file:
+ When providing an application theme, then you need to follow the Icon Theme
+ Specification to specify which files to use for different resolutions.
+ To make QIcon use the high DPI version of an image, add an additional entry
+ to the appropriate \c index.theme file:
\badcode
[Icon Theme]
@@ -666,8 +683,6 @@ QFactoryLoader *qt_iconEngineFactoryLoader()
│ └── appointment-new.png
└── index.theme
\endcode
-
- \sa {fowler}{GUI Design Handbook: Iconic Label}, {Icons Example}
*/
@@ -876,7 +891,7 @@ QPixmap QIcon::pixmap(const QSize &size, qreal devicePixelRatio, Mode mode, Stat
#if QT_DEPRECATED_SINCE(6, 0)
/*!
\since 5.1
- \deprecated
+ \deprecated [6.0] Use pixmap(size, devicePixelRatio) instead.
Returns a pixmap with the requested \a window \a size, \a mode, and \a
state, generating one if necessary.
@@ -885,8 +900,6 @@ QPixmap QIcon::pixmap(const QSize &size, qreal devicePixelRatio, Mode mode, Stat
a high-dpi display the pixmap can be larger. In that case it will have
a devicePixelRatio larger than 1.
- \deprecated Use the overload which takes qreal devicePixelRatio instead.
-
\sa actualSize(), paint()
*/
@@ -926,6 +939,7 @@ QSize QIcon::actualSize(const QSize &size, Mode mode, State state) const
#if QT_DEPRECATED_SINCE(6, 0)
/*!
\since 5.1
+ \deprecated [6.0] Use actualSize(size) instead.
Returns the actual size of the icon for the requested \a window \a size, \a
mode, and \a state.
@@ -1054,9 +1068,9 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state)
static QIconEngine *iconEngineFromSuffix(const QString &fileName, const QString &suffix)
{
if (!suffix.isEmpty()) {
- const int index = loader()->indexOf(suffix);
+ const int index = iceLoader()->indexOf(suffix);
if (index != -1) {
- if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(loader()->instance(index))) {
+ if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) {
return factory->create(fileName);
}
}
@@ -1138,10 +1152,9 @@ QList<QSize> QIcon::availableSizes(Mode mode, State state) const
Returns the name used to create the icon, if available.
Depending on the way the icon was created, it may have an associated
- name. This is the case for icons created with fromTheme() or icons
- using a QIconEngine which supports the QIconEngine::IconNameHook.
+ name. This is the case for icons created with fromTheme().
- \sa fromTheme(), QIconEngine
+ \sa fromTheme(), QIconEngine::iconName()
*/
QString QIcon::name() const
{
@@ -1154,6 +1167,10 @@ QString QIcon::name() const
\since 4.6
Sets the search paths for icon themes to \a paths.
+
+ The content of \a paths should follow the theme format
+ documented by setThemeName().
+
\sa themeSearchPaths(), fromTheme(), setThemeName()
*/
void QIcon::setThemeSearchPaths(const QStringList &paths)
@@ -1162,20 +1179,14 @@ void QIcon::setThemeSearchPaths(const QStringList &paths)
}
/*!
- \since 4.6
-
- Returns the search paths for icon themes.
-
- The default value will depend on the platform:
+ \since 4.6
- On X11, the search path will use the XDG_DATA_DIRS environment
- variable if available.
+ Returns the search paths for icon themes.
- By default all platforms will have the resource directory
- \c{:\icons} as a fallback. You can use "rcc -project" to generate a
- resource file from your icon theme.
+ The default search paths will be defined by the platform.
+ All platforms will also have the resource directory \c{:\icons} as a fallback.
- \sa setThemeSearchPaths(), fromTheme(), setThemeName()
+ \sa setThemeSearchPaths(), fromTheme(), setThemeName()
*/
QStringList QIcon::themeSearchPaths()
{
@@ -1187,7 +1198,13 @@ QStringList QIcon::themeSearchPaths()
Returns the fallback search paths for icons.
- The default value will depend on the platform.
+ The fallback search paths are consulted for standalone
+ icon files if the \l{themeName()}{current icon theme}
+ or \l{fallbackThemeName()}{fallback icon theme} do
+ not provide results for an icon lookup.
+
+ If not set, the fallback search paths will be defined
+ by the platform.
\sa setFallbackSearchPaths(), themeSearchPaths()
*/
@@ -1201,7 +1218,12 @@ QStringList QIcon::fallbackSearchPaths()
Sets the fallback search paths for icons to \a paths.
- \note To add some path without replacing existing ones:
+ The fallback search paths are consulted for standalone
+ icon files if the \l{themeName()}{current icon theme}
+ or \l{fallbackThemeName()}{fallback icon theme} do
+ not provide results for an icon lookup.
+
+ For example:
\snippet code/src_gui_image_qicon.cpp 5
@@ -1217,11 +1239,15 @@ void QIcon::setFallbackSearchPaths(const QStringList &paths)
Sets the current icon theme to \a name.
- The \a name should correspond to a directory name in the
- themeSearchPath() containing an index.theme
- file describing its contents.
+ The theme will be will be looked up in themeSearchPaths().
+
+ At the moment the only supported icon theme format is the
+ \l{Freedesktop Icon Theme Specification}. The \a name should
+ correspond to a directory name in the themeSearchPath()
+ containing an \c index.theme file describing its contents.
- \sa themeSearchPaths(), themeName()
+ \sa themeSearchPaths(), themeName(),
+ {Freedesktop Icon Theme Specification}
*/
void QIcon::setThemeName(const QString &name)
{
@@ -1233,8 +1259,12 @@ void QIcon::setThemeName(const QString &name)
Returns the name of the current icon theme.
- On X11, the current icon theme depends on your desktop
- settings. On other platforms it is not set by default.
+ If not set, the current icon theme will be defined by the
+ platform.
+
+ \note Platform icon themes are only implemented on
+ \l{Freedesktop} based systems at the moment, and the
+ icon theme depends on your desktop settings.
\sa setThemeName(), themeSearchPaths(), fromTheme(),
hasThemeIcon()
@@ -1249,8 +1279,12 @@ QString QIcon::themeName()
Returns the name of the fallback icon theme.
- On X11, if not set, the fallback icon theme depends on your desktop
- settings. On other platforms it is not set by default.
+ If not set, the fallback icon theme will be defined by the
+ platform.
+
+ \note Platform fallback icon themes are only implemented on
+ \l{Freedesktop} based systems at the moment, and the
+ icon theme depends on your desktop settings.
\sa setFallbackThemeName(), themeName()
*/
@@ -1264,12 +1298,16 @@ QString QIcon::fallbackThemeName()
Sets the fallback icon theme to \a name.
- The \a name should correspond to a directory name in the
- themeSearchPath() containing an index.theme
- file describing its contents.
+ The fallback icon theme is consulted for icons not provided by
+ the \l{themeName()}{current icon theme}, or if the \l{themeName()}
+ {current icon theme} does not exist.
- \note This should be done before creating \l QGuiApplication, to ensure
- correct initialization.
+ The \a name should correspond to theme in the same format
+ as documented by setThemeName(), and will be looked up
+ in themeSearchPaths().
+
+ \note Fallback icon themes should be set before creating
+ QGuiApplication, to ensure correct initialization.
\sa fallbackThemeName(), themeSearchPaths(), themeName()
*/
@@ -1281,67 +1319,63 @@ void QIcon::setFallbackThemeName(const QString &name)
/*!
\since 4.6
- Returns the QIcon corresponding to \a name in the current
- icon theme.
-
- The latest version of the freedesktop icon specification and naming
- specification can be obtained here:
+ Returns the QIcon corresponding to \a name in the
+ \l{themeName()}{current icon theme}.
- \list
- \li \l{http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html}
- \li \l{http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html}
- \endlist
+ If the current theme does not provide an icon for \a name,
+ the \l{fallbackThemeName()}{fallback icon theme} is consulted,
+ before falling back to looking up standalone icon files in the
+ \l{QIcon::fallbackSearchPaths()}{fallback icon search path}.
+ Finally, the platform's native icon library is consulted.
To fetch an icon from the current icon theme:
- \snippet code/src_gui_image_qicon.cpp 3
-
- \note By default, only X11 will support themed icons. In order to
- use themed icons on Mac and Windows, you will have to bundle a
- compliant theme in one of your themeSearchPaths() and set the
- appropriate themeName().
+ \snippet code/src_gui_image_qicon.cpp fromTheme
- \note Qt will make use of GTK's icon-theme.cache if present to speed up
- the lookup. These caches can be generated using gtk-update-icon-cache:
- \l{https://developer.gnome.org/gtk3/stable/gtk-update-icon-cache.html}.
+ If an \l{themeName()}{icon theme} has not been explicitly
+ set via setThemeName() a platform defined icon theme will
+ be used.
- \note If an icon can't be found in the current theme, then it will be
- searched in fallbackSearchPaths() as an unthemed icon.
-
- \sa themeName(), setThemeName(), themeSearchPaths(), fallbackSearchPaths()
+ \sa themeName(), fallbackThemeName(), setThemeName(), themeSearchPaths(), fallbackSearchPaths(),
+ {Freedesktop Icon Naming Specification}
*/
QIcon QIcon::fromTheme(const QString &name)
{
- QIcon icon;
- if (qtIconCache()->contains(name)) {
- icon = *qtIconCache()->object(name);
- } else if (QDir::isAbsolutePath(name)) {
+ if (QIcon *cachedIcon = qtIconCache()->object(name))
+ return *cachedIcon;
+
+ if (QDir::isAbsolutePath(name))
return QIcon(name);
- } else {
- QPlatformTheme * const platformTheme = QGuiApplicationPrivate::platformTheme();
- bool hasUserTheme = QIconLoader::instance()->hasUserTheme();
- QIconEngine * const engine = (platformTheme && !hasUserTheme) ? platformTheme->createIconEngine(name)
- : new QIconLoaderEngine(name);
- icon = QIcon(engine);
- if (!icon.isNull())
- qtIconCache()->insert(name, new QIcon(icon));
- }
+ QIcon icon(new QThemeIconEngine(name));
+ qtIconCache()->insert(name, new QIcon(icon));
return icon;
}
/*!
\overload
- Returns the QIcon corresponding to \a name in the current
- icon theme. If no such icon is found in the current theme
- \a fallback is returned instead.
+ Returns the QIcon corresponding to \a name in the
+ \l{themeName()}{current icon theme}.
+
+ If the current theme does not provide an icon for \a name,
+ the \l{fallbackThemeName()}{fallback icon theme} is consulted,
+ before falling back to looking up standalone icon files in the
+ \l{QIcon::fallbackSearchPaths()}{fallback icon search path}.
+ Finally, the platform's native icon library is consulted.
+
+ If no icon is found \a fallback is returned.
+
+ This is useful to provide a guaranteed fallback, regardless of
+ whether the current set of icon themes and fallbacks paths
+ support the requested icon.
- If you want to provide a guaranteed fallback for platforms that
- do not support theme icons, you can use the second argument:
+ For example:
\snippet code/src_gui_image_qicon.cpp 4
+
+ \sa fallbackThemeName(), fallbackSearchPaths()
*/
QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
{
@@ -1357,7 +1391,8 @@ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
\since 4.6
Returns \c true if there is an icon available for \a name in the
- current icon theme, otherwise returns \c false.
+ current icon theme or any of the fallbacks, as described by
+ fromTheme(), otherwise returns \c false.
\sa themeSearchPaths(), fromTheme(), setThemeName()
*/
@@ -1368,6 +1403,401 @@ bool QIcon::hasThemeIcon(const QString &name)
return icon.name() == name;
}
+static constexpr auto themeIconMapping = qOffsetStringArray(
+ "address-book-new",
+ "application-exit",
+ "appointment-new",
+ "call-start",
+ "call-stop",
+ "contact-new",
+ "document-new",
+ "document-open",
+ "document-open-recent",
+ "document-page-setup",
+ "document-print",
+ "document-print-preview",
+ "document-properties",
+ "document-revert",
+ "document-save",
+ "document-save-as",
+ "document-send",
+ "edit-clear",
+ "edit-copy",
+ "edit-cut",
+ "edit-delete",
+ "edit-find",
+ "edit-paste",
+ "edit-redo",
+ "edit-select-all",
+ "edit-undo",
+ "folder-new",
+ "format-indent-less",
+ "format-indent-more",
+ "format-justify-center",
+ "format-justify-fill",
+ "format-justify-left",
+ "format-justify-right",
+ "format-text-direction-ltr",
+ "format-text-direction-rtl",
+ "format-text-bold",
+ "format-text-italic",
+ "format-text-underline",
+ "format-text-strikethrough",
+ "go-down",
+ "go-home",
+ "go-next",
+ "go-previous",
+ "go-up",
+ "help-about",
+ "help-faq",
+ "insert-image",
+ "insert-link",
+ "insert-text",
+ "list-add",
+ "list-remove",
+ "mail-forward",
+ "mail-mark-important",
+ "mail-mark-read",
+ "mail-mark-unread",
+ "mail-message-new",
+ "mail-reply-all",
+ "mail-reply-sender",
+ "mail-send",
+ "media-eject",
+ "media-playback-pause",
+ "media-playback-start",
+ "media-playback-stop",
+ "media-record",
+ "media-seek-backward",
+ "media-seek-forward",
+ "media-skip-backward",
+ "media-skip-forward",
+ "object-rotate-left",
+ "object-rotate-right",
+ "process-stop",
+ "system-lock-screen",
+ "system-log-out",
+ "system-search",
+ "system-reboot",
+ "system-shutdown",
+ "tools-check-spelling",
+ "view-fullscreen",
+ "view-refresh",
+ "view-restore",
+ "window-close",
+ "window-new",
+ "zoom-fit-best",
+ "zoom-in",
+ "zoom-out",
+
+ "audio-card",
+ "audio-input-microphone",
+ "battery",
+ "camera-photo",
+ "camera-video",
+ "camera-web",
+ "computer",
+ "drive-harddisk",
+ "drive-optical",
+ "input-gaming",
+ "input-keyboard",
+ "input-mouse",
+ "input-tablet",
+ "media-flash",
+ "media-optical",
+ "media-tape",
+ "multimedia-player",
+ "network-wired",
+ "network-wireless",
+ "phone",
+ "printer",
+ "scanner",
+ "video-display",
+
+ "appointment-missed",
+ "appointment-soon",
+ "audio-volume-high",
+ "audio-volume-low",
+ "audio-volume-medium",
+ "audio-volume-muted",
+ "battery-caution",
+ "battery-low",
+ "dialog-error",
+ "dialog-information",
+ "dialog-password",
+ "dialog-question",
+ "dialog-warning",
+ "folder-drag-accept",
+ "folder-open",
+ "folder-visiting",
+ "image-loading",
+ "image-missing",
+ "mail-attachment",
+ "mail-unread",
+ "mail-read",
+ "mail-replied",
+ "media-playlist-repeat",
+ "media-playlist-shuffle",
+ "network-offline",
+ "printer-printing",
+ "security-high",
+ "security-low",
+ "software-update-available",
+ "software-update-urgent",
+ "sync-error",
+ "sync-synchronizing",
+ "user-available",
+ "user-offline",
+ "weather-clear",
+ "weather-clear-night",
+ "weather-few-clouds",
+ "weather-few-clouds-night",
+ "weather-fog",
+ "weather-showers",
+ "weather-snow",
+ "weather-storm"
+);
+static_assert(QIcon::ThemeIcon::NThemeIcons == QIcon::ThemeIcon(themeIconMapping.count()));
+
+static constexpr QLatin1StringView themeIconName(QIcon::ThemeIcon icon)
+{
+ using ThemeIconIndex = std::underlying_type_t<QIcon::ThemeIcon>;
+ const auto index = static_cast<ThemeIconIndex>(icon);
+ Q_ASSERT(index < themeIconMapping.count());
+ return QLatin1StringView(themeIconMapping.viewAt(index));
+}
+
+/*!
+ \enum QIcon::ThemeIcon
+ \since 6.7
+
+ This enum provides access to icons that are provided by most
+ icon theme implementations.
+
+ \value AddressBookNew The icon for the action to create a new address book.
+ \value ApplicationExit The icon for exiting an application.
+ \value AppointmentNew The icon for the action to create a new appointment.
+ \value CallStart The icon for initiating or accepting a call.
+ \value CallStop The icon for stopping a current call.
+ \value ContactNew The icon for the action to create a new contact.
+ \value DocumentNew The icon for the action to create a new document.
+ \value DocumentOpen The icon for the action to open a document.
+ \value DocumentOpenRecent The icon for the action to open a document that was recently opened.
+ \value DocumentPageSetup The icon for the \e{page setup} action.
+ \value DocumentPrint The icon for the \e{print} action.
+ \value DocumentPrintPreview The icon for the \e{print preview} action.
+ \value DocumentProperties The icon for the action to view the properties of a document.
+ \value DocumentRevert The icon for the action of reverting to a previous version of a document.
+ \value DocumentSave The icon for the \e{save} action.
+ \value DocumentSaveAs The icon for the \e{save as} action.
+ \value DocumentSend The icon for the \e{send} action.
+ \value EditClear The icon for the \e{clear} action.
+ \value EditCopy The icon for the \e{copy} action.
+ \value EditCut The icon for the \e{cut} action.
+ \value EditDelete The icon for the \e{delete} action.
+ \value EditFind The icon for the \e{find} action.
+ \value EditPaste The icon for the \e{paste} action.
+ \value EditRedo The icon for the \e{redo} action.
+ \value EditSelectAll The icon for the \e{select all} action.
+ \value EditUndo The icon for the \e{undo} action.
+ \value FolderNew The icon for creating a new folder.
+ \value FormatIndentLess The icon for the \e{decrease indent formatting} action.
+ \value FormatIndentMore The icon for the \e{increase indent formatting} action.
+ \value FormatJustifyCenter The icon for the \e{center justification formatting} action.
+ \value FormatJustifyFill The icon for the \e{fill justification formatting} action.
+ \value FormatJustifyLeft The icon for the \e{left justification formatting} action.
+ \value FormatJustifyRight The icon for the \e{right justification} action.
+ \value FormatTextDirectionLtr The icon for the \e{left-to-right text formatting} action.
+ \value FormatTextDirectionRtl The icon for the \e{right-to-left formatting} action.
+ \value FormatTextBold The icon for the \e{bold text formatting} action.
+ \value FormatTextItalic The icon for the \e{italic text formatting} action.
+ \value FormatTextUnderline The icon for the \e{underlined text formatting} action.
+ \value FormatTextStrikethrough The icon for the \e{strikethrough text formatting} action.
+ \value GoDown The icon for the \e{go down in a list} action.
+ \value GoHome The icon for the \e{go to home location} action.
+ \value GoNext The icon for the \e{go to the next item in a list} action.
+ \value GoPrevious The icon for the \e{go to the previous item in a list} action.
+ \value GoUp The icon for the \e{go up in a list} action.
+ \value HelpAbout The icon for the \e{About} item in the Help menu.
+ \value HelpFaq The icon for the \e{FAQ} item in the Help menu.
+ \value InsertImage The icon for the \e{insert image} action of an application.
+ \value InsertLink The icon for the \e{insert link} action of an application.
+ \value InsertText The icon for the \e{insert text} action of an application.
+ \value ListAdd The icon for the \e{add to list} action.
+ \value ListRemove The icon for the \e{remove from list} action.
+ \value MailForward The icon for the \e{forward} action.
+ \value MailMarkImportant The icon for the \e{mark as important} action.
+ \value MailMarkRead The icon for the \e{mark as read} action.
+ \value MailMarkUnread The icon for the \e{mark as unread} action.
+ \value MailMessageNew The icon for the \e{compose new mail} action.
+ \value MailReplyAll The icon for the \e{reply to all} action.
+ \value MailReplySender The icon for the \e{reply to sender} action.
+ \value MailSend The icon for the \e{send} action.
+ \value MediaEject The icon for the \e{eject} action of a media player or file manager.
+ \value MediaPlaybackPause The icon for the \e{pause} action of a media player.
+ \value MediaPlaybackStart The icon for the \e{start playback} action of a media player.
+ \value MediaPlaybackStop The icon for the \e{stop} action of a media player.
+ \value MediaRecord The icon for the \e{record} action of a media application.
+ \value MediaSeekBackward The icon for the \e{seek backward} action of a media player.
+ \value MediaSeekForward The icon for the \e{seek forward} action of a media player.
+ \value MediaSkipBackward The icon for the \e{skip backward} action of a media player.
+ \value MediaSkipForward The icon for the \e{skip forward} action of a media player.
+ \value ObjectRotateLeft The icon for the \e{rotate left} action performed on an object.
+ \value ObjectRotateRight The icon for the \e{rotate right} action performed on an object.
+ \value ProcessStop The icon for the \e{stop action in applications with} actions that
+ may take a while to process, such as web page loading in a browser.
+ \value SystemLockScreen The icon for the \e{lock screen} action.
+ \value SystemLogOut The icon for the \e{log out} action.
+ \value SystemSearch The icon for the \e{search} action.
+ \value SystemReboot The icon for the \e{reboot} action.
+ \value SystemShutdown The icon for the \e{shutdown} action.
+ \value ToolsCheckSpelling The icon for the \e{check spelling} action.
+ \value ViewFullscreen The icon for the \e{fullscreen} action.
+ \value ViewRefresh The icon for the \e{refresh} action.
+ \value ViewRestore The icon for leaving the fullscreen view.
+ \value WindowClose The icon for the \e{close window} action.
+ \value WindowNew The icon for the \e{new window} action.
+ \value ZoomFitBest The icon for the \e{best fit} action.
+ \value ZoomIn The icon for the \e{zoom in} action.
+ \value ZoomOut The icon for the \e{zoom out} action.
+
+ \value AudioCard The icon for the audio rendering device.
+ \value AudioInputMicrophone The icon for the microphone audio input device.
+ \value Battery The icon for the system battery device.
+ \value CameraPhoto The icon for a digital still camera devices.
+ \value CameraVideo The icon for a video camera device.
+ \value CameraWeb The icon for a web camera device.
+ \value Computer The icon for the computing device as a whole.
+ \value DriveHarddisk The icon for hard disk drives.
+ \value DriveOptical The icon for optical media drives such as CD and DVD.
+ \value InputGaming The icon for the gaming input device.
+ \value InputKeyboard The icon for the keyboard input device.
+ \value InputMouse The icon for the mousing input device.
+ \value InputTablet The icon for graphics tablet input devices.
+ \value MediaFlash The icon for flash media, such as a memory stick.
+ \value MediaOptical The icon for physical optical media such as CD and DVD.
+ \value MediaTape The icon for generic physical tape media.
+ \value MultimediaPlayer The icon for generic multimedia playing devices.
+ \value NetworkWired The icon for wired network connections.
+ \value NetworkWireless The icon for wireless network connections.
+ \value Phone The icon for phone devices.
+ \value Printer The icon for a printer device.
+ \value Scanner The icon for a scanner device.
+ \value VideoDisplay The icon for the monitor that video gets displayed on.
+
+ \value AppointmentMissed The icon for when an appointment was missed.
+ \value AppointmentSoon The icon for when an appointment will occur soon.
+ \value AudioVolumeHigh The icon used to indicate high audio volume.
+ \value AudioVolumeLow The icon used to indicate low audio volume.
+ \value AudioVolumeMedium The icon used to indicate medium audio volume.
+ \value AudioVolumeMuted The icon used to indicate the muted state for audio playback.
+ \value BatteryCaution The icon used when the battery is below 40%.
+ \value BatteryLow The icon used when the battery is below 20%.
+ \value DialogError The icon used when a dialog is opened to explain an error
+ condition to the user.
+ \value DialogInformation The icon used when a dialog is opened to give information to the
+ user that may be pertinent to the requested action.
+ \value DialogPassword The icon used when a dialog requesting the authentication
+ credentials for a user is opened.
+ \value DialogQuestion The icon used when a dialog is opened to ask a simple question
+ to the user.
+ \value DialogWarning The icon used when a dialog is opened to warn the user of
+ impending issues with the requested action.
+ \value FolderDragAccept The icon used for a folder while an acceptable object is being
+ dragged onto it.
+ \value FolderOpen The icon used for folders, while their contents are being displayed
+ within the same window.
+ \value FolderVisiting The icon used for folders, while their contents are being displayed
+ in another window.
+ \value ImageLoading The icon used while another image is being loaded.
+ \value ImageMissing The icon used when another image could not be loaded.
+ \value MailAttachment The icon for a message that contains attachments.
+ \value MailUnread The icon for an unread message.
+ \value MailRead The icon for a read message.
+ \value MailReplied The icon for a message that has been replied to.
+ \value MediaPlaylistRepeat The icon for the repeat mode of a media player.
+ \value MediaPlaylistShuffle The icon for the shuffle mode of a media player.
+ \value NetworkOffline The icon used to indicate that the device is not connected to the
+ network.
+ \value PrinterPrinting The icon used while a print job is successfully being spooled to a
+ printing device.
+ \value SecurityHigh The icon used to indicate that the security level of an item is
+ known to be high.
+ \value SecurityLow The icon used to indicate that the security level of an item is
+ known to be low.
+ \value SoftwareUpdateAvailable The icon used to indicate that an update is available.
+ \value SoftwareUpdateUrgent The icon used to indicate that an urgent update is available.
+ \value SyncError The icon used when an error occurs while attempting to synchronize
+ data across devices.
+ \value SyncSynchronizing The icon used while data is successfully synchronizing across
+ devices.
+ \value UserAvailable The icon used to indicate that a user is available.
+ \value UserOffline The icon used to indicate that a user is not available.
+ \value WeatherClear The icon used to indicate that the sky is clear.
+ \value WeatherClearNight The icon used to indicate that the sky is clear
+ during the night.
+ \value WeatherFewClouds The icon used to indicate that the sky is partly cloudy.
+ \value WeatherFewCloudsNight The icon used to indicate that the sky is partly cloudy
+ during the night.
+ \value WeatherFog The icon used to indicate that the weather is foggy.
+ \value WeatherShowers The icon used to indicate that rain showers are occurring.
+ \value WeatherSnow The icon used to indicate that snow is falling.
+ \value WeatherStorm The icon used to indicate that the weather is stormy.
+
+ \omitvalue NThemeIcons
+
+ \sa {QIcon#Creating an icon from a theme or icon library},
+ fromTheme()
+*/
+
+/*!
+ \since 6.7
+ \overload
+
+ Returns \c true if there is an icon available for \a icon in the
+ current icon theme or any of the fallbacks, as described by
+ fromTheme(), otherwise returns \c false.
+
+ \sa fromTheme()
+*/
+bool QIcon::hasThemeIcon(QIcon::ThemeIcon icon)
+{
+ return hasThemeIcon(themeIconName(icon));
+}
+
+/*!
+ \fn QIcon QIcon::fromTheme(QIcon::ThemeIcon icon)
+ \fn QIcon QIcon::fromTheme(QIcon::ThemeIcon icon, const QIcon &fallback)
+ \since 6.7
+ \overload
+
+ Returns the QIcon corresponding to \a icon in the
+ \l{themeName()}{current icon theme}.
+
+ If the current theme does not provide an icon for \a icon,
+ the \l{fallbackThemeName()}{fallback icon theme} is consulted,
+ before falling back to looking up standalone icon files in the
+ \l{QIcon::fallbackSearchPaths()}{fallback icon search path}.
+ Finally, the platform's native icon library is consulted.
+
+ If no icon is found and a \a fallback is provided, \a fallback is
+ returned. This is useful to provide a guaranteed fallback, regardless
+ of whether the current set of icon themes and fallbacks paths
+ support the requested icon.
+
+ If no icon is found and no \a fallback is provided, a default
+ constructed, empty QIcon is returned.
+*/
+QIcon QIcon::fromTheme(QIcon::ThemeIcon icon)
+{
+ return fromTheme(themeIconName(icon));
+}
+
+QIcon QIcon::fromTheme(QIcon::ThemeIcon icon, const QIcon &fallback)
+{
+ return fromTheme(themeIconName(icon), fallback);
+}
+
/*!
\since 5.6
@@ -1459,16 +1889,16 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon)
icon = QIcon();
QString key;
s >> key;
- if (key == QLatin1String("QPixmapIconEngine")) {
+ if (key == "QPixmapIconEngine"_L1) {
icon.d = new QIconPrivate(new QPixmapIconEngine);
icon.d->engine->read(s);
- } else if (key == QLatin1String("QIconLoaderEngine")) {
- icon.d = new QIconPrivate(new QIconLoaderEngine());
+ } else if (key == "QIconLoaderEngine"_L1 || key == "QThemeIconEngine"_L1) {
+ icon.d = new QIconPrivate(new QThemeIconEngine);
icon.d->engine->read(s);
} else {
- const int index = loader()->indexOf(key);
+ const int index = iceLoader()->indexOf(key);
if (index != -1) {
- if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(loader()->instance(index))) {
+ if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) {
if (QIconEngine *engine= factory->create()) {
icon.d = new QIconPrivate(engine);
engine->read(s);
@@ -1559,17 +1989,17 @@ QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRati
if (disableNxImageLoading)
return baseFileName;
- int dotIndex = baseFileName.lastIndexOf(QLatin1Char('.'));
+ int dotIndex = baseFileName.lastIndexOf(u'.');
if (dotIndex == -1) { /* no dot */
dotIndex = baseFileName.size(); /* append */
- } else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == QLatin1Char('9')
- && baseFileName[dotIndex - 2] == QLatin1Char('.')) {
+ } else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == u'9'
+ && baseFileName[dotIndex - 2] == u'.') {
// If the file has a .9.* (9-patch image) extension, we must ensure that the @nx goes before it.
dotIndex -= 2;
}
QString atNxfileName = baseFileName;
- atNxfileName.insert(dotIndex, QLatin1String("@2x"));
+ atNxfileName.insert(dotIndex, "@2x"_L1);
// Check for @Nx, ..., @3x, @2x file versions,
for (int n = qMin(qCeil(targetDevicePixelRatio), 9); n > 1; --n) {
atNxfileName[dotIndex + 1] = QLatin1Char('0' + n);
diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h
index fab8c3fe21..5100ada548 100644
--- a/src/gui/image/qicon.h
+++ b/src/gui/image/qicon.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICON_H
#define QICON_H
@@ -58,11 +22,168 @@ public:
enum Mode { Normal, Disabled, Active, Selected };
enum State { On, Off };
+ enum class ThemeIcon {
+ AddressBookNew,
+ ApplicationExit,
+ AppointmentNew,
+ CallStart,
+ CallStop,
+ ContactNew,
+ DocumentNew,
+ DocumentOpen,
+ DocumentOpenRecent,
+ DocumentPageSetup,
+ DocumentPrint,
+ DocumentPrintPreview,
+ DocumentProperties,
+ DocumentRevert,
+ DocumentSave,
+ DocumentSaveAs,
+ DocumentSend,
+ EditClear,
+ EditCopy,
+ EditCut,
+ EditDelete,
+ EditFind,
+ EditPaste,
+ EditRedo,
+ EditSelectAll,
+ EditUndo,
+ FolderNew,
+ FormatIndentLess,
+ FormatIndentMore,
+ FormatJustifyCenter,
+ FormatJustifyFill,
+ FormatJustifyLeft,
+ FormatJustifyRight,
+ FormatTextDirectionLtr,
+ FormatTextDirectionRtl,
+ FormatTextBold,
+ FormatTextItalic,
+ FormatTextUnderline,
+ FormatTextStrikethrough,
+ GoDown,
+ GoHome,
+ GoNext,
+ GoPrevious,
+ GoUp,
+ HelpAbout,
+ HelpFaq,
+ InsertImage,
+ InsertLink,
+ InsertText,
+ ListAdd,
+ ListRemove,
+ MailForward,
+ MailMarkImportant,
+ MailMarkRead,
+ MailMarkUnread,
+ MailMessageNew,
+ MailReplyAll,
+ MailReplySender,
+ MailSend,
+ MediaEject,
+ MediaPlaybackPause,
+ MediaPlaybackStart,
+ MediaPlaybackStop,
+ MediaRecord,
+ MediaSeekBackward,
+ MediaSeekForward,
+ MediaSkipBackward,
+ MediaSkipForward,
+ ObjectRotateLeft,
+ ObjectRotateRight,
+ ProcessStop,
+ SystemLockScreen,
+ SystemLogOut,
+ SystemSearch,
+ SystemReboot,
+ SystemShutdown,
+ ToolsCheckSpelling,
+ ViewFullscreen,
+ ViewRefresh,
+ ViewRestore,
+ WindowClose,
+ WindowNew,
+ ZoomFitBest,
+ ZoomIn,
+ ZoomOut,
+
+ AudioCard,
+ AudioInputMicrophone,
+ Battery,
+ CameraPhoto,
+ CameraVideo,
+ CameraWeb,
+ Computer,
+ DriveHarddisk,
+ DriveOptical,
+ InputGaming,
+ InputKeyboard,
+ InputMouse,
+ InputTablet,
+ MediaFlash,
+ MediaOptical,
+ MediaTape,
+ MultimediaPlayer,
+ NetworkWired,
+ NetworkWireless,
+ Phone,
+ Printer,
+ Scanner,
+ VideoDisplay,
+
+ AppointmentMissed,
+ AppointmentSoon,
+ AudioVolumeHigh,
+ AudioVolumeLow,
+ AudioVolumeMedium,
+ AudioVolumeMuted,
+ BatteryCaution,
+ BatteryLow,
+ DialogError,
+ DialogInformation,
+ DialogPassword,
+ DialogQuestion,
+ DialogWarning,
+ FolderDragAccept,
+ FolderOpen,
+ FolderVisiting,
+ ImageLoading,
+ ImageMissing,
+ MailAttachment,
+ MailUnread,
+ MailRead,
+ MailReplied,
+ MediaPlaylistRepeat,
+ MediaPlaylistShuffle,
+ NetworkOffline,
+ PrinterPrinting,
+ SecurityHigh,
+ SecurityLow,
+ SoftwareUpdateAvailable,
+ SoftwareUpdateUrgent,
+ SyncError,
+ SyncSynchronizing,
+ UserAvailable,
+ UserOffline,
+ WeatherClear,
+ WeatherClearNight,
+ WeatherFewClouds,
+ WeatherFewCloudsNight,
+ WeatherFog,
+ WeatherShowers,
+ WeatherSnow,
+ WeatherStorm,
+
+ NThemeIcons
+ };
+
QIcon() noexcept;
QIcon(const QPixmap &pixmap);
QIcon(const QIcon &other);
QIcon(QIcon &&other) noexcept
- : d(qExchange(other.d, nullptr))
+ : d(std::exchange(other.d, nullptr))
{}
explicit QIcon(const QString &fileName); // file or resource name
explicit QIcon(QIconEngine *engine);
@@ -70,7 +191,7 @@ public:
QIcon &operator=(const QIcon &other);
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QIcon)
inline void swap(QIcon &other) noexcept
- { qSwap(d, other.d); }
+ { qt_ptr_swap(d, other.d); }
bool operator==(const QIcon &) const = delete;
bool operator!=(const QIcon &) const = delete;
@@ -117,6 +238,10 @@ public:
static QIcon fromTheme(const QString &name, const QIcon &fallback);
static bool hasThemeIcon(const QString &name);
+ static QIcon fromTheme(ThemeIcon icon);
+ static QIcon fromTheme(ThemeIcon icon, const QIcon &fallback);
+ static bool hasThemeIcon(ThemeIcon icon);
+
static QStringList themeSearchPaths();
static void setThemeSearchPaths(const QStringList &searchpath);
@@ -129,8 +254,6 @@ public:
static QString fallbackThemeName();
static void setFallbackThemeName(const QString &name);
- Q_DUMMY_COMPARISON_OPERATOR(QIcon)
-
private:
QIconPrivate *d;
#if !defined(QT_NO_DATASTREAM)
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index 244da260b0..c5bf120620 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICON_P_H
#define QICON_P_H
@@ -78,6 +42,8 @@ public:
int serialNum;
int detach_no;
bool is_mask;
+
+ static void clearIconCache();
};
@@ -118,7 +84,7 @@ public:
QList<QSize> availableSizes(QIcon::Mode mode, QIcon::State state) override;
void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) override;
void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state) override;
-
+ bool isNull() override;
QString key() const override;
QIconEngine *clone() const override;
diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp
index c5727e8ae6..78273bdeb3 100644
--- a/src/gui/image/qiconengine.cpp
+++ b/src/gui/image/qiconengine.cpp
@@ -1,43 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qiconengine.h"
+#include "qiconengine_p.h"
#include "qpainter.h"
QT_BEGIN_NAMESPACE
@@ -343,4 +308,78 @@ QPixmap QIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::St
return arg.pixmap;
}
+
+// ------- QProxyIconEngine -----
+
+void QProxyIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
+{
+ proxiedEngine()->paint(painter, rect, mode, state);
+}
+
+QSize QProxyIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ return proxiedEngine()->actualSize(size, mode, state);
+}
+
+QPixmap QProxyIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ return proxiedEngine()->pixmap(size, mode, state);
+}
+
+void QProxyIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state)
+{
+ proxiedEngine()->addPixmap(pixmap, mode, state);
+}
+
+void QProxyIconEngine::addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ proxiedEngine()->addFile(fileName, size, mode, state);
+}
+
+QString QProxyIconEngine::key() const
+{
+ return proxiedEngine()->key();
+}
+
+QIconEngine *QProxyIconEngine::clone() const
+{
+ return proxiedEngine()->clone();
+}
+
+bool QProxyIconEngine::read(QDataStream &in)
+{
+ return proxiedEngine()->read(in);
+}
+
+bool QProxyIconEngine::write(QDataStream &out) const
+{
+ return proxiedEngine()->write(out);
+}
+
+QList<QSize> QProxyIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state)
+{
+ return proxiedEngine()->availableSizes(mode, state);
+}
+
+QString QProxyIconEngine::iconName()
+{
+ return proxiedEngine()->iconName();
+}
+
+bool QProxyIconEngine::isNull()
+{
+ return proxiedEngine()->isNull();
+}
+
+QPixmap QProxyIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
+{
+ return proxiedEngine()->scaledPixmap(size, mode, state, scale);
+}
+
+void QProxyIconEngine::virtual_hook(int id, void *data)
+{
+ proxiedEngine()->virtual_hook(id, data);
+}
+
+
QT_END_NAMESPACE
diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h
index 383e116f43..61411b0660 100644
--- a/src/gui/image/qiconengine.h
+++ b/src/gui/image/qiconengine.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICONENGINE_H
#define QICONENGINE_H
diff --git a/src/gui/image/qiconengine_p.h b/src/gui/image/qiconengine_p.h
new file mode 100644
index 0000000000..3cf0998429
--- /dev/null
+++ b/src/gui/image/qiconengine_p.h
@@ -0,0 +1,59 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QICONENGINE_P_H
+#define QICONENGINE_P_H
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#ifndef QT_NO_ICON
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/QIcon>
+#include <QtGui/QIconEngine>
+
+QT_BEGIN_NAMESPACE
+
+class QIconEngine;
+
+class QProxyIconEngine : public QIconEngine
+{
+public:
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
+ QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+
+ void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) override;
+ void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+
+ QString key() const override;
+ QIconEngine *clone() const override;
+ bool read(QDataStream &in) override;
+ bool write(QDataStream &out) const override;
+
+ QList<QSize> availableSizes(QIcon::Mode mode = QIcon::Normal,
+ QIcon::State state = QIcon::Off) override;
+
+ QString iconName() override;
+ bool isNull() override;
+ QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
+
+ void virtual_hook(int id, void *data) override;
+protected:
+ virtual QIconEngine *proxiedEngine() const = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ICON
+
+#endif // QICONENGINE_P_H
diff --git a/src/gui/image/qiconengineplugin.cpp b/src/gui/image/qiconengineplugin.cpp
index ca80ee50a7..f75b5370f1 100644
--- a/src/gui/image/qiconengineplugin.cpp
+++ b/src/gui/image/qiconengineplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qiconengineplugin.h"
#include "qiconengine.h"
@@ -97,3 +61,5 @@ QIconEnginePlugin::~QIconEnginePlugin()
QT_END_NAMESPACE
+
+#include "moc_qiconengineplugin.cpp"
diff --git a/src/gui/image/qiconengineplugin.h b/src/gui/image/qiconengineplugin.h
index f2a1c0107a..b005baff0b 100644
--- a/src/gui/image/qiconengineplugin.h
+++ b/src/gui/image/qiconengineplugin.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICONENGINEPLUGIN_H
#define QICONENGINEPLUGIN_H
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index e5aa7cd0ac..982b9a26b4 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QT_NO_ICON
#include <private/qiconloader_p.h>
@@ -50,6 +14,7 @@
#include <QtCore/qmath.h>
#include <QtCore/QList>
#include <QtCore/QDir>
+#include <QtCore/qloggingcategory.h>
#if QT_CONFIG(settings)
#include <QtCore/QSettings>
#endif
@@ -59,6 +24,10 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcIconLoader, "qt.gui.icon.loader")
+
+using namespace Qt::StringLiterals;
+
Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)
/* Theme to use in last resort, if the theme does not have the icon, neither the parents */
@@ -122,8 +91,11 @@ void QIconLoader::ensureInitialized()
if (m_systemTheme.isEmpty())
m_systemTheme = systemFallbackThemeName();
- if (qt_iconEngineFactoryLoader()->keyMap().key(QLatin1String("svg"), -1) != -1)
+ if (qt_iconEngineFactoryLoader()->keyMap().key("svg"_L1, -1) != -1)
m_supportsSvg = true;
+
+ qCDebug(lcIconLoader) << "Initialized icon loader with system theme"
+ << m_systemTheme << "and SVG support" << m_supportsSvg;
}
}
@@ -135,7 +107,7 @@ void QIconLoader::ensureInitialized()
created, to avoid a race condition (QTBUG-74252). When this function is
called from there, ensureInitialized() does not succeed because there
is no QPlatformTheme yet, so systemThemeName() is empty, and we don't want
- m_systemTheme to get intialized to the fallback theme instead of the normal one.
+ m_systemTheme to get initialized to the fallback theme instead of the normal one.
*/
QIconLoader *QIconLoader::instance()
{
@@ -147,21 +119,45 @@ QIconLoader *QIconLoader::instance()
// icons if the theme has changed.
void QIconLoader::updateSystemTheme()
{
- // Only change if this is not explicitly set by the user
- if (m_userTheme.isEmpty()) {
- QString theme = systemThemeName();
- if (theme.isEmpty())
- theme = fallbackThemeName();
- if (theme != m_systemTheme) {
- m_systemTheme = theme;
- invalidateKey();
- }
- }
+ const QString currentSystemTheme = m_systemTheme;
+ m_systemTheme = systemThemeName();
+ if (m_systemTheme.isEmpty())
+ m_systemTheme = systemFallbackThemeName();
+ if (m_systemTheme != currentSystemTheme)
+ qCDebug(lcIconLoader) << "Updated system theme to" << m_systemTheme;
+ // Invalidate even if the system theme name hasn't changed, as the
+ // theme itself may have changed its underlying icon lookup logic.
+ if (!hasUserTheme())
+ invalidateKey();
+}
+
+void QIconLoader::invalidateKey()
+{
+ // Invalidating the key here will result in QThemeIconEngine
+ // recreating the actual engine the next time the icon is used.
+ // We don't need to clear the QIcon cache itself.
+ m_themeKey++;
+}
+
+QString QIconLoader::themeName() const
+{
+ return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme;
}
void QIconLoader::setThemeName(const QString &themeName)
{
+ if (m_userTheme == themeName)
+ return;
+
+ qCDebug(lcIconLoader) << "Setting user theme name to" << themeName;
+
+ const bool hadUserTheme = hasUserTheme();
m_userTheme = themeName;
+ // if we cleared the user theme, then reset search paths as well,
+ // otherwise we'll keep looking in the user-defined search paths for
+ // a system-provide theme, which will never work.
+ if (!hasUserTheme() && hadUserTheme)
+ setThemeSearchPath(systemIconSearchPaths());
invalidateKey();
}
@@ -172,11 +168,14 @@ QString QIconLoader::fallbackThemeName() const
void QIconLoader::setFallbackThemeName(const QString &themeName)
{
+ qCDebug(lcIconLoader) << "Setting fallback theme name to" << themeName;
m_userFallbackTheme = themeName;
+ invalidateKey();
}
void QIconLoader::setThemeSearchPath(const QStringList &searchPaths)
{
+ qCDebug(lcIconLoader) << "Setting theme search path to" << searchPaths;
m_iconDirs = searchPaths;
themeList.clear();
invalidateKey();
@@ -187,13 +186,14 @@ QStringList QIconLoader::themeSearchPaths() const
if (m_iconDirs.isEmpty()) {
m_iconDirs = systemIconSearchPaths();
// Always add resource directory as search path
- m_iconDirs.append(QLatin1String(":/icons"));
+ m_iconDirs.append(":/icons"_L1);
}
return m_iconDirs;
}
void QIconLoader::setFallbackSearchPaths(const QStringList &searchPaths)
{
+ qCDebug(lcIconLoader) << "Setting fallback search path to" << searchPaths;
m_fallbackDirs = searchPaths;
invalidateKey();
}
@@ -248,8 +248,8 @@ private:
QIconCacheGtkReader::QIconCacheGtkReader(const QString &dirName)
: m_isValid(false)
{
- QFileInfo info(dirName + QLatin1String("/icon-theme.cache"));
- if (!info.exists() || info.lastModified() < QFileInfo(dirName).lastModified())
+ QFileInfo info(dirName + "/icon-theme.cache"_L1);
+ if (!info.exists() || info.lastModified(QTimeZone::UTC) < QFileInfo(dirName).lastModified(QTimeZone::UTC))
return;
m_file.setFileName(info.absoluteFilePath());
if (!m_file.open(QFile::ReadOnly))
@@ -264,13 +264,13 @@ QIconCacheGtkReader::QIconCacheGtkReader(const QString &dirName)
m_isValid = true;
// Check that all the directories are older than the cache
- auto lastModified = info.lastModified();
+ const QDateTime lastModified = info.lastModified(QTimeZone::UTC);
quint32 dirListOffset = read32(8);
quint32 dirListLen = read32(dirListOffset);
for (uint i = 0; i < dirListLen; ++i) {
quint32 offset = read32(dirListOffset + 4 + 4 * i);
- if (!m_isValid || offset >= m_size || lastModified < QFileInfo(dirName + QLatin1Char('/')
- + QString::fromUtf8(reinterpret_cast<const char*>(m_data + offset))).lastModified()) {
+ if (!m_isValid || offset >= m_size || lastModified < QFileInfo(dirName + u'/'
+ + QString::fromUtf8(reinterpret_cast<const char*>(m_data + offset))).lastModified(QTimeZone::UTC)) {
m_isValid = false;
return;
}
@@ -348,7 +348,7 @@ QIconTheme::QIconTheme(const QString &themeName)
const QStringList iconDirs = QIcon::themeSearchPaths();
for ( int i = 0 ; i < iconDirs.size() ; ++i) {
QDir iconDir(iconDirs[i]);
- QString themeDir = iconDir.path() + QLatin1Char('/') + themeName;
+ QString themeDir = iconDir.path() + u'/' + themeName;
QFileInfo themeDirInfo(themeDir);
if (themeDirInfo.isDir()) {
@@ -357,77 +357,96 @@ QIconTheme::QIconTheme(const QString &themeName)
}
if (!m_valid) {
- themeIndex.setFileName(themeDir + QLatin1String("/index.theme"));
- if (themeIndex.exists())
- m_valid = true;
+ themeIndex.setFileName(themeDir + "/index.theme"_L1);
+ m_valid = themeIndex.exists();
+ qCDebug(lcIconLoader) << "Probing theme file at" << themeIndex.fileName() << m_valid;
}
}
#if QT_CONFIG(settings)
- if (themeIndex.exists()) {
+ if (m_valid) {
const QSettings indexReader(themeIndex.fileName(), QSettings::IniFormat);
const QStringList keys = indexReader.allKeys();
for (const QString &key : keys) {
- if (key.endsWith(QLatin1String("/Size"))) {
+ if (key.endsWith("/Size"_L1)) {
// Note the QSettings ini-format does not accept
// slashes in key names, hence we have to cheat
if (int size = indexReader.value(key).toInt()) {
QString directoryKey = key.left(key.size() - 5);
QIconDirInfo dirInfo(directoryKey);
dirInfo.size = size;
- QString type = indexReader.value(directoryKey +
- QLatin1String("/Type")
- ).toString();
+ QString type = indexReader.value(directoryKey + "/Type"_L1).toString();
- if (type == QLatin1String("Fixed"))
+ if (type == "Fixed"_L1)
dirInfo.type = QIconDirInfo::Fixed;
- else if (type == QLatin1String("Scalable"))
+ else if (type == "Scalable"_L1)
dirInfo.type = QIconDirInfo::Scalable;
else
dirInfo.type = QIconDirInfo::Threshold;
dirInfo.threshold = indexReader.value(directoryKey +
- QLatin1String("/Threshold"),
- 2).toInt();
+ "/Threshold"_L1,
+ 2).toInt();
- dirInfo.minSize = indexReader.value(directoryKey +
- QLatin1String("/MinSize"),
- size).toInt();
+ dirInfo.minSize = indexReader.value(directoryKey + "/MinSize"_L1, size).toInt();
- dirInfo.maxSize = indexReader.value(directoryKey +
- QLatin1String("/MaxSize"),
- size).toInt();
+ dirInfo.maxSize = indexReader.value(directoryKey + "/MaxSize"_L1, size).toInt();
+
+ dirInfo.scale = indexReader.value(directoryKey + "/Scale"_L1, 1).toInt();
+
+ const QString context = indexReader.value(directoryKey + "/Context"_L1).toString();
+ dirInfo.context = [context]() {
+ if (context == "Applications"_L1)
+ return QIconDirInfo::Applications;
+ else if (context == "MimeTypes"_L1)
+ return QIconDirInfo::MimeTypes;
+ else
+ return QIconDirInfo::UnknownContext;
+ }();
- dirInfo.scale = indexReader.value(directoryKey +
- QLatin1String("/Scale"),
- 1).toInt();
m_keyList.append(dirInfo);
}
}
}
// Parent themes provide fallbacks for missing icons
- m_parents = indexReader.value(
- QLatin1String("Icon Theme/Inherits")).toStringList();
+ m_parents = indexReader.value("Icon Theme/Inherits"_L1).toStringList();
m_parents.removeAll(QString());
-
- // Ensure a default platform fallback for all themes
- if (m_parents.isEmpty()) {
- const QString fallback = QIconLoader::instance()->fallbackThemeName();
- if (!fallback.isEmpty())
- m_parents.append(fallback);
- }
-
- // Ensure that all themes fall back to hicolor
- if (!m_parents.contains(QLatin1String("hicolor")))
- m_parents.append(QLatin1String("hicolor"));
}
#endif // settings
}
+QStringList QIconTheme::parents() const
+{
+ // Respect explicitly declared parents
+ QStringList result = m_parents;
+
+ // Ensure a default fallback for all themes
+ const QString fallback = QIconLoader::instance()->fallbackThemeName();
+ if (!fallback.isEmpty())
+ result.append(fallback);
+
+ // Ensure that all themes fall back to hicolor as the last theme
+ result.removeAll("hicolor"_L1);
+ result.append("hicolor"_L1);
+
+ return result;
+}
+
+QDebug operator<<(QDebug debug, const std::unique_ptr<QIconLoaderEngineEntry> &entry)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote() << entry->filename;
+ return debug;
+}
+
QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
const QString &iconName,
- QStringList &visited) const
+ QStringList &visited,
+ DashRule rule) const
{
+ qCDebug(lcIconLoader) << "Finding icon" << iconName << "in theme" << themeName
+ << "skipping" << visited;
+
QThemeIconInfo info;
Q_ASSERT(!themeName.isEmpty());
@@ -437,18 +456,21 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
QIconTheme &theme = themeList[themeName];
if (!theme.isValid()) {
theme = QIconTheme(themeName);
- if (!theme.isValid())
- theme = QIconTheme(fallbackThemeName());
+ if (!theme.isValid()) {
+ qCDebug(lcIconLoader) << "Theme" << themeName << "not found";
+ return info;
+ }
}
const QStringList contentDirs = theme.contentDirs();
QStringView iconNameFallback(iconName);
+ bool searchingGenericFallback = m_iconName.length() > iconName.length();
// Iterate through all icon's fallbacks in current theme
- while (info.entries.isEmpty()) {
- const QString svgIconName = iconNameFallback + QLatin1String(".svg");
- const QString pngIconName = iconNameFallback + QLatin1String(".png");
+ if (info.entries.empty()) {
+ const QString svgIconName = iconNameFallback + ".svg"_L1;
+ const QString pngIconName = iconNameFallback + ".png"_L1;
// Add all relevant files
for (int i = 0; i < contentDirs.size(); ++i) {
@@ -462,7 +484,7 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
if (cache->isValid()) {
const QList<QIconDirInfo> subDirsCopy = subDirs;
subDirs.clear();
- subDirs.reserve(result.count());
+ subDirs.reserve(result.size());
for (const char *s : result) {
QString path = QString::fromUtf8(s);
auto it = std::find_if(subDirsCopy.cbegin(), subDirsCopy.cend(),
@@ -475,94 +497,109 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
}
}
- QString contentDir = contentDirs.at(i) + QLatin1Char('/');
+ QString contentDir = contentDirs.at(i) + u'/';
for (int j = 0; j < subDirs.size() ; ++j) {
const QIconDirInfo &dirInfo = subDirs.at(j);
- const QString subDir = contentDir + dirInfo.path + QLatin1Char('/');
+ if (searchingGenericFallback &&
+ (dirInfo.context == QIconDirInfo::Applications ||
+ dirInfo.context == QIconDirInfo::MimeTypes))
+ continue;
+
+ const QString subDir = contentDir + dirInfo.path + u'/';
const QString pngPath = subDir + pngIconName;
if (QFile::exists(pngPath)) {
- PixmapEntry *iconEntry = new PixmapEntry;
+ auto iconEntry = std::make_unique<PixmapEntry>();
iconEntry->dir = dirInfo;
iconEntry->filename = pngPath;
// Notice we ensure that pixmap entries always come before
// scalable to preserve search order afterwards
- info.entries.prepend(iconEntry);
+ info.entries.insert(info.entries.begin(), std::move(iconEntry));
} else if (m_supportsSvg) {
const QString svgPath = subDir + svgIconName;
if (QFile::exists(svgPath)) {
- ScalableEntry *iconEntry = new ScalableEntry;
+ auto iconEntry = std::make_unique<ScalableEntry>();
iconEntry->dir = dirInfo;
iconEntry->filename = svgPath;
- info.entries.append(iconEntry);
+ info.entries.push_back(std::move(iconEntry));
}
}
}
}
- if (!info.entries.isEmpty()) {
+ if (!info.entries.empty()) {
info.iconName = iconNameFallback.toString();
- break;
}
-
- // If it's possible - find next fallback for the icon
- const int indexOfDash = iconNameFallback.lastIndexOf(QLatin1Char('-'));
- if (indexOfDash == -1)
- break;
-
- iconNameFallback.truncate(indexOfDash);
}
- if (info.entries.isEmpty()) {
+ if (info.entries.empty()) {
const QStringList parents = theme.parents();
+ qCDebug(lcIconLoader) << "Did not find matching icons in theme;"
+ << "trying parent themes" << parents
+ << "skipping visited" << visited;
+
// Search recursively through inherited themes
for (int i = 0 ; i < parents.size() ; ++i) {
const QString parentTheme = parents.at(i).trimmed();
if (!visited.contains(parentTheme)) // guard against recursion
- info = findIconHelper(parentTheme, iconName, visited);
+ info = findIconHelper(parentTheme, iconName, visited, QIconLoader::NoFallBack);
- if (!info.entries.isEmpty()) // success
+ if (!info.entries.empty()) // success
break;
}
}
+
+ if (rule == QIconLoader::FallBack && info.entries.empty()) {
+ // If it's possible - find next fallback for the icon
+ const int indexOfDash = iconNameFallback.lastIndexOf(u'-');
+ if (indexOfDash != -1) {
+ qCDebug(lcIconLoader) << "Did not find matching icons in all themes;"
+ << "trying dash fallback";
+ iconNameFallback.truncate(indexOfDash);
+ QStringList _visited;
+ info = findIconHelper(themeName, iconNameFallback.toString(), _visited, QIconLoader::FallBack);
+ }
+ }
+
return info;
}
QThemeIconInfo QIconLoader::lookupFallbackIcon(const QString &iconName) const
{
+ qCDebug(lcIconLoader) << "Looking up fallback icon" << iconName;
+
QThemeIconInfo info;
- const QString pngIconName = iconName + QLatin1String(".png");
- const QString xpmIconName = iconName + QLatin1String(".xpm");
- const QString svgIconName = iconName + QLatin1String(".svg");
+ const QString pngIconName = iconName + ".png"_L1;
+ const QString xpmIconName = iconName + ".xpm"_L1;
+ const QString svgIconName = iconName + ".svg"_L1;
const auto searchPaths = QIcon::fallbackSearchPaths();
for (const QString &iconDir: searchPaths) {
QDir currentDir(iconDir);
+ std::unique_ptr<QIconLoaderEngineEntry> iconEntry;
if (currentDir.exists(pngIconName)) {
- PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry = std::make_unique<PixmapEntry>();
iconEntry->dir.type = QIconDirInfo::Fallback;
iconEntry->filename = currentDir.filePath(pngIconName);
- info.entries.append(iconEntry);
- break;
} else if (currentDir.exists(xpmIconName)) {
- PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry = std::make_unique<PixmapEntry>();
iconEntry->dir.type = QIconDirInfo::Fallback;
iconEntry->filename = currentDir.filePath(xpmIconName);
- info.entries.append(iconEntry);
- break;
} else if (m_supportsSvg &&
currentDir.exists(svgIconName)) {
- ScalableEntry *iconEntry = new ScalableEntry;
+ iconEntry = std::make_unique<ScalableEntry>();
iconEntry->dir.type = QIconDirInfo::Fallback;
iconEntry->filename = currentDir.filePath(svgIconName);
- info.entries.append(iconEntry);
+ }
+ if (iconEntry) {
+ info.entries.push_back(std::move(iconEntry));
break;
}
}
- if (!info.entries.isEmpty())
+ if (!info.entries.empty())
info.iconName = iconName;
return info;
@@ -570,72 +607,162 @@ QThemeIconInfo QIconLoader::lookupFallbackIcon(const QString &iconName) const
QThemeIconInfo QIconLoader::loadIcon(const QString &name) const
{
- if (!themeName().isEmpty()) {
- QStringList visited;
- const QThemeIconInfo iconInfo = findIconHelper(themeName(), name, visited);
- if (!iconInfo.entries.isEmpty())
- return iconInfo;
+ qCDebug(lcIconLoader) << "Loading icon" << name;
+
+ m_iconName = name;
+ QThemeIconInfo iconInfo;
+ QStringList visitedThemes;
+ if (!themeName().isEmpty())
+ iconInfo = findIconHelper(themeName(), name, visitedThemes, QIconLoader::FallBack);
+
+ if (iconInfo.entries.empty() && !fallbackThemeName().isEmpty())
+ iconInfo = findIconHelper(fallbackThemeName(), name, visitedThemes, QIconLoader::FallBack);
+
+ if (iconInfo.entries.empty())
+ iconInfo = lookupFallbackIcon(name);
+
+ qCDebug(lcIconLoader) << "Resulting icon entries" << iconInfo.entries;
+ return iconInfo;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, QIconEngine *engine)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ if (engine) {
+ debug.noquote() << engine->key() << "(";
+ debug << static_cast<const void *>(engine);
+ if (!engine->isNull())
+ debug.quote() << ", " << engine->iconName();
+ else
+ debug << ", null";
+ debug << ")";
+ } else {
+ debug << "QIconEngine(nullptr)";
+ }
+ return debug;
+}
+#endif
- return lookupFallbackIcon(name);
+QIconEngine *QIconLoader::iconEngine(const QString &iconName) const
+{
+ qCDebug(lcIconLoader) << "Resolving icon engine for icon" << iconName;
+
+ std::unique_ptr<QIconEngine> iconEngine;
+ if (hasUserTheme())
+ iconEngine.reset(new QIconLoaderEngine(iconName));
+ if (!iconEngine || iconEngine->isNull()) {
+ qCDebug(lcIconLoader) << "Icon is not available from theme or fallback theme.";
+ if (auto *platformTheme = QGuiApplicationPrivate::platformTheme()) {
+ qCDebug(lcIconLoader) << "Trying platform engine.";
+ std::unique_ptr<QIconEngine> themeEngine(platformTheme->createIconEngine(iconName));
+ if (themeEngine && !themeEngine->isNull()) {
+ iconEngine = std::move(themeEngine);
+ qCDebug(lcIconLoader) << "Icon provided by platform engine.";
+ }
+ }
}
+ // We need to maintain the invariant that the QIcon has a valid engine
+ if (!iconEngine)
+ iconEngine.reset(new QIconLoaderEngine(iconName));
- return QThemeIconInfo();
+ qCDebug(lcIconLoader) << "Resulting engine" << iconEngine.get();
+ return iconEngine.release();
}
+/*!
+ \internal
+ \class QThemeIconEngine
+ \inmodule QtGui
-// -------- Icon Loader Engine -------- //
+ \brief A named-based icon engine for providing theme icons.
+ The engine supports invalidation of prior lookups, e.g. when
+ the platform theme changes or the user sets an explicit icon
+ theme.
-QIconLoaderEngine::QIconLoaderEngine(const QString& iconName)
- : m_iconName(iconName), m_key(0)
+ The actual icon lookup is handed over to an engine provided
+ by QIconLoader::iconEngine().
+*/
+
+QThemeIconEngine::QThemeIconEngine(const QString& iconName)
+ : QProxyIconEngine()
+ , m_iconName(iconName)
{
}
-QIconLoaderEngine::~QIconLoaderEngine()
+QThemeIconEngine::QThemeIconEngine(const QThemeIconEngine &other)
+ : QProxyIconEngine()
+ , m_iconName(other.m_iconName)
{
- qDeleteAll(m_info.entries);
}
-QIconLoaderEngine::QIconLoaderEngine(const QIconLoaderEngine &other)
- : QIconEngine(other),
- m_iconName(other.m_iconName),
- m_key(0)
+QString QThemeIconEngine::key() const
{
+ // Although we proxy the underlying engine, that's an implementation
+ // detail, so from the point of view of QIcon, and in terms of
+ // serialization, we are the one and only theme icon engine.
+ return u"QThemeIconEngine"_s;
}
-QIconEngine *QIconLoaderEngine::clone() const
+QIconEngine *QThemeIconEngine::clone() const
{
- return new QIconLoaderEngine(*this);
+ return new QThemeIconEngine(*this);
}
-bool QIconLoaderEngine::read(QDataStream &in) {
+bool QThemeIconEngine::read(QDataStream &in) {
in >> m_iconName;
return true;
}
-bool QIconLoaderEngine::write(QDataStream &out) const
+bool QThemeIconEngine::write(QDataStream &out) const
{
out << m_iconName;
return true;
}
-bool QIconLoaderEngine::hasIcon() const
+QIconEngine *QThemeIconEngine::proxiedEngine() const
{
- return !(m_info.entries.isEmpty());
+ const auto *iconLoader = QIconLoader::instance();
+ auto mostRecentThemeKey = iconLoader->themeKey();
+ if (mostRecentThemeKey != m_themeKey) {
+ qCDebug(lcIconLoader) << "Theme key" << mostRecentThemeKey << "is different"
+ << "than cached key" << m_themeKey << "for icon" << m_iconName;
+ m_proxiedEngine.reset(iconLoader->iconEngine(m_iconName));
+ m_themeKey = mostRecentThemeKey;
+ }
+ return m_proxiedEngine.get();
}
-// Lazily load the icon
-void QIconLoaderEngine::ensureLoaded()
+/*!
+ \internal
+ \class QIconLoaderEngine
+ \inmodule QtGui
+
+ \brief An icon engine based on icon entries collected by QIconLoader.
+
+ The design and implementation of QIconLoader is based on
+ the XDG icon specification.
+*/
+
+QIconLoaderEngine::QIconLoaderEngine(const QString& iconName)
+ : m_iconName(iconName)
+ , m_info(QIconLoader::instance()->loadIcon(m_iconName))
{
- if (!(QIconLoader::instance()->themeKey() == m_key)) {
- qDeleteAll(m_info.entries);
- m_info.entries.clear();
- m_info.iconName.clear();
+}
- Q_ASSERT(m_info.entries.size() == 0);
- m_info = QIconLoader::instance()->loadIcon(m_iconName);
- m_key = QIconLoader::instance()->themeKey();
- }
+QIconLoaderEngine::~QIconLoaderEngine() = default;
+
+QIconEngine *QIconLoaderEngine::clone() const
+{
+ Q_UNREACHABLE();
+ return nullptr; // Cannot be cloned
+}
+
+bool QIconLoaderEngine::hasIcon() const
+{
+ return !(m_info.entries.empty());
}
void QIconLoaderEngine::paint(QPainter *painter, const QRect &rect,
@@ -711,25 +838,21 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QThemeIconInfo &in
// Note that m_info.entries are sorted so that png-files
// come first
- const int numEntries = info.entries.size();
-
// Search for exact matches first
- for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = info.entries.at(i);
+ for (const auto &entry : info.entries) {
if (directoryMatchesSize(entry->dir, iconsize, scale)) {
- return entry;
+ return entry.get();
}
}
// Find the minimum distance icon
int minimalSize = INT_MAX;
QIconLoaderEngineEntry *closestMatch = nullptr;
- for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = info.entries.at(i);
+ for (const auto &entry : info.entries) {
int distance = directorySizeDistance(entry->dir, iconsize, scale);
if (distance < minimalSize) {
minimalSize = distance;
- closestMatch = entry;
+ closestMatch = entry.get();
}
}
return closestMatch;
@@ -747,8 +870,6 @@ QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,
Q_UNUSED(mode);
Q_UNUSED(state);
- ensureLoaded();
-
QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry) {
const QIconDirInfo &dir = entry->dir;
@@ -757,7 +878,7 @@ QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,
} else if (dir.type == QIconDirInfo::Fallback) {
return QIcon(entry->filename).actualSize(size, mode, state);
} else {
- int result = qMin<int>(dir.size, qMin(size.width(), size.height()));
+ int result = qMin<int>(dir.size * dir.scale, qMin(size.width(), size.height()));
return QSize(result, result);
}
}
@@ -779,7 +900,7 @@ QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State st
if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
actualSize.scale(size, Qt::KeepAspectRatio);
- QString key = QLatin1String("$qt_theme_")
+ QString key = "$qt_theme_"_L1
% HexString<qint64>(basePixmap.cacheKey())
% HexString<int>(mode)
% HexString<qint64>(QGuiApplication::palette().cacheKey())
@@ -817,8 +938,6 @@ QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State
QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode,
QIcon::State state)
{
- ensureLoaded();
-
QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry)
return entry->pixmap(size, mode, state);
@@ -828,24 +947,21 @@ QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode,
QString QIconLoaderEngine::key() const
{
- return QLatin1String("QIconLoaderEngine");
+ return u"QIconLoaderEngine"_s;
}
QString QIconLoaderEngine::iconName()
{
- ensureLoaded();
return m_info.iconName;
}
bool QIconLoaderEngine::isNull()
{
- ensureLoaded();
- return m_info.entries.isEmpty();
+ return m_info.entries.empty();
}
QPixmap QIconLoaderEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
{
- ensureLoaded();
const int integerScale = qCeil(scale);
QIconLoaderEngineEntry *entry = entryForSize(m_info, size / integerScale, integerScale);
return entry ? entry->pixmap(size, mode, state) : QPixmap();
@@ -855,14 +971,13 @@ QList<QSize> QIconLoaderEngine::availableSizes(QIcon::Mode mode, QIcon::State st
{
Q_UNUSED(mode);
Q_UNUSED(state);
- ensureLoaded();
- const int N = m_info.entries.size();
+
+ const qsizetype N = qsizetype(m_info.entries.size());
QList<QSize> sizes;
sizes.reserve(N);
// Gets all sizes from the DirectoryInfo entries
- for (int i = 0; i < N; ++i) {
- const QIconLoaderEngineEntry *entry = m_info.entries.at(i);
+ for (const auto &entry : m_info.entries) {
if (entry->dir.type == QIconDirInfo::Fallback) {
sizes.append(QIcon(entry->filename).availableSizes());
} else {
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
index d02b2da2cc..3cfa9381d1 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICONLOADER_P_H
#define QICONLOADER_P_H
@@ -58,11 +22,15 @@
#include <QtGui/QIconEngine>
#include <QtGui/QPixmapCache>
#include <private/qicon_p.h>
+#include <private/qiconengine_p.h>
#include <private/qfactoryloader_p.h>
#include <QtCore/QHash>
#include <QtCore/QList>
#include <QtCore/QTypeInfo>
+#include <vector>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QIconLoader;
@@ -70,6 +38,7 @@ class QIconLoader;
struct QIconDirInfo
{
enum Type { Fixed, Scalable, Threshold, Fallback };
+ enum Context { UnknownContext, Applications, MimeTypes };
QIconDirInfo(const QString &_path = QString()) :
path(_path),
size(0),
@@ -77,7 +46,8 @@ struct QIconDirInfo
minSize(0),
threshold(0),
scale(1),
- type(Threshold) {}
+ type(Threshold),
+ context(UnknownContext) {}
QString path;
short size;
short maxSize;
@@ -85,6 +55,7 @@ struct QIconDirInfo
short threshold;
short scale;
Type type;
+ Context context;
};
Q_DECLARE_TYPEINFO(QIconDirInfo, Q_RELOCATABLE_TYPE);
@@ -111,7 +82,7 @@ struct PixmapEntry : public QIconLoaderEngineEntry
QPixmap basePixmap;
};
-typedef QList<QIconLoaderEngineEntry*> QThemeIconEntries;
+using QThemeIconEntries = std::vector<std::unique_ptr<QIconLoaderEngineEntry>>;
struct QThemeIconInfo
{
@@ -119,6 +90,27 @@ struct QThemeIconInfo
QString iconName;
};
+class QThemeIconEngine : public QProxyIconEngine
+{
+public:
+ QThemeIconEngine(const QString& iconName = QString());
+ QIconEngine *clone() const override;
+ bool read(QDataStream &in) override;
+ bool write(QDataStream &out) const override;
+
+protected:
+ QIconEngine *proxiedEngine() const override;
+
+private:
+ QThemeIconEngine(const QThemeIconEngine &other);
+ QString key() const override;
+
+ QString m_iconName;
+ mutable uint m_themeKey = 0;
+
+ mutable std::unique_ptr<QIconEngine> m_proxiedEngine;
+};
+
class QIconLoaderEngine : public QIconEngine
{
public:
@@ -129,8 +121,6 @@ public:
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
QIconEngine *clone() const override;
- bool read(QDataStream &in) override;
- bool write(QDataStream &out) const override;
QString iconName() override;
bool isNull() override;
@@ -140,14 +130,13 @@ public:
Q_GUI_EXPORT static QIconLoaderEngineEntry *entryForSize(const QThemeIconInfo &info, const QSize &size, int scale = 1);
private:
+ Q_DISABLE_COPY(QIconLoaderEngine)
+
QString key() const override;
bool hasIcon() const;
- void ensureLoaded();
- QIconLoaderEngine(const QIconLoaderEngine &other);
- QThemeIconInfo m_info;
QString m_iconName;
- uint m_key;
+ QThemeIconInfo m_info;
friend class QIconLoader;
};
@@ -159,7 +148,7 @@ class QIconTheme
public:
QIconTheme(const QString &name);
QIconTheme() : m_valid(false) {}
- QStringList parents() { return m_parents; }
+ QStringList parents() const;
QList<QIconDirInfo> keyList() { return m_keyList; }
QStringList contentDirs() { return m_contentDirs; }
bool isValid() { return m_valid; }
@@ -179,7 +168,7 @@ public:
QThemeIconInfo loadIcon(const QString &iconName) const;
uint themeKey() const { return m_themeKey; }
- QString themeName() const { return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme; }
+ QString themeName() const;
void setThemeName(const QString &themeName);
QString fallbackThemeName() const;
void setFallbackThemeName(const QString &themeName);
@@ -191,14 +180,18 @@ public:
QIconDirInfo dirInfo(int dirindex);
static QIconLoader *instance();
void updateSystemTheme();
- void invalidateKey() { m_themeKey++; }
+ void invalidateKey();
void ensureInitialized();
bool hasUserTheme() const { return !m_userTheme.isEmpty(); }
+ QIconEngine *iconEngine(const QString &iconName) const;
+
private:
+ enum DashRule { FallBack, NoFallBack };
QThemeIconInfo findIconHelper(const QString &themeName,
const QString &iconName,
- QStringList &visited) const;
+ QStringList &visited,
+ DashRule rule) const;
QThemeIconInfo lookupFallbackIcon(const QString &iconName) const;
uint m_themeKey;
@@ -211,6 +204,7 @@ private:
mutable QStringList m_iconDirs;
mutable QHash <QString, QIconTheme> themeList;
mutable QStringList m_fallbackDirs;
+ mutable QString m_iconName;
};
QT_END_NAMESPACE
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 9875881623..3bbf21320e 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qimage.h"
@@ -57,6 +21,7 @@
#include <stdlib.h>
#include <limits.h>
#include <qpa/qplatformpixmap.h>
+#include <private/qcolorspace_p.h>
#include <private/qcolortransform_p.h>
#include <private/qmemrotate_p.h>
#include <private/qimagescale_p.h>
@@ -71,24 +36,25 @@
#include <private/qfont_p.h>
#if QT_CONFIG(thread)
-#include "qsemaphore.h"
-#include "qthreadpool.h"
+#include <qsemaphore.h>
+#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
#include <qtgui_tracepoints_p.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
+class QCmyk32;
+
+using namespace Qt::StringLiterals;
// MSVC 19.28 does show spurious warning "C4723: potential divide by 0" for code that divides
// by height() in release builds. Anyhow, all the code paths in this file are only executed
// for valid QImage's, where height() cannot be 0. Therefore disable the warning.
QT_WARNING_DISABLE_MSVC(4723)
-static inline bool isLocked(QImageData *data)
-{
- return data != nullptr && data->is_locked;
-}
-
#if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001)
#pragma message disable narrowptr
#endif
@@ -100,6 +66,17 @@ static inline bool isLocked(QImageData *data)
return QImage(); \
}
+Q_TRACE_PREFIX(qtgui,
+ "#include <qimagereader.h>"
+);
+
+Q_TRACE_METADATA(qtgui,
+"ENUM { } QImage::Format;" \
+"FLAGS { } Qt::ImageConversionFlags;"
+);
+
+Q_TRACE_PARAM_REPLACE(Qt::AspectRatioMode, int);
+Q_TRACE_PARAM_REPLACE(Qt::TransformationMode, int);
static QImage rotated90(const QImage &src);
static QImage rotated180(const QImage &src);
@@ -107,7 +84,7 @@ static QImage rotated270(const QImage &src);
static int next_qimage_serial_number()
{
- static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
return 1 + serial.fetchAndAddRelaxed(1);
}
@@ -119,7 +96,7 @@ QImageData::QImageData()
dpmx(qt_defaultDpiX() * 100 / qreal(2.54)),
dpmy(qt_defaultDpiY() * 100 / qreal(2.54)),
offset(0, 0), own_data(true), ro_data(false), has_alpha_clut(false),
- is_cached(false), is_locked(false), cleanupFunction(nullptr), cleanupInfo(nullptr),
+ is_cached(false), cleanupFunction(nullptr), cleanupInfo(nullptr),
paintEngine(nullptr)
{
}
@@ -131,7 +108,7 @@ QImageData::QImageData()
Creates a new image data.
Returns \nullptr if invalid parameters are give or anything else failed.
*/
-QImageData * QImageData::create(const QSize &size, QImage::Format format)
+QImageData * Q_TRACE_INSTRUMENT(qtgui) QImageData::create(const QSize &size, QImage::Format format)
{
if (size.isEmpty() || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
return nullptr; // invalid parameter(s)
@@ -145,7 +122,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format)
if (!params.isValid())
return nullptr;
- QScopedPointer<QImageData> d(new QImageData);
+ auto d = std::make_unique<QImageData>();
switch (format) {
case QImage::Format_Mono:
@@ -173,7 +150,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format)
return nullptr;
d->ref.ref();
- return d.take();
+ return d.release();
}
QImageData::~QImageData()
@@ -329,6 +306,7 @@ bool QImageData::checkForAlphaPixels() const
case QImage::Format_RGBX64:
case QImage::Format_RGBX16FPx4:
case QImage::Format_RGBX32FPx4:
+ case QImage::Format_CMYK8888:
break;
case QImage::Format_Invalid:
case QImage::NImageFormats:
@@ -385,7 +363,7 @@ bool QImageData::checkForAlphaPixels() const
refer to the \l{How to Create Qt Plugins}{Plugin HowTo}.
\warning Painting on a QImage with the format
- QImage::Format_Indexed8 is not supported.
+ QImage::Format_Indexed8 or QImage::Format_CMYK8888 is not supported.
\tableofcontents
@@ -453,7 +431,7 @@ bool QImageData::checkForAlphaPixels() const
The color of a pixel can be retrieved by passing its coordinates
to the pixel() function. The pixel() function returns the color
- as a QRgb value indepedent of the image's format.
+ as a QRgb value independent of the image's format.
In case of monochrome and 8-bit images, the colorCount() and
colorTable() functions provide information about the color
@@ -641,8 +619,8 @@ bool QImageData::checkForAlphaPixels() const
\endtable
- \sa QImageReader, QImageWriter, QPixmap, QSvgRenderer, {Image Composition Example},
- {Image Viewer Example}, {Scribble Example}, {Pixelator Example}
+ \sa QImageReader, QImageWriter, QPixmap, QSvgRenderer,
+ {Image Composition Example}, {Scribble Example}
*/
/*!
@@ -735,40 +713,62 @@ bool QImageData::checkForAlphaPixels() const
The unused bits are always zero.
\value Format_ARGB4444_Premultiplied The image is stored using a
premultiplied 16-bit ARGB format (4-4-4-4).
- \value Format_RGBX8888 The image is stored using a 32-bit byte-ordered RGB(x) format (8-8-8-8).
- This is the same as the Format_RGBA8888 except alpha must always be 255. (added in Qt 5.2)
- \value Format_RGBA8888 The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8).
+ \value [since 5.2]
+ Format_RGBX8888 The image is stored using a 32-bit byte-ordered RGB(x) format (8-8-8-8).
+ This is the same as the Format_RGBA8888 except alpha must always be 255.
+ \value [since 5.2]
+ Format_RGBA8888 The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8).
Unlike ARGB32 this is a byte-ordered format, which means the 32bit
encoding differs between big endian and little endian architectures,
being respectively (0xRRGGBBAA) and (0xAABBGGRR). The order of the colors
- is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA. (added in Qt 5.2)
- \value Format_RGBA8888_Premultiplied The image is stored using a
- premultiplied 32-bit byte-ordered RGBA format (8-8-8-8). (added in Qt 5.2)
- \value Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10). (added in Qt 5.4)
- \value Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10). (added in Qt 5.4)
- \value Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10). (added in Qt 5.4)
- \value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10). (added in Qt 5.4)
- \value Format_Alpha8 The image is stored using an 8-bit alpha only format. (added in Qt 5.5)
- \value Format_Grayscale8 The image is stored using an 8-bit grayscale format. (added in Qt 5.5)
- \value Format_Grayscale16 The image is stored using an 16-bit grayscale format. (added in Qt 5.13)
- \value Format_RGBX64 The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16).
- This is the same as the Format_RGBA64 except alpha must always be 65535. (added in Qt 5.12)
- \value Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16). (added in Qt 5.12)
- \value Format_RGBA64_Premultiplied The image is stored using a premultiplied 64-bit halfword-ordered
- RGBA format (16-16-16-16). (added in Qt 5.12)
- \value Format_BGR888 The image is stored using a 24-bit BGR format. (added in Qt 5.14)
- \value Format_RGBX16FPx4 The image is stored using a 4 16-bit halfword floating point RGBx format (16FP-16FP-16FP-16FP).
- This is the same as the Format_RGBA16FPx4 except alpha must always be 1.0. (added in Qt 6.2)
- \value Format_RGBA16FPx4 The image is stored using a 4 16-bit halfword floating point RGBA format (16FP-16FP-16FP-16FP). (added in Qt 6.2)
- \value Format_RGBA16FPx4_Premultiplied The image is stored using a premultiplied 4 16-bit halfword floating point
- RGBA format (16FP-16FP-16FP-16FP). (added in Qt 6.2)
- \value Format_RGBX32FPx4 The image is stored using a 4 32-bit floating point RGBx format (32FP-32FP-32FP-32FP).
- This is the same as the Format_RGBA32FPx4 except alpha must always be 1.0. (added in Qt 6.2)
- \value Format_RGBA32FPx4 The image is stored using a 4 32-bit floating point RGBA format (32FP-32FP-32FP-32FP). (added in Qt 6.2)
- \value Format_RGBA32FPx4_Premultiplied The image is stored using a premultiplied 4 32-bit floating point
- RGBA format (32FP-32FP-32FP-32FP). (added in Qt 6.2)
-
- \note Drawing into a QImage with QImage::Format_Indexed8 is not
+ is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA.
+ \value [since 5.2]
+ Format_RGBA8888_Premultiplied The image is stored using a
+ premultiplied 32-bit byte-ordered RGBA format (8-8-8-8).
+ \value [since 5.4]
+ Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10).
+ \value [since 5.4]
+ Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10).
+ \value [since 5.4]
+ Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10).
+ \value [since 5.4]
+ Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10).
+ \value [since 5.5]
+ Format_Alpha8 The image is stored using an 8-bit alpha only format.
+ \value [since 5.5]
+ Format_Grayscale8 The image is stored using an 8-bit grayscale format.
+ \value [since 5.13]
+ Format_Grayscale16 The image is stored using an 16-bit grayscale format.
+ \value [since 5.12]
+ Format_RGBX64 The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16).
+ This is the same as the Format_RGBA64 except alpha must always be 65535.
+ \value [since 5.12]
+ Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16).
+ \value [since 5.12]
+ Format_RGBA64_Premultiplied The image is stored using a premultiplied 64-bit halfword-ordered
+ RGBA format (16-16-16-16).
+ \value [since 5.14]
+ Format_BGR888 The image is stored using a 24-bit BGR format.
+ \value [since 6.2]
+ Format_RGBX16FPx4 The image is stored using a four 16-bit halfword floating point RGBx format (16FP-16FP-16FP-16FP).
+ This is the same as the Format_RGBA16FPx4 except alpha must always be 1.0.
+ \value [since 6.2]
+ Format_RGBA16FPx4 The image is stored using a four 16-bit halfword floating point RGBA format (16FP-16FP-16FP-16FP).
+ \value [since 6.2]
+ Format_RGBA16FPx4_Premultiplied The image is stored using a premultiplied four 16-bit halfword floating point
+ RGBA format (16FP-16FP-16FP-16FP).
+ \value [since 6.2]
+ Format_RGBX32FPx4 The image is stored using a four 32-bit floating point RGBx format (32FP-32FP-32FP-32FP).
+ This is the same as the Format_RGBA32FPx4 except alpha must always be 1.0.
+ \value [since 6.2]
+ Format_RGBA32FPx4 The image is stored using a four 32-bit floating point RGBA format (32FP-32FP-32FP-32FP).
+ \value [since 6.2]
+ Format_RGBA32FPx4_Premultiplied The image is stored using a premultiplied four 32-bit floating point
+ RGBA format (32FP-32FP-32FP-32FP).
+ \value [since 6.8]
+ Format_CMYK8888 The image is stored using a 32-bit byte-ordered CMYK format.
+
+ \note Drawing into a QImage with format QImage::Format_Indexed8 or QImage::Format_CMYK8888 is not
supported.
\note Avoid most rendering directly to most of these formats using QPainter. Rendering
@@ -844,7 +844,7 @@ QImageData *QImageData::create(uchar *data, int width, int height, qsizetype bp
// recalculate the total with this value
params.bytesPerLine = bpl;
- if (mul_overflow<qsizetype>(bpl, height, &params.totalSize))
+ if (qMulOverflow<qsizetype>(bpl, height, &params.totalSize))
return nullptr;
}
@@ -1030,7 +1030,7 @@ QImage::QImage(const char * const xpm[])
if (!xpm)
return;
if (!qt_read_xpm_image_or_array(nullptr, xpm, *this))
- // Issue: Warning because the constructor may be ambigious
+ // Issue: Warning because the constructor may be ambiguous
qWarning("QImage::QImage(), XPM is not supported");
}
#endif // QT_NO_IMAGEFORMAT_XPM
@@ -1047,7 +1047,7 @@ QImage::QImage(const char * const xpm[])
QImage::QImage(const QImage &image)
: QPaintDevice()
{
- if (image.paintingActive() || isLocked(image.d)) {
+ if (image.paintingActive()) {
d = nullptr;
image.copy().swap(*this);
} else {
@@ -1079,7 +1079,7 @@ QImage::~QImage()
QImage &QImage::operator=(const QImage &image)
{
- if (image.paintingActive() || isLocked(image.d)) {
+ if (image.paintingActive()) {
operator=(image.copy());
} else {
if (image.d)
@@ -1141,6 +1141,28 @@ void QImage::detach()
}
+/*!
+ \internal
+
+ A variant for metadata-only detach, which will not detach readonly image data,
+ and only invalidate caches of the image data if asked to.
+
+ \sa detach(), isDetached()
+*/
+void QImage::detachMetadata(bool invalidateCache)
+{
+ if (d) {
+ if (d->is_cached && d->ref.loadRelaxed() == 1)
+ QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
+
+ if (d->ref.loadRelaxed() != 1)
+ *this = copy();
+
+ if (d && invalidateCache)
+ ++d->detach_no;
+ }
+}
+
static void copyPhysicalMetadata(QImageData *dst, const QImageData *src)
{
dst->dpmx = src->dpmx;
@@ -1150,9 +1172,10 @@ static void copyPhysicalMetadata(QImageData *dst, const QImageData *src)
static void copyMetadata(QImageData *dst, const QImageData *src)
{
- // Doesn't copy colortable and alpha_clut, or offset.
+ // Doesn't copy colortable and alpha_clut.
copyPhysicalMetadata(dst, src);
dst->text = src->text;
+ dst->offset = src->offset;
dst->colorSpace = src->colorSpace;
}
@@ -1197,7 +1220,7 @@ static void copyMetadata(QImage *dst, const QImage &src)
\sa QImage()
*/
-QImage QImage::copy(const QRect& r) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::copy(const QRect& r) const
{
Q_TRACE_SCOPE(QImage_copy, r);
if (!d)
@@ -1217,7 +1240,6 @@ QImage QImage::copy(const QRect& r) const
} else
memcpy(image.bits(), bits(), d->nbytes);
image.d->colortable = d->colortable;
- image.d->offset = d->offset;
image.d->has_alpha_clut = d->has_alpha_clut;
copyMetadata(image.d, d);
return image;
@@ -1306,7 +1328,6 @@ QImage QImage::copy(const QRect& r) const
}
copyMetadata(image.d, d);
- image.d->offset = offset();
image.d->has_alpha_clut = d->has_alpha_clut;
return image;
}
@@ -1422,7 +1443,7 @@ void QImage::setColorTable(const QList<QRgb> &colors)
{
if (!d)
return;
- detach();
+ detachMetadata(true);
// In case detach() ran out of memory
if (!d)
@@ -1496,18 +1517,20 @@ void QImage::setDevicePixelRatio(qreal scaleFactor)
if (scaleFactor == d->devicePixelRatio)
return;
- detach();
+ detachMetadata();
if (d)
d->devicePixelRatio = scaleFactor;
}
/*!
- Returns the size of the pixmap in device independent pixels.
+ Returns the size of the image in device independent pixels.
- This value should be used when using the pixmap size in user interface
+ This value should be used when using the image size in user interface
size calculations.
- The return value is equivalent to pixmap.size() / pixmap.devicePixelRatio(),
+ The return value is equivalent to image.size() / image.devicePixelRatio().
+
+ \since 6.2
*/
QSizeF QImage::deviceIndependentSize() const
{
@@ -1579,7 +1602,7 @@ void QImage::setColor(int i, QRgb c)
qWarning("QImage::setColor: Index out of bound %d", i);
return;
}
- detach();
+ detachMetadata(true);
// In case detach() run out of memory
if (!d)
@@ -1914,6 +1937,31 @@ void QImage::fill(const QColor &color)
qt_rectfill<quint64>(reinterpret_cast<quint64 *>(d->data), color.rgba64().premultiplied(),
0, 0, d->width, d->height, d->bytes_per_line);
break;
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:{
+ float r, g, b, a;
+ color.getRgbF(&r, &g, &b, &a);
+ if (!hasAlphaChannel())
+ a = 1.0f;
+ if (depth() == 64) {
+ QRgbaFloat16 c16{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
+ if (d->format == Format_RGBA16FPx4_Premultiplied)
+ c16 = c16.premultiplied();
+ qt_rectfill<QRgbaFloat16>(reinterpret_cast<QRgbaFloat16 *>(d->data), c16,
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ } else {
+ QRgbaFloat32 c32{r, g, b, a};
+ if (d->format == Format_RGBA32FPx4_Premultiplied)
+ c32 = c32.premultiplied();
+ qt_rectfill<QRgbaFloat32>(reinterpret_cast<QRgbaFloat32 *>(d->data), c32,
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ }
+ break;
+ }
default: {
QPainter p(this);
p.setCompositionMode(QPainter::CompositionMode_Source);
@@ -1986,11 +2034,11 @@ void QImage::invertPixels(InvertMode mode)
qfloat16 *p = reinterpret_cast<qfloat16 *>(d->data);
qfloat16 *end = reinterpret_cast<qfloat16 *>(d->data + d->nbytes);
while (p < end) {
- p[0] = 1.0f - p[0];
- p[1] = 1.0f - p[1];
- p[2] = 1.0f - p[2];
+ p[0] = qfloat16(1) - p[0];
+ p[1] = qfloat16(1) - p[1];
+ p[2] = qfloat16(1) - p[2];
if (mode == InvertRgba)
- p[3] = 1.0f - p[3];
+ p[3] = qfloat16(1) - p[3];
p += 4;
}
} else if (format() >= QImage::Format_RGBX32FPx4 && format() <= QImage::Format_RGBA32FPx4_Premultiplied) {
@@ -2096,7 +2144,7 @@ void QImage::setColorCount(int colorCount)
return;
}
- detach();
+ detachMetadata(true);
// In case detach() ran out of memory
if (!d)
@@ -2179,7 +2227,6 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
QIMAGE_SANITYCHECK_MEMORY(image);
- image.d->offset = offset();
copyMetadata(image.d, d);
converter(image.d, d, flags);
@@ -2236,7 +2283,7 @@ static QImage convertWithPalette(const QImage &src, QImage::Format format,
QImage dest(src.size(), format);
dest.setColorTable(clut);
- QImageData::get(dest)->text = QImageData::get(src)->text;
+ copyMetadata(QImageData::get(dest), QImageData::get(src));
int h = src.height();
int w = src.width();
@@ -2337,6 +2384,7 @@ bool QImage::reinterpretAsFormat(Format format)
// In case detach() ran out of memory
if (!d) {
d = oldD;
+ d->ref.ref();
return false;
}
}
@@ -2608,6 +2656,9 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
case Format_A2RGB30_Premultiplied:
((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderRGB>(index_or_rgb);
return;
+ case Format_RGBX64:
+ ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb | 0xff000000);
+ return;
case Format_RGBA64:
case Format_RGBA64_Premultiplied:
((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb);
@@ -2792,7 +2843,7 @@ void QImage::setPixelColor(int x, int y, const QColor &color)
color.getRgbF(&r, &g, &b, &a);
if (d->format == Format_RGBX16FPx4)
a = 1.0f;
- QRgbaFloat16 c16f{r, g, b, a};
+ QRgbaFloat16 c16f{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
if (d->format == Format_RGBA16FPx4_Premultiplied)
c16f = c16f.premultiplied();
((QRgbaFloat16 *)s)[x] = c16f;
@@ -2967,7 +3018,7 @@ bool QImage::isGrayscale() const
\sa isNull(), {QImage#Image Transformations}{Image
Transformations}
*/
-QImage QImage::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode) const
{
if (!d) {
qWarning("QImage::scaled: Image is a null image");
@@ -3004,7 +3055,7 @@ QImage QImage::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::Transf
\sa {QImage#Image Transformations}{Image Transformations}
*/
-QImage QImage::scaledToWidth(int w, Qt::TransformationMode mode) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToWidth(int w, Qt::TransformationMode mode) const
{
if (!d) {
qWarning("QImage::scaleWidth: Image is a null image");
@@ -3034,7 +3085,7 @@ QImage QImage::scaledToWidth(int w, Qt::TransformationMode mode) const
\sa {QImage#Image Transformations}{Image Transformations}
*/
-QImage QImage::scaledToHeight(int h, Qt::TransformationMode mode) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToHeight(int h, Qt::TransformationMode mode) const
{
if (!d) {
qWarning("QImage::scaleHeight: Image is a null image");
@@ -3067,7 +3118,7 @@ QImage QImage::scaledToHeight(int h, Qt::TransformationMode mode) const
\sa createHeuristicMask(), {QImage#Image Transformations}{Image
Transformations}
*/
-QImage QImage::createAlphaMask(Qt::ImageConversionFlags flags) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::createAlphaMask(Qt::ImageConversionFlags flags) const
{
if (!d || d->format == QImage::Format_RGB32)
return QImage();
@@ -3519,7 +3570,7 @@ static inline void rgbSwapped_generic(int width, int height, const QImage *src,
/*!
\internal
*/
-QImage QImage::rgbSwapped_helper() const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::rgbSwapped_helper() const
{
if (isNull())
return *this;
@@ -3875,10 +3926,15 @@ bool QImage::save(QIODevice* device, const char* format, int quality) const
bool QImageData::doImageIO(const QImage *image, QImageWriter *writer, int quality) const
{
if (quality > 100 || quality < -1)
- qWarning("QPixmap::save: Quality out of range [-1, 100]");
+ qWarning("QImage::save: Quality out of range [-1, 100]");
if (quality >= 0)
writer->setQuality(qMin(quality,100));
- return writer->write(*image);
+ const bool result = writer->write(*image);
+#ifdef QT_DEBUG
+ if (!result)
+ qWarning("QImage::save: failed to write image - %s", qPrintable(writer->errorString()));
+#endif
+ return result;
}
/*****************************************************************************
@@ -3963,7 +4019,7 @@ bool QImage::operator==(const QImage & i) const
return false;
// obviously different stuff?
- if (i.d->height != d->height || i.d->width != d->width || i.d->format != d->format)
+ if (i.d->height != d->height || i.d->width != d->width || i.d->format != d->format || i.d->colorSpace != d->colorSpace)
return false;
if (d->format != Format_RGB32) {
@@ -4067,9 +4123,9 @@ int QImage::dotsPerMeterY() const
*/
void QImage::setDotsPerMeterX(int x)
{
- if (!d || !x)
+ if (!d || !x || d->dpmx == x)
return;
- detach();
+ detachMetadata();
if (d)
d->dpmx = x;
@@ -4089,9 +4145,9 @@ void QImage::setDotsPerMeterX(int x)
*/
void QImage::setDotsPerMeterY(int y)
{
- if (!d || !y)
+ if (!d || !y || d->dpmy == y)
return;
- detach();
+ detachMetadata();
if (d)
d->dpmy = y;
@@ -4121,9 +4177,9 @@ QPoint QImage::offset() const
*/
void QImage::setOffset(const QPoint& p)
{
- if (!d)
+ if (!d || d->offset == p)
return;
- detach();
+ detachMetadata();
if (d)
d->offset = p;
@@ -4159,7 +4215,7 @@ QString QImage::text(const QString &key) const
QString tmp;
for (auto it = d->text.begin(), end = d->text.end(); it != end; ++it)
- tmp += it.key() + QLatin1String(": ") + it.value().simplified() + QLatin1String("\n\n");
+ tmp += it.key() + ": "_L1 + it.value().simplified() + "\n\n"_L1;
if (!tmp.isEmpty())
tmp.chop(2); // remove final \n\n
return tmp;
@@ -4193,7 +4249,7 @@ void QImage::setText(const QString &key, const QString &value)
{
if (!d)
return;
- detach();
+ detachMetadata();
if (d)
d->text.insert(key, value);
@@ -4661,6 +4717,8 @@ QImage QImage::smoothScaled(int w, int h) const
static QImage rotated90(const QImage &image)
{
QImage out(image.height(), image.width(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
@@ -4689,6 +4747,8 @@ static QImage rotated180(const QImage &image)
return image.mirrored(true, true);
QImage out(image.width(), image.height(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
@@ -4701,6 +4761,8 @@ static QImage rotated180(const QImage &image)
static QImage rotated270(const QImage &image)
{
QImage out(image.height(), image.width(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
@@ -4731,7 +4793,7 @@ static QImage rotated270(const QImage &image)
image where not all pixels are covered by the transformed pixels of the
original image. In such cases, those background pixels will be assigned a
transparent color value, and the transformed image will be given a format
- with an alpha channel, even if the orginal image did not have that.
+ with an alpha channel, even if the original image did not have that.
The transformation \a matrix is internally adjusted to compensate
for unwanted translation; i.e. the image produced is the smallest
@@ -4746,12 +4808,15 @@ static QImage rotated270(const QImage &image)
Transformations}
*/
-QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode ) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode ) const
{
if (!d)
return QImage();
- Q_TRACE_SCOPE(QImage_transformed, matrix, mode);
+ Q_TRACE_PARAM_REPLACE(const QTransform &, double[9]);
+ Q_TRACE_SCOPE(QImage_transformed, QList<double>({matrix.m11(), matrix.m12(), matrix.m13(),
+ matrix.m21(), matrix.m22(), matrix.m23(),
+ matrix.m31(), matrix.m32(), matrix.m33()}).data(), mode);
// source image data
const int ws = width();
@@ -4772,13 +4837,8 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
else if (mat.m11() == -1. && mat.m22() == -1.)
return rotated180(*this);
- if (mode == Qt::FastTransformation) {
- hd = qRound(qAbs(mat.m22()) * hs);
- wd = qRound(qAbs(mat.m11()) * ws);
- } else {
- hd = int(qAbs(mat.m22()) * hs + 0.9999);
- wd = int(qAbs(mat.m11()) * ws + 0.9999);
- }
+ hd = qRound(qAbs(mat.m22()) * hs);
+ wd = qRound(qAbs(mat.m11()) * ws);
scale_xform = true;
// The paint-based scaling is only bilinear, and has problems
// with scaling smoothly more than 2x down.
@@ -4828,14 +4888,24 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
|| (ws * hs) >= (1<<20)
#endif
) {
+ QImage scaledImage;
if (mat.m11() < 0.0F && mat.m22() < 0.0F) { // horizontal/vertical flip
- return smoothScaled(wd, hd).mirrored(true, true).convertToFormat(format());
+ scaledImage = smoothScaled(wd, hd).mirrored(true, true);
} else if (mat.m11() < 0.0F) { // horizontal flip
- return smoothScaled(wd, hd).mirrored(true, false).convertToFormat(format());
+ scaledImage = smoothScaled(wd, hd).mirrored(true, false);
} else if (mat.m22() < 0.0F) { // vertical flip
- return smoothScaled(wd, hd).mirrored(false, true).convertToFormat(format());
+ scaledImage = smoothScaled(wd, hd).mirrored(false, true);
} else { // no flipping
- return smoothScaled(wd, hd).convertToFormat(format());
+ scaledImage = smoothScaled(wd, hd);
+ }
+
+ switch (format()) {
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ return scaledImage;
+ default:
+ return scaledImage.convertToFormat(format());
}
}
}
@@ -4877,7 +4947,14 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
if (target_format >= QImage::Format_RGB32) {
// Prevent QPainter from applying devicePixelRatio corrections
- const QImage sImage = (devicePixelRatio() != 1) ? QImage(constBits(), width(), height(), format()) : *this;
+ QImage sImage = (devicePixelRatio() != 1) ? QImage(constBits(), width(), height(), format()) : *this;
+ if (sImage.d != d
+ && (d->format == QImage::Format_MonoLSB
+ || d->format == QImage::Format_Mono
+ || d->format == QImage::Format_Indexed8)) {
+ sImage.d->colortable = d->colortable;
+ sImage.d->has_alpha_clut = d->has_alpha_clut;
+ }
Q_ASSERT(sImage.devicePixelRatio() == 1);
Q_ASSERT(sImage.devicePixelRatio() == dImage.devicePixelRatio());
@@ -4947,9 +5024,12 @@ void QImage::setColorSpace(const QColorSpace &colorSpace)
return;
if (d->colorSpace == colorSpace)
return;
- if (!isDetached()) // Detach only if shared, not for read-only data.
- detach();
- d->colorSpace = colorSpace;
+ if (colorSpace.isValid() && !qt_compatibleColorModel(pixelFormat().colorModel(), colorSpace.colorModel()))
+ return;
+
+ detachMetadata(false);
+ if (d)
+ d->colorSpace = colorSpace;
}
/*!
@@ -4959,20 +5039,60 @@ void QImage::setColorSpace(const QColorSpace &colorSpace)
If the image has no valid color space, the method does nothing.
+ \note If \a colorSpace is not compatible with the current format, the image
+ will be converted to one that is.
+
\sa convertedToColorSpace(), setColorSpace()
*/
void QImage::convertToColorSpace(const QColorSpace &colorSpace)
{
- if (!d)
- return;
- if (!d->colorSpace.isValid())
+ if (!d || !d->colorSpace.isValid())
return;
- if (!colorSpace.isValid()) {
+ if (!colorSpace.isValidTarget()) {
qWarning() << "QImage::convertToColorSpace: Output colorspace is not valid";
return;
}
- detach();
+ if (d->colorSpace == colorSpace)
+ return;
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), colorSpace.colorModel())) {
+ *this = convertedToColorSpace(colorSpace);
+ return;
+ }
applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace));
+ if (d->ref.loadRelaxed() != 1)
+ detachMetadata(false);
+ d->colorSpace = colorSpace;
+}
+
+/*!
+ \since 6.8
+
+ Converts the image to \a colorSpace and \a format.
+
+ If the image has no valid color space, the method does nothing,
+ nor if the color space is not compatible with with the format.
+
+ The specified image conversion \a flags control how the image data
+ is handled during the format conversion process.
+
+ \sa convertedToColorSpace(), setColorSpace()
+*/
+void QImage::convertToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags)
+{
+ if (!d || !d->colorSpace.isValid())
+ return;
+ if (!colorSpace.isValidTarget()) {
+ qWarning() << "QImage::convertToColorSpace: Output colorspace is not valid";
+ return;
+ }
+ if (!qt_compatibleColorModel(toPixelFormat(format).colorModel(), colorSpace.colorModel())) {
+ qWarning() << "QImage::convertToColorSpace: Color space is not compatible with format";
+ return;
+ }
+
+ if (d->colorSpace == colorSpace)
+ return convertTo(format, flags);
+ applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
d->colorSpace = colorSpace;
}
@@ -4983,14 +5103,56 @@ void QImage::convertToColorSpace(const QColorSpace &colorSpace)
If the image has no valid color space, a null QImage is returned.
- \sa convertToColorSpace()
+ \note If \a colorSpace is not compatible with the current format,
+ the returned image will also be converted to a format this is.
+ For more control over returned image format, see the three argument
+ overload of this method.
+
+ \sa convertToColorSpace(), colorTransformed()
*/
QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace) const
{
- if (!d || !d->colorSpace.isValid() || !colorSpace.isValid())
+ if (!d || !d->colorSpace.isValid())
return QImage();
- QImage image = copy();
- image.convertToColorSpace(colorSpace);
+ if (!colorSpace.isValidTarget()) {
+ qWarning() << "QImage::convertedToColorSpace: Output colorspace is not valid";
+ return QImage();
+ }
+ if (d->colorSpace == colorSpace)
+ return *this;
+ QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace));
+ image.setColorSpace(colorSpace);
+ return image;
+}
+
+/*!
+ \since 6.8
+
+ Returns the image converted to \a colorSpace and \a format.
+
+ If the image has no valid color space, a null QImage is returned.
+
+ The specified image conversion \a flags control how the image data
+ is handled during the format conversion process.
+
+ \sa colorTransformed()
+*/
+QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags) const
+{
+ if (!d || !d->colorSpace.isValid())
+ return QImage();
+ if (!colorSpace.isValidTarget()) {
+ qWarning() << "QImage::convertedToColorSpace: Output colorspace is not valid";
+ return QImage();
+ }
+ if (!qt_compatibleColorModel(toPixelFormat(format).colorModel(), colorSpace.colorModel())) {
+ qWarning() << "QImage::convertedToColorSpace: Color space is not compatible with format";
+ return QImage();
+ }
+ if (d->colorSpace == colorSpace)
+ return convertedTo(format, flags);
+ QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
+ image.setColorSpace(colorSpace);
return image;
}
@@ -5013,6 +5175,16 @@ QColorSpace QImage::colorSpace() const
*/
void QImage::applyColorTransform(const QColorTransform &transform)
{
+ if (transform.isIdentity())
+ return;
+
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel) ||
+ !qt_compatibleColorModel(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel)) {
+ qWarning() << "QImage::applyColorTransform can not apply format switching transform without switching format";
+ return;
+ }
+
+ detach();
if (!d)
return;
if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
@@ -5021,30 +5193,41 @@ void QImage::applyColorTransform(const QColorTransform &transform)
return;
}
QImage::Format oldFormat = format();
- if (depth() > 32) {
- if (format() != QImage::Format_RGBX64 && format() != QImage::Format_RGBA64
- && format() != QImage::Format_RGBA64_Premultiplied)
- *this = std::move(*this).convertToFormat(QImage::Format_RGBA64);
- } else if (format() != QImage::Format_ARGB32 && format() != QImage::Format_RGB32
- && format() != QImage::Format_ARGB32_Premultiplied) {
+ if (qt_fpColorPrecision(oldFormat)) {
+ if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
+ && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
+ convertTo(QImage::Format_RGBA32FPx4);
+ } else if (depth() > 32) {
+ if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
+ && oldFormat != QImage::Format_RGBA64_Premultiplied)
+ convertTo(QImage::Format_RGBA64);
+ } else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
+ && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
+ && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
if (hasAlphaChannel())
- *this = std::move(*this).convertToFormat(QImage::Format_ARGB32);
+ convertTo(QImage::Format_ARGB32);
else
- *this = std::move(*this).convertToFormat(QImage::Format_RGB32);
+ convertTo(QImage::Format_RGB32);
}
QColorTransformPrivate::TransformFlags flags = QColorTransformPrivate::Unpremultiplied;
switch (format()) {
case Format_ARGB32_Premultiplied:
case Format_RGBA64_Premultiplied:
+ case Format_RGBA32FPx4_Premultiplied:
flags = QColorTransformPrivate::Premultiplied;
break;
+ case Format_Grayscale8:
+ case Format_Grayscale16:
case Format_RGB32:
+ case Format_CMYK8888:
case Format_RGBX64:
+ case Format_RGBX32FPx4:
flags = QColorTransformPrivate::InputOpaque;
break;
case Format_ARGB32:
case Format_RGBA64:
+ case Format_RGBA32FPx4:
break;
default:
Q_UNREACHABLE();
@@ -5052,18 +5235,46 @@ void QImage::applyColorTransform(const QColorTransform &transform)
std::function<void(int,int)> transformSegment;
- if (depth() > 32) {
+ if (format() == Format_Grayscale8) {
transformSegment = [&](int yStart, int yEnd) {
for (int y = yStart; y < yEnd; ++y) {
- QRgba64 *scanline = reinterpret_cast<QRgba64 *>(scanLine(y));
- transform.d->apply(scanline, scanline, width(), flags);
+ uint8_t *scanline = reinterpret_cast<uint8_t *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->applyGray(scanline, scanline, width(), flags);
+ }
+ };
+ } else if (format() == Format_Grayscale16) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ uint16_t *scanline = reinterpret_cast<uint16_t *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->applyGray(scanline, scanline, width(), flags);
+ }
+ };
+ } else if (qt_fpColorPrecision(format())) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ QRgbaFloat32 *scanline = reinterpret_cast<QRgbaFloat32 *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
+ }
+ };
+ } else if (depth() > 32) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ QRgba64 *scanline = reinterpret_cast<QRgba64 *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
+ }
+ };
+ } else if (oldFormat == QImage::Format_CMYK8888) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ QCmyk32 *scanline = reinterpret_cast<QCmyk32 *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
}
};
} else {
transformSegment = [&](int yStart, int yEnd) {
for (int y = yStart; y < yEnd; ++y) {
- QRgb *scanline = reinterpret_cast<QRgb *>(scanLine(y));
- transform.d->apply(scanline, scanline, width(), flags);
+ QRgb *scanline = reinterpret_cast<QRgb *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
}
};
}
@@ -5071,7 +5282,7 @@ void QImage::applyColorTransform(const QColorTransform &transform)
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
int segments = (qsizetype(width()) * height()) >> 16;
segments = std::min(segments, height());
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -5092,6 +5303,549 @@ void QImage::applyColorTransform(const QColorTransform &transform)
*this = std::move(*this).convertToFormat(oldFormat);
}
+/*!
+ \since 6.8
+
+ Applies the color transformation \a transform to all pixels in the image, and converts the format of the image to \a toFormat.
+
+ The specified image conversion \a flags control how the image data
+ is handled during the format conversion process.
+*/
+void QImage::applyColorTransform(const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags)
+{
+ if (!d)
+ return;
+ if (transform.isIdentity())
+ return convertTo(toFormat, flags);
+
+ *this = colorTransformed(transform, toFormat, flags);
+}
+
+/*!
+ \since 6.4
+
+ Returns the image color transformed using \a transform on all pixels in the image.
+
+ \note If \a transform has a source color space which is incompatible with the format of this image,
+ returns a null QImage. If \a transform has a target color space which is incompatible with the format
+ of this image, the image will also be converted to a compatible format. For more control about the
+ choice of the target pixel format, see the three argument overload of this method.
+
+ \sa applyColorTransform()
+*/
+QImage QImage::colorTransformed(const QColorTransform &transform) const &
+{
+ if (!d)
+ return QImage();
+ if (transform.isIdentity())
+ return *this;
+
+ QColorSpace::ColorModel inColorModel = QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel;
+ QColorSpace::ColorModel outColorModel = QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel;
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), inColorModel)) {
+ qWarning() << "QImage::colorTransformed: Invalid input color space for transform";
+ return QImage();
+ }
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), outColorModel)) {
+ // All model switching transforms are opaque in at least one end.
+ switch (outColorModel) {
+ case QColorSpace::ColorModel::Rgb:
+ return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
+ case QColorSpace::ColorModel::Gray:
+ return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
+ case QColorSpace::ColorModel::Cmyk:
+ return colorTransformed(transform, QImage::Format_CMYK8888);
+ case QColorSpace::ColorModel::Undefined:
+ break;
+ }
+ return QImage();
+ }
+
+ QImage image = copy();
+ image.applyColorTransform(transform);
+ return image;
+}
+
+static bool isRgb32Data(QImage::Format f)
+{
+ switch (f) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static bool isRgb64Data(QImage::Format f)
+{
+ switch (f) {
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static bool isRgb32fpx4Data(QImage::Format f)
+{
+ switch (f) {
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+/*!
+ \since 6.8
+
+ Returns the image color transformed using \a transform on all pixels in the image, returning an image of format \a toFormat.
+
+ The specified image conversion \a flags control how the image data
+ is handled during the format conversion process.
+
+ \note If \a transform has a source color space which is incompatible with the format of this image,
+ or a target color space that is incompatible with \a toFormat, returns a null QImage.
+
+ \sa applyColorTransform()
+*/
+QImage QImage::colorTransformed(const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags) const &
+{
+ if (!d)
+ return QImage();
+ if (toFormat == QImage::Format_Invalid)
+ toFormat = format();
+ if (transform.isIdentity())
+ return convertedTo(toFormat, flags);
+
+ QColorSpace::ColorModel inColorModel = QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel;
+ QColorSpace::ColorModel outColorModel = QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel;
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), inColorModel)) {
+ qWarning() << "QImage::colorTransformed: Invalid input color space for transform";
+ return QImage();
+ }
+ if (!qt_compatibleColorModel(toPixelFormat(toFormat).colorModel(), outColorModel)) {
+ qWarning() << "QImage::colorTransformed: Invalid output color space for transform";
+ return QImage();
+ }
+
+ QImage fromImage = *this;
+
+ QImage::Format tmpFormat = toFormat;
+ switch (toFormat) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
+ case QImage::Format_CMYK8888:
+ // can be output natively
+ break;
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB444:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB666:
+ case QImage::Format_RGB888:
+ case QImage::Format_BGR888:
+ case QImage::Format_RGBX8888:
+ tmpFormat = QImage::Format_RGB32;
+ break;
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ tmpFormat = QImage::Format_ARGB32;
+ break;
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
+ tmpFormat = QImage::Format_RGBX64;
+ break;
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
+ tmpFormat = QImage::Format_RGBA64;
+ break;
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ tmpFormat = QImage::Format_RGBA32FPx4;
+ break;
+ case QImage::Format_Alpha8:
+ return convertedTo(QImage::Format_Alpha8);
+ case QImage::Format_Invalid:
+ case QImage::NImageFormats:
+ Q_UNREACHABLE();
+ break;
+ }
+ QColorSpace::ColorModel inColorData = qt_csColorData(pixelFormat().colorModel());
+ QColorSpace::ColorModel outColorData = qt_csColorData(toPixelFormat(toFormat).colorModel());
+ // Ensure only precision increasing transforms
+ if (inColorData != outColorData) {
+ if (fromImage.format() == QImage::Format_Grayscale8 && outColorData == QColorSpace::ColorModel::Rgb)
+ tmpFormat = QImage::Format_RGB32;
+ else if (tmpFormat == QImage::Format_Grayscale8 && qt_highColorPrecision(fromImage.format()))
+ tmpFormat = QImage::Format_Grayscale16;
+ else if (fromImage.format() == QImage::Format_Grayscale16 && outColorData == QColorSpace::ColorModel::Rgb)
+ tmpFormat = QImage::Format_RGBX64;
+ } else {
+ if (tmpFormat == QImage::Format_Grayscale8 && fromImage.format() == QImage::Format_Grayscale16)
+ tmpFormat = QImage::Format_Grayscale16;
+ else if (qt_fpColorPrecision(fromImage.format()) && !qt_fpColorPrecision(tmpFormat))
+ tmpFormat = QImage::Format_RGBA32FPx4;
+ else if (isRgb32Data(tmpFormat) && qt_highColorPrecision(fromImage.format(), true))
+ tmpFormat = QImage::Format_RGBA64;
+ }
+
+ QImage toImage(size(), tmpFormat);
+ copyMetadata(&toImage, *this);
+
+ std::function<void(int, int)> transformSegment;
+ QColorTransformPrivate::TransformFlags transFlags = QColorTransformPrivate::Unpremultiplied;
+
+ if (inColorData != outColorData) {
+ // Needs color model switching transform
+ if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Rgb) {
+ // Gray -> RGB
+ if (format() == QImage::Format_Grayscale8) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint8 *in_scanline = reinterpret_cast<const quint8 *>(d->data + y * d->bytes_per_line);
+ QRgb *out_scanline = reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint16 *in_scanline = reinterpret_cast<const quint16 *>(d->data + y * d->bytes_per_line);
+ QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ }
+ } else if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Cmyk) {
+ // Gray -> CMYK
+ if (format() == QImage::Format_Grayscale8) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint8 *in_scanline = reinterpret_cast<const quint8 *>(d->data + y * d->bytes_per_line);
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint16 *in_scanline = reinterpret_cast<const quint16 *>(d->data + y * d->bytes_per_line);
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ }
+ } else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Gray) {
+ // RGB -> Gray
+ if (tmpFormat == QImage::Format_Grayscale8) {
+ fromImage.convertTo(QImage::Format_RGB32);
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgb *in_scanline = reinterpret_cast<const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ quint8 *out_scanline = reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyReturnGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else {
+ fromImage.convertTo(QImage::Format_RGBX64);
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgba64 *in_scanline = reinterpret_cast<const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyReturnGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ }
+ } else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Gray) {
+ // CMYK -> Gray
+ if (tmpFormat == QImage::Format_Grayscale8) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ quint8 *out_scanline = reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyReturnGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyReturnGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ }
+ } else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Rgb) {
+ // CMYK -> RGB
+ if (isRgb32Data(tmpFormat) ) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QRgb *out_scanline = reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else if (isRgb64Data(tmpFormat)) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else {
+ Q_ASSERT(isRgb32fpx4Data(tmpFormat));
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ }
+ } else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Cmyk) {
+ // RGB -> CMYK
+ if (!fromImage.hasAlphaChannel())
+ transFlags = QColorTransformPrivate::InputOpaque;
+ else if (qPixelLayouts[fromImage.format()].premultiplied)
+ transFlags = QColorTransformPrivate::Premultiplied;
+ if (isRgb32Data(fromImage.format()) ) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgb *in_scanline = reinterpret_cast<const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ } else if (isRgb64Data(fromImage.format())) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgba64 *in_scanline = reinterpret_cast<const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ } else {
+ Q_ASSERT(isRgb32fpx4Data(fromImage.format()));
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgbaFloat32 *in_scanline = reinterpret_cast<const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ }
+ } else {
+ Q_UNREACHABLE();
+ }
+ } else {
+ // Conversion on same color model
+ if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
+ for (int i = 0; i < d->colortable.size(); ++i)
+ fromImage.d->colortable[i] = transform.map(d->colortable[i]);
+ return fromImage.convertedTo(toFormat, flags);
+ }
+
+ QImage::Format oldFormat = format();
+ if (qt_fpColorPrecision(oldFormat)) {
+ if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
+ && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
+ fromImage.convertTo(QImage::Format_RGBA32FPx4);
+ } else if (qt_highColorPrecision(oldFormat, true)) {
+ if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
+ && oldFormat != QImage::Format_RGBA64_Premultiplied && oldFormat != QImage::Format_Grayscale16)
+ fromImage.convertTo(QImage::Format_RGBA64);
+ } else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
+ && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
+ && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
+ if (hasAlphaChannel())
+ fromImage.convertTo(QImage::Format_ARGB32);
+ else
+ fromImage.convertTo(QImage::Format_RGB32);
+ }
+
+ if (!fromImage.hasAlphaChannel())
+ transFlags = QColorTransformPrivate::InputOpaque;
+ else if (qPixelLayouts[fromImage.format()].premultiplied)
+ transFlags = QColorTransformPrivate::Premultiplied;
+
+ if (fromImage.format() == Format_Grayscale8) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint8 *in_scanline = reinterpret_cast<const quint8 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ if (tmpFormat == Format_Grayscale8) {
+ quint8 *out_scanline = reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), transFlags);
+ } else {
+ Q_ASSERT(tmpFormat == Format_Grayscale16);
+ quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), transFlags);
+ }
+ }
+ };
+ } else if (fromImage.format() == Format_Grayscale16) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint16 *in_scanline = reinterpret_cast<const quint16 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ } else if (fromImage.format() == Format_CMYK8888) {
+ Q_ASSERT(tmpFormat == Format_CMYK8888);
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ } else if (isRgb32fpx4Data(fromImage.format())) {
+ Q_ASSERT(isRgb32fpx4Data(tmpFormat));
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgbaFloat32 *in_scanline = reinterpret_cast<const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ } else if (isRgb64Data(fromImage.format())) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgba64 *in_scanline = reinterpret_cast<const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ if (isRgb32fpx4Data(tmpFormat)) {
+ QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ } else {
+ Q_ASSERT(isRgb64Data(tmpFormat));
+ QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ }
+ };
+ } else {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgb *in_scanline = reinterpret_cast<const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ if (isRgb32fpx4Data(tmpFormat)) {
+ QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ } else if (isRgb64Data(tmpFormat)) {
+ QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ } else {
+ Q_ASSERT(isRgb32Data(tmpFormat));
+ QRgb *out_scanline = reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ }
+ };
+ }
+ }
+
+#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+ int segments = (qsizetype(width()) * height()) >> 16;
+ segments = std::min(segments, height());
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
+ QSemaphore semaphore;
+ int y = 0;
+ for (int i = 0; i < segments; ++i) {
+ int yn = (height() - y) / (segments - i);
+ threadPool->start([&, y, yn]() {
+ transformSegment(y, y + yn);
+ semaphore.release(1);
+ });
+ y += yn;
+ }
+ semaphore.acquire(segments);
+ } else
+#endif
+ transformSegment(0, height());
+
+ if (tmpFormat != toFormat)
+ toImage.convertTo(toFormat);
+
+ return toImage;
+}
+
+/*!
+ \since 6.4
+ \overload
+
+ Returns the image color transformed using \a transform on all pixels in the image.
+
+ \sa applyColorTransform()
+*/
+QImage QImage::colorTransformed(const QColorTransform &transform) &&
+{
+ if (!d)
+ return QImage();
+
+ QColorSpace::ColorModel inColorModel = QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel;
+ QColorSpace::ColorModel outColorModel = QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel;
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), inColorModel)) {
+ qWarning() << "QImage::colorTransformed: Invalid input color space for transform";
+ return QImage();
+ }
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), outColorModel)) {
+ // There is currently no inplace conversion of both colorspace and format, so just use the normal version.
+ switch (outColorModel) {
+ case QColorSpace::ColorModel::Rgb:
+ return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
+ case QColorSpace::ColorModel::Gray:
+ return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
+ case QColorSpace::ColorModel::Cmyk:
+ return colorTransformed(transform, QImage::Format_CMYK8888);
+ case QColorSpace::ColorModel::Undefined:
+ break;
+ }
+ return QImage();
+ }
+
+ applyColorTransform(transform);
+ return std::move(*this);
+}
+
+/*!
+ \since 6.8
+ \overload
+
+ Returns the image color transformed using \a transform on all pixels in the image.
+
+ \sa applyColorTransform()
+*/
+QImage QImage::colorTransformed(const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags) &&
+{
+ // There is currently no inplace conversion of both colorspace and format, so just use the normal version.
+ return colorTransformed(transform, format, flags);
+}
bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags)
{
@@ -5617,6 +6371,19 @@ static constexpr QPixelFormat pixelformats[] = {
/*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
/*INTERPRETATION*/ QPixelFormat::FloatingPoint,
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_CMYK8888:
+ QPixelFormat(QPixelFormat::CMYK,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 8,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
};
static_assert(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
@@ -5677,12 +6444,11 @@ QMap<QString, QString> qt_getImageText(const QImage &image, const QString &descr
QMap<QString, QString> qt_getImageTextFromDescription(const QString &description)
{
QMap<QString, QString> text;
- const auto pairs = QStringView{description}.split(u"\n\n");
- for (const auto &pair : pairs) {
- int index = pair.indexOf(QLatin1Char(':'));
- if (index >= 0 && pair.indexOf(QLatin1Char(' ')) < index) {
+ for (const auto &pair : QStringView{description}.tokenize(u"\n\n")) {
+ int index = pair.indexOf(u':');
+ if (index >= 0 && pair.indexOf(u' ') < index) {
if (!pair.trimmed().isEmpty())
- text.insert(QLatin1String("Description"), pair.toString().simplified());
+ text.insert("Description"_L1, pair.toString().simplified());
} else {
const auto key = pair.left(index);
if (!key.trimmed().isEmpty())
@@ -5693,3 +6459,5 @@ QMap<QString, QString> qt_getImageTextFromDescription(const QString &description
}
QT_END_NAMESPACE
+
+#include "moc_qimage.cpp"
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 6561359dae..cba50e5e4c 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGE_H
#define QIMAGE_H
@@ -111,6 +75,7 @@ public:
Format_RGBX32FPx4,
Format_RGBA32FPx4,
Format_RGBA32FPx4_Premultiplied,
+ Format_CMYK8888,
#ifndef Q_QDOC
NImageFormats
#endif
@@ -132,14 +97,14 @@ public:
QImage(const QImage &);
QImage(QImage &&other) noexcept
- : QPaintDevice(), d(qExchange(other.d, nullptr))
+ : QPaintDevice(), d(std::exchange(other.d, nullptr))
{}
~QImage();
QImage &operator=(const QImage &);
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QImage)
void swap(QImage &other) noexcept
- { qSwap(d, other.d); }
+ { qt_ptr_swap(d, other.d); }
bool isNull() const;
@@ -266,11 +231,18 @@ public:
void invertPixels(InvertMode = InvertRgb);
QColorSpace colorSpace() const;
- [[nodiscard]] QImage convertedToColorSpace(const QColorSpace &) const;
- void convertToColorSpace(const QColorSpace &);
- void setColorSpace(const QColorSpace &);
-
+ [[nodiscard]] QImage convertedToColorSpace(const QColorSpace &colorSpace) const;
+ [[nodiscard]] QImage convertedToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor) const;
+ void convertToColorSpace(const QColorSpace &colorSpace);
+ void convertToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor);
+ void setColorSpace(const QColorSpace &colorSpace);
+
+ QImage colorTransformed(const QColorTransform &transform) const &;
+ QImage colorTransformed(const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor) const &;
+ QImage colorTransformed(const QColorTransform &transform) &&;
+ QImage colorTransformed(const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor) &&;
void applyColorTransform(const QColorTransform &transform);
+ void applyColorTransform(const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor);
bool load(QIODevice *device, const char *format);
bool load(const QString &fileName, const char *format = nullptr);
@@ -328,6 +300,8 @@ protected:
bool convertToFormat_inplace(Format format, Qt::ImageConversionFlags flags);
QImage smoothScaled(int w, int h) const;
+ void detachMetadata(bool invalidateCache = false);
+
private:
QImageData *d;
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index cae52ca330..a806954df2 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qguiapplication_p.h>
#include <private/qcolortransform_p.h>
#include <private/qcolortrclut_p.h>
+#include <private/qcmyk_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qendian_p.h>
#include <private/qpixellayout_p.h>
@@ -51,6 +16,7 @@
#if QT_CONFIG(thread)
#include <qsemaphore.h>
#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#ifdef Q_OS_WASM
// WebAssembly has threads; however we can't block the main thread.
#else
@@ -200,7 +166,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
- fetch = qPixelLayouts[src->format + 1].fetchToARGB32PM;
+ fetch = qPixelLayouts[qt_toPremultipliedFormat(src->format)].fetchToARGB32PM;
if (dest->format == QImage::Format_RGB32)
store = storeRGB32FromARGB32;
else
@@ -239,7 +205,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -294,7 +260,7 @@ void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::Ima
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -348,7 +314,7 @@ void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::I
int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -418,7 +384,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
- fetch = qPixelLayouts[data->format + 1].fetchToARGB32PM;
+ fetch = qPixelLayouts[qt_toPremultipliedFormat(data->format)].fetchToARGB32PM;
if (data->format == QImage::Format_RGB32)
store = storeRGB32FromARGB32;
else
@@ -455,7 +421,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -520,9 +486,8 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
destLayout->hasAlphaChannel && !destLayout->premultiplied) {
// Avoid unnecessary premultiply and unpremultiply when converting between two unpremultiplied formats.
- // This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
- fetch = qPixelLayouts[data->format + 1].fetchToRGBA64PM;
- store = qStoreFromRGBA64PM[dst_format + 1];
+ fetch = qPixelLayouts[qt_toPremultipliedFormat(data->format)].fetchToRGBA64PM;
+ store = qStoreFromRGBA64PM[qt_toPremultipliedFormat(dst_format)];
}
auto convertSegment = [=](int yStart, int yEnd) {
@@ -549,7 +514,7 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -615,9 +580,8 @@ bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_f
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
destLayout->hasAlphaChannel && !destLayout->premultiplied) {
// Avoid unnecessary premultiply and unpremultiply when converting between two unpremultiplied formats.
- // This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
- fetch = qFetchToRGBA32F[data->format + 1];
- store = qStoreFromRGBA32F[dst_format + 1];
+ fetch = qFetchToRGBA32F[qt_toPremultipliedFormat(data->format)];
+ store = qStoreFromRGBA32F[qt_toPremultipliedFormat(dst_format)];
}
auto convertSegment = [=](int yStart, int yEnd) {
@@ -644,7 +608,7 @@ bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_f
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -1069,8 +1033,7 @@ static inline uint qUnpremultiplyRgb30(uint rgb30)
case 3:
return rgb30;
}
- Q_UNREACHABLE();
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
template<bool rgbswap>
@@ -1359,11 +1322,11 @@ static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt
const uchar *src_data = src->data;
uchar *dest_data = dest->data;
- const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[src->format + 1].fetchToRGBA64PM;
+ const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[qt_toPremultipliedFormat(src->format)].fetchToRGBA64PM;
for (int i = 0; i < src->height; ++i) {
fetch(reinterpret_cast<QRgba64 *>(dest_data), src_data, 0, src->width, nullptr, nullptr);
- src_data += src->bytes_per_line;;
+ src_data += src->bytes_per_line;
dest_data += dest->bytes_per_line;
}
}
@@ -1454,14 +1417,14 @@ static void convert_ARGB_to_gray8(QImageData *dest, const QImageData *src, Qt::I
QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
- QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
QColorTransformPrivate::TransformFlags flags = Premultiplied
? QColorTransformPrivate::InputPremultiplied
: QColorTransformPrivate::Unpremultiplied;
for (int i = 0; i < src->height; ++i) {
const QRgb *src_line = reinterpret_cast<const QRgb *>(src_data);
- tfd->apply(dest_data, src_line, src->width, flags);
+ tfd->applyReturnGray(dest_data, src_line, src->width, flags);
src_data += sbpl;
dest_data += dbpl;
}
@@ -1484,7 +1447,7 @@ static void convert_ARGB_to_gray16(QImageData *dest, const QImageData *src, Qt::
QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
- QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
QColorTransformPrivate::TransformFlags flags = Premultiplied
? QColorTransformPrivate::InputPremultiplied
: QColorTransformPrivate::Unpremultiplied;
@@ -1498,7 +1461,7 @@ static void convert_ARGB_to_gray16(QImageData *dest, const QImageData *src, Qt::
const int len = std::min(src->width - j, BufferSize);
for (int k = 0; k < len; ++k)
tmp_line[k] = QRgba64::fromArgb32(src_line[j + k]);
- tfd->apply(dest_line + j, tmp_line, len, flags);
+ tfd->applyReturnGray(dest_line + j, tmp_line, len, flags);
j += len;
}
src_data += sbpl;
@@ -1523,7 +1486,7 @@ static void convert_RGBA64_to_gray8(QImageData *dest, const QImageData *src, Qt:
QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
- QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
QColorTransformPrivate::TransformFlags flags = Premultiplied
? QColorTransformPrivate::InputPremultiplied
: QColorTransformPrivate::Unpremultiplied;
@@ -1535,7 +1498,7 @@ static void convert_RGBA64_to_gray8(QImageData *dest, const QImageData *src, Qt:
int j = 0;
while (j < src->width) {
const int len = std::min(src->width - j, BufferSize);
- tfd->apply(gray_line, src_line + j, len, flags);
+ tfd->applyReturnGray(gray_line, src_line + j, len, flags);
for (int k = 0; k < len; ++k)
dest_line[j + k] = qt_div_257(gray_line[k]);
j += len;
@@ -1562,7 +1525,7 @@ static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt
QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
- QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
QColorTransformPrivate::TransformFlags flags = Premultiplied
? QColorTransformPrivate::InputPremultiplied
: QColorTransformPrivate::Unpremultiplied;
@@ -1570,7 +1533,7 @@ static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt
for (int i = 0; i < src->height; ++i) {
const QRgba64 *src_line = reinterpret_cast<const QRgba64 *>(src_data);
quint16 *dest_line = reinterpret_cast<quint16 *>(dest_data);
- tfd->apply(dest_line, src_line, src->width, flags);
+ tfd->applyReturnGray(dest_line, src_line, src->width, flags);
src_data += sbpl;
dest_data += dbpl;
}
@@ -2492,6 +2455,34 @@ static bool convert_Grayscale8_to_Indexed8_inplace(QImageData *data, Qt::ImageCo
return true;
}
+template <bool SourceIsPremultiplied>
+static void convert_ARGB32_to_CMYK8888(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGB32 ||
+ src->format == QImage::Format_ARGB32 ||
+ src->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_CMYK8888);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+ for (int y = 0; y < src->height; ++y) {
+ const QRgb *srcRgba = reinterpret_cast<const QRgb *>(src_data);
+ uint *destCmyk = reinterpret_cast<uint *>(dest_data);
+
+ for (int x = 0; x < src->width; ++x) {
+ QRgb sourcePixel = srcRgba[x];
+ if constexpr (SourceIsPremultiplied)
+ sourcePixel = qUnpremultiply(sourcePixel);
+
+ destCmyk[x] = QCmyk32::fromRgba(sourcePixel).toUint();
+ }
+
+ src_data += src->bytes_per_line;;
+ dest_data += dest->bytes_per_line;
+ }
+}
// first index source, second dest
Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats] = {};
@@ -2628,6 +2619,11 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4] = convert_passthrough;
qimage_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4_Premultiplied] = convert_passthrough;
+ qimage_converter_map[QImage::Format_CMYK8888][QImage::Format_CMYK8888] = convert_passthrough;
+ qimage_converter_map[QImage::Format_RGB32][QImage::Format_CMYK8888] = convert_ARGB32_to_CMYK8888<false>;
+ qimage_converter_map[QImage::Format_ARGB32][QImage::Format_CMYK8888] = convert_ARGB32_to_CMYK8888<false>;
+ qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_CMYK8888] = convert_ARGB32_to_CMYK8888<true>;
+
// Inline converters:
qimage_inplace_converter_map[QImage::Format_Indexed8][QImage::Format_Grayscale8] =
convert_Indexed8_to_Grayscale8_inplace;
diff --git a/src/gui/image/qimage_darwin.mm b/src/gui/image/qimage_darwin.mm
index e2ec52d2df..3744da2e32 100644
--- a/src/gui/image/qimage_darwin.mm
+++ b/src/gui/image/qimage_darwin.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qimage.h"
@@ -88,7 +52,7 @@ QT_BEGIN_NAMESPACE
Other formats are not supported; this function returns a null
CGImageRef for those cases. Users of this function may then
- convert the QImage to a supported formate first, for example
+ convert the QImage to a supported format first, for example
Format_ARGB32_Premultiplied.
The CGImageRef color space is set to the sRGB color space.
diff --git a/src/gui/image/qimage_mips_dspr2.cpp b/src/gui/image/qimage_mips_dspr2.cpp
index 13cca12cfa..5022e21ee8 100644
--- a/src/gui/image/qimage_mips_dspr2.cpp
+++ b/src/gui/image/qimage_mips_dspr2.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qimage.h"
#include <private/qimage_p.h>
diff --git a/src/gui/image/qimage_mips_dspr2_asm.S b/src/gui/image/qimage_mips_dspr2_asm.S
index 15beab29dc..61bccdb3d1 100644
--- a/src/gui/image/qimage_mips_dspr2_asm.S
+++ b/src/gui/image/qimage_mips_dspr2_asm.S
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "../painting/qt_mips_asm_dsp_p.h"
diff --git a/src/gui/image/qimage_neon.cpp b/src/gui/image/qimage_neon.cpp
index 9dbcb11db5..b513dc2894 100644
--- a/src/gui/image/qimage_neon.cpp
+++ b/src/gui/image/qimage_neon.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qimage.h>
#include <private/qimage_p.h>
@@ -54,7 +18,7 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons
// align dst on 128 bits
const int offsetToAlignOn16Bytes = (reinterpret_cast<quintptr>(dst) >> 2) & 0x3;
- for (int i = 0; i < offsetToAlignOn16Bytes; ++i) {
+ for (int i = 0; i < qMin(len, offsetToAlignOn16Bytes); ++i) {
*dst++ = qRgb(src[0], src[1], src[2]);
src += 3;
}
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index a2c50adc43..0d42f94253 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGE_P_H
#define QIMAGE_P_H
@@ -57,6 +21,8 @@
#include <QtCore/private/qnumeric_p.h>
#include <QtCore/qlist.h>
#include <QtCore/qmap.h>
+#include <QtCore/qttypetraits.h>
+
QT_BEGIN_NAMESPACE
@@ -93,7 +59,6 @@ struct Q_GUI_EXPORT QImageData { // internal image data
uint ro_data : 1;
uint has_alpha_clut : 1;
uint is_cached : 1;
- uint is_locked : 1;
QImageCleanupFunction cleanupFunction;
void* cleanupInfo;
@@ -129,18 +94,18 @@ QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetyp
// calculate the size, taking care of overflows
qsizetype bytes_per_line;
- if (mul_overflow(width, depth, &bytes_per_line))
+ if (qMulOverflow(width, depth, &bytes_per_line))
return invalid;
- if (add_overflow(bytes_per_line, qsizetype(31), &bytes_per_line))
+ if (qAddOverflow(bytes_per_line, qsizetype(31), &bytes_per_line))
return invalid;
// bytes per scanline (must be multiple of 4)
bytes_per_line = (bytes_per_line >> 5) << 2; // can't overflow
qsizetype total_size;
- if (mul_overflow(height, bytes_per_line, &total_size))
+ if (qMulOverflow(height, bytes_per_line, &total_size))
return invalid;
qsizetype dummy;
- if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy))
+ if (qMulOverflow(height, qsizetype(sizeof(uchar *)), &dummy))
return invalid; // why is this here?
#if 1 || QT_VERSION < QT_VERSION_CHECK(6,0,0) // ### can only fix this if QImage dimensions are not int anymore
// Disallow images where width * depth calculations might overflow
@@ -230,6 +195,9 @@ inline int qt_depthForFormat(QImage::Format format)
case QImage::Format_RGBA32FPx4_Premultiplied:
depth = 128;
break;
+ case QImage::Format_CMYK8888:
+ depth = 32;
+ break;
}
return depth;
}
@@ -283,6 +251,7 @@ inline QImage::Format qt_opaqueVersion(QImage::Format format)
case QImage::Format_RGBX32FPx4:
case QImage::Format_Grayscale8:
case QImage::Format_Grayscale16:
+ case QImage::Format_CMYK8888:
return format;
case QImage::Format_Mono:
case QImage::Format_MonoLSB:
@@ -346,12 +315,84 @@ inline QImage::Format qt_alphaVersion(QImage::Format format)
case QImage::Format_Alpha8:
case QImage::Format_Grayscale8:
case QImage::Format_Invalid:
+ case QImage::Format_CMYK8888:
case QImage::NImageFormats:
break;
}
return QImage::Format_ARGB32_Premultiplied;
}
+// Returns an opaque version that is compatible with format
+inline QImage::Format qt_maybeDataCompatibleOpaqueVersion(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_ARGB6666_Premultiplied:
+ return QImage::Format_RGB666;
+ case QImage::Format_ARGB4444_Premultiplied:
+ return QImage::Format_RGB444;
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ return QImage::Format_RGBX8888;
+ case QImage::Format_A2BGR30_Premultiplied:
+ return QImage::Format_BGR30;
+ case QImage::Format_A2RGB30_Premultiplied:
+ return QImage::Format_RGB30;
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ return QImage::Format_RGBX64;
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ return QImage::Format_RGBX16FPx4;
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return QImage::Format_RGBX32FPx4;
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB32:
+ return QImage::Format_RGB32;
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB32:
+ case QImage::Format_RGB444:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB666:
+ case QImage::Format_RGB888:
+ case QImage::Format_BGR888:
+ case QImage::Format_RGBX8888:
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
+ case QImage::Format_CMYK8888:
+ return format; // Already opaque
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_Alpha8:
+ case QImage::Format_Invalid:
+ case QImage::NImageFormats:
+ break;
+ }
+ return format; // No compatible opaque versions
+}
+
+constexpr QImage::Format qt_toUnpremultipliedFormat(QImage::Format format)
+{
+ // Assumes input is already a premultiplied format with an unpremultiplied counterpart
+ // This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
+ return static_cast<QImage::Format>(qToUnderlying(format) - 1);
+}
+
+constexpr QImage::Format qt_toPremultipliedFormat(QImage::Format format)
+{
+ // Assumes input is already an unpremultiplied format
+ // This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
+ return static_cast<QImage::Format>(qToUnderlying(format) + 1);
+}
+
inline bool qt_highColorPrecision(QImage::Format format, bool opaque = false)
{
// Formats with higher color precision than ARGB32_Premultiplied.
@@ -396,10 +437,98 @@ inline bool qt_fpColorPrecision(QImage::Format format)
return false;
}
-inline QImage::Format qt_maybeAlphaVersionWithSameDepth(QImage::Format format)
+inline QColorSpace::ColorModel qt_csColorData(QPixelFormat::ColorModel format)
{
- const QImage::Format toFormat = qt_alphaVersion(format);
- return qt_depthForFormat(format) == qt_depthForFormat(toFormat) ? toFormat : format;
+ switch (format) {
+ case QPixelFormat::ColorModel::RGB:
+ case QPixelFormat::ColorModel::BGR:
+ case QPixelFormat::ColorModel::Indexed:
+ return QColorSpace::ColorModel::Rgb;
+ case QPixelFormat::ColorModel::Alpha:
+ return QColorSpace::ColorModel::Undefined; // No valid colors
+ case QPixelFormat::ColorModel::Grayscale:
+ return QColorSpace::ColorModel::Gray;
+ case QPixelFormat::ColorModel::CMYK:
+ return QColorSpace::ColorModel::Cmyk;
+ default:
+ break;
+ }
+ return QColorSpace::ColorModel::Undefined;
+}
+
+inline bool qt_compatibleColorModel(QPixelFormat::ColorModel data, QColorSpace::ColorModel cs)
+{
+ QColorSpace::ColorModel dataCs = qt_csColorData(data);
+
+ if (data == QPixelFormat::ColorModel::Alpha)
+ return true; // Alpha data has no colors and can be handled by any color space
+
+ if (cs == QColorSpace::ColorModel::Undefined || dataCs == QColorSpace::ColorModel::Undefined)
+ return false;
+
+ if (dataCs == cs)
+ return true; // Matching color models
+
+ if (dataCs == QColorSpace::ColorModel::Gray)
+ return true; // Can apply any CS with white point to Gray data
+
+ return false;
+}
+
+inline QImage::Format qt_maybeDataCompatibleAlphaVersion(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_RGB32:
+ return QImage::Format_ARGB32_Premultiplied;
+ case QImage::Format_RGB666:
+ return QImage::Format_ARGB6666_Premultiplied;
+ case QImage::Format_RGB444:
+ return QImage::Format_ARGB4444_Premultiplied;
+ case QImage::Format_RGBX8888:
+ return QImage::Format_RGBA8888_Premultiplied;
+ case QImage::Format_BGR30:
+ return QImage::Format_A2BGR30_Premultiplied;
+ case QImage::Format_RGB30:
+ return QImage::Format_A2RGB30_Premultiplied;
+ case QImage::Format_RGBX64:
+ return QImage::Format_RGBA64_Premultiplied;
+ case QImage::Format_RGBX16FPx4:
+ return QImage::Format_RGBA16FPx4_Premultiplied;
+ case QImage::Format_RGBX32FPx4:
+ return QImage::Format_RGBA32FPx4_Premultiplied;
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
+ case QImage::Format_Alpha8:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return format; // Already alpha versions
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB888:
+ case QImage::Format_BGR888:
+ case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
+ case QImage::Format_CMYK8888:
+ case QImage::Format_Invalid:
+ case QImage::NImageFormats:
+ break;
+ }
+ return format; // No data-compatible alpha version
}
inline QImage::Format qt_opaqueVersionForPainting(QImage::Format format)
diff --git a/src/gui/image/qimage_ssse3.cpp b/src/gui/image/qimage_ssse3.cpp
index fb81a1a6c3..40f52b6ce6 100644
--- a/src/gui/image/qimage_ssse3.cpp
+++ b/src/gui/image/qimage_ssse3.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qimage.h>
#include <private/qimage_p.h>
diff --git a/src/gui/image/qimageiohandler.cpp b/src/gui/image/qimageiohandler.cpp
index 75a2f2ac65..1dcfd9a074 100644
--- a/src/gui/image/qimageiohandler.cpp
+++ b/src/gui/image/qimageiohandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QImageIOHandler
@@ -160,20 +124,15 @@
variants should return a list of supported variant names
(QList<QByteArray>) in this option.
- \value OptimizedWrite. A handler which supports this option
+ \value OptimizedWrite A handler which supports this option
is expected to turn on optimization flags when writing.
- \value ProgressiveScanWrite. A handler which supports
+ \value ProgressiveScanWrite A handler which supports
this option is expected to write the image as a progressive scan image.
- \value ImageTransformation. A handler which supports this option can read
+ \value ImageTransformation A handler which supports this option can read
the transformation metadata of an image. A handler that supports this option
should not apply the transformation itself.
-
-\if !defined(qt6)
- \value TransformedByDefault. A handler that reports support for this feature
- will have image transformation metadata applied by default on read.
-\endif
*/
/*! \enum QImageIOHandler::Transformation
@@ -580,7 +539,7 @@ bool QImageIOHandler::allocateImage(QSize size, QImage::Format format, QImage *i
image->detach();
} else {
if (const int mbLimit = QImageReader::allocationLimit()) {
- qsizetype depth = qt_depthForFormat(format);
+ qsizetype depth = qMax(qt_depthForFormat(format), 32); // Effective gui depth = 32
QImageData::ImageSizeParameters szp =
QImageData::calculateImageParameters(size.width(), size.height(), depth);
if (!szp.isValid())
@@ -652,3 +611,5 @@ QImageIOPlugin::~QImageIOPlugin()
#endif // QT_NO_IMAGEFORMATPLUGIN
QT_END_NAMESPACE
+
+#include "moc_qimageiohandler.cpp"
diff --git a/src/gui/image/qimageiohandler.h b/src/gui/image/qimageiohandler.h
index 8eb5264499..ccd215203a 100644
--- a/src/gui/image/qimageiohandler.h
+++ b/src/gui/image/qimageiohandler.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGEIOHANDLER_H
#define QIMAGEIOHANDLER_H
diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp
index f383e7a60e..f6d891eed9 100644
--- a/src/gui/image/qimagepixmapcleanuphooks.cpp
+++ b/src/gui/image/qimagepixmapcleanuphooks.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qimagepixmapcleanuphooks_p.h"
#include <qpa/qplatformpixmap.h>
diff --git a/src/gui/image/qimagepixmapcleanuphooks_p.h b/src/gui/image/qimagepixmapcleanuphooks_p.h
index 29144c6656..3a3d5aa5f8 100644
--- a/src/gui/image/qimagepixmapcleanuphooks_p.h
+++ b/src/gui/image/qimagepixmapcleanuphooks_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGEPIXMAP_CLEANUPHOOKS_P_H
#define QIMAGEPIXMAP_CLEANUPHOOKS_P_H
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 8af36f911b..9366e9cbb1 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QIMAGEREADER_DEBUG
@@ -47,7 +11,6 @@
\inmodule QtGui
\reentrant
\ingroup painting
- \ingroup io
The most common way to read images is through QImage and QPixmap's
constructors, or by calling QImage::load() and
@@ -172,6 +135,10 @@
QT_BEGIN_NAMESPACE
using namespace QImageReaderWriterHelpers;
+using namespace Qt::StringLiterals;
+
+Q_TRACE_POINT(qtgui, QImageReader_read_before_reading, QImageReader *reader, const QString &filename);
+Q_TRACE_POINT(qtgui, QImageReader_read_after_reading, QImageReader *reader, bool result);
static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
const QByteArray &format,
@@ -186,7 +153,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
QByteArray suffix;
#ifndef QT_NO_IMAGEFORMATPLUGIN
- static QBasicMutex mutex;
+ Q_CONSTINIT static QBasicMutex mutex;
const auto locker = qt_scoped_lock(mutex);
typedef QMultiMap<int, QString> PluginKeyMap;
@@ -271,7 +238,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
}
}
} else {
- const int testIndex = keyMap.key(QLatin1String(testFormat), -1);
+ const int testIndex = keyMap.key(QLatin1StringView(testFormat), -1);
if (testIndex != -1) {
QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(testIndex));
if (plugin && plugin->capabilities(device, testFormat) & QImageIOPlugin::CanRead) {
@@ -496,7 +463,7 @@ public:
static int maxAlloc;
};
-int QImageReaderPrivate::maxAlloc = 128; // 128 MB is enough for an 8K 32bpp image
+int QImageReaderPrivate::maxAlloc = 256; // 256 MB is enough for an 8K 64bpp image
/*!
\internal
@@ -519,9 +486,9 @@ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq)
*/
QImageReaderPrivate::~QImageReaderPrivate()
{
+ delete handler;
if (deleteDevice)
delete device;
- delete handler;
}
/*!
@@ -529,6 +496,9 @@ QImageReaderPrivate::~QImageReaderPrivate()
*/
bool QImageReaderPrivate::initHandler()
{
+ if (handler)
+ return true;
+
// check some preconditions
if (!device || (!deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly))) {
imageReaderError = QImageReader::DeviceError;
@@ -559,14 +529,15 @@ bool QImageReaderPrivate::initHandler()
int currentExtension = 0;
QString fileName = file->fileName();
+ bool fileIsOpen;
do {
- file->setFileName(fileName + QLatin1Char('.')
- + QLatin1String(extensions.at(currentExtension++).constData()));
- file->open(QIODevice::ReadOnly);
- } while (!file->isOpen() && currentExtension < extensions.size());
+ file->setFileName(fileName + u'.'
+ + QLatin1StringView(extensions.at(currentExtension++).constData()));
+ fileIsOpen = file->open(QIODevice::ReadOnly);
+ } while (!fileIsOpen && currentExtension < extensions.size());
- if (!device->isOpen()) {
+ if (!fileIsOpen) {
imageReaderError = QImageReader::FileNotFoundError;
errorString = QImageReader::tr("File not found");
file->setFileName(fileName); // restore the old file name
@@ -575,7 +546,7 @@ bool QImageReaderPrivate::initHandler()
}
// assign a handler
- if (!handler && (handler = createReadHandlerHelper(device, format, autoDetectImageFormat, ignoresFormatAndExtension)) == nullptr) {
+ if ((handler = createReadHandlerHelper(device, format, autoDetectImageFormat, ignoresFormatAndExtension)) == nullptr) {
imageReaderError = QImageReader::UnsupportedFormatError;
errorString = QImageReader::tr("Unsupported image format");
return false;
@@ -588,7 +559,7 @@ bool QImageReaderPrivate::initHandler()
*/
void QImageReaderPrivate::getText()
{
- if (text.isEmpty() && (handler || initHandler()) && handler->supportsOption(QImageIOHandler::Description))
+ if (text.isEmpty() && q->supportsOption(QImageIOHandler::Description))
text = qt_getImageTextFromDescription(handler->option(QImageIOHandler::Description).toString());
}
@@ -778,12 +749,12 @@ bool QImageReader::decideFormatFromContent() const
*/
void QImageReader::setDevice(QIODevice *device)
{
+ delete d->handler;
+ d->handler = nullptr;
if (d->device && d->deleteDevice)
delete d->device;
d->device = device;
d->deleteDevice = false;
- delete d->handler;
- d->handler = nullptr;
d->text.clear();
}
@@ -878,10 +849,7 @@ int QImageReader::quality() const
*/
QSize QImageReader::size() const
{
- if (!d->initHandler())
- return QSize();
-
- if (d->handler->supportsOption(QImageIOHandler::Size))
+ if (supportsOption(QImageIOHandler::Size))
return d->handler->option(QImageIOHandler::Size).toSize();
return QSize();
@@ -901,10 +869,7 @@ QSize QImageReader::size() const
*/
QImage::Format QImageReader::imageFormat() const
{
- if (!d->initHandler())
- return QImage::Format_Invalid;
-
- if (d->handler->supportsOption(QImageIOHandler::ImageFormat))
+ if (supportsOption(QImageIOHandler::ImageFormat))
return (QImage::Format)d->handler->option(QImageIOHandler::ImageFormat).toInt();
return QImage::Format_Invalid;
@@ -976,6 +941,10 @@ QRect QImageReader::clipRect() const
support scaling), QImageReader will use QImage::scale() with
Qt::SmoothScaling.
+ If only one dimension is set in \a size, the other one will be
+ computed from the image's \l {size()} {natural size} so as to
+ maintain the aspect ratio.
+
\sa scaledSize(), setClipRect(), setScaledClipRect()
*/
void QImageReader::setScaledSize(const QSize &size)
@@ -1026,9 +995,7 @@ QRect QImageReader::scaledClipRect() const
*/
void QImageReader::setBackgroundColor(const QColor &color)
{
- if (!d->initHandler())
- return;
- if (d->handler->supportsOption(QImageIOHandler::BackgroundColor))
+ if (supportsOption(QImageIOHandler::BackgroundColor))
d->handler->setOption(QImageIOHandler::BackgroundColor, color);
}
@@ -1043,9 +1010,7 @@ void QImageReader::setBackgroundColor(const QColor &color)
*/
QColor QImageReader::backgroundColor() const
{
- if (!d->initHandler())
- return QColor();
- if (d->handler->supportsOption(QImageIOHandler::BackgroundColor))
+ if (supportsOption(QImageIOHandler::BackgroundColor))
return qvariant_cast<QColor>(d->handler->option(QImageIOHandler::BackgroundColor));
return QColor();
}
@@ -1060,9 +1025,7 @@ QColor QImageReader::backgroundColor() const
*/
bool QImageReader::supportsAnimation() const
{
- if (!d->initHandler())
- return false;
- if (d->handler->supportsOption(QImageIOHandler::Animation))
+ if (supportsOption(QImageIOHandler::Animation))
return d->handler->option(QImageIOHandler::Animation).toBool();
return false;
}
@@ -1074,10 +1037,7 @@ bool QImageReader::supportsAnimation() const
*/
QByteArray QImageReader::subType() const
{
- if (!d->initHandler())
- return QByteArray();
-
- if (d->handler->supportsOption(QImageIOHandler::SubType))
+ if (supportsOption(QImageIOHandler::SubType))
return d->handler->option(QImageIOHandler::SubType).toByteArray();
return QByteArray();
}
@@ -1089,10 +1049,7 @@ QByteArray QImageReader::subType() const
*/
QList<QByteArray> QImageReader::supportedSubTypes() const
{
- if (!d->initHandler())
- return QList<QByteArray>();
-
- if (d->handler->supportsOption(QImageIOHandler::SupportedSubTypes))
+ if (supportsOption(QImageIOHandler::SupportedSubTypes))
return qvariant_cast<QList<QByteArray> >(d->handler->option(QImageIOHandler::SupportedSubTypes));
return QList<QByteArray>();
}
@@ -1108,7 +1065,7 @@ QList<QByteArray> QImageReader::supportedSubTypes() const
QImageIOHandler::Transformations QImageReader::transformation() const
{
int option = QImageIOHandler::TransformationNone;
- if (d->initHandler() && d->handler->supportsOption(QImageIOHandler::ImageTransformation))
+ if (supportsOption(QImageIOHandler::ImageTransformation))
option = d->handler->option(QImageIOHandler::ImageTransformation).toInt();
return QImageIOHandler::Transformations(option);
}
@@ -1223,31 +1180,48 @@ bool QImageReader::read(QImage *image)
return false;
}
- if (!d->handler && !d->initHandler())
+ if (!d->initHandler())
return false;
+ QSize scaledSize = d->scaledSize;
+ if ((scaledSize.width() <= 0 && scaledSize.height() > 0) ||
+ (scaledSize.height() <= 0 && scaledSize.width() > 0)) {
+ // if only one dimension is given, let's try to calculate the second one
+ // based on the original image size and maintaining the aspect ratio
+ if (const QSize originalSize = size(); !originalSize.isEmpty()) {
+ if (scaledSize.width() <= 0) {
+ const auto ratio = qreal(scaledSize.height()) / originalSize.height();
+ scaledSize.setWidth(qRound(originalSize.width() * ratio));
+ } else {
+ const auto ratio = qreal(scaledSize.width()) / originalSize.width();
+ scaledSize.setHeight(qRound(originalSize.height() * ratio));
+ }
+ }
+ }
+
+ const bool supportScaledSize = supportsOption(QImageIOHandler::ScaledSize) && scaledSize.isValid();
+ const bool supportClipRect = supportsOption(QImageIOHandler::ClipRect) && !d->clipRect.isNull();
+ const bool supportScaledClipRect = supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull();
+
// set the handler specific options.
- if (d->handler->supportsOption(QImageIOHandler::ScaledSize) && d->scaledSize.isValid()) {
- if ((d->handler->supportsOption(QImageIOHandler::ClipRect) && !d->clipRect.isNull())
- || d->clipRect.isNull()) {
+ if (supportScaledSize) {
+ if (supportClipRect || d->clipRect.isNull()) {
// Only enable the ScaledSize option if there is no clip rect, or
// if the handler also supports ClipRect.
- d->handler->setOption(QImageIOHandler::ScaledSize, d->scaledSize);
+ d->handler->setOption(QImageIOHandler::ScaledSize, scaledSize);
}
}
- if (d->handler->supportsOption(QImageIOHandler::ClipRect) && !d->clipRect.isNull())
+ if (supportClipRect)
d->handler->setOption(QImageIOHandler::ClipRect, d->clipRect);
- if (d->handler->supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull())
+ if (supportScaledClipRect)
d->handler->setOption(QImageIOHandler::ScaledClipRect, d->scaledClipRect);
- if (d->handler->supportsOption(QImageIOHandler::Quality))
+ if (supportsOption(QImageIOHandler::Quality))
d->handler->setOption(QImageIOHandler::Quality, d->quality);
// read the image
+ QString filename = fileName();
if (Q_TRACE_ENABLED(QImageReader_read_before_reading)) {
- QString fileName = QStringLiteral("unknown");
- if (QFile *file = qobject_cast<QFile *>(d->device))
- fileName = file->fileName();
- Q_TRACE(QImageReader_read_before_reading, this, fileName);
+ Q_TRACE(QImageReader_read_before_reading, this, filename.isEmpty() ? u"unknown"_s : filename);
}
const bool result = d->handler->read(image);
@@ -1262,9 +1236,9 @@ bool QImageReader::read(QImage *image)
// provide default implementations for any unsupported image
// options
- if (d->handler->supportsOption(QImageIOHandler::ClipRect) && !d->clipRect.isNull()) {
- if (d->handler->supportsOption(QImageIOHandler::ScaledSize) && d->scaledSize.isValid()) {
- if (d->handler->supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull()) {
+ if (supportClipRect) {
+ if (supportScaledSize) {
+ if (supportScaledClipRect) {
// all features are supported by the handler; nothing to do.
} else {
// the image is already scaled, so apply scaled clipping.
@@ -1272,12 +1246,12 @@ bool QImageReader::read(QImage *image)
*image = image->copy(d->scaledClipRect);
}
} else {
- if (d->handler->supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull()) {
+ if (supportScaledClipRect) {
// supports scaled clipping but not scaling, most
// likely a broken handler.
} else {
- if (d->scaledSize.isValid()) {
- *image = image->scaled(d->scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ if (scaledSize.isValid()) {
+ *image = image->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
if (d->scaledClipRect.isValid()) {
*image = image->copy(d->scaledClipRect);
@@ -1285,8 +1259,8 @@ bool QImageReader::read(QImage *image)
}
}
} else {
- if (d->handler->supportsOption(QImageIOHandler::ScaledSize) && d->scaledSize.isValid() && d->clipRect.isNull()) {
- if (d->handler->supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull()) {
+ if (supportScaledSize && d->clipRect.isNull()) {
+ if (supportScaledClipRect) {
// nothing to do (ClipRect is ignored!)
} else {
// provide all workarounds.
@@ -1295,7 +1269,7 @@ bool QImageReader::read(QImage *image)
}
}
} else {
- if (d->handler->supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull()) {
+ if (supportScaledClipRect) {
// this makes no sense; a handler that supports
// ScaledClipRect but not ScaledSize is broken, and we
// can't work around it.
@@ -1303,8 +1277,8 @@ bool QImageReader::read(QImage *image)
// provide all workarounds.
if (d->clipRect.isValid())
*image = image->copy(d->clipRect);
- if (d->scaledSize.isValid())
- *image = image->scaled(d->scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ if (scaledSize.isValid())
+ *image = image->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
if (d->scaledClipRect.isValid())
*image = image->copy(d->scaledClipRect);
}
@@ -1314,8 +1288,8 @@ bool QImageReader::read(QImage *image)
// successful read; check for "@Nx" file name suffix and set device pixel ratio.
static bool disableNxImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING");
if (!disableNxImageLoading) {
- const QByteArray suffix = QFileInfo(fileName()).baseName().right(3).toLatin1();
- if (suffix.length() == 3 && suffix[0] == '@' && suffix[1] >= '2' && suffix[1] <= '9' && suffix[2] == 'x')
+ const QByteArray suffix = QFileInfo(filename).baseName().right(3).toLatin1();
+ if (suffix.size() == 3 && suffix[0] == '@' && suffix[1] >= '2' && suffix[1] <= '9' && suffix[2] == 'x')
image->setDevicePixelRatio(suffix[1] - '0');
}
if (autoTransform())
@@ -1584,7 +1558,13 @@ QList<QByteArray> QImageReader::imageFormatsForMimeType(const QByteArray &mimeTy
*/
int QImageReader::allocationLimit()
{
- return QImageReaderPrivate::maxAlloc;
+ static int envLimit = []() {
+ bool ok = false;
+ int res = qEnvironmentVariableIntValue("QT_IMAGEIO_MAXALLOC", &ok);
+ return ok ? res : -1;
+ }();
+
+ return envLimit >= 0 ? envLimit : QImageReaderPrivate::maxAlloc;
}
/*!
@@ -1592,11 +1572,18 @@ int QImageReader::allocationLimit()
Sets the allocation limit to \a mbLimit megabytes. Images that would
require a QImage memory allocation above this limit will be rejected.
+ If \a mbLimit is 0, the allocation size check will be disabled.
This limit helps applications avoid unexpectedly large memory usage from
loading corrupt image files. It is normally not needed to change it. The
default limit is large enough for all commonly used image sizes.
+ At runtime, this value may be overridden by the environment variable \c QT_IMAGEIO_MAXALLOC.
+
+ \note The memory requirements are calculated for a minimum of 32 bits per pixel, since Qt will
+ typically convert an image to that depth when it is used in GUI. This means that the effective
+ allocation limit is significantly smaller than \a mbLimit when reading 1 bpp and 8 bpp images.
+
\sa allocationLimit()
*/
void QImageReader::setAllocationLimit(int mbLimit)
diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h
index 23c8a916d2..c5ea883c83 100644
--- a/src/gui/image/qimagereader.h
+++ b/src/gui/image/qimagereader.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGEREADER_H
#define QIMAGEREADER_H
diff --git a/src/gui/image/qimagereaderwriterhelpers.cpp b/src/gui/image/qimagereaderwriterhelpers.cpp
index dd56d887a7..502b0f95f0 100644
--- a/src/gui/image/qimagereaderwriterhelpers.cpp
+++ b/src/gui/image/qimagereaderwriterhelpers.cpp
@@ -1,57 +1,23 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qimagereaderwriterhelpers_p.h"
-#include <qjsonarray.h>
+#include <qcborarray.h>
#include <qmutex.h>
#include <private/qfactoryloader_p.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
namespace QImageReaderWriterHelpers {
#ifndef QT_NO_IMAGEFORMATPLUGIN
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats")))
-Q_GLOBAL_STATIC(QMutex, loaderMutex)
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, irhLoader,
+ (QImageIOHandlerFactoryInterface_iid, "/imageformats"_L1))
+Q_GLOBAL_STATIC(QMutex, irhLoaderMutex)
static void appendImagePluginFormats(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
@@ -81,13 +47,12 @@ static void appendImagePluginMimeTypes(QFactoryLoader *loader,
QList<QByteArray> *result,
QList<QByteArray> *resultKeys = nullptr)
{
- QList<QJsonObject> metaDataList = loader->metaData();
-
+ QList<QPluginParsedMetaData> metaDataList = loader->metaData();
const int pluginCount = metaDataList.size();
for (int i = 0; i < pluginCount; ++i) {
- const QJsonObject metaData = metaDataList.at(i).value(QLatin1String("MetaData")).toObject();
- const QJsonArray keys = metaData.value(QLatin1String("Keys")).toArray();
- const QJsonArray mimeTypes = metaData.value(QLatin1String("MimeTypes")).toArray();
+ const QCborMap metaData = metaDataList.at(i).value(QtPluginMetaDataKeys::MetaData).toMap();
+ const QCborArray keys = metaData.value("Keys"_L1).toArray();
+ const QCborArray mimeTypes = metaData.value("MimeTypes"_L1).toArray();
QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(loader->instance(i));
const int keyCount = keys.size();
for (int k = 0; k < keyCount; ++k) {
@@ -103,9 +68,9 @@ static void appendImagePluginMimeTypes(QFactoryLoader *loader,
QSharedPointer<QFactoryLoader> pluginLoader()
{
- loaderMutex()->lock();
- return QSharedPointer<QFactoryLoader>(loader(), [](QFactoryLoader *) {
- loaderMutex()->unlock();
+ irhLoaderMutex()->lock();
+ return QSharedPointer<QFactoryLoader>(irhLoader(), [](QFactoryLoader *) {
+ irhLoaderMutex()->unlock();
});
}
@@ -124,7 +89,7 @@ QList<QByteArray> supportedImageFormats(Capability cap)
formats << _qt_BuiltInFormats[i].extension;
#ifndef QT_NO_IMAGEFORMATPLUGIN
- appendImagePluginFormats(loader(), pluginCapability(cap), &formats);
+ appendImagePluginFormats(irhLoader(), pluginCapability(cap), &formats);
#endif // QT_NO_IMAGEFORMATPLUGIN
std::sort(formats.begin(), formats.end());
@@ -132,15 +97,17 @@ QList<QByteArray> supportedImageFormats(Capability cap)
return formats;
}
+static constexpr QByteArrayView imagePrefix() noexcept { return "image/"; }
+
QList<QByteArray> supportedMimeTypes(Capability cap)
{
QList<QByteArray> mimeTypes;
mimeTypes.reserve(_qt_NumFormats);
for (const auto &fmt : _qt_BuiltInFormats)
- mimeTypes.append(QByteArrayLiteral("image/") + fmt.mimeType);
+ mimeTypes.emplace_back(imagePrefix() + fmt.mimeType);
#ifndef QT_NO_IMAGEFORMATPLUGIN
- appendImagePluginMimeTypes(loader(), pluginCapability(cap), &mimeTypes);
+ appendImagePluginMimeTypes(irhLoader(), pluginCapability(cap), &mimeTypes);
#endif // QT_NO_IMAGEFORMATPLUGIN
std::sort(mimeTypes.begin(), mimeTypes.end());
@@ -148,11 +115,11 @@ QList<QByteArray> supportedMimeTypes(Capability cap)
return mimeTypes;
}
-QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType, Capability cap)
+QList<QByteArray> imageFormatsForMimeType(QByteArrayView mimeType, Capability cap)
{
QList<QByteArray> formats;
- if (mimeType.startsWith("image/")) {
- const QByteArray type = mimeType.mid(sizeof("image/") - 1);
+ if (mimeType.startsWith(imagePrefix())) {
+ const QByteArrayView type = mimeType.mid(imagePrefix().size());
for (const auto &fmt : _qt_BuiltInFormats) {
if (fmt.mimeType == type && !formats.contains(fmt.extension))
formats << fmt.extension;
@@ -162,7 +129,7 @@ QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType, Capability
#ifndef QT_NO_IMAGEFORMATPLUGIN
QList<QByteArray> mimeTypes;
QList<QByteArray> keys;
- appendImagePluginMimeTypes(loader(), pluginCapability(cap), &mimeTypes, &keys);
+ appendImagePluginMimeTypes(irhLoader(), pluginCapability(cap), &mimeTypes, &keys);
for (int i = 0; i < mimeTypes.size(); ++i) {
if (mimeTypes.at(i) == mimeType) {
const auto &key = keys.at(i);
diff --git a/src/gui/image/qimagereaderwriterhelpers_p.h b/src/gui/image/qimagereaderwriterhelpers_p.h
index ae1141b3ab..930a57b536 100644
--- a/src/gui/image/qimagereaderwriterhelpers_p.h
+++ b/src/gui/image/qimagereaderwriterhelpers_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGEREADERWRITERHELPERS_P_H
#define QIMAGEREADERWRITERHELPERS_P_H
@@ -130,7 +94,7 @@ enum Capability {
};
QList<QByteArray> supportedImageFormats(Capability cap);
QList<QByteArray> supportedMimeTypes(Capability cap);
-QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType, Capability cap);
+QList<QByteArray> imageFormatsForMimeType(QByteArrayView mimeType, Capability cap);
}
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index 668d366208..d2176e4189 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QImageWriter
@@ -45,7 +9,6 @@
\inmodule QtGui
\reentrant
\ingroup painting
- \ingroup io
QImageWriter supports setting format specific options, such as
compression level and quality, prior to storing the
@@ -133,6 +96,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static QImageIOHandler *createWriteHandlerHelper(QIODevice *device,
const QByteArray &format)
{
@@ -349,9 +314,9 @@ QImageWriter::QImageWriter(const QString &fileName, const QByteArray &format)
*/
QImageWriter::~QImageWriter()
{
+ delete d->handler;
if (d->deleteDevice)
delete d->device;
- delete d->handler;
delete d;
}
@@ -396,13 +361,13 @@ QByteArray QImageWriter::format() const
*/
void QImageWriter::setDevice(QIODevice *device)
{
+ delete d->handler;
+ d->handler = nullptr;
if (d->device && d->deleteDevice)
delete d->device;
d->device = device;
d->deleteDevice = false;
- delete d->handler;
- d->handler = nullptr;
}
/*!
@@ -646,8 +611,8 @@ QImageIOHandler::Transformations QImageWriter::transformation() const
void QImageWriter::setText(const QString &key, const QString &text)
{
if (!d->description.isEmpty())
- d->description += QLatin1String("\n\n");
- d->description += key.simplified() + QLatin1String(": ") + text.simplified();
+ d->description += "\n\n"_L1;
+ d->description += key.simplified() + ": "_L1 + text.simplified();
}
/*!
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index 3969acbe80..b01161025a 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGEWRITER_H
#define QIMAGEWRITER_H
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index b00d3ff25c..435f1dced9 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QMovie
@@ -89,7 +53,7 @@
Call supportedFormats() for a list of formats that QMovie supports.
- \sa QLabel, QImageReader, {Movie Example}
+ \sa QLabel, QImageReader
*/
/*! \enum QMovie::MovieState
@@ -180,11 +144,11 @@
#include "qrect.h"
#include "qelapsedtimer.h"
#include "qtimer.h"
-#include "qpair.h"
#include "qmap.h"
#include "qlist.h"
#include "qbuffer.h"
#include "qdir.h"
+#include "qloggingcategory.h"
#include "private/qobject_p.h"
#include "private/qproperty_p.h"
@@ -192,6 +156,8 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
+
class QFrameInfo
{
public:
@@ -342,6 +308,19 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
return QFrameInfo(); // Invalid
}
+ // For an animated image format, the tradition is that QMovie calls read()
+ // until canRead() == false, because the number of frames may not be known
+ // in advance; but if we're abusing a multi-frame format as an animation,
+ // canRead() may remain true, and we need to stop after reading the maximum
+ // number of frames that the image provides.
+ const bool supportsAnimation = reader->supportsOption(QImageIOHandler::Animation);
+ const int stopAtFrame = supportsAnimation ? -1 : frameCount();
+
+ // For an animated image format, QImageIOHandler::nextImageDelay() should
+ // provide the time to wait until showing the next frame; but multi-frame
+ // formats are not expected to provide this value, so use 1000 ms by default.
+ const int nextFrameDelay = supportsAnimation ? reader->nextImageDelay() : 1000;
+
if (cacheMode == QMovie::CacheNone) {
if (frameNumber != currentFrameNumber+1) {
// Non-sequential frame access
@@ -371,8 +350,12 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
}
}
}
- if (reader->canRead()) {
+ qCDebug(lcImageIo, "CacheNone: read frame %d of %d", frameNumber, stopAtFrame);
+ if (stopAtFrame > 0 ? (frameNumber < stopAtFrame) : reader->canRead()) {
// reader says we can read. Attempt to actually read image
+ // But if it's a non-animated multi-frame format and we know the frame count, stop there.
+ if (stopAtFrame > 0)
+ reader->jumpToImage(frameNumber);
QImage anImage = reader->read();
if (anImage.isNull()) {
// Reading image failed.
@@ -380,7 +363,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
}
if (frameNumber > greatestFrameNumber)
greatestFrameNumber = frameNumber;
- return QFrameInfo(QPixmap::fromImage(std::move(anImage)), reader->nextImageDelay());
+ return QFrameInfo(QPixmap::fromImage(std::move(anImage)), nextFrameDelay);
} else if (frameNumber != 0) {
// We've read all frames now. Return an end marker
haveReadAll = true;
@@ -396,15 +379,19 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
if (frameNumber > greatestFrameNumber) {
// Frame hasn't been read from file yet. Try to do it
for (int i = greatestFrameNumber + 1; i <= frameNumber; ++i) {
- if (reader->canRead()) {
+ qCDebug(lcImageIo, "CacheAll: read frame %d of %d", frameNumber, stopAtFrame);
+ if (stopAtFrame > 0 ? (frameNumber < stopAtFrame) : reader->canRead()) {
// reader says we can read. Attempt to actually read image
+ // But if it's a non-animated multi-frame format and we know the frame count, stop there.
+ if (stopAtFrame > 0)
+ reader->jumpToImage(frameNumber);
QImage anImage = reader->read();
if (anImage.isNull()) {
// Reading image failed.
return QFrameInfo(); // Invalid
}
greatestFrameNumber = i;
- QFrameInfo info(QPixmap::fromImage(std::move(anImage)), reader->nextImageDelay());
+ QFrameInfo info(QPixmap::fromImage(std::move(anImage)), nextFrameDelay);
// Cache it!
frameMap.insert(i, info);
if (i == frameNumber) {
@@ -462,11 +449,7 @@ bool QMoviePrivate::next()
}
// Image and delay OK, update internal state
currentFrameNumber = nextFrameNumber++;
- QSize scaledSize = reader->scaledSize();
- if (scaledSize.isValid() && (scaledSize != info.pixmap.size()))
- currentPixmap = QPixmap::fromImage( info.pixmap.toImage().scaled(scaledSize) );
- else
- currentPixmap = info.pixmap;
+ currentPixmap = info.pixmap;
if (!speed)
return true;
diff --git a/src/gui/image/qmovie.h b/src/gui/image/qmovie.h
index e1452ed760..874e6189ba 100644
--- a/src/gui/image/qmovie.h
+++ b/src/gui/image/qmovie.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMOVIE_H
#define QMOVIE_H
diff --git a/src/gui/image/qpaintengine_pic.cpp b/src/gui/image/qpaintengine_pic.cpp
index 224938bd9c..438305742c 100644
--- a/src/gui/image/qpaintengine_pic.cpp
+++ b/src/gui/image/qpaintengine_pic.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qpaintengine_p.h"
#include "private/qpainter_p.h"
diff --git a/src/gui/image/qpaintengine_pic_p.h b/src/gui/image/qpaintengine_pic_p.h
index c9e4b43197..44d0eb63db 100644
--- a/src/gui/image/qpaintengine_pic_p.h
+++ b/src/gui/image/qpaintengine_pic_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTENGINE_PIC_P_H
#define QPAINTENGINE_PIC_P_H
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index 1f16318f2e..da8c5ef1e5 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpicture.h"
#include <private/qpicture_p.h>
@@ -850,6 +814,8 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
bool(ul & QPainter::Antialiasing));
painter->setRenderHint(QPainter::SmoothPixmapTransform,
bool(ul & QPainter::SmoothPixmapTransform));
+ painter->setRenderHint(QPainter::NonCosmeticBrushPatterns,
+ bool(ul & QPainter::NonCosmeticBrushPatterns));
break;
case QPicturePrivate::PdcSetCompositionMode:
s >> ul;
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index c3e622a1fe..bc8be6c4e9 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -1,49 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPICTURE_H
#define QPICTURE_H
#include <QtGui/qtguiglobal.h>
#include <QtCore/qiodevice.h>
+#include <QtCore/qshareddata.h>
#include <QtCore/qstringlist.h>
-#include <QtCore/qsharedpointer.h>
#include <QtGui/qpaintdevice.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/image/qpicture_p.h b/src/gui/image/qpicture_p.h
index 6e9510c77f..c512f49320 100644
--- a/src/gui/image/qpicture_p.h
+++ b/src/gui/image/qpicture_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPICTURE_P_H
#define QPICTURE_P_H
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 3d46dc4a6b..89b8d5303b 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qglobal.h>
@@ -68,8 +32,15 @@
#include <qtgui_tracepoints_p.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+Q_TRACE_PARAM_REPLACE(Qt::AspectRatioMode, int);
+Q_TRACE_PARAM_REPLACE(Qt::TransformationMode, int);
+
// MSVC 19.28 does show spurious warning "C4723: potential divide by 0" for code that divides
// by height() in release builds. Anyhow, all the code paths in this file are only executed
// for valid QPixmap's, where height() cannot be 0. Therefore disable the warning.
@@ -81,17 +52,11 @@ static bool qt_pixmap_thread_test()
qFatal("QPixmap: Must construct a QGuiApplication before a QPixmap");
return false;
}
-
- if (qApp->thread() != QThread::currentThread()) {
- bool fail = false;
- if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) {
- printf("Platform plugin does not support threaded pixmaps!\n");
- fail = true;
- }
- if (fail) {
- qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread");
- return false;
- }
+ if (QGuiApplicationPrivate::instance()
+ && qApp->thread() != QThread::currentThread()
+ && !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) {
+ qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread on this platform");
+ return false;
}
return true;
}
@@ -658,7 +623,9 @@ void QPixmap::setDevicePixelRatio(qreal scaleFactor)
This value should be used when using the pixmap size in user interface
size calculations.
- The return value is equivalent to pixmap.size() / pixmap.devicePixelRatio(),
+ The return value is equivalent to pixmap.size() / pixmap.devicePixelRatio().
+
+ \since 6.2
*/
QSizeF QPixmap::deviceIndependentSize() const
{
@@ -748,9 +715,9 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers
if (info.completeSuffix().isEmpty() || info.exists()) {
const bool inGuiThread = qApp->thread() == QThread::currentThread();
- QString key = QLatin1String("qt_pixmap")
+ QString key = "qt_pixmap"_L1
% info.absoluteFilePath()
- % HexString<uint>(info.lastModified().toSecsSinceEpoch())
+ % HexString<uint>(info.lastModified(QTimeZone::UTC).toSecsSinceEpoch())
% HexString<quint64>(info.size())
% HexString<uint>(data ? data->pixelType() : QPlatformPixmap::PixmapType);
@@ -905,6 +872,7 @@ void QPixmap::fill(const QColor &color)
// it will be filled with new pixel data anyway.
QPlatformPixmap *d = data->createCompatiblePlatformPixmap();
d->resize(data->width(), data->height());
+ d->setDevicePixelRatio(data->devicePixelRatio());
data = d;
}
data->fill(color);
@@ -1067,7 +1035,7 @@ bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags fla
Transformations}
*/
-QPixmap QPixmap::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode) const
+QPixmap Q_TRACE_INSTRUMENT(qtgui) QPixmap::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode) const
{
if (isNull()) {
qWarning("QPixmap::scaled: Pixmap is a null pixmap");
@@ -1105,7 +1073,7 @@ QPixmap QPixmap::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::Tran
\sa isNull(), {QPixmap#Pixmap Transformations}{Pixmap
Transformations}
*/
-QPixmap QPixmap::scaledToWidth(int w, Qt::TransformationMode mode) const
+QPixmap Q_TRACE_INSTRUMENT(qtgui) QPixmap::scaledToWidth(int w, Qt::TransformationMode mode) const
{
if (isNull()) {
qWarning("QPixmap::scaleWidth: Pixmap is a null pixmap");
@@ -1135,7 +1103,7 @@ QPixmap QPixmap::scaledToWidth(int w, Qt::TransformationMode mode) const
\sa isNull(), {QPixmap#Pixmap Transformations}{Pixmap
Transformations}
*/
-QPixmap QPixmap::scaledToHeight(int h, Qt::TransformationMode mode) const
+QPixmap Q_TRACE_INSTRUMENT(qtgui) QPixmap::scaledToHeight(int h, Qt::TransformationMode mode) const
{
if (isNull()) {
qWarning("QPixmap::scaleHeight: Pixmap is a null pixmap");
@@ -1312,8 +1280,9 @@ QPixmap QPixmap::transformed(const QTransform &transform,
QPixmap using the fromImage(). If this is too expensive an
operation, you can use QBitmap::fromImage() instead.
- To convert a QPixmap to and from HICON you can use the QtWinExtras
- functions QtWin::toHICON() and QtWin::fromHICON() respectively.
+ To convert a QPixmap to and from HICON you can use the
+ QImage::toHICON() and QImage::fromHICON() functions respectively
+ (after converting the QPixmap to a QImage, as explained above).
\section1 Pixmap Transformations
@@ -1442,7 +1411,7 @@ void QPixmap::detach()
return;
// QPixmap.data member may be QRuntimePlatformPixmap so use handle() function to get
- // the actual underlaying runtime pixmap data.
+ // the actual underlying runtime pixmap data.
QPlatformPixmap *pd = handle();
QPlatformPixmap::ClassId id = pd->classId();
if (id == QPlatformPixmap::RasterClass) {
@@ -1484,9 +1453,9 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
return QPixmap();
}
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
+ std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImage(image, flags);
- return QPixmap(data.take());
+ return QPixmap(data.release());
}
/*!
@@ -1511,9 +1480,9 @@ QPixmap QPixmap::fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags)
return QPixmap();
}
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
+ std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImageInPlace(image, flags);
- return QPixmap(data.take());
+ return QPixmap(data.release());
}
/*!
@@ -1535,9 +1504,9 @@ QPixmap QPixmap::fromImageReader(QImageReader *imageReader, Qt::ImageConversionF
return QPixmap();
}
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
+ std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImageReader(imageReader, flags);
- return QPixmap(data.take());
+ return QPixmap(data.release());
}
/*!
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 9d4d8e582d..5be98be14d 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXMAP_H
#define QPIXMAP_H
@@ -44,8 +8,8 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qcolor.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qshareddata.h>
#include <QtCore/qstring.h> // char*->QString conversion
-#include <QtCore/qsharedpointer.h>
#include <QtGui/qimage.h>
#include <QtGui/qtransform.h>
@@ -77,7 +41,7 @@ public:
QPixmap &operator=(const QPixmap &);
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QPixmap)
inline void swap(QPixmap &other) noexcept
- { qSwap(data, other.data); }
+ { data.swap(other.data); }
bool operator==(const QPixmap &) const = delete;
bool operator!=(const QPixmap &) const = delete;
@@ -165,7 +129,6 @@ private:
QPixmap(const QSize &s, int type);
void doInit(int, int, int);
- Q_DUMMY_COMPARISON_OPERATOR(QPixmap)
friend class QPlatformPixmap;
friend class QBitmap;
friend class QPaintDevice;
@@ -200,7 +163,7 @@ inline void QPixmap::scroll(int dx, int dy, int ax, int ay, int awidth, int ahei
inline bool QPixmap::loadFromData(const QByteArray &buf, const char *format,
Qt::ImageConversionFlags flags)
{
- return loadFromData(reinterpret_cast<const uchar *>(buf.constData()), buf.size(), format, flags);
+ return loadFromData(reinterpret_cast<const uchar *>(buf.constData()), uint(buf.size()), format, flags);
}
diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp
index 510a46e7b1..41563bf380 100644
--- a/src/gui/image/qpixmap_blitter.cpp
+++ b/src/gui/image/qpixmap_blitter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpixmap_blitter_p.h"
diff --git a/src/gui/image/qpixmap_blitter_p.h b/src/gui/image/qpixmap_blitter_p.h
index d39905f883..89928026a2 100644
--- a/src/gui/image/qpixmap_blitter_p.h
+++ b/src/gui/image/qpixmap_blitter_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXMAP_BLITTER_P_H
#define QPIXMAP_BLITTER_P_H
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 2732bbd197..6e10bdd562 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpixmap.h"
diff --git a/src/gui/image/qpixmap_raster_p.h b/src/gui/image/qpixmap_raster_p.h
index fe2a1e581d..5f5c117002 100644
--- a/src/gui/image/qpixmap_raster_p.h
+++ b/src/gui/image/qpixmap_raster_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXMAP_RASTER_P_H
#define QPIXMAP_RASTER_P_H
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index aae4a1cbf4..fc601bccfc 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -1,44 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbitmap.h"
#include "qpixmap.h"
+#include <private/qpixmap_win_p.h>
#include <qpa/qplatformpixmap.h>
#include "qpixmap_raster_p.h"
@@ -199,7 +164,7 @@ static QImage copyImageData(const BITMAPINFOHEADER &header, const RGBQUAD *color
Q_ASSERT(DWORD(image.sizeInBytes()) == header.biSizeImage);
memcpy(image.bits(), data, header.biSizeImage);
if (format == QImage::Format_RGB888)
- image = image.rgbSwapped();
+ image = std::move(image).rgbSwapped();
break;
default:
Q_UNREACHABLE();
@@ -242,7 +207,7 @@ static HBITMAP qt_createIconMask(QImage bm)
return hbm;
}
-Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap)
+HBITMAP qt_createIconMask(const QBitmap &bitmap)
{
return qt_createIconMask(bitmap.toImage().convertToFormat(QImage::Format_Mono));
}
@@ -260,7 +225,7 @@ static inline QImage::Format format32(int hbitmapFormat)
return QImage::Format_ARGB32_Premultiplied;
}
-Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapFormat = 0)
+HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapFormat)
{
if (imageIn.isNull())
return nullptr;
@@ -340,6 +305,7 @@ Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapForm
return nullptr;
}
if (!pixels) {
+ DeleteObject(bitmap);
qErrnoWarning("%s, did not allocate pixel data", __FUNCTION__);
return nullptr;
}
@@ -359,7 +325,7 @@ Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapForm
It is the caller's responsibility to free the \c HBITMAP data
after use.
- For usage with with standard GDI calls, such as \c BitBlt(), the image
+ For usage with standard GDI calls, such as \c BitBlt(), the image
should have the format QImage::Format_RGB32.
When using the resulting HBITMAP for the \c AlphaBlend() GDI function,
@@ -386,7 +352,7 @@ HBITMAP QImage::toHBITMAP() const
return qt_imageToWinHBITMAP(*this);
}
-Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0)
+HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat)
{
if (p.isNull())
return nullptr;
@@ -485,7 +451,7 @@ static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int
return copyImageData(info.bmiHeader, bmiColorTable256.bmiColors, data.data(), imageFormat);
}
-Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0)
+QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat)
{
QImage result = imageFromWinHBITMAP_DibSection(bitmap, hbitmapFormat);
if (result.isNull())
@@ -517,7 +483,7 @@ QImage QImage::fromHBITMAP(HBITMAP hbitmap)
return qt_imageFromWinHBITMAP(hbitmap);
}
-Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0)
+QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat)
{
return QPixmap::fromImage(imageFromWinHBITMAP_GetDiBits(bitmap, /* forceQuads */ true, hbitmapFormat));
}
@@ -568,7 +534,7 @@ HICON QImage::toHICON(const QImage &mask) const
return hIcon;
}
-Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p)
+HICON qt_pixmapToWinHICON(const QPixmap &p)
{
QImage mask;
QBitmap maskBitmap = p.mask();
@@ -577,7 +543,7 @@ Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p)
return p.toImage().toHICON(mask);
}
-Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
+QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
{
QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
if (image.isNull())
@@ -677,7 +643,7 @@ QImage QImage::fromHICON(HICON icon)
return image;
}
-Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon)
+QPixmap qt_pixmapFromWinHICON(HICON icon)
{
return QPixmap::fromImage(QImage::fromHICON(icon));
}
diff --git a/src/gui/image/qpixmap_win_p.h b/src/gui/image/qpixmap_win_p.h
new file mode 100644
index 0000000000..64abca3428
--- /dev/null
+++ b/src/gui/image/qpixmap_win_p.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QPIXMAP_WIN_P_H
+#define QPIXMAP_WIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include <QtCore/qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBitmap;
+class QImage;
+class QPixmap;
+
+Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap);
+Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapFormat = 0);
+Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0);
+Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0);
+Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0);
+Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p);
+Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h);
+Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon);
+
+QT_END_NAMESPACE
+
+#endif // QPIXMAP_WIN_P_H
diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index 26cc80b5b0..45c9743f93 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -1,43 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#define Q_TEST_QPIXMAPCACHE
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
#include "qpixmapcache.h"
#include "qobject.h"
#include "qdebug.h"
@@ -45,6 +8,8 @@
#include "qthread.h"
#include "qcoreapplication.h"
+using namespace std::chrono_literals;
+
QT_BEGIN_NAMESPACE
/*!
@@ -93,14 +58,14 @@ QT_BEGIN_NAMESPACE
static const int cache_limit_default = 10240; // 10 MB cache limit
-static inline int cost(const QPixmap &pixmap)
+static inline qsizetype cost(const QPixmap &pixmap)
{
- // make sure to do a 64bit calculation
- const qint64 costKb = static_cast<qint64>(pixmap.width()) *
- pixmap.height() * pixmap.depth() / (8 * 1024);
- const qint64 costMax = std::numeric_limits<int>::max();
+ // make sure to do a 64bit calculation; qsizetype might be smaller
+ const qint64 costKb = static_cast<qint64>(pixmap.width())
+ * pixmap.height() * pixmap.depth() / (8 * 1024);
+ const qint64 costMax = std::numeric_limits<qsizetype>::max();
// a small pixmap should have at least a cost of 1(kb)
- return static_cast<int>(qBound(1LL, costKb, costMax));
+ return static_cast<qsizetype>(qBound(1LL, costKb, costMax));
}
static inline bool qt_pixmapcache_thread_test()
@@ -219,7 +184,6 @@ public:
void timerEvent(QTimerEvent *) override;
bool insert(const QString& key, const QPixmap &pixmap, int cost);
QPixmapCache::Key insert(const QPixmap &pixmap, int cost);
- bool replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost);
bool remove(const QString &key);
bool remove(const QPixmapCache::Key &key);
@@ -239,7 +203,8 @@ public:
bool flushDetachedPixmaps(bool nt);
private:
- enum { soon_time = 10000, flush_time = 30000 };
+ static constexpr auto soon_time = 10s;
+ static constexpr auto flush_time = 30s;
int *keyArray;
int theid;
int ps;
@@ -253,9 +218,15 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qpixmapcache.moc"
QT_END_INCLUDE_NAMESPACE
-size_t qHash(const QPixmapCache::Key &k, size_t seed)
+/*!
+ size_t QPixmapCache::qHash(const Key &key, size_t seed = 0);
+ \since 6.6
+
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+*/
+size_t QPixmapCache::Key::hash(size_t seed) const noexcept
{
- return qHash(QPMCache::get(k)->key, seed);
+ return qHash(this->d ? this->d->key : 0, seed);
}
QPMCache::QPMCache()
@@ -286,24 +257,14 @@ QPMCache::~QPMCache()
*/
bool QPMCache::flushDetachedPixmaps(bool nt)
{
- int mc = maxCost();
- setMaxCost(nt ? totalCost() * 3 / 4 : totalCost() -1);
+ auto mc = maxCost();
+ const qsizetype currentTotal = totalCost();
+ const qsizetype oldSize = size();
+ if (currentTotal)
+ setMaxCost(nt ? currentTotal * 3 / 4 : currentTotal - 1);
setMaxCost(mc);
ps = totalCost();
-
- bool any = false;
- QHash<QString, QPixmapCache::Key>::iterator it = cacheKeys.begin();
- while (it != cacheKeys.end()) {
- if (!contains(it.value())) {
- releaseKey(it.value());
- it = cacheKeys.erase(it);
- any = true;
- } else {
- ++it;
- }
- }
-
- return any;
+ return size() != oldSize;
}
void QPMCache::timerEvent(QTimerEvent *)
@@ -322,22 +283,14 @@ void QPMCache::timerEvent(QTimerEvent *)
QPixmap *QPMCache::object(const QString &key) const
{
- QPixmapCache::Key cacheKey = cacheKeys.value(key);
- if (!cacheKey.d || !cacheKey.d->isValid) {
- const_cast<QPMCache *>(this)->cacheKeys.remove(key);
- return nullptr;
- }
- QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(cacheKey);
- //We didn't find the pixmap in the cache, the key is not valid anymore
- if (!ptr) {
- const_cast<QPMCache *>(this)->cacheKeys.remove(key);
- }
- return ptr;
+ if (const auto it = cacheKeys.find(key); it != cacheKeys.cend())
+ return object(it.value());
+ return nullptr;
}
QPixmap *QPMCache::object(const QPixmapCache::Key &key) const
{
- Q_ASSERT(key.d->isValid);
+ Q_ASSERT(key.isValid());
QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(key);
//We didn't find the pixmap in the cache, the key is not valid anymore
if (!ptr)
@@ -347,31 +300,24 @@ QPixmap *QPMCache::object(const QPixmapCache::Key &key) const
bool QPMCache::insert(const QString& key, const QPixmap &pixmap, int cost)
{
- QPixmapCache::Key &cacheKey = cacheKeys[key];
//If for the same key we add already a pixmap we should delete it
- if (cacheKey.d)
- QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(cacheKey);
-
- //we create a new key the old one has been removed
- cacheKey = createKey();
+ remove(key);
- bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost);
- if (success) {
- if (!theid) {
- theid = startTimer(flush_time);
- t = false;
- }
- } else {
- //Insertion failed we released the new allocated key
- cacheKeys.remove(key);
+ // this will create a new key; the old one has been removed
+ auto k = insert(pixmap, cost);
+ if (k.isValid()) {
+ k.d->stringKey = key;
+ cacheKeys[key] = std::move(k);
+ return true;
}
- return success;
+ return false;
}
QPixmapCache::Key QPMCache::insert(const QPixmap &pixmap, int cost)
{
- QPixmapCache::Key cacheKey = createKey();
+ QPixmapCache::Key cacheKey = createKey(); // invalidated by ~QPixmapCacheEntry on failed insert
bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost);
+ Q_ASSERT(success || !cacheKey.isValid());
if (success) {
if (!theid) {
theid = startTimer(flush_time);
@@ -381,34 +327,10 @@ QPixmapCache::Key QPMCache::insert(const QPixmap &pixmap, int cost)
return cacheKey;
}
-bool QPMCache::replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost)
-{
- Q_ASSERT(key.d->isValid);
- //If for the same key we had already an entry so we should delete the pixmap and use the new one
- QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(key);
-
- QPixmapCache::Key cacheKey = createKey();
-
- bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost);
- if (success) {
- if (!theid) {
- theid = startTimer(flush_time);
- t = false;
- }
- const_cast<QPixmapCache::Key&>(key) = cacheKey;
- }
- return success;
-}
-
bool QPMCache::remove(const QString &key)
{
- auto cacheKey = cacheKeys.constFind(key);
- //The key was not in the cache
- if (cacheKey == cacheKeys.constEnd())
- return false;
- const bool result = QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(cacheKey.value());
- cacheKeys.erase(cacheKey);
- return result;
+ const auto cacheKey = cacheKeys.take(key);
+ return cacheKey.isValid() && remove(cacheKey);
}
bool QPMCache::remove(const QPixmapCache::Key &key)
@@ -420,7 +342,7 @@ void QPMCache::resizeKeyArray(int size)
{
if (size <= keyArraySize || size == 0)
return;
- keyArray = q_check_ptr(reinterpret_cast<int *>(realloc(keyArray,
+ keyArray = q_check_ptr(static_cast<int *>(realloc(keyArray,
size * sizeof(int))));
for (int i = keyArraySize; i != size; ++i)
keyArray[i] = i + 1;
@@ -441,13 +363,18 @@ QPixmapCache::Key QPMCache::createKey()
void QPMCache::releaseKey(const QPixmapCache::Key &key)
{
- if (key.d->key > keyArraySize || key.d->key <= 0)
+ QPixmapCache::KeyData *keyData = key.d;
+ if (!keyData)
+ return;
+ if (!keyData->stringKey.isNull())
+ cacheKeys.remove(keyData->stringKey);
+ if (keyData->key > keyArraySize || keyData->key <= 0)
return;
- key.d->key--;
- keyArray[key.d->key] = freeKey;
- freeKey = key.d->key;
- key.d->isValid = false;
- key.d->key = 0;
+ keyData->key--;
+ keyArray[keyData->key] = freeKey;
+ freeKey = keyData->key;
+ keyData->isValid = false;
+ keyData->key = 0;
}
void QPMCache::clear()
@@ -457,10 +384,17 @@ void QPMCache::clear()
freeKey = 0;
keyArraySize = 0;
//Mark all keys as invalid
- QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QPixmapCacheEntry>::keys();
- for (int i = 0; i < keys.size(); ++i)
- keys.at(i).d->isValid = false;
+ const QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QPixmapCacheEntry>::keys();
+ for (const auto &key : keys) {
+ if (key.d)
+ key.d->isValid = false;
+ }
QCache<QPixmapCache::Key, QPixmapCacheEntry>::clear();
+ // Nothing left to flush; stop the timer
+ if (theid) {
+ killTimer(theid);
+ theid = 0;
+ }
}
QPixmapCache::KeyData* QPMCache::getKeyData(QPixmapCache::Key *key)
@@ -495,7 +429,7 @@ QPixmapCacheEntry::~QPixmapCacheEntry()
bool QPixmapCache::find(const QString &key, QPixmap *pixmap)
{
- if (!qt_pixmapcache_thread_test())
+ if (key.isEmpty() || !qt_pixmapcache_thread_test())
return false;
QPixmap *ptr = pm_cache()->object(key);
if (ptr && pixmap)
@@ -547,7 +481,7 @@ bool QPixmapCache::find(const Key &key, QPixmap *pixmap)
bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
{
- if (!qt_pixmapcache_thread_test())
+ if (key.isEmpty() || !qt_pixmapcache_thread_test())
return false;
return pm_cache()->insert(key, pixmap, cost(pixmap));
}
@@ -574,24 +508,25 @@ QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
return pm_cache()->insert(pixmap, cost(pixmap));
}
+#if QT_DEPRECATED_SINCE(6, 6)
/*!
+ \fn bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
+
+ \deprecated [6.6] Use \c{remove(key); key = insert(pixmap);} instead.
+
Replaces the pixmap associated with the given \a key with the \a pixmap
specified. Returns \c true if the \a pixmap has been correctly inserted into
the cache; otherwise returns \c false.
+ The passed \a key is updated to reference \a pixmap now. Other copies of \a
+ key, if any, still refer to the old pixmap, which is, however, removed from
+ the cache by this function.
+
\sa setCacheLimit(), insert()
\since 4.6
*/
-bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
-{
- if (!qt_pixmapcache_thread_test())
- return false;
- //The key is not valid anymore, a flush happened before probably
- if (!key.d || !key.d->isValid)
- return false;
- return pm_cache()->replace(key, pixmap, cost(pixmap));
-}
+#endif // QT_DEPRECATED_SINCE(6, 6)
/*!
Returns the cache limit (in kilobytes).
@@ -603,6 +538,8 @@ bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
int QPixmapCache::cacheLimit()
{
+ if (!qt_pixmapcache_thread_test())
+ return 0;
return pm_cache()->maxCost();
}
@@ -626,7 +563,7 @@ void QPixmapCache::setCacheLimit(int n)
*/
void QPixmapCache::remove(const QString &key)
{
- if (!qt_pixmapcache_thread_test())
+ if (key.isEmpty() || !qt_pixmapcache_thread_test())
return;
pm_cache()->remove(key);
}
@@ -664,13 +601,17 @@ void QPixmapCache::clear()
}
}
-void QPixmapCache::flushDetachedPixmaps()
+Q_AUTOTEST_EXPORT void qt_qpixmapcache_flush_detached_pixmaps() // for tst_qpixmapcache
{
+ if (!qt_pixmapcache_thread_test())
+ return;
pm_cache()->flushDetachedPixmaps(true);
}
-int QPixmapCache::totalUsed()
+Q_AUTOTEST_EXPORT int qt_qpixmapcache_qpixmapcache_total_used() // for tst_qpixmapcache
{
+ if (!qt_pixmapcache_thread_test())
+ return 0;
return (pm_cache()->totalCost()+1023) / 1024;
}
diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h
index 33021d1773..72ee1b797f 100644
--- a/src/gui/image/qpixmapcache.h
+++ b/src/gui/image/qpixmapcache.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXMAPCACHE_H
#define QPIXMAPCACHE_H
@@ -63,10 +27,14 @@ public:
{ return !operator==(key); }
Key &operator =(const Key &other);
- void swap(Key &other) noexcept { qSwap(d, other.d); }
+ void swap(Key &other) noexcept { qt_ptr_swap(d, other.d); }
bool isValid() const noexcept;
private:
+ friend size_t qHash(const QPixmapCache::Key &k, size_t seed = 0) noexcept
+ { return k.hash(seed); }
+ size_t hash(size_t seed) const noexcept;
+
KeyData *d;
friend class QPMCache;
friend class QPixmapCache;
@@ -78,18 +46,30 @@ public:
static bool find(const Key &key, QPixmap *pixmap);
static bool insert(const QString &key, const QPixmap &pixmap);
static Key insert(const QPixmap &pixmap);
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Use remove(key), followed by key = insert(pixmap).")
+ QT_GUI_INLINE_SINCE(6, 6)
static bool replace(const Key &key, const QPixmap &pixmap);
+#endif
static void remove(const QString &key);
static void remove(const Key &key);
static void clear();
-
-#ifdef Q_TEST_QPIXMAPCACHE
- static void flushDetachedPixmaps();
- static int totalUsed();
-#endif
};
Q_DECLARE_SHARED(QPixmapCache::Key)
+#if QT_DEPRECATED_SINCE(6, 6)
+#if QT_GUI_INLINE_IMPL_SINCE(6, 6)
+bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
+{
+ if (!key.isValid())
+ return false;
+ remove(key);
+ const_cast<Key&>(key) = insert(pixmap);
+ return key.isValid();
+}
+#endif // QT_GUI_INLINE_IMPL_SINCE(6, 6)
+#endif // QT_DEPRECATED_SINCE(6, 6)
+
QT_END_NAMESPACE
#endif // QPIXMAPCACHE_H
diff --git a/src/gui/image/qpixmapcache_p.h b/src/gui/image/qpixmapcache_p.h
index fce2b2d9a1..43c4d9784c 100644
--- a/src/gui/image/qpixmapcache_p.h
+++ b/src/gui/image/qpixmapcache_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXMAPCACHE_P_H
#define QPIXMAPCACHE_P_H
@@ -59,8 +23,6 @@
QT_BEGIN_NAMESPACE
-size_t qHash(const QPixmapCache::Key &k, size_t seed = 0);
-
class QPixmapCache::KeyData
{
public:
@@ -69,6 +31,7 @@ public:
: isValid(other.isValid), key(other.key), ref(1) {}
~KeyData() {}
+ QString stringKey;
bool isValid;
int key;
int ref;
diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp
index ea4243ba07..a297736095 100644
--- a/src/gui/image/qplatformpixmap.cpp
+++ b/src/gui/image/qplatformpixmap.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformpixmap.h"
#include <qpa/qplatformintegration.h>
@@ -83,7 +47,7 @@ QPlatformPixmap::QPlatformPixmap(PixelType pixelType, int objectId)
QPlatformPixmap::~QPlatformPixmap()
{
- // Sometimes the pixmap cleanup hooks will be called from derrived classes, which will
+ // Sometimes the pixmap cleanup hooks will be called from derived classes, which will
// then set is_cached to false. For example, on X11 Qt GUI needs to delete the GLXPixmap
// or EGL Pixmap Surface for a given pixmap _before_ the native X11 pixmap is deleted,
// otherwise some drivers will leak the GL surface. In this case, QX11PlatformPixmap will
@@ -101,10 +65,10 @@ QPlatformPixmap *QPlatformPixmap::createCompatiblePlatformPixmap() const
return d;
}
-static QImage makeBitmapCompliantIfNeeded(QPlatformPixmap *d, const QImage &image, Qt::ImageConversionFlags flags)
+static QImage makeBitmapCompliantIfNeeded(QPlatformPixmap *d, QImage image, Qt::ImageConversionFlags flags)
{
if (d->pixelType() == QPlatformPixmap::BitmapType) {
- QImage img = image.convertToFormat(QImage::Format_MonoLSB, flags);
+ QImage img = std::move(image).convertToFormat(QImage::Format_MonoLSB, flags);
// make sure image.color(0) == Qt::color0 (white)
// and image.color(1) == Qt::color1 (black)
@@ -134,7 +98,7 @@ bool QPlatformPixmap::fromFile(const QString &fileName, const char *format,
QImage image = QImageReader(fileName, format).read();
if (image.isNull())
return false;
- fromImage(makeBitmapCompliantIfNeeded(this, image, flags), flags);
+ fromImage(makeBitmapCompliantIfNeeded(this, std::move(image), flags), flags);
return !isNull();
}
@@ -146,7 +110,7 @@ bool QPlatformPixmap::fromData(const uchar *buf, uint len, const char *format, Q
QImage image = QImageReader(&b, format).read();
if (image.isNull())
return false;
- fromImage(makeBitmapCompliantIfNeeded(this, image, flags), flags);
+ fromImage(makeBitmapCompliantIfNeeded(this, std::move(image), flags), flags);
return !isNull();
}
@@ -168,9 +132,9 @@ QBitmap QPlatformPixmap::mask() const
if (!hasAlphaChannel())
return QBitmap();
- const QImage img = toImage();
+ QImage img = toImage();
bool shouldConvert = (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied);
- const QImage image = (shouldConvert ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
+ const QImage image = (shouldConvert ? std::move(img).convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
const int w = image.width();
const int h = image.height();
@@ -196,7 +160,7 @@ QBitmap QPlatformPixmap::mask() const
}
}
- return QBitmap::fromImage(mask);
+ return QBitmap::fromImage(std::move(mask));
}
void QPlatformPixmap::setMask(const QBitmap &mask)
@@ -204,7 +168,7 @@ void QPlatformPixmap::setMask(const QBitmap &mask)
QImage image = toImage();
if (mask.size().isEmpty()) {
if (image.depth() != 1) { // hw: ????
- image = image.convertToFormat(QImage::Format_RGB32);
+ image = std::move(image).convertToFormat(QImage::Format_RGB32);
}
} else {
const int w = image.width();
@@ -224,7 +188,7 @@ void QPlatformPixmap::setMask(const QBitmap &mask)
}
default: {
const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
- image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ image = std::move(image).convertToFormat(QImage::Format_ARGB32_Premultiplied);
for (int y = 0; y < h; ++y) {
const uchar *mscan = imageMask.scanLine(y);
QRgb *tscan = (QRgb *)image.scanLine(y);
diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h
index 9c7f5e5edf..be86bf8850 100644
--- a/src/gui/image/qplatformpixmap.h
+++ b/src/gui/image/qplatformpixmap.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMPIXMAP_H
#define QPLATFORMPIXMAP_H
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index c013a06813..615a36fa36 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qpnghandler_p.h"
@@ -81,6 +45,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
// avoid going through QImage::scanLine() which calls detach
@@ -101,7 +67,7 @@ public:
ReadingEnd,
Error
};
- // Defines the order of how the various ways of setting colorspace overrides eachother:
+ // Defines the order of how the various ways of setting colorspace overrides each other:
enum ColorSpaceState {
Undefined = 0,
GammaChrm = 1, // gAMA+cHRM chunks
@@ -199,7 +165,7 @@ void iod_read_fn(png_structp png_ptr, png_bytep data, png_size_t length)
QPngHandlerPrivate *d = (QPngHandlerPrivate *)png_get_io_ptr(png_ptr);
QIODevice *in = d->q->device();
- if (d->state == QPngHandlerPrivate::ReadingEnd && !in->isSequential() && (in->size() - in->pos()) < 4 && length == 4) {
+ if (d->state == QPngHandlerPrivate::ReadingEnd && !in->isSequential() && in->size() > 0 && (in->size() - in->pos()) < 4 && length == 4) {
// Workaround for certain malformed PNGs that lack the final crc bytes
uchar endcrc[4] = { 0xae, 0x42, 0x60, 0x82 };
memcpy(data, endcrc, 4);
@@ -525,8 +491,8 @@ void QPngHandlerPrivate::readPngTexts(png_info *info)
value = QString::fromLatin1(text_ptr->text, int(text_ptr->text_length));
}
if (!description.isEmpty())
- description += QLatin1String("\n\n");
- description += key + QLatin1String(": ") + value.simplified();
+ description += "\n\n"_L1;
+ description += key + ": "_L1 + value.simplified();
readTexts.append(key);
readTexts.append(value);
text_ptr++;
@@ -588,10 +554,10 @@ bool QPngHandlerPrivate::readPngHeader()
#endif
png_uint_32 profLen;
png_get_iCCP(png_ptr, info_ptr, &name, &compressionType, &profileData, &profLen);
- colorSpace = QColorSpace::fromIccProfile(QByteArray((const char *)profileData, profLen));
- if (!colorSpace.isValid()) {
- qCDebug(lcImageIo) << "QPngHandler: Failed to parse ICC profile";
- } else {
+ Q_UNUSED(name);
+ Q_UNUSED(compressionType);
+ if (profLen > 0) {
+ colorSpace = QColorSpace::fromIccProfile(QByteArray((const char *)profileData, profLen));
QColorSpacePrivate *csD = QColorSpacePrivate::get(colorSpace);
if (csD->description.isEmpty())
csD->description = QString::fromLatin1((const char *)name);
@@ -832,7 +798,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt
int i = 0;
while (it != text.constEnd()) {
text_ptr[i].key = qstrdup(QStringView{it.key()}.left(79).toLatin1().constData());
- bool noCompress = (it.value().length() < 40);
+ bool noCompress = (it.value().size() < 40);
#ifdef PNG_iTXt_SUPPORTED
bool needsItxt = false;
@@ -960,15 +926,15 @@ bool QPNGImageWriter::writeImage(const QImage& image, int compression_in, const
color_type, 0, 0, 0); // sets #channels
#ifdef PNG_iCCP_SUPPORTED
- if (image.colorSpace().isValid()) {
- QColorSpace cs = image.colorSpace();
- // Support the old gamma making it override transferfunction.
- if (gamma != 0.0 && !qFuzzyCompare(cs.gamma(), 1.0f / gamma))
- cs = cs.withTransferFunction(QColorSpace::TransferFunction::Gamma, 1.0f / gamma);
+ QColorSpace cs = image.colorSpace();
+ // Support the old gamma making it override transferfunction (if possible)
+ if (cs.isValid() && gamma != 0.0 && !qFuzzyCompare(cs.gamma(), 1.0f / gamma))
+ cs = cs.withTransferFunction(QColorSpace::TransferFunction::Gamma, 1.0f / gamma);
+ QByteArray iccProfile = cs.iccProfile();
+ if (!iccProfile.isEmpty()) {
QByteArray iccProfileName = cs.description().toLatin1();
if (iccProfileName.isEmpty())
iccProfileName = QByteArrayLiteral("Custom");
- QByteArray iccProfile = cs.iccProfile();
png_set_iCCP(png_ptr, info_ptr,
#if PNG_LIBPNG_VER < 10500
iccProfileName.data(), PNG_COMPRESSION_TYPE_BASE, iccProfile.data(),
@@ -976,7 +942,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, int compression_in, const
iccProfileName.constData(), PNG_COMPRESSION_TYPE_BASE,
(png_const_bytep)iccProfile.constData(),
#endif
- iccProfile.length());
+ iccProfile.size());
} else
#endif
if (gamma != 0.0) {
diff --git a/src/gui/image/qpnghandler_p.h b/src/gui/image/qpnghandler_p.h
index 9e12d2d081..fa4a7788f7 100644
--- a/src/gui/image/qpnghandler_p.h
+++ b/src/gui/image/qpnghandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPNGHANDLER_P_H
#define QPNGHANDLER_P_H
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index 71dbefe354..3a4af46195 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qppmhandler_p.h"
@@ -47,8 +11,8 @@
#include <qloggingcategory.h>
#include <qrgba64.h>
#include <qvariant.h>
-
-#include <ctype.h>
+#include <private/qlocale_p.h>
+#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
@@ -68,7 +32,7 @@ static void discard_pbm_line(QIODevice *d)
} while (res > 0 && buf[res-1] != '\n');
}
-static int read_pbm_int(QIODevice *d)
+static int read_pbm_int(QIODevice *d, bool *ok, int maxDigits = -1)
{
char c;
int val = -1;
@@ -77,7 +41,7 @@ static int read_pbm_int(QIODevice *d)
for (;;) {
if (!d->getChar(&c)) // end of file
break;
- digit = isdigit((uchar) c);
+ digit = QtMiscUtils::isAsciiDigit(c);
if (val != -1) {
if (digit) {
const int cValue = c - '0';
@@ -86,6 +50,8 @@ static int read_pbm_int(QIODevice *d)
} else {
hasOverflow = true;
}
+ if (maxDigits > 0 && --maxDigits == 0)
+ break;
continue;
} else {
if (c == '#') // comment
@@ -95,13 +61,17 @@ static int read_pbm_int(QIODevice *d)
}
if (digit) // first digit
val = c - '0';
- else if (isspace((uchar) c))
+ else if (ascii_isspace(c))
continue;
else if (c == '#')
discard_pbm_line(d);
else
break;
+ if (maxDigits > 0 && --maxDigits == 0)
+ break;
}
+ if (val < 0)
+ *ok = false;
return hasOverflow ? -1 : val;
}
@@ -111,23 +81,24 @@ static bool read_pbm_header(QIODevice *device, char& type, int& w, int& h, int&
if (device->read(buf, 3) != 3) // read P[1-6]<white-space>
return false;
- if (!(buf[0] == 'P' && isdigit((uchar) buf[1]) && isspace((uchar) buf[2])))
+ if (!(buf[0] == 'P' && QtMiscUtils::isAsciiDigit(buf[1]) && ascii_isspace(buf[2])))
return false;
type = buf[1];
if (type < '1' || type > '6')
return false;
- w = read_pbm_int(device); // get image width
- h = read_pbm_int(device); // get image height
+ bool ok = true;
+ w = read_pbm_int(device, &ok); // get image width
+ h = read_pbm_int(device, &ok); // get image height
if (type == '1' || type == '4')
mcc = 1; // ignore max color component
else
- mcc = read_pbm_int(device); // get max color component
+ mcc = read_pbm_int(device, &ok); // get max color component
- if (w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0 || mcc > 0xffff)
- return false; // weird P.M image
+ if (!ok || w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0 || mcc > 0xffff)
+ return false; // weird P.M image
return true;
}
@@ -235,18 +206,18 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
} else { // read ascii data
uchar *p;
qsizetype n;
- char buf;
- for (y = 0; (y < h) && (device->peek(&buf, 1) == 1); y++) {
+ bool ok = true;
+ for (y = 0; y < h && ok; y++) {
p = outImage->scanLine(y);
n = pbm_bpl;
if (nbits == 1) {
int b;
int bitsLeft = w;
- while (n--) {
+ while (n-- && ok) {
b = 0;
for (int i=0; i<8; i++) {
if (i < bitsLeft)
- b = (b << 1) | (read_pbm_int(device) & 1);
+ b = (b << 1) | (read_pbm_int(device, &ok, 1) & 1);
else
b = (b << 1) | (0 & 1); // pad it our self if we need to
}
@@ -255,36 +226,38 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
}
} else if (nbits == 8) {
if (mcc == 255) {
- while (n--) {
- *p++ = read_pbm_int(device);
+ while (n-- && ok) {
+ *p++ = read_pbm_int(device, &ok);
}
} else {
- while (n--) {
- *p++ = (read_pbm_int(device) & 0xffff) * 255 / mcc;
+ while (n-- && ok) {
+ *p++ = (read_pbm_int(device, &ok) & 0xffff) * 255 / mcc;
}
}
} else { // 32 bits
n /= 4;
int r, g, b;
if (mcc == 255) {
- while (n--) {
- r = read_pbm_int(device);
- g = read_pbm_int(device);
- b = read_pbm_int(device);
+ while (n-- && ok) {
+ r = read_pbm_int(device, &ok);
+ g = read_pbm_int(device, &ok);
+ b = read_pbm_int(device, &ok);
*((QRgb*)p) = qRgb(r, g, b);
p += 4;
}
} else {
- while (n--) {
- r = read_pbm_int(device);
- g = read_pbm_int(device);
- b = read_pbm_int(device);
+ while (n-- && ok) {
+ r = read_pbm_int(device, &ok);
+ g = read_pbm_int(device, &ok);
+ b = read_pbm_int(device, &ok);
*((QRgb*)p) = scale_pbm_color(mcc, r, g, b);
p += 4;
}
}
}
}
+ if (!ok)
+ return false;
}
if (format == QImage::Format_Mono) {
@@ -296,13 +269,12 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
return true;
}
-static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QByteArray &sourceFormat)
+static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, QByteArrayView sourceFormat)
{
QByteArray str;
QImage image = sourceImage;
- QByteArray format = sourceFormat;
+ const QByteArrayView format = sourceFormat.left(3); // ignore RAW part
- format = format.left(3); // ignore RAW part
bool gray = format == "pgm";
if (format == "pbm") {
@@ -353,7 +325,7 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
switch (image.depth()) {
case 1: {
str.insert(1, '4');
- if (out->write(str, str.length()) != str.length())
+ if (out->write(str, str.size()) != str.size())
return false;
w = (w+7)/8;
for (uint y=0; y<h; y++) {
@@ -367,12 +339,12 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
case 8: {
str.insert(1, gray ? '5' : '6');
str.append("255\n");
- if (out->write(str, str.length()) != str.length())
+ if (out->write(str, str.size()) != str.size())
return false;
qsizetype bpl = qsizetype(w) * (gray ? 1 : 3);
uchar *buf = new uchar[bpl];
if (image.format() == QImage::Format_Indexed8) {
- QList<QRgb> color = image.colorTable();
+ const QList<QRgb> color = image.colorTable();
for (uint y=0; y<h; y++) {
const uchar *b = image.constScanLine(y);
uchar *p = buf;
@@ -420,7 +392,7 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
case 32: {
str.insert(1, '6');
str.append("255\n");
- if (out->write(str, str.length()) != str.length())
+ if (out->write(str, str.size()) != str.size())
return false;
qsizetype bpl = qsizetype(w) * 3;
uchar *buf = new uchar[bpl];
diff --git a/src/gui/image/qppmhandler_p.h b/src/gui/image/qppmhandler_p.h
index f2faf93984..49663ebc53 100644
--- a/src/gui/image/qppmhandler_p.h
+++ b/src/gui/image/qppmhandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPPMHANDLER_P_H
#define QPPMHANDLER_P_H
diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp
index 9c324aeeb9..8206fe3b29 100644
--- a/src/gui/image/qxbmhandler.cpp
+++ b/src/gui/image/qxbmhandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qplatformdefs.h>
#include "private/qxbmhandler_p.h"
@@ -46,12 +10,14 @@
#include <qiodevice.h>
#include <qloggingcategory.h>
#include <qvariant.h>
+#include <private/qtools_p.h>
#include <stdio.h>
-#include <ctype.h>
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
/*****************************************************************************
@@ -60,8 +26,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
static inline int hex2byte(char *p)
{
- return ((isdigit((uchar) *p) ? *p - '0' : toupper((uchar) *p) - 'A' + 10) << 4) |
- (isdigit((uchar) *(p+1)) ? *(p+1) - '0' : toupper((uchar) *(p+1)) - 'A' + 10);
+ return QtMiscUtils::fromHex(p[0]) * 16 | QtMiscUtils::fromHex(p[1]);
}
static bool read_xbm_header(QIODevice *device, int& w, int& h)
@@ -91,11 +56,9 @@ static bool read_xbm_header(QIODevice *device, int& w, int& h)
}
auto parseDefine = [] (const char *buf, int len) -> int {
- auto isAsciiLetterOrNumber = [] (char ch) -> bool {
- return (ch >= '0' && ch <= '9') ||
- (ch >= 'A' && ch <= 'Z') ||
- (ch >= 'a' && ch <= 'z') ||
- ch == '_' || ch == '.';
+ auto checkChar = [] (char ch) -> bool {
+ return isAsciiLetterOrNumber(ch)
+ || ch == '_' || ch == '.';
};
auto isAsciiSpace = [] (char ch) -> bool {
return ch == ' ' || ch == '\t';
@@ -107,7 +70,7 @@ static bool read_xbm_header(QIODevice *device, int& w, int& h)
int index = defineLen;
while (buf[index] && isAsciiSpace(buf[index]))
++index;
- while (buf[index] && isAsciiLetterOrNumber(buf[index]))
+ while (buf[index] && checkChar(buf[index]))
++index;
while (buf[index] && isAsciiSpace(buf[index]))
++index;
@@ -165,9 +128,10 @@ static bool read_xbm_body(QIODevice *device, int w, int h, QImage *outImage)
while (y < h) { // for all encoded bytes...
if (p && p < (buf + readBytes - 3)) { // p = "0x.."
- if (!isxdigit(p[2]) || !isxdigit(p[3]))
+ const int byte = hex2byte(p + 2);
+ if (byte < 0) // non-hex char encountered
return false;
- *b++ = hex2byte(p+2);
+ *b++ = byte;
p += 2;
if (++x == w && ++y < h) {
b = outImage->scanLine(y);
@@ -200,7 +164,7 @@ static bool write_xbm_image(const QImage &sourceImage, QIODevice *device, const
int h = image.height();
int i;
QString s = fileName; // get file base name
- int msize = s.length() + 100;
+ int msize = s.size() + 100;
char *buf = new char[msize];
qsnprintf(buf, msize, "#define %s_width %d\n", s.toUtf8().data(), w);
diff --git a/src/gui/image/qxbmhandler_p.h b/src/gui/image/qxbmhandler_p.h
index db5f352d46..6a04faa42b 100644
--- a/src/gui/image/qxbmhandler_p.h
+++ b/src/gui/image/qxbmhandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXBMHANDLER_P_H
#define QXBMHANDLER_P_H
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index 8ec09f2480..50f9f035a6 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qxpmhandler_p.h"
@@ -50,11 +14,16 @@
#include <qvariant.h>
#include <private/qcolor_p.h>
+#include <private/qduplicatetracker_p.h> // for easier std::pmr detection
+#include <private/qtools_p.h>
#include <algorithm>
+#include <array>
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
static quint64 xpmHash(const QString &str)
@@ -752,15 +721,12 @@ inline bool operator<(const char *name, const XPMRGBData &data)
inline bool operator<(const XPMRGBData &data, const char *name)
{ return qstrcmp(data.name, name) < 0; }
-static inline bool qt_get_named_xpm_rgb(const char *name_no_space, QRgb *rgb)
+static inline std::optional<QRgb> qt_get_named_xpm_rgb(const char *name_no_space)
{
const XPMRGBData *r = std::lower_bound(xpmRgbTbl, xpmRgbTbl + xpmRgbTblSize, name_no_space);
- if ((r != xpmRgbTbl + xpmRgbTblSize) && !(name_no_space < *r)) {
- *rgb = r->value;
- return true;
- } else {
- return false;
- }
+ if ((r != xpmRgbTbl + xpmRgbTblSize) && !(name_no_space < *r))
+ return r->value;
+ return {};
}
/*****************************************************************************
@@ -770,18 +736,16 @@ static QString fbname(const QString &fileName) // get file basename (sort of)
{
QString s = fileName;
if (!s.isEmpty()) {
- int i = qMax(s.lastIndexOf(QLatin1Char('/')), s.lastIndexOf(QLatin1Char('\\')));
+ int i = qMax(s.lastIndexOf(u'/'), s.lastIndexOf(u'\\'));
if (i < 0)
i = 0;
- auto isAsciiLetterOrNumber = [](QChar ch) -> bool {
- return (ch.unicode() >= '0' && ch.unicode() <= '9') ||
- (ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
- (ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
- ch.unicode() == '_';
+ auto checkChar = [](QChar ch) -> bool {
+ uchar uc = ch.unicode();
+ return isAsciiLetterOrNumber(uc) || uc == '_';
};
int start = -1;
- for (; i < s.length(); ++i) {
- if (isAsciiLetterOrNumber(s.at(i))) {
+ for (; i < s.size(); ++i) {
+ if (checkChar(s.at(i))) {
start = i;
} else if (start > 0)
break;
@@ -929,25 +893,25 @@ static bool read_xpm_body(
int transparentColor = currentColor;
if (ncols <= 256) {
image.setColor(transparentColor, 0);
- colorMap.insert(xpmHash(QLatin1String(index.constData())), transparentColor);
+ colorMap.insert(xpmHash(QLatin1StringView(index.constData())), transparentColor);
} else {
- colorMap.insert(xpmHash(QLatin1String(index.constData())), 0);
+ colorMap.insert(xpmHash(QLatin1StringView(index.constData())), 0);
}
} else {
QRgb c_rgb = 0;
- if (((buf.length()-1) % 3) && (buf[0] == '#')) {
- buf.truncate(((buf.length()-1) / 4 * 3) + 1); // remove alpha channel left by imagemagick
+ if (((buf.size()-1) % 3) && (buf[0] == '#')) {
+ buf.truncate(((buf.size()-1) / 4 * 3) + 1); // remove alpha channel left by imagemagick
}
if (buf[0] == '#') {
- qt_get_hex_rgb(buf, &c_rgb);
+ c_rgb = qt_get_hex_rgb(buf).value_or(0);
} else {
- qt_get_named_xpm_rgb(buf, &c_rgb);
+ c_rgb = qt_get_named_xpm_rgb(buf).value_or(0);
}
if (ncols <= 256) {
image.setColor(currentColor, 0xff000000 | c_rgb);
- colorMap.insert(xpmHash(QLatin1String(index.constData())), currentColor);
+ colorMap.insert(xpmHash(QLatin1StringView(index.constData())), currentColor);
} else {
- colorMap.insert(xpmHash(QLatin1String(index.constData())), 0xff000000 | c_rgb);
+ colorMap.insert(xpmHash(QLatin1StringView(index.constData())), 0xff000000 | c_rgb);
}
}
}
@@ -969,7 +933,7 @@ static bool read_xpm_body(
if (image.depth() == 8) {
uchar *p = image.scanLine(y);
uchar *d = (uchar *)buf.data();
- uchar *end = d + buf.length();
+ uchar *end = d + buf.size();
int x;
if (cpp == 1) {
char b[2];
@@ -995,7 +959,7 @@ static bool read_xpm_body(
} else {
QRgb *p = (QRgb*)image.scanLine(y);
uchar *d = (uchar *)buf.data();
- uchar *end = d + buf.length();
+ uchar *end = d + buf.size();
int x;
char b[16];
b[cpp] = '\0';
@@ -1063,15 +1027,23 @@ bool qt_read_xpm_image_or_array(QIODevice *device, const char * const * source,
return read_xpm_body(device, source, index, state, cpp, ncols, w, h, image);
}
-static const char* xpm_color_name(int cpp, int index)
+namespace {
+template <size_t N>
+struct CharBuffer : std::array<char, N>
+{
+ CharBuffer() {} // avoid value-initializing the whole array
+};
+}
+
+static const char* xpm_color_name(int cpp, int index, CharBuffer<5> && returnable = {})
{
- static char returnable[5];
static const char code[] = ".#abcdefghijklmnopqrstuvwxyzABCD"
"EFGHIJKLMNOPQRSTUVWXYZ0123456789";
// cpp is limited to 4 and index is limited to 64^cpp
if (cpp > 1) {
if (cpp > 2) {
if (cpp > 3) {
+ returnable[4] = '\0';
returnable[3] = code[index % 64];
index /= 64;
} else
@@ -1091,7 +1063,7 @@ static const char* xpm_color_name(int cpp, int index)
returnable[1] = '\0';
returnable[0] = code[index];
- return returnable;
+ return returnable.data();
}
@@ -1107,18 +1079,25 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
else
image = sourceImage;
- QMap<QRgb, int> colorMap;
+#ifdef __cpp_lib_memory_resource
+ char buffer[1024];
+ std::pmr::monotonic_buffer_resource res{&buffer, sizeof buffer};
+ std::pmr::map<QRgb, int> colorMap(&res);
+#else
+ std::map<QRgb, int> colorMap;
+#endif
- int w = image.width(), h = image.height(), ncolors = 0;
- int x, y;
+ const int w = image.width();
+ const int h = image.height();
+ int ncolors = 0;
// build color table
- for(y=0; y<h; y++) {
+ for (int y = 0; y < h; ++y) {
const QRgb *yp = reinterpret_cast<const QRgb *>(image.constScanLine(y));
- for(x=0; x<w; x++) {
- QRgb color = *(yp + x);
- if (!colorMap.contains(color))
- colorMap.insert(color, ncolors++);
+ for (int x = 0; x < w; ++x) {
+ const auto [it, inserted] = colorMap.try_emplace(yp[x], ncolors);
+ if (inserted)
+ ++ncolors;
}
}
@@ -1128,8 +1107,11 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
++cpp;
// limit to 4 characters per pixel
// 64^4 colors is enough for a 4096x4096 image
- if (cpp > 4)
- break;
+ if (cpp > 4) {
+ qCWarning(lcImageIo, "Qt does not support writing XPM images with more than "
+ "64^4 colors (requested: %d colors).", ncolors);
+ return false;
+ }
}
// write header
@@ -1139,36 +1121,21 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
<< '\"' << w << ' ' << h << ' ' << ncolors << ' ' << cpp << '\"';
// write palette
- QMap<QRgb, int>::Iterator c = colorMap.begin();
- while (c != colorMap.end()) {
- QRgb color = c.key();
+ for (const auto &[color, index] : colorMap) {
const QString line = image.format() != QImage::Format_RGB32 && !qAlpha(color)
- ? QString::asprintf("\"%s c None\"", xpm_color_name(cpp, *c))
- : QString::asprintf("\"%s c #%02x%02x%02x\"", xpm_color_name(cpp, *c),
+ ? QString::asprintf("\"%s c None\"", xpm_color_name(cpp, index))
+ : QString::asprintf("\"%s c #%02x%02x%02x\"", xpm_color_name(cpp, index),
qRed(color), qGreen(color), qBlue(color));
- ++c;
s << ',' << Qt::endl << line;
}
// write pixels, limit to 4 characters per pixel
- QByteArray line;
- for(y=0; y<h; y++) {
- line.clear();
+ for (int y = 0; y < h; ++y) {
+ s << ',' << Qt::endl << '\"';
const QRgb *yp = reinterpret_cast<const QRgb *>(image.constScanLine(y));
- for(x=0; x<w; x++) {
- int color = (int)(*(yp + x));
- const QByteArray chars(xpm_color_name(cpp, colorMap[color]));
- line.append(chars[0]);
- if (cpp > 1) {
- line.append(chars[1]);
- if (cpp > 2) {
- line.append(chars[2]);
- if (cpp > 3)
- line.append(chars[3]);
- }
- }
- }
- s << ',' << Qt::endl << '\"' << line << '\"';
+ for (int x = 0; x < w; ++x)
+ s << xpm_color_name(cpp, colorMap[yp[x]]);
+ s << '\"';
}
s << "};" << Qt::endl;
return (s.status() == QTextStream::Ok);
diff --git a/src/gui/image/qxpmhandler_p.h b/src/gui/image/qxpmhandler_p.h
index 646e8df69e..c55653f3ec 100644
--- a/src/gui/image/qxpmhandler_p.h
+++ b/src/gui/image/qxpmhandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXPMHANDLER_P_H
#define QXPMHANDLER_P_H
diff --git a/src/gui/itemmodels/qfileinfogatherer.cpp b/src/gui/itemmodels/qfileinfogatherer.cpp
index bd368e945c..41fb0a0db5 100644
--- a/src/gui/itemmodels/qfileinfogatherer.cpp
+++ b/src/gui/itemmodels/qfileinfogatherer.cpp
@@ -1,45 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfileinfogatherer_p.h"
+#include <qcoreapplication.h>
#include <qdebug.h>
-#include <qdiriterator.h>
+#include <qdirlisting.h>
+#include <private/qabstractfileiconprovider_p.h>
#include <private/qfileinfo_p.h>
#ifndef Q_OS_WIN
# include <unistd.h>
@@ -51,8 +17,10 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#ifdef QT_BUILD_INTERNAL
-static QBasicAtomicInt fetchedRoot = Q_BASIC_ATOMIC_INITIALIZER(false);
+Q_CONSTINIT static QBasicAtomicInt fetchedRoot = Q_BASIC_ATOMIC_INITIALIZER(false);
Q_AUTOTEST_EXPORT void qt_test_resetFetchedRoot()
{
fetchedRoot.storeRelaxed(false);
@@ -68,9 +36,9 @@ static QString translateDriveName(const QFileInfo &drive)
{
QString driveName = drive.absoluteFilePath();
#ifdef Q_OS_WIN
- if (driveName.startsWith(QLatin1Char('/'))) // UNC host
+ if (driveName.startsWith(u'/')) // UNC host
return drive.fileName();
- if (driveName.endsWith(QLatin1Char('/')))
+ if (driveName.endsWith(u'/'))
driveName.chop(1);
#endif // Q_OS_WIN
return driveName;
@@ -91,11 +59,40 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent)
*/
QFileInfoGatherer::~QFileInfoGatherer()
{
- abort.storeRelaxed(true);
+ requestAbort();
+ wait();
+}
+
+bool QFileInfoGatherer::event(QEvent *event)
+{
+ if (event->type() == QEvent::DeferredDelete && isRunning()) {
+ // We have been asked to shut down later but were blocked,
+ // so the owning QFileSystemModel proceeded with its shut-down
+ // and deferred the destruction of the gatherer.
+ // If we are still blocked now, then we have three bad options:
+ // terminate, wait forever (preventing the process from shutting down),
+ // or accept a memory leak.
+ requestAbort();
+ if (!wait(5000)) {
+ // If the application is shutting down, then we terminate.
+ // Otherwise assume that sooner or later the thread will finish,
+ // and we delete it then.
+ if (QCoreApplication::closingDown())
+ terminate();
+ else
+ connect(this, &QThread::finished, this, [this]{ delete this; });
+ return true;
+ }
+ }
+
+ return QThread::event(event);
+}
+
+void QFileInfoGatherer::requestAbort()
+{
+ requestInterruption();
QMutexLocker locker(&mutex);
condition.wakeAll();
- locker.unlock();
- wait();
}
void QFileInfoGatherer::setResolveSymlinks(bool enable)
@@ -117,7 +114,7 @@ void QFileInfoGatherer::driveRemoved()
const QFileInfoList driveInfoList = QDir::drives();
for (const QFileInfo &fi : driveInfoList)
drives.append(translateDriveName(fi));
- newListOfFiles(QString(), drives);
+ emit newListOfFiles(QString(), drives);
}
bool QFileInfoGatherer::resolveSymlinks() const
@@ -148,21 +145,24 @@ void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStr
{
QMutexLocker locker(&mutex);
// See if we already have this dir/file in our queue
- int loc = this->path.lastIndexOf(path);
- while (loc > 0) {
- if (this->files.at(loc) == files) {
+ qsizetype loc = 0;
+ while ((loc = this->path.lastIndexOf(path, loc - 1)) != -1) {
+ if (this->files.at(loc) == files)
return;
- }
- loc = this->path.lastIndexOf(path, loc - 1);
}
+
+#if QT_CONFIG(thread)
this->path.push(path);
this->files.push(files);
condition.wakeAll();
+#else // !QT_CONFIG(thread)
+ getFileInfos(path, files);
+#endif // QT_CONFIG(thread)
#if QT_CONFIG(filesystemwatcher)
if (files.isEmpty()
&& !path.isEmpty()
- && !path.startsWith(QLatin1String("//")) /*don't watch UNC path*/) {
+ && !path.startsWith("//"_L1) /*don't watch UNC path*/) {
if (!watchedDirectories().contains(path))
watchPaths(QStringList(path));
}
@@ -176,8 +176,8 @@ void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStr
*/
void QFileInfoGatherer::updateFile(const QString &filePath)
{
- QString dir = filePath.mid(0, filePath.lastIndexOf(QLatin1Char('/')));
- QString fileName = filePath.mid(dir.length() + 1);
+ QString dir = filePath.mid(0, filePath.lastIndexOf(u'/'));
+ QString fileName = filePath.mid(dir.size() + 1);
fetchExtendedInformation(dir, QStringList(fileName));
}
@@ -250,16 +250,23 @@ bool QFileInfoGatherer::isWatching() const
return result;
}
+/*! \internal
+
+ If \a v is \c false, the QFileSystemWatcher used internally will be deleted
+ and subsequent calls to watchPaths() will do nothing.
+
+ If \a v is \c true, subsequent calls to watchPaths() will add those paths to
+ the filesystem watcher; watchPaths() will initialize a QFileSystemWatcher if
+ one hasn't already been initialized.
+*/
void QFileInfoGatherer::setWatching(bool v)
{
#if QT_CONFIG(filesystemwatcher)
QMutexLocker locker(&mutex);
if (v != m_watching) {
- if (!v) {
- delete m_watcher;
- m_watcher = nullptr;
- }
m_watching = v;
+ if (!m_watching)
+ delete std::exchange(m_watcher, nullptr);
}
#else
Q_UNUSED(v);
@@ -311,17 +318,24 @@ void QFileInfoGatherer::list(const QString &directoryPath)
void QFileInfoGatherer::run()
{
forever {
+ // Disallow termination while we are holding a mutex or can be
+ // woken up cleanly.
+ setTerminationEnabled(false);
QMutexLocker locker(&mutex);
- while (!abort.loadRelaxed() && path.isEmpty())
+ while (!isInterruptionRequested() && path.isEmpty())
condition.wait(&mutex);
- if (abort.loadRelaxed())
+ if (isInterruptionRequested())
return;
- const QString thisPath = qAsConst(path).front();
+ const QString thisPath = std::as_const(path).front();
path.pop_front();
- const QStringList thisList = qAsConst(files).front();
+ const QStringList thisList = std::as_const(files).front();
files.pop_front();
locker.unlock();
+ // Some of the system APIs we call when gathering file infomration
+ // might hang (e.g. waiting for network), so we explicitly allow
+ // termination now.
+ setTerminationEnabled(true);
getFileInfos(thisPath, thisList);
}
}
@@ -329,8 +343,12 @@ void QFileInfoGatherer::run()
QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const
{
QExtendedInformation info(fileInfo);
- info.icon = m_iconProvider->icon(fileInfo);
- info.displayType = m_iconProvider->type(fileInfo);
+ if (m_iconProvider) {
+ info.icon = m_iconProvider->icon(fileInfo);
+ info.displayType = m_iconProvider->type(fileInfo);
+ } else {
+ info.displayType = QAbstractFileIconProviderPrivate::getFileType(fileInfo);
+ }
#if QT_CONFIG(filesystemwatcher)
// ### Not ready to listen all modifications by default
static const bool watchFiles = qEnvironmentVariableIsSet("QT_FILESYSTEMMODEL_WATCH_FILES");
@@ -370,21 +388,23 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
#ifdef QT_BUILD_INTERNAL
fetchedRoot.storeRelaxed(true);
#endif
- QFileInfoList infoList;
+ QList<std::pair<QString, QFileInfo>> updatedFiles;
+ auto addToUpdatedFiles = [&updatedFiles](QFileInfo &&fileInfo) {
+ fileInfo.stat();
+ updatedFiles.emplace_back(std::pair{translateDriveName(fileInfo), fileInfo});
+ };
+
if (files.isEmpty()) {
- infoList = QDir::drives();
+ // QDir::drives() calls QFSFileEngine::drives() which creates the QFileInfoList on
+ // the stack and return it, so this list is not shared, so no detaching.
+ QFileInfoList infoList = QDir::drives();
+ updatedFiles.reserve(infoList.size());
+ for (auto rit = infoList.rbegin(), rend = infoList.rend(); rit != rend; ++rit)
+ addToUpdatedFiles(std::move(*rit));
} else {
- infoList.reserve(files.count());
- for (const auto &file : files)
- infoList << QFileInfo(file);
- }
- QList<QPair<QString, QFileInfo>> updatedFiles;
- updatedFiles.reserve(infoList.count());
- for (int i = infoList.count() - 1; i >= 0; --i) {
- QFileInfo driveInfo = infoList.at(i);
- driveInfo.stat();
- QString driveName = translateDriveName(driveInfo);
- updatedFiles.append(QPair<QString,QFileInfo>(driveName, driveInfo));
+ updatedFiles.reserve(files.size());
+ for (auto rit = files.crbegin(), rend = files.crend(); rit != rend; ++rit)
+ addToUpdatedFiles(QFileInfo(*rit));
}
emit updates(path, updatedFiles);
return;
@@ -394,15 +414,16 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
base.start();
QFileInfo fileInfo;
bool firstTime = true;
- QList<QPair<QString, QFileInfo>> updatedFiles;
+ QList<std::pair<QString, QFileInfo>> updatedFiles;
QStringList filesToCheck = files;
QStringList allFiles;
if (files.isEmpty()) {
- QDirIterator dirIt(path, QDir::AllEntries | QDir::System | QDir::Hidden);
- while (!abort.loadRelaxed() && dirIt.hasNext()) {
- dirIt.next();
- fileInfo = dirIt.fileInfo();
+ constexpr auto dirFilters = QDir::AllEntries | QDir::System | QDir::Hidden;
+ for (const auto &dirEntry : QDirListing(path, dirFilters)) {
+ if (isInterruptionRequested())
+ break;
+ fileInfo = dirEntry.fileInfo();
fileInfo.stat();
allFiles.append(fileInfo.fileName());
fetch(fileInfo, base, firstTime, updatedFiles, path);
@@ -412,7 +433,7 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
emit newListOfFiles(path, allFiles);
QStringList::const_iterator filesIt = filesToCheck.constBegin();
- while (!abort.loadRelaxed() && filesIt != filesToCheck.constEnd()) {
+ while (!isInterruptionRequested() && filesIt != filesToCheck.constEnd()) {
fileInfo.setFile(path + QDir::separator() + *filesIt);
++filesIt;
fileInfo.stat();
@@ -424,12 +445,12 @@ void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &fil
}
void QFileInfoGatherer::fetch(const QFileInfo &fileInfo, QElapsedTimer &base, bool &firstTime,
- QList<QPair<QString, QFileInfo>> &updatedFiles, const QString &path)
+ QList<std::pair<QString, QFileInfo>> &updatedFiles, const QString &path)
{
- updatedFiles.append(QPair<QString, QFileInfo>(fileInfo.fileName(), fileInfo));
+ updatedFiles.emplace_back(std::pair(fileInfo.fileName(), fileInfo));
QElapsedTimer current;
current.start();
- if ((firstTime && updatedFiles.count() > 100) || base.msecsTo(current) > 1000) {
+ if ((firstTime && updatedFiles.size() > 100) || base.msecsTo(current) > 1000) {
emit updates(path, updatedFiles);
updatedFiles.clear();
base = current;
diff --git a/src/gui/itemmodels/qfileinfogatherer_p.h b/src/gui/itemmodels/qfileinfogatherer_p.h
index 374331a588..3d5f59c22e 100644
--- a/src/gui/itemmodels/qfileinfogatherer_p.h
+++ b/src/gui/itemmodels/qfileinfogatherer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILEINFOGATHERER_H
#define QFILEINFOGATHERER_H
@@ -60,7 +24,6 @@
#include <qfilesystemwatcher.h>
#endif
#include <qabstractfileiconprovider.h>
-#include <qpair.h>
#include <qstack.h>
#include <qdatetime.h>
#include <qdir.h>
@@ -68,6 +31,8 @@
#include <private/qfilesystemengine_p.h>
+#include <utility>
+
QT_REQUIRE_CONFIG(filesystemmodel);
QT_BEGIN_NAMESPACE
@@ -87,7 +52,7 @@ public:
return mFileInfo == fileInfo.mFileInfo
&& displayType == fileInfo.displayType
&& permissions() == fileInfo.permissions()
- && lastModified() == fileInfo.lastModified();
+ && lastModified(QTimeZone::UTC) == fileInfo.lastModified(QTimeZone::UTC);
}
#ifndef QT_NO_FSFILEENGINE
@@ -117,7 +82,7 @@ public:
{
if (ignoreNtfsSymLinks) {
#ifdef Q_OS_WIN
- return !mFileInfo.suffix().compare(QLatin1String("lnk"), Qt::CaseInsensitive);
+ return !mFileInfo.suffix().compare(QLatin1StringView("lnk"), Qt::CaseInsensitive);
#endif
}
return mFileInfo.isSymLink();
@@ -131,8 +96,8 @@ public:
return mFileInfo;
}
- QDateTime lastModified() const {
- return mFileInfo.lastModified();
+ QDateTime lastModified(const QTimeZone &tz) const {
+ return mFileInfo.lastModified(tz);
}
qint64 size() const {
@@ -160,7 +125,7 @@ class Q_GUI_EXPORT QFileInfoGatherer : public QThread
Q_OBJECT
Q_SIGNALS:
- void updates(const QString &directory, const QList<QPair<QString, QFileInfo>> &updates);
+ void updates(const QString &directory, const QList<std::pair<QString, QFileInfo>> &updates);
void newListOfFiles(const QString &directory, const QStringList &listOfFiles) const;
void nameResolved(const QString &fileName, const QString &resolvedName) const;
void directoryLoaded(const QString &path);
@@ -184,6 +149,8 @@ public:
QAbstractFileIconProvider *iconProvider() const;
bool resolveSymlinks() const;
+ void requestAbort();
+
public Q_SLOTS:
void list(const QString &directoryPath);
void fetchExtendedInformation(const QString &path, const QStringList &files);
@@ -195,12 +162,15 @@ private Q_SLOTS:
void driveAdded();
void driveRemoved();
+protected:
+ bool event(QEvent *event) override;
+
private:
void run() override;
// called by run():
void getFileInfos(const QString &path, const QStringList &files);
void fetch(const QFileInfo &info, QElapsedTimer &base, bool &firstTime,
- QList<QPair<QString, QFileInfo>> &updatedFiles, const QString &path);
+ QList<std::pair<QString, QFileInfo>> &updatedFiles, const QString &path);
private:
void createWatcher();
@@ -211,7 +181,6 @@ private:
QStack<QString> path;
QStack<QStringList> files;
// end protected by mutex
- QAtomicInt abort;
#if QT_CONFIG(filesystemwatcher)
QFileSystemWatcher *m_watcher = nullptr;
diff --git a/src/gui/itemmodels/qfilesystemmodel.cpp b/src/gui/itemmodels/qfilesystemmodel.cpp
index 4786e18ef3..290891322f 100644
--- a/src/gui/itemmodels/qfilesystemmodel.cpp
+++ b/src/gui/itemmodels/qfilesystemmodel.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfilesystemmodel_p.h"
#include "qfilesystemmodel.h"
@@ -59,12 +23,15 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\enum QFileSystemModel::Roles
\value FileIconRole
\value FilePathRole
\value FileNameRole
\value FilePermissions
+ \value FileInfoRole The QFileInfo object for the index
*/
/*!
@@ -142,7 +109,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QIcon QFileSystemModel::fileName(const QModelIndex &index) const
+ \fn QString QFileSystemModel::fileName(const QModelIndex &index) const
Returns the file name for the item stored in the model under the given
\a index.
@@ -177,7 +144,7 @@ QFileInfo QFileSystemModel::fileInfo(const QModelIndex &index) const
\fn void QFileSystemModel::fileRenamed(const QString &path, const QString &oldName, const QString &newName)
This signal is emitted whenever a file with the \a oldName is successfully
- renamed to \a newName. The file is located in in the directory \a path.
+ renamed to \a newName. The file is located in the directory \a path.
*/
/*!
@@ -274,7 +241,7 @@ QModelIndex QFileSystemModel::index(int row, int column, const QModelIndex &pare
*/
QModelIndex QFileSystemModel::sibling(int row, int column, const QModelIndex &idx) const
{
- if (row == idx.row() && column < QFileSystemModelPrivate::NumColumns) {
+ if (row == idx.row() && column < columnCount(idx.parent())) {
// cheap sibling operation: just adjust the column:
return createIndex(row, column, idx.internalPointer());
} else {
@@ -314,17 +281,17 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QM
static QString qt_GetLongPathName(const QString &strShortPath)
{
if (strShortPath.isEmpty()
- || strShortPath == QLatin1String(".") || strShortPath == QLatin1String(".."))
+ || strShortPath == "."_L1 || strShortPath == ".."_L1)
return strShortPath;
- if (strShortPath.length() == 2 && strShortPath.endsWith(QLatin1Char(':')))
+ if (strShortPath.length() == 2 && strShortPath.endsWith(u':'))
return strShortPath.toUpper();
const QString absPath = QDir(strShortPath).absolutePath();
- if (absPath.startsWith(QLatin1String("//"))
- || absPath.startsWith(QLatin1String("\\\\"))) // unc
+ if (absPath.startsWith("//"_L1)
+ || absPath.startsWith("\\\\"_L1)) // unc
return QDir::fromNativeSeparators(absPath);
- if (absPath.startsWith(QLatin1Char('/')))
+ if (absPath.startsWith(u'/'))
return QString();
- const QString inputString = QLatin1String("\\\\?\\") + QDir::toNativeSeparators(absPath);
+ const QString inputString = "\\\\?\\"_L1 + QDir::toNativeSeparators(absPath);
QVarLengthArray<TCHAR, MAX_PATH> buffer(MAX_PATH);
DWORD result = ::GetLongPathName((wchar_t*)inputString.utf16(),
buffer.data(),
@@ -354,7 +321,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
{
Q_Q(const QFileSystemModel);
Q_UNUSED(q);
- if (path.isEmpty() || path == myComputer() || path.startsWith(QLatin1Char(':')))
+ if (path.isEmpty() || path == myComputer() || path.startsWith(u':'))
return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
// Construct the nodes up to the new root path if they need to be built
@@ -370,33 +337,33 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
absolutePath = QDir(longPath).absolutePath();
// ### TODO can we use bool QAbstractFileEngine::caseSensitive() const?
- QStringList pathElements = absolutePath.split(QLatin1Char('/'), Qt::SkipEmptyParts);
+ QStringList pathElements = absolutePath.split(u'/', Qt::SkipEmptyParts);
if ((pathElements.isEmpty())
#if !defined(Q_OS_WIN)
- && QDir::fromNativeSeparators(longPath) != QLatin1String("/")
+ && QDir::fromNativeSeparators(longPath) != "/"_L1
#endif
)
return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
QModelIndex index = QModelIndex(); // start with "My Computer"
QString elementPath;
- QChar separator = QLatin1Char('/');
+ QChar separator = u'/';
QString trailingSeparator;
#if defined(Q_OS_WIN)
- if (absolutePath.startsWith(QLatin1String("//"))) { // UNC path
- QString host = QLatin1String("\\\\") + pathElements.constFirst();
+ if (absolutePath.startsWith("//"_L1)) { // UNC path
+ QString host = "\\\\"_L1 + pathElements.constFirst();
if (absolutePath == QDir::fromNativeSeparators(host))
- absolutePath.append(QLatin1Char('/'));
- if (longPath.endsWith(QLatin1Char('/')) && !absolutePath.endsWith(QLatin1Char('/')))
- absolutePath.append(QLatin1Char('/'));
- if (absolutePath.endsWith(QLatin1Char('/')))
- trailingSeparator = QLatin1String("\\");
+ absolutePath.append(u'/');
+ if (longPath.endsWith(u'/') && !absolutePath.endsWith(u'/'))
+ absolutePath.append(u'/');
+ if (absolutePath.endsWith(u'/'))
+ trailingSeparator = "\\"_L1;
int r = 0;
auto rootNode = const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
auto it = root.children.constFind(host);
if (it != root.children.cend()) {
host = it.key(); // Normalize case for lookup in visibleLocation()
} else {
- if (pathElements.count() == 1 && !absolutePath.endsWith(QLatin1Char('/')))
+ if (pathElements.count() == 1 && !absolutePath.endsWith(u'/'))
return rootNode;
QFileInfo info(host);
if (!info.exists())
@@ -409,31 +376,31 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
r = translateVisibleLocation(rootNode, r);
index = q->index(r, 0, QModelIndex());
pathElements.pop_front();
- separator = QLatin1Char('\\');
+ separator = u'\\';
elementPath = host;
elementPath.append(separator);
} else {
- if (!pathElements.at(0).contains(QLatin1Char(':'))) {
+ if (!pathElements.at(0).contains(u':')) {
QString rootPath = QDir(longPath).rootPath();
pathElements.prepend(rootPath);
}
- if (pathElements.at(0).endsWith(QLatin1Char('/')))
+ if (pathElements.at(0).endsWith(u'/'))
pathElements[0].chop(1);
}
#else
// add the "/" item, since it is a valid path element on Unix
- if (absolutePath[0] == QLatin1Char('/'))
- pathElements.prepend(QLatin1String("/"));
+ if (absolutePath[0] == u'/')
+ pathElements.prepend("/"_L1);
#endif
QFileSystemModelPrivate::QFileSystemNode *parent = node(index);
- for (int i = 0; i < pathElements.count(); ++i) {
+ for (int i = 0; i < pathElements.size(); ++i) {
QString element = pathElements.at(i);
if (i != 0)
elementPath.append(separator);
elementPath.append(element);
- if (i == pathElements.count() - 1)
+ if (i == pathElements.size() - 1)
elementPath.append(trailingSeparator);
#ifdef Q_OS_WIN
// On Windows, "filename " and "filename" are equivalent and
@@ -443,7 +410,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
// If after stripping the characters there is nothing left then we
// just return the parent directory as it is assumed that the path
// is referring to the parent
- while (element.endsWith(QLatin1Char('.')) || element.endsWith(QLatin1Char(' ')))
+ while (element.endsWith(u'.') || element.endsWith(u' '))
element.chop(1);
// Only filenames that can't possibly exist will be end up being empty
if (element.isEmpty())
@@ -454,7 +421,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
// we couldn't find the path element, we create a new node since we
// _know_ that the path is valid
if (alreadyExisted) {
- if ((parent->children.count() == 0)
+ if ((parent->children.size() == 0)
|| (parent->caseSensitive()
&& parent->children.value(element)->fileName != element)
|| (!parent->caseSensitive()
@@ -472,7 +439,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this);
node = p->addNode(parent, element,info);
#if QT_CONFIG(filesystemwatcher)
- node->populate(fileInfoGatherer.getInfo(info));
+ node->populate(fileInfoGatherer->getInfo(info));
#endif
} else {
node = parent->children.value(element);
@@ -510,10 +477,10 @@ void QFileSystemModel::timerEvent(QTimerEvent *event)
if (event->timerId() == d->fetchingTimer.timerId()) {
d->fetchingTimer.stop();
#if QT_CONFIG(filesystemwatcher)
- for (int i = 0; i < d->toFetch.count(); ++i) {
+ for (int i = 0; i < d->toFetch.size(); ++i) {
const QFileSystemModelPrivate::QFileSystemNode *node = d->toFetch.at(i).node;
if (!node->hasInformation()) {
- d->fileInfoGatherer.fetchExtendedInformation(d->toFetch.at(i).dir,
+ d->fileInfoGatherer->fetchExtendedInformation(d->toFetch.at(i).dir,
QStringList(d->toFetch.at(i).file));
} else {
// qDebug("yah!, you saved a little gerbil soul");
@@ -563,14 +530,38 @@ QString QFileSystemModel::type(const QModelIndex &index) const
}
/*!
- Returns the date and time when \a index was last modified.
+ Returns the date and time (in local time) when \a index was last modified.
+
+ This is an overloaded function, equivalent to calling:
+ \code
+ lastModified(index, QTimeZone::LocalTime);
+ \endcode
+
+ If \a index is invalid, a default constructed QDateTime is returned.
*/
QDateTime QFileSystemModel::lastModified(const QModelIndex &index) const
{
+ return lastModified(index, QTimeZone::LocalTime);
+}
+
+/*!
+ \since 6.6
+ Returns the date and time, in the time zone \a tz, when
+ \a index was last modified.
+
+ Typical arguments for \a tz are \c QTimeZone::UTC or \c QTimeZone::LocalTime.
+ UTC does not require any conversion from the time returned by the native file
+ system API, therefore getting the time in UTC is potentially faster. LocalTime
+ is typically chosen if the time is shown to the user.
+
+ If \a index is invalid, a default constructed QDateTime is returned.
+ */
+QDateTime QFileSystemModel::lastModified(const QModelIndex &index, const QTimeZone &tz) const
+{
Q_D(const QFileSystemModel);
if (!index.isValid())
return QDateTime();
- return d->node(index)->lastModified();
+ return d->node(index)->lastModified(tz);
}
/*!
@@ -660,7 +651,7 @@ void QFileSystemModel::fetchMore(const QModelIndex &parent)
return;
indexNode->populatedChildren = true;
#if QT_CONFIG(filesystemwatcher)
- d->fileInfoGatherer.list(filePath(parent));
+ d->fileInfoGatherer->list(filePath(parent));
#endif
}
@@ -674,10 +665,10 @@ int QFileSystemModel::rowCount(const QModelIndex &parent) const
return 0;
if (!parent.isValid())
- return d->root.visibleChildren.count();
+ return d->root.visibleChildren.size();
const QFileSystemModelPrivate::QFileSystemNode *parentNode = d->node(parent);
- return parentNode->visibleChildren.count();
+ return parentNode->visibleChildren.size();
}
/*!
@@ -703,7 +694,9 @@ QVariant QFileSystemModel::myComputer(int role) const
return QFileSystemModelPrivate::myComputer();
#if QT_CONFIG(filesystemwatcher)
case Qt::DecorationRole:
- return d->fileInfoGatherer.iconProvider()->icon(QAbstractFileIconProvider::Computer);
+ if (auto *provider = d->fileInfoGatherer->iconProvider())
+ return provider->icon(QAbstractFileIconProvider::Computer);
+ break;
#endif
}
return QVariant();
@@ -720,15 +713,15 @@ QVariant QFileSystemModel::data(const QModelIndex &index, int role) const
switch (role) {
case Qt::EditRole:
- if (index.column() == 0)
+ if (index.column() == QFileSystemModelPrivate::NameColumn)
return d->name(index);
Q_FALLTHROUGH();
case Qt::DisplayRole:
switch (index.column()) {
- case 0: return d->displayName(index);
- case 1: return d->size(index);
- case 2: return d->type(index);
- case 3: return d->time(index);
+ case QFileSystemModelPrivate::NameColumn: return d->displayName(index);
+ case QFileSystemModelPrivate::SizeColumn: return d->size(index);
+ case QFileSystemModelPrivate::TypeColumn: return d->type(index);
+ case QFileSystemModelPrivate::TimeColumn: return d->time(index);
default:
qWarning("data: invalid display value column %d", index.column());
break;
@@ -738,22 +731,23 @@ QVariant QFileSystemModel::data(const QModelIndex &index, int role) const
return filePath(index);
case FileNameRole:
return d->name(index);
+ case FileInfoRole:
+ return QVariant::fromValue(fileInfo(index));
case Qt::DecorationRole:
- if (index.column() == 0) {
+ if (index.column() == QFileSystemModelPrivate::NameColumn) {
QIcon icon = d->icon(index);
#if QT_CONFIG(filesystemwatcher)
if (icon.isNull()) {
- if (d->node(index)->isDir())
- icon = d->fileInfoGatherer.iconProvider()->icon(QAbstractFileIconProvider::Folder);
- else
- icon = d->fileInfoGatherer.iconProvider()->icon(QAbstractFileIconProvider::File);
+ using P = QAbstractFileIconProvider;
+ if (auto *provider = d->fileInfoGatherer->iconProvider())
+ icon = provider->icon(d->node(index)->isDir() ? P::Folder: P::File);
}
#endif // filesystemwatcher
return icon;
}
break;
case Qt::TextAlignmentRole:
- if (index.column() == 1)
+ if (index.column() == QFileSystemModelPrivate::SizeColumn)
return QVariant(Qt::AlignTrailing | Qt::AlignVCenter);
break;
case FilePermissions:
@@ -774,9 +768,9 @@ QString QFileSystemModelPrivate::size(const QModelIndex &index) const
const QFileSystemNode *n = node(index);
if (n->isDir()) {
#ifdef Q_OS_MAC
- return QLatin1String("--");
+ return "--"_L1;
#else
- return QLatin1String("");
+ return ""_L1;
#endif
// Windows - ""
// OS X - "--"
@@ -799,7 +793,7 @@ QString QFileSystemModelPrivate::time(const QModelIndex &index) const
if (!index.isValid())
return QString();
#if QT_CONFIG(datestring)
- return QLocale::system().toString(node(index)->lastModified(), QLocale::ShortFormat);
+ return QLocale::system().toString(node(index)->lastModified(QTimeZone::LocalTime), QLocale::ShortFormat);
#else
Q_UNUSED(index);
return QString();
@@ -826,7 +820,7 @@ QString QFileSystemModelPrivate::name(const QModelIndex &index) const
QFileSystemNode *dirNode = node(index);
if (
#if QT_CONFIG(filesystemwatcher)
- fileInfoGatherer.resolveSymlinks() &&
+ fileInfoGatherer->resolveSymlinks() &&
#endif
!resolvedSymLinks.isEmpty() && dirNode->isSymLink(/* ignoreNtfsSymLinks = */ true)) {
QString fullPath = QDir::fromNativeSeparators(filePath(index));
@@ -896,7 +890,7 @@ bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, in
*After re-naming something we don't want the selection to change*
- can't remove rows and later insert
- can't quickly remove and insert
- - index pointer can't change because treeview doesn't use persistant index's
+ - index pointer can't change because treeview doesn't use persistent index's
- if this get any more complicated think of changing it to just
use layoutChanged
@@ -907,14 +901,14 @@ bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, in
int visibleLocation = parentNode->visibleLocation(parentNode->children.value(indexNode->fileName)->fileName);
parentNode->visibleChildren.removeAt(visibleLocation);
- QScopedPointer<QFileSystemModelPrivate::QFileSystemNode> nodeToRename(parentNode->children.take(oldName));
+ std::unique_ptr<QFileSystemModelPrivate::QFileSystemNode> nodeToRename(parentNode->children.take(oldName));
nodeToRename->fileName = newName;
nodeToRename->parent = parentNode;
#if QT_CONFIG(filesystemwatcher)
- nodeToRename->populate(d->fileInfoGatherer.getInfo(QFileInfo(parentPath, newName)));
+ nodeToRename->populate(d->fileInfoGatherer->getInfo(QFileInfo(parentPath, newName)));
#endif
nodeToRename->isVisible = true;
- parentNode->children[newName] = nodeToRename.take();
+ parentNode->children[newName] = nodeToRename.release();
parentNode->visibleChildren.insert(visibleLocation, newName);
d->delayedSort();
@@ -947,23 +941,27 @@ QVariant QFileSystemModel::headerData(int section, Qt::Orientation orientation,
QString returnValue;
switch (section) {
- case 0: returnValue = tr("Name");
- break;
- case 1: returnValue = tr("Size");
- break;
- case 2: returnValue =
+ case QFileSystemModelPrivate::NameColumn:
+ returnValue = tr("Name");
+ break;
+ case QFileSystemModelPrivate::SizeColumn:
+ returnValue = tr("Size");
+ break;
+ case QFileSystemModelPrivate::TypeColumn:
+ returnValue =
#ifdef Q_OS_MAC
- tr("Kind", "Match OS X Finder");
+ tr("Kind", "Match OS X Finder");
#else
- tr("Type", "All other platforms");
+ tr("Type", "All other platforms");
#endif
- break;
+ break;
// Windows - Type
// OS X - Kind
// Konqueror - File Type
// Nautilus - Type
- case 3: returnValue = tr("Date Modified");
- break;
+ case QFileSystemModelPrivate::TimeColumn:
+ returnValue = tr("Date Modified");
+ break;
default: return QVariant();
}
return returnValue;
@@ -987,14 +985,15 @@ Qt::ItemFlags QFileSystemModel::flags(const QModelIndex &index) const
}
flags |= Qt::ItemIsDragEnabled;
+
+ if (!indexNode->isDir())
+ flags |= Qt::ItemNeverHasChildren;
if (d->readOnly)
return flags;
if ((index.column() == 0) && indexNode->permissions() & QFile::WriteUser) {
flags |= Qt::ItemIsEditable;
if (indexNode->isDir())
flags |= Qt::ItemIsDropEnabled;
- else
- flags |= Qt::ItemNeverHasChildren;
}
return flags;
}
@@ -1002,7 +1001,7 @@ Qt::ItemFlags QFileSystemModel::flags(const QModelIndex &index) const
/*!
\internal
*/
-void QFileSystemModelPrivate::_q_performDelayedSort()
+void QFileSystemModelPrivate::performDelayedSort()
{
Q_Q(QFileSystemModel);
q->sort(sortColumn, sortOrder);
@@ -1026,7 +1025,7 @@ public:
const QFileSystemModelPrivate::QFileSystemNode *r) const
{
switch (sortColumn) {
- case 0: {
+ case QFileSystemModelPrivate::NameColumn: {
#ifndef Q_OS_MAC
// place directories before files
bool left = l->isDir();
@@ -1036,7 +1035,7 @@ public:
#endif
return naturalCompare.compare(l->fileName, r->fileName) < 0;
}
- case 1:
+ case QFileSystemModelPrivate::SizeColumn:
{
// Directories go first
bool left = l->isDir();
@@ -1050,7 +1049,7 @@ public:
return sizeDifference < 0;
}
- case 2:
+ case QFileSystemModelPrivate::TypeColumn:
{
int compare = naturalCompare.compare(l->type(), r->type());
if (compare == 0)
@@ -1058,12 +1057,14 @@ public:
return compare < 0;
}
- case 3:
+ case QFileSystemModelPrivate::TimeColumn:
{
- if (l->lastModified() == r->lastModified())
+ const QDateTime left = l->lastModified(QTimeZone::UTC);
+ const QDateTime right = r->lastModified(QTimeZone::UTC);
+ if (left == right)
return naturalCompare.compare(l->fileName, r->fileName) < 0;
- return l->lastModified() < r->lastModified();
+ return left < right;
}
}
Q_ASSERT(false);
@@ -1091,7 +1092,7 @@ void QFileSystemModelPrivate::sortChildren(int column, const QModelIndex &parent
{
Q_Q(QFileSystemModel);
QFileSystemModelPrivate::QFileSystemNode *indexNode = node(parent);
- if (indexNode->children.count() == 0)
+ if (indexNode->children.size() == 0)
return;
QList<QFileSystemModelPrivate::QFileSystemNode *> values;
@@ -1109,11 +1110,10 @@ void QFileSystemModelPrivate::sortChildren(int column, const QModelIndex &parent
indexNode->visibleChildren.clear();
//No more dirty item we reset our internal dirty index
indexNode->dirtyChildrenIndex = -1;
- const int numValues = values.count();
- indexNode->visibleChildren.reserve(numValues);
- for (int i = 0; i < numValues; ++i) {
- indexNode->visibleChildren.append(values.at(i)->fileName);
- values.at(i)->isVisible = true;
+ indexNode->visibleChildren.reserve(values.size());
+ for (QFileSystemNode *node : std::as_const(values)) {
+ indexNode->visibleChildren.append(node->fileName);
+ node->isVisible = true;
}
if (!disableRecursiveSort) {
@@ -1139,10 +1139,8 @@ void QFileSystemModel::sort(int column, Qt::SortOrder order)
emit layoutAboutToBeChanged();
QModelIndexList oldList = persistentIndexList();
QList<QPair<QFileSystemModelPrivate::QFileSystemNode *, int>> oldNodes;
- const int nodeCount = oldList.count();
- oldNodes.reserve(nodeCount);
- for (int i = 0; i < nodeCount; ++i) {
- const QModelIndex &oldNode = oldList.at(i);
+ oldNodes.reserve(oldList.size());
+ for (const QModelIndex &oldNode : oldList) {
QPair<QFileSystemModelPrivate::QFileSystemNode*, int> pair(d->node(oldNode), oldNode.column());
oldNodes.append(pair);
}
@@ -1156,12 +1154,10 @@ void QFileSystemModel::sort(int column, Qt::SortOrder order)
d->sortOrder = order;
QModelIndexList newList;
- const int numOldNodes = oldNodes.size();
- newList.reserve(numOldNodes);
- for (int i = 0; i < numOldNodes; ++i) {
- const QPair<QFileSystemModelPrivate::QFileSystemNode*, int> &oldNode = oldNodes.at(i);
- newList.append(d->index(oldNode.first, oldNode.second));
- }
+ newList.reserve(oldNodes.size());
+ for (const auto &[node, col]: std::as_const(oldNodes))
+ newList.append(d->index(node, col));
+
changePersistentIndexList(oldList, newList);
emit layoutChanged();
}
@@ -1172,7 +1168,7 @@ void QFileSystemModel::sort(int column, Qt::SortOrder order)
*/
QStringList QFileSystemModel::mimeTypes() const
{
- return QStringList(QLatin1String("text/uri-list"));
+ return QStringList("text/uri-list"_L1);
}
/*!
@@ -1188,7 +1184,7 @@ QMimeData *QFileSystemModel::mimeData(const QModelIndexList &indexes) const
QList<QUrl> urls;
QList<QModelIndex>::const_iterator it = indexes.begin();
for (; it != indexes.end(); ++it)
- if ((*it).column() == 0)
+ if ((*it).column() == QFileSystemModelPrivate::NameColumn)
urls << QUrl::fromLocalFile(filePath(*it));
QMimeData *data = new QMimeData();
data->setUrls(urls);
@@ -1262,6 +1258,7 @@ QHash<int, QByteArray> QFileSystemModel::roleNames() const
ret.insert(QFileSystemModel::FilePathRole, QByteArrayLiteral("filePath"));
ret.insert(QFileSystemModel::FileNameRole, QByteArrayLiteral("fileName"));
ret.insert(QFileSystemModel::FilePermissions, QByteArrayLiteral("filePermissions"));
+ ret.insert(QFileSystemModel::FileInfoRole, QByteArrayLiteral("fileInfo"));
return ret;
}
@@ -1334,7 +1331,7 @@ void QFileSystemModel::setOptions(Options options)
#if QT_CONFIG(filesystemwatcher)
Q_D(QFileSystemModel);
if (changed.testFlag(DontWatchForChanges))
- d->fileInfoGatherer.setWatching(!options.testFlag(DontWatchForChanges));
+ d->fileInfoGatherer->setWatching(!options.testFlag(DontWatchForChanges));
#endif
if (changed.testFlag(DontUseCustomDirectoryIcons)) {
@@ -1355,7 +1352,7 @@ QFileSystemModel::Options QFileSystemModel::options() const
result.setFlag(DontResolveSymlinks, !resolveSymlinks());
#if QT_CONFIG(filesystemwatcher)
Q_D(const QFileSystemModel);
- result.setFlag(DontWatchForChanges, !d->fileInfoGatherer.isWatching());
+ result.setFlag(DontWatchForChanges, !d->fileInfoGatherer->isWatching());
#else
result.setFlag(DontWatchForChanges);
#endif
@@ -1377,7 +1374,7 @@ QString QFileSystemModel::filePath(const QModelIndex &index) const
QFileSystemModelPrivate::QFileSystemNode *dirNode = d->node(index);
if (dirNode->isSymLink()
#if QT_CONFIG(filesystemwatcher)
- && d->fileInfoGatherer.resolveSymlinks()
+ && d->fileInfoGatherer->resolveSymlinks()
#endif
&& d->resolvedSymLinks.contains(fullPath)
&& dirNode->isDir()) {
@@ -1413,11 +1410,11 @@ QString QFileSystemModelPrivate::filePath(const QModelIndex &index) const
}
QString fullPath = QDir::fromNativeSeparators(path.join(QDir::separator()));
#if !defined(Q_OS_WIN)
- if ((fullPath.length() > 2) && fullPath[0] == QLatin1Char('/') && fullPath[1] == QLatin1Char('/'))
+ if ((fullPath.size() > 2) && fullPath[0] == u'/' && fullPath[1] == u'/')
fullPath = fullPath.mid(1);
#else
- if (fullPath.length() == 2 && fullPath.endsWith(QLatin1Char(':')))
- fullPath.append(QLatin1Char('/'));
+ if (fullPath.length() == 2 && fullPath.endsWith(u':'))
+ fullPath.append(u'/');
#endif
return fullPath;
}
@@ -1439,7 +1436,7 @@ QModelIndex QFileSystemModel::mkdir(const QModelIndex &parent, const QString &na
Q_ASSERT(parentNode->children.contains(name));
QFileSystemModelPrivate::QFileSystemNode *node = parentNode->children[name];
#if QT_CONFIG(filesystemwatcher)
- node->populate(d->fileInfoGatherer.getInfo(QFileInfo(dir.absolutePath() + QDir::separator() + name)));
+ node->populate(d->fileInfoGatherer->getInfo(QFileInfo(dir.absolutePath() + QDir::separator() + name)));
#endif
d->addVisibleFiles(parentNode, QStringList(name));
return d->index(node);
@@ -1504,10 +1501,10 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath)
return d->index(rootPath());
//We remove the watcher on the previous path
- if (!rootPath().isEmpty() && rootPath() != QLatin1String(".")) {
+ if (!rootPath().isEmpty() && rootPath() != "."_L1) {
//This remove the watcher for the old rootPath
#if QT_CONFIG(filesystemwatcher)
- d->fileInfoGatherer.removePath(rootPath());
+ d->fileInfoGatherer->removePath(rootPath());
#endif
//This line "marks" the node as dirty, so the next fetchMore
//call on the path will ask the gatherer to install a watcher again
@@ -1520,7 +1517,7 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath)
QModelIndex newRootIndex;
if (showDrives) {
// otherwise dir will become '.'
- d->rootDir.setPath(QLatin1String(""));
+ d->rootDir.setPath(""_L1);
} else {
newRootIndex = d->index(d->rootDir.path());
}
@@ -1563,7 +1560,7 @@ void QFileSystemModel::setIconProvider(QAbstractFileIconProvider *provider)
{
Q_D(QFileSystemModel);
#if QT_CONFIG(filesystemwatcher)
- d->fileInfoGatherer.setIconProvider(provider);
+ d->fileInfoGatherer->setIconProvider(provider);
#endif
d->root.updateIcon(provider, QString());
}
@@ -1575,9 +1572,9 @@ QAbstractFileIconProvider *QFileSystemModel::iconProvider() const
{
#if QT_CONFIG(filesystemwatcher)
Q_D(const QFileSystemModel);
- return d->fileInfoGatherer.iconProvider();
+ return d->fileInfoGatherer->iconProvider();
#else
- return 0;
+ return nullptr;
#endif
}
@@ -1594,9 +1591,11 @@ void QFileSystemModel::setFilter(QDir::Filters filters)
Q_D(QFileSystemModel);
if (d->filters == filters)
return;
+ const bool changingCaseSensitivity =
+ filters.testFlag(QDir::CaseSensitive) != d->filters.testFlag(QDir::CaseSensitive);
d->filters = filters;
- // CaseSensitivity might have changed
- setNameFilters(nameFilters());
+ if (changingCaseSensitivity)
+ d->rebuildNameFilterRegexps();
d->forceSort = true;
d->delayedSort();
}
@@ -1629,7 +1628,7 @@ void QFileSystemModel::setResolveSymlinks(bool enable)
{
#if QT_CONFIG(filesystemwatcher)
Q_D(QFileSystemModel);
- d->fileInfoGatherer.setResolveSymlinks(enable);
+ d->fileInfoGatherer->setResolveSymlinks(enable);
#else
Q_UNUSED(enable);
#endif
@@ -1639,7 +1638,7 @@ bool QFileSystemModel::resolveSymlinks() const
{
#if QT_CONFIG(filesystemwatcher)
Q_D(const QFileSystemModel);
- return d->fileInfoGatherer.resolveSymlinks();
+ return d->fileInfoGatherer->resolveSymlinks();
#else
return false;
#endif
@@ -1693,7 +1692,6 @@ bool QFileSystemModel::nameFilterDisables() const
*/
void QFileSystemModel::setNameFilters(const QStringList &filters)
{
- // Prep the regexp's ahead of time
#if QT_CONFIG(regularexpression)
Q_D(QFileSystemModel);
@@ -1716,6 +1714,7 @@ void QFileSystemModel::setNameFilters(const QStringList &filters)
}
d->nameFilters = filters;
+ d->rebuildNameFilterRegexps();
d->forceSort = true;
d->delayedSort();
#else
@@ -1744,7 +1743,7 @@ bool QFileSystemModel::event(QEvent *event)
#if QT_CONFIG(filesystemwatcher)
Q_D(QFileSystemModel);
if (event->type() == QEvent::LanguageChange) {
- d->root.retranslateStrings(d->fileInfoGatherer.iconProvider(), QString());
+ d->root.retranslateStrings(d->fileInfoGatherer->iconProvider(), QString());
return true;
}
#endif
@@ -1758,7 +1757,7 @@ bool QFileSystemModel::rmdir(const QModelIndex &aindex)
#if QT_CONFIG(filesystemwatcher)
if (success) {
QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
- d->fileInfoGatherer.removePath(path);
+ d->fileInfoGatherer->removePath(path);
}
#endif
return success;
@@ -1770,10 +1769,10 @@ bool QFileSystemModel::rmdir(const QModelIndex &aindex)
Performed quick listing and see if any files have been added or removed,
then fetch more information on visible files.
*/
-void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, const QStringList &files)
+void QFileSystemModelPrivate::directoryChanged(const QString &directory, const QStringList &files)
{
QFileSystemModelPrivate::QFileSystemNode *parentNode = node(directory, false);
- if (parentNode->children.count() == 0)
+ if (parentNode->children.size() == 0)
return;
QStringList toRemove;
QStringList newFiles = files;
@@ -1783,7 +1782,7 @@ void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, cons
if ((iterator == newFiles.end()) || (i.value()->fileName < *iterator))
toRemove.append(i.value()->fileName);
}
- for (int i = 0 ; i < toRemove.count() ; ++i )
+ for (int i = 0 ; i < toRemove.size() ; ++i )
removeNode(parentNode, toRemove[i]);
}
@@ -1875,11 +1874,11 @@ void QFileSystemModelPrivate::addVisibleFiles(QFileSystemNode *parentNode, const
QModelIndex parent = index(parentNode);
bool indexHidden = isHiddenByFilter(parentNode, parent);
if (!indexHidden) {
- q->beginInsertRows(parent, parentNode->visibleChildren.count() , parentNode->visibleChildren.count() + newFiles.count() - 1);
+ q->beginInsertRows(parent, parentNode->visibleChildren.size() , parentNode->visibleChildren.size() + newFiles.size() - 1);
}
if (parentNode->dirtyChildrenIndex == -1)
- parentNode->dirtyChildrenIndex = parentNode->visibleChildren.count();
+ parentNode->dirtyChildrenIndex = parentNode->visibleChildren.size();
for (const auto &newFile : newFiles) {
parentNode->visibleChildren.append(newFile);
@@ -1918,8 +1917,8 @@ void QFileSystemModelPrivate::removeVisibleFile(QFileSystemNode *parentNode, int
The thread has received new information about files,
update and emit dataChanged if it has actually changed.
*/
-void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path,
- const QList<QPair<QString, QFileInfo>> &updates)
+void QFileSystemModelPrivate::fileSystemChanged(const QString &path,
+ const QList<std::pair<QString, QFileInfo>> &updates)
{
#if QT_CONFIG(filesystemwatcher)
Q_Q(QFileSystemModel);
@@ -1930,7 +1929,7 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path,
for (const auto &update : updates) {
QString fileName = update.first;
Q_ASSERT(!fileName.isEmpty());
- QExtendedInformation info = fileInfoGatherer.getInfo(update.second);
+ QExtendedInformation info = fileInfoGatherer->getInfo(update.second);
bool previouslyHere = parentNode->children.contains(fileName);
if (!previouslyHere) {
addNode(parentNode, fileName, info.fileInfo());
@@ -1975,7 +1974,7 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path,
std::sort(rowsToUpdate.begin(), rowsToUpdate.end());
QString min;
QString max;
- for (const QString &value : qAsConst(rowsToUpdate)) {
+ for (const QString &value : std::as_const(rowsToUpdate)) {
//##TODO is there a way to bundle signals with QString as the content of the list?
/*if (min.isEmpty()) {
min = value;
@@ -1993,23 +1992,30 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path,
int visibleMin = parentNode->visibleLocation(min);
int visibleMax = parentNode->visibleLocation(max);
if (visibleMin >= 0
- && visibleMin < parentNode->visibleChildren.count()
+ && visibleMin < parentNode->visibleChildren.size()
&& parentNode->visibleChildren.at(visibleMin) == min
&& visibleMax >= 0) {
- QModelIndex bottom = q->index(translateVisibleLocation(parentNode, visibleMin), 0, parentIndex);
- QModelIndex top = q->index(translateVisibleLocation(parentNode, visibleMax), 3, parentIndex);
- emit q->dataChanged(bottom, top);
+ // don't use NumColumns here, a subclass might override columnCount
+ const int lastColumn = q->columnCount(parentIndex) - 1;
+ const QModelIndex top = q->index(translateVisibleLocation(parentNode, visibleMin),
+ QFileSystemModelPrivate::NameColumn, parentIndex);
+ const QModelIndex bottom = q->index(translateVisibleLocation(parentNode, visibleMax),
+ lastColumn, parentIndex);
+ // We document that emitting dataChanged with indexes that don't have the
+ // same parent is undefined behavior.
+ Q_ASSERT(bottom.parent() == top.parent());
+ emit q->dataChanged(top, bottom);
}
/*min = QString();
max = QString();*/
}
- if (newFiles.count() > 0) {
+ if (newFiles.size() > 0) {
addVisibleFiles(parentNode, newFiles);
}
- if (newFiles.count() > 0 || (sortColumn != 0 && rowsToUpdate.count() > 0)) {
+ if (newFiles.size() > 0 || (sortColumn != 0 && rowsToUpdate.size() > 0)) {
forceSort = true;
delayedSort();
}
@@ -2022,7 +2028,7 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path,
/*!
\internal
*/
-void QFileSystemModelPrivate::_q_resolvedName(const QString &fileName, const QString &resolvedName)
+void QFileSystemModelPrivate::resolvedName(const QString &fileName, const QString &resolvedName)
{
resolvedSymLinks[fileName] = resolvedName;
}
@@ -2048,25 +2054,48 @@ QStringList QFileSystemModelPrivate::unwatchPathsAt(const QModelIndex &index)
if (pathSize == watchedPath.size()) {
return path.compare(watchedPath, caseSensitivity) == 0;
} else if (watchedPath.size() > pathSize) {
- return watchedPath.at(pathSize) == QLatin1Char('/')
+ return watchedPath.at(pathSize) == u'/'
&& watchedPath.startsWith(path, caseSensitivity);
}
return false;
};
- const QStringList &watchedFiles = fileInfoGatherer.watchedFiles();
+ const QStringList &watchedFiles = fileInfoGatherer->watchedFiles();
std::copy_if(watchedFiles.cbegin(), watchedFiles.cend(),
std::back_inserter(result), filter);
- const QStringList &watchedDirectories = fileInfoGatherer.watchedDirectories();
+ const QStringList &watchedDirectories = fileInfoGatherer->watchedDirectories();
std::copy_if(watchedDirectories.cbegin(), watchedDirectories.cend(),
std::back_inserter(result), filter);
- fileInfoGatherer.unwatchPaths(result);
+ fileInfoGatherer->unwatchPaths(result);
return result;
}
#endif // filesystemwatcher && Q_OS_WIN
+QFileSystemModelPrivate::QFileSystemModelPrivate()
+#if QT_CONFIG(filesystemwatcher)
+ : fileInfoGatherer(new QFileInfoGatherer)
+#endif // filesystemwatcher
+{
+}
+
+QFileSystemModelPrivate::~QFileSystemModelPrivate()
+{
+#if QT_CONFIG(filesystemwatcher)
+ fileInfoGatherer->requestAbort();
+ if (!fileInfoGatherer->wait(1000)) {
+ // If the thread hangs, perhaps because the network was disconnected
+ // while the gatherer was stat'ing a remote file, then don't block
+ // shutting down the model (which might block a file dialog and the
+ // main thread). Schedule the gatherer for later deletion; it's
+ // destructor will wait for the thread to finish.
+ auto *rawGatherer = fileInfoGatherer.release();
+ rawGatherer->deleteLater();
+ }
+#endif // filesystemwatcher
+}
+
/*!
\internal
*/
@@ -2076,18 +2105,20 @@ void QFileSystemModelPrivate::init()
delayedSortTimer.setSingleShot(true);
- qRegisterMetaType<QList<QPair<QString, QFileInfo>>>();
+ qRegisterMetaType<QList<std::pair<QString, QFileInfo>>>();
#if QT_CONFIG(filesystemwatcher)
- q->connect(&fileInfoGatherer, SIGNAL(newListOfFiles(QString,QStringList)),
- q, SLOT(_q_directoryChanged(QString,QStringList)));
- q->connect(&fileInfoGatherer, SIGNAL(updates(QString, QList<QPair<QString, QFileInfo>>)), q,
- SLOT(_q_fileSystemChanged(QString, QList<QPair<QString, QFileInfo>>)));
- q->connect(&fileInfoGatherer, SIGNAL(nameResolved(QString,QString)),
- q, SLOT(_q_resolvedName(QString,QString)));
- q->connect(&fileInfoGatherer, SIGNAL(directoryLoaded(QString)),
- q, SIGNAL(directoryLoaded(QString)));
+ QObjectPrivate::connect(fileInfoGatherer.get(), &QFileInfoGatherer::newListOfFiles,
+ this, &QFileSystemModelPrivate::directoryChanged);
+ QObjectPrivate::connect(fileInfoGatherer.get(), &QFileInfoGatherer::updates,
+ this, &QFileSystemModelPrivate::fileSystemChanged);
+ QObjectPrivate::connect(fileInfoGatherer.get(), &QFileInfoGatherer::nameResolved,
+ this, &QFileSystemModelPrivate::resolvedName);
+ q->connect(fileInfoGatherer.get(), &QFileInfoGatherer::directoryLoaded,
+ q, &QFileSystemModel::directoryLoaded);
#endif // filesystemwatcher
- q->connect(&delayedSortTimer, SIGNAL(timeout()), q, SLOT(_q_performDelayedSort()), Qt::QueuedConnection);
+ QObjectPrivate::connect(&delayedSortTimer, &QTimer::timeout,
+ this, &QFileSystemModelPrivate::performDelayedSort,
+ Qt::QueuedConnection);
}
/*!
@@ -2100,8 +2131,14 @@ void QFileSystemModelPrivate::init()
*/
bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) const
{
+ // When the model is set to only show files, then a node representing a dir
+ // should be hidden regardless of bypassFilters.
+ // QTBUG-74471
+ const bool hideDirs = (filters & (QDir::Dirs | QDir::AllDirs)) == 0;
+ const bool shouldHideDirNode = hideDirs && node->isDir();
+
// always accept drives
- if (node->parent == &root || bypassFilters.contains(node))
+ if (node->parent == &root || (!shouldHideDirNode && bypassFilters.contains(node)))
return true;
// If we don't know anything yet don't accept it
@@ -2110,7 +2147,6 @@ bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) co
const bool filterPermissions = ((filters & QDir::PermissionMask)
&& (filters & QDir::PermissionMask) != QDir::PermissionMask);
- const bool hideDirs = !(filters & (QDir::Dirs | QDir::AllDirs));
const bool hideFiles = !(filters & QDir::Files);
const bool hideReadable = !(!filterPermissions || (filters & QDir::Readable));
const bool hideWritable = !(!filterPermissions || (filters & QDir::Writable));
@@ -2122,8 +2158,8 @@ bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) co
const bool hideDotDot = (filters & QDir::NoDotDot);
// Note that we match the behavior of entryList and not QFileInfo on this.
- bool isDot = (node->fileName == QLatin1String("."));
- bool isDotDot = (node->fileName == QLatin1String(".."));
+ bool isDot = (node->fileName == "."_L1);
+ bool isDotDot = (node->fileName == ".."_L1);
if ( (hideHidden && !(isDot || isDotDot) && node->isHidden())
|| (hideSystem && node->isSystem())
|| (hideDirs && node->isDir())
@@ -2152,15 +2188,13 @@ bool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const
// Check the name regularexpression filters
if (!(node->isDir() && (filters & QDir::AllDirs))) {
- auto cs = (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive;
-
- for (const auto &nameFilter : nameFilters) {
- auto rx = QRegularExpression::fromWildcard(nameFilter, cs);
- QRegularExpressionMatch match = rx.match(node->fileName);
- if (match.hasMatch())
- return true;
- }
- return false;
+ const auto matchesNodeFileName = [node](const QRegularExpression &re)
+ {
+ return node->fileName.contains(re);
+ };
+ return std::any_of(nameFiltersRegexps.begin(),
+ nameFiltersRegexps.end(),
+ matchesNodeFileName);
}
#else
Q_UNUSED(node);
@@ -2168,6 +2202,23 @@ bool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const
return true;
}
+#if QT_CONFIG(regularexpression)
+void QFileSystemModelPrivate::rebuildNameFilterRegexps()
+{
+ nameFiltersRegexps.clear();
+ nameFiltersRegexps.reserve(nameFilters.size());
+ const auto cs = (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ const auto convertWildcardToRegexp = [cs](const QString &nameFilter)
+ {
+ return QRegularExpression::fromWildcard(nameFilter, cs);
+ };
+ std::transform(nameFilters.constBegin(),
+ nameFilters.constEnd(),
+ std::back_inserter(nameFiltersRegexps),
+ convertWildcardToRegexp);
+}
+#endif
+
QT_END_NAMESPACE
#include "moc_qfilesystemmodel.cpp"
diff --git a/src/gui/itemmodels/qfilesystemmodel.h b/src/gui/itemmodels/qfilesystemmodel.h
index a79c4c14df..1fd1041f15 100644
--- a/src/gui/itemmodels/qfilesystemmodel.h
+++ b/src/gui/itemmodels/qfilesystemmodel.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMMODEL_H
#define QFILESYSTEMMODEL_H
@@ -45,7 +9,6 @@
#include <QtCore/qpair.h>
#include <QtCore/qdir.h>
#include <QtGui/qicon.h>
-#include <QtCore/qdiriterator.h>
QT_REQUIRE_CONFIG(filesystemmodel);
@@ -69,11 +32,13 @@ Q_SIGNALS:
void directoryLoaded(const QString &path);
public:
+ // ### Qt 7: renumber these values to be before Qt::UserRole comment.
enum Roles {
FileIconRole = Qt::DecorationRole,
+ FileInfoRole = Qt::UserRole - 1,
FilePathRole = Qt::UserRole + 1,
FileNameRole = Qt::UserRole + 2,
- FilePermissions = Qt::UserRole + 3
+ FilePermissions = Qt::UserRole + 3,
};
enum Option
@@ -149,7 +114,9 @@ public:
bool isDir(const QModelIndex &index) const;
qint64 size(const QModelIndex &index) const;
QString type(const QModelIndex &index) const;
+
QDateTime lastModified(const QModelIndex &index) const;
+ QDateTime lastModified(const QModelIndex &index, const QTimeZone &tz) const;
QModelIndex mkdir(const QModelIndex &parent, const QString &name);
bool rmdir(const QModelIndex &index);
@@ -168,13 +135,6 @@ private:
Q_DECLARE_PRIVATE(QFileSystemModel)
Q_DISABLE_COPY(QFileSystemModel)
- Q_PRIVATE_SLOT(d_func(), void _q_directoryChanged(const QString &directory, const QStringList &list))
- Q_PRIVATE_SLOT(d_func(), void _q_performDelayedSort())
- Q_PRIVATE_SLOT(d_func(),
- void _q_fileSystemChanged(const QString &path,
- const QList<QPair<QString, QFileInfo>> &))
- Q_PRIVATE_SLOT(d_func(), void _q_resolvedName(const QString &fileName, const QString &resolvedName))
-
friend class QFileDialogPrivate;
};
diff --git a/src/gui/itemmodels/qfilesystemmodel_p.h b/src/gui/itemmodels/qfilesystemmodel_p.h
index 4acd6a92df..e01b0d56e6 100644
--- a/src/gui/itemmodels/qfilesystemmodel_p.h
+++ b/src/gui/itemmodels/qfilesystemmodel_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFILESYSTEMMODEL_P_H
#define QFILESYSTEMMODEL_P_H
@@ -64,6 +28,8 @@
#include <qtimer.h>
#include <qhash.h>
+#include <vector>
+
QT_REQUIRE_CONFIG(filesystemmodel);
QT_BEGIN_NAMESPACE
@@ -84,7 +50,10 @@ public:
Q_DECLARE_TYPEINFO(QFileSystemModelNodePathKey, Q_RELOCATABLE_TYPE);
-inline size_t qHash(const QFileSystemModelNodePathKey &key) { return qHash(key.toCaseFolded()); }
+inline size_t qHash(const QFileSystemModelNodePathKey &key, size_t seed = 0)
+{
+ return qHash(key.toCaseFolded(), seed);
+}
#else // Q_OS_WIN
typedef QString QFileSystemModelNodePathKey;
#endif
@@ -94,7 +63,13 @@ class Q_GUI_EXPORT QFileSystemModelPrivate : public QAbstractItemModelPrivate
Q_DECLARE_PUBLIC(QFileSystemModel)
public:
- enum { NumColumns = 4 };
+ enum {
+ NameColumn,
+ SizeColumn,
+ TypeColumn,
+ TimeColumn,
+ NumColumns = 4
+ };
class QFileSystemNode
{
@@ -114,8 +89,8 @@ public:
#endif
inline qint64 size() const { if (info && !info->isDir()) return info->size(); return 0; }
- inline QString type() const { if (info) return info->displayType; return QLatin1String(""); }
- inline QDateTime lastModified() const { if (info) return info->lastModified(); return QDateTime(); }
+ inline QString type() const { if (info) return info->displayType; return QLatin1StringView(""); }
+ inline QDateTime lastModified(const QTimeZone &tz) const { return info ? info->lastModified(tz) : QDateTime(); }
inline QFile::Permissions permissions() const { if (info) return info->permissions(); return { }; }
inline bool isReadable() const { return ((permissions() & QFile::ReadUser) != 0); }
inline bool isWritable() const { return ((permissions() & QFile::WriteUser) != 0); }
@@ -123,7 +98,7 @@ public:
inline bool isDir() const {
if (info)
return info->isDir();
- if (children.count() > 0)
+ if (children.size() > 0)
return true;
return false;
}
@@ -175,30 +150,37 @@ public:
return visibleChildren.indexOf(childName);
}
void updateIcon(QAbstractFileIconProvider *iconProvider, const QString &path) {
+ if (!iconProvider)
+ return;
+
if (info)
info->icon = iconProvider->icon(QFileInfo(path));
- for (QFileSystemNode *child : qAsConst(children)) {
+
+ for (QFileSystemNode *child : std::as_const(children)) {
//On windows the root (My computer) has no path so we don't want to add a / for nothing (e.g. /C:/)
if (!path.isEmpty()) {
- if (path.endsWith(QLatin1Char('/')))
+ if (path.endsWith(u'/'))
child->updateIcon(iconProvider, path + child->fileName);
else
- child->updateIcon(iconProvider, path + QLatin1Char('/') + child->fileName);
+ child->updateIcon(iconProvider, path + u'/' + child->fileName);
} else
child->updateIcon(iconProvider, child->fileName);
}
}
void retranslateStrings(QAbstractFileIconProvider *iconProvider, const QString &path) {
+ if (!iconProvider)
+ return;
+
if (info)
info->displayType = iconProvider->type(QFileInfo(path));
- for (QFileSystemNode *child : qAsConst(children)) {
+ for (QFileSystemNode *child : std::as_const(children)) {
//On windows the root (My computer) has no path so we don't want to add a / for nothing (e.g. /C:/)
if (!path.isEmpty()) {
- if (path.endsWith(QLatin1Char('/')))
+ if (path.endsWith(u'/'))
child->retranslateStrings(iconProvider, path + child->fileName);
else
- child->retranslateStrings(iconProvider, path + QLatin1Char('/') + child->fileName);
+ child->retranslateStrings(iconProvider, path + u'/' + child->fileName);
} else
child->retranslateStrings(iconProvider, child->fileName);
}
@@ -213,7 +195,8 @@ public:
bool isVisible = false;
};
- QFileSystemModelPrivate() = default;
+ QFileSystemModelPrivate();
+ ~QFileSystemModelPrivate();
void init();
/*
\internal
@@ -239,7 +222,7 @@ public:
inline int translateVisibleLocation(QFileSystemNode *parent, int row) const {
if (sortOrder != Qt::AscendingOrder) {
if (parent->dirtyChildrenIndex == -1)
- return parent->visibleChildren.count() - row - 1;
+ return parent->visibleChildren.size() - row - 1;
if (row < parent->dirtyChildrenIndex)
return parent->dirtyChildrenIndex - row - 1;
@@ -274,23 +257,25 @@ public:
QString type(const QModelIndex &index) const;
QString time(const QModelIndex &index) const;
- void _q_directoryChanged(const QString &directory, const QStringList &list);
- void _q_performDelayedSort();
- void _q_fileSystemChanged(const QString &path, const QList<QPair<QString, QFileInfo>> &);
- void _q_resolvedName(const QString &fileName, const QString &resolvedName);
+ void directoryChanged(const QString &directory, const QStringList &list);
+ void performDelayedSort();
+ void fileSystemChanged(const QString &path, const QList<std::pair<QString, QFileInfo>> &);
+ void resolvedName(const QString &fileName, const QString &resolvedName);
QDir rootDir;
#if QT_CONFIG(filesystemwatcher)
# ifdef Q_OS_WIN
QStringList unwatchPathsAt(const QModelIndex &);
- void watchPaths(const QStringList &paths) { fileInfoGatherer.watchPaths(paths); }
+ void watchPaths(const QStringList &paths) { fileInfoGatherer->watchPaths(paths); }
# endif // Q_OS_WIN
- QFileInfoGatherer fileInfoGatherer;
+ std::unique_ptr<QFileInfoGatherer> fileInfoGatherer;
#endif // filesystemwatcher
QTimer delayedSortTimer;
QHash<const QFileSystemNode*, bool> bypassFilters;
#if QT_CONFIG(regularexpression)
QStringList nameFilters;
+ std::vector<QRegularExpression> nameFiltersRegexps;
+ void rebuildNameFilterRegexps();
#endif
QHash<QString, QString> resolvedSymLinks;
diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp
index 675b71c530..8b3e381431 100644
--- a/src/gui/itemmodels/qstandarditemmodel.cpp
+++ b/src/gui/itemmodels/qstandarditemmodel.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstandarditemmodel.h"
@@ -55,6 +19,11 @@
QT_BEGIN_NAMESPACE
+// Used internally to store the flags
+namespace {
+constexpr auto DataFlagsRole = Qt::ItemDataRole(Qt::UserRole - 1);
+}
+
static inline QString qStandardItemModelDataListMimeType()
{
return QStringLiteral("application/x-qstandarditemmodeldatalist");
@@ -311,14 +280,12 @@ void QStandardItemPrivate::setItemData(const QMap<int, QVariant> &roles)
/*!
\internal
*/
-const QMap<int, QVariant> QStandardItemPrivate::itemData() const
+QMap<int, QVariant> QStandardItemPrivate::itemData() const
{
QMap<int, QVariant> result;
- QList<QStandardItemData>::const_iterator it;
- for (it = values.cbegin(); it != values.cend(); ++it){
- // Qt::UserRole - 1 is used internally to store the flags
- if (it->role != Qt::UserRole - 1)
- result.insert(it->role, it->value);
+ for (const auto &data : values) {
+ if (data.role != DataFlagsRole)
+ result.insert(data.role, data.value);
}
return result;
}
@@ -355,11 +322,11 @@ void QStandardItemPrivate::sortChildren(int column, Qt::SortOrder order)
}
QModelIndexList changedPersistentIndexesFrom, changedPersistentIndexesTo;
- QList<QStandardItem*> sorted_children(children.count());
+ QList<QStandardItem*> sorted_children(children.size());
for (int i = 0; i < rowCount(); ++i) {
- int r = (i < sortable.count()
+ int r = (i < sortable.size()
? sortable.at(i).second
- : unsortable.at(i - sortable.count()));
+ : unsortable.at(i - sortable.size()));
for (int c = 0; c < columnCount(); ++c) {
QStandardItem *itm = q->child(r, c);
sorted_children[childIndex(i, c)] = itm;
@@ -407,7 +374,7 @@ void QStandardItemPrivate::setModel(QStandardItemModel *mod)
}
itm->d_func()->model = mod;
const QList<QStandardItem*> &childList = itm->d_func()->children;
- for (int i = 0; i < childList.count(); ++i) {
+ for (int i = 0; i < childList.size(); ++i) {
QStandardItem *chi = childList.at(i);
if (chi)
stack.push(chi);
@@ -468,7 +435,7 @@ bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &item
Q_Q(QStandardItem);
if ((row < 0) || (row > rowCount()) || items.isEmpty())
return false;
- int count = items.count();
+ int count = items.size();
if (model)
model->d_func()->rowsAboutToBeInserted(q, row, row + count - 1);
if (rowCount() == 0) {
@@ -482,7 +449,7 @@ bool QStandardItemPrivate::insertRows(int row, const QList<QStandardItem*> &item
if (index != -1)
children.insert(index, columnCount() * count, nullptr);
}
- for (int i = 0; i < items.count(); ++i) {
+ for (int i = 0; i < items.size(); ++i) {
QStandardItem *item = items.at(i);
item->d_func()->model = model;
item->d_func()->parent = q;
@@ -514,7 +481,7 @@ bool QStandardItemPrivate::insertRows(int row, int count, const QList<QStandardI
}
if (!items.isEmpty()) {
int index = childIndex(row, 0);
- int limit = qMin(items.count(), columnCount() * count);
+ int limit = qMin(items.size(), columnCount() * count);
for (int i = 0; i < limit; ++i) {
QStandardItem *item = items.at(i);
if (item) {
@@ -559,7 +526,7 @@ bool QStandardItemPrivate::insertColumns(int column, int count, const QList<QSta
}
}
if (!items.isEmpty()) {
- int limit = qMin(items.count(), rowCount() * count);
+ int limit = qMin(items.size(), rowCount() * count);
for (int i = 0; i < limit; ++i) {
QStandardItem *item = items.at(i);
if (item) {
@@ -876,7 +843,7 @@ QStandardItem &QStandardItem::operator=(const QStandardItem &other)
QStandardItem::~QStandardItem()
{
Q_D(QStandardItem);
- for (QStandardItem *child : qAsConst(d->children)) {
+ for (QStandardItem *child : std::as_const(d->children)) {
if (child)
child->d_func()->setModel(nullptr);
delete child;
@@ -905,9 +872,15 @@ QStandardItem *QStandardItem::parent() const
Sets the item's data for the given \a role to the specified \a value.
If you subclass QStandardItem and reimplement this function, your
- reimplementation should call emitDataChanged() if you do not call
- the base implementation of setData(). This will ensure that e.g.
- views using the model are notified of the changes.
+ reimplementation should:
+ \list
+ \li call emitDataChanged() if you do not call the base implementation of
+ setData(). This will ensure that e.g. views using the model are notified
+ of the changes
+ \li call the base implementation for roles you don't handle, otherwise
+ setting flags, e.g. by calling setFlags(), setCheckable(), setEditable()
+ etc., will not work.
+ \endlist
\note The default implementation treats Qt::EditRole and Qt::DisplayRole
as referring to the same data.
@@ -961,6 +934,11 @@ void QStandardItem::clearData()
Returns the item's data for the given \a role, or an invalid
QVariant if there is no data for the role.
+ If you reimplement this function, your reimplementation should call
+ the base implementation for roles you don't handle, otherwise getting
+ flags, e.g. by calling flags(), isCheckable(), isEditable() etc.,
+ will not work.
+
\note The default implementation treats Qt::EditRole and Qt::DisplayRole
as referring to the same data.
*/
@@ -1020,7 +998,7 @@ void QStandardItem::emitDataChanged()
*/
void QStandardItem::setFlags(Qt::ItemFlags flags)
{
- setData((int)flags, Qt::UserRole - 1);
+ setData((int)flags, DataFlagsRole);
}
/*!
@@ -1035,7 +1013,7 @@ void QStandardItem::setFlags(Qt::ItemFlags flags)
*/
Qt::ItemFlags QStandardItem::flags() const
{
- QVariant v = data(Qt::UserRole - 1);
+ QVariant v = data(DataFlagsRole);
if (!v.isValid())
return (Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable
|Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled);
@@ -1624,8 +1602,8 @@ void QStandardItem::insertRow(int row, const QList<QStandardItem*> &items)
Q_D(QStandardItem);
if (row < 0)
return;
- if (columnCount() < items.count())
- setColumnCount(items.count());
+ if (columnCount() < items.size())
+ setColumnCount(items.size());
d->insertRows(row, 1, items);
}
@@ -1653,8 +1631,8 @@ void QStandardItem::insertColumn(int column, const QList<QStandardItem*> &items)
Q_D(QStandardItem);
if (column < 0)
return;
- if (rowCount() < items.count())
- setRowCount(items.count());
+ if (rowCount() < items.size())
+ setRowCount(items.size());
d->insertColumns(column, 1, items);
}
@@ -1895,28 +1873,30 @@ QStandardItem *QStandardItem::takeChild(int row, int column)
if (index != -1) {
QModelIndex changedIdx;
item = d->children.at(index);
- if (item && d->model) {
+ if (item) {
QStandardItemPrivate *const item_d = item->d_func();
- const int savedRows = item_d->rows;
- const int savedCols = item_d->columns;
- const QVector<QStandardItem*> savedChildren = item_d->children;
- if (savedRows > 0) {
- d->model->d_func()->rowsAboutToBeRemoved(item, 0, savedRows - 1);
- item_d->rows = 0;
- item_d->children = QVector<QStandardItem*>(); //slightly faster than clear
- d->model->d_func()->rowsRemoved(item, 0, savedRows);
- }
- if (savedCols > 0) {
- d->model->d_func()->columnsAboutToBeRemoved(item, 0, savedCols - 1);
- item_d->columns = 0;
- if (!item_d->children.isEmpty())
+ if (d->model) {
+ QStandardItemModelPrivate *const model_d = d->model->d_func();
+ const int savedRows = item_d->rows;
+ const int savedCols = item_d->columns;
+ const QVector<QStandardItem*> savedChildren = item_d->children;
+ if (savedRows > 0) {
+ model_d->rowsAboutToBeRemoved(item, 0, savedRows - 1);
+ item_d->rows = 0;
+ item_d->children = QVector<QStandardItem*>(); //slightly faster than clear
+ model_d->rowsRemoved(item, 0, savedRows);
+ }
+ if (savedCols > 0) {
+ model_d->columnsAboutToBeRemoved(item, 0, savedCols - 1);
+ item_d->columns = 0;
item_d->children = QVector<QStandardItem*>(); //slightly faster than clear
- d->model->d_func()->columnsRemoved(item, 0, savedCols);
+ model_d->columnsRemoved(item, 0, savedCols);
+ }
+ item_d->rows = savedRows;
+ item_d->columns = savedCols;
+ item_d->children = savedChildren;
+ changedIdx = d->model->indexFromItem(item);
}
- item_d->rows = savedRows;
- item_d->columns = savedCols;
- item_d->children = savedChildren;
- changedIdx = d->model->indexFromItem(item);
item_d->setParentAndModel(nullptr, nullptr);
}
d->children.replace(index, nullptr);
@@ -2565,9 +2545,9 @@ QStandardItem *QStandardItemModel::verticalHeaderItem(int row) const
void QStandardItemModel::setHorizontalHeaderLabels(const QStringList &labels)
{
Q_D(QStandardItemModel);
- if (columnCount() < labels.count())
- setColumnCount(labels.count());
- for (int i = 0; i < labels.count(); ++i) {
+ if (columnCount() < labels.size())
+ setColumnCount(labels.size());
+ for (int i = 0; i < labels.size(); ++i) {
QStandardItem *item = horizontalHeaderItem(i);
if (!item) {
item = d->createItem();
@@ -2588,9 +2568,9 @@ void QStandardItemModel::setHorizontalHeaderLabels(const QStringList &labels)
void QStandardItemModel::setVerticalHeaderLabels(const QStringList &labels)
{
Q_D(QStandardItemModel);
- if (rowCount() < labels.count())
- setRowCount(labels.count());
- for (int i = 0; i < labels.count(); ++i) {
+ if (rowCount() < labels.size())
+ setRowCount(labels.size());
+ for (int i = 0; i < labels.size(); ++i) {
QStandardItem *item = verticalHeaderItem(i);
if (!item) {
item = d->createItem();
@@ -3136,21 +3116,21 @@ QStringList QStandardItemModel::mimeTypes() const
*/
QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
{
- QMimeData *data = QAbstractItemModel::mimeData(indexes);
+ std::unique_ptr<QMimeData> data(QAbstractItemModel::mimeData(indexes));
if (!data)
return nullptr;
const QString format = qStandardItemModelDataListMimeType();
if (!mimeTypes().contains(format))
- return data;
+ return data.release();
QByteArray encoded;
QDataStream stream(&encoded, QIODevice::WriteOnly);
QSet<QStandardItem*> itemsSet;
QStack<QStandardItem*> stack;
- itemsSet.reserve(indexes.count());
- stack.reserve(indexes.count());
- for (int i = 0; i < indexes.count(); ++i) {
+ itemsSet.reserve(indexes.size());
+ stack.reserve(indexes.size());
+ for (int i = 0; i < indexes.size(); ++i) {
if (QStandardItem *item = itemFromIndex(indexes.at(i))) {
itemsSet << item;
stack.push(item);
@@ -3160,7 +3140,7 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
}
}
- //remove duplicates childrens
+ //remove duplicates children
{
QDuplicateTracker<QStandardItem *> seen;
while (!stack.isEmpty()) {
@@ -3169,7 +3149,7 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
continue;
const QList<QStandardItem*> &childList = itm->d_func()->children;
- for (int i = 0; i < childList.count(); ++i) {
+ for (int i = 0; i < childList.size(); ++i) {
QStandardItem *chi = childList.at(i);
if (chi) {
itemsSet.remove(chi);
@@ -3179,8 +3159,8 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
}
}
- stack.reserve(itemsSet.count());
- for (QStandardItem *item : qAsConst(itemsSet))
+ stack.reserve(itemsSet.size());
+ for (QStandardItem *item : std::as_const(itemsSet))
stack.push(item);
//stream everything recursively
@@ -3189,12 +3169,12 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
if (itemsSet.contains(item)) //if the item is selection 'top-level', stream its position
stream << item->row() << item->column();
- stream << *item << item->columnCount() << int(item->d_ptr->children.count());
+ stream << *item << item->columnCount() << int(item->d_ptr->children.size());
stack += item->d_ptr->children;
}
data->setData(format, encoded);
- return data;
+ return data.release();
}
@@ -3278,15 +3258,15 @@ bool QStandardItemModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
// Compute the number of continuous rows upon insertion and modify the rows to match
QList<int> rowsToInsert(bottom + 1);
- for (int i = 0; i < rows.count(); ++i)
+ for (int i = 0; i < rows.size(); ++i)
rowsToInsert[rows.at(i)] = 1;
- for (int i = 0; i < rowsToInsert.count(); ++i) {
+ for (int i = 0; i < rowsToInsert.size(); ++i) {
if (rowsToInsert.at(i) == 1){
rowsToInsert[i] = dragRowCount;
++dragRowCount;
}
}
- for (int i = 0; i < rows.count(); ++i)
+ for (int i = 0; i < rows.size(); ++i)
rows[i] = top + rowsToInsert.at(rows.at(i));
QBitArray isWrittenTo(dragRowCount * dragColumnCount);
diff --git a/src/gui/itemmodels/qstandarditemmodel.h b/src/gui/itemmodels/qstandarditemmodel.h
index 66ae3a27cd..a5ae05feeb 100644
--- a/src/gui/itemmodels/qstandarditemmodel.h
+++ b/src/gui/itemmodels/qstandarditemmodel.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTANDARDITEMMODEL_H
#define QSTANDARDITEMMODEL_H
@@ -110,7 +74,7 @@ public:
inline void setFont(const QFont &font);
inline Qt::Alignment textAlignment() const {
- return Qt::Alignment(qvariant_cast<int>(data(Qt::TextAlignmentRole)));
+ return qvariant_cast<Qt::Alignment>(data(Qt::TextAlignmentRole));
}
inline void setTextAlignment(Qt::Alignment textAlignment);
@@ -143,43 +107,43 @@ public:
void setFlags(Qt::ItemFlags flags);
inline bool isEnabled() const {
- return (flags() & Qt::ItemIsEnabled) != 0;
+ return bool(flags() & Qt::ItemIsEnabled);
}
void setEnabled(bool enabled);
inline bool isEditable() const {
- return (flags() & Qt::ItemIsEditable) != 0;
+ return bool(flags() & Qt::ItemIsEditable);
}
void setEditable(bool editable);
inline bool isSelectable() const {
- return (flags() & Qt::ItemIsSelectable) != 0;
+ return bool(flags() & Qt::ItemIsSelectable);
}
void setSelectable(bool selectable);
inline bool isCheckable() const {
- return (flags() & Qt::ItemIsUserCheckable) != 0;
+ return bool(flags() & Qt::ItemIsUserCheckable);
}
void setCheckable(bool checkable);
inline bool isAutoTristate() const {
- return (flags() & Qt::ItemIsAutoTristate) != 0;
+ return bool(flags() & Qt::ItemIsAutoTristate);
}
void setAutoTristate(bool tristate);
inline bool isUserTristate() const {
- return (flags() & Qt::ItemIsUserTristate) != 0;
+ return bool(flags() & Qt::ItemIsUserTristate);
}
void setUserTristate(bool tristate);
#if QT_CONFIG(draganddrop)
inline bool isDragEnabled() const {
- return (flags() & Qt::ItemIsDragEnabled) != 0;
+ return bool(flags() & Qt::ItemIsDragEnabled);
}
void setDragEnabled(bool dragEnabled);
inline bool isDropEnabled() const {
- return (flags() & Qt::ItemIsDropEnabled) != 0;
+ return bool(flags() & Qt::ItemIsDropEnabled);
}
void setDropEnabled(bool dropEnabled);
#endif // QT_CONFIG(draganddrop)
@@ -274,7 +238,7 @@ inline void QStandardItem::setFont(const QFont &afont)
{ setData(afont, Qt::FontRole); }
inline void QStandardItem::setTextAlignment(Qt::Alignment atextAlignment)
-{ setData(int(atextAlignment), Qt::TextAlignmentRole); }
+{ setData(QVariant::fromValue(atextAlignment), Qt::TextAlignmentRole); }
inline void QStandardItem::setBackground(const QBrush &abrush)
{ setData(abrush, Qt::BackgroundRole); }
diff --git a/src/gui/itemmodels/qstandarditemmodel_p.h b/src/gui/itemmodels/qstandarditemmodel_p.h
index 8a9a2c8d50..a0c3f8a161 100644
--- a/src/gui/itemmodels/qstandarditemmodel_p.h
+++ b/src/gui/itemmodels/qstandarditemmodel_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTANDARDITEMMODEL_P_H
#define QSTANDARDITEMMODEL_P_H
@@ -51,6 +15,8 @@
// We mean it.
//
+#include <QtGui/qstandarditemmodel.h>
+
#include <QtGui/private/qtguiglobal_p.h>
#include "private/qabstractitemmodel_p.h"
@@ -68,8 +34,10 @@ class QStandardItemData
{
public:
inline QStandardItemData() : role(-1) {}
- inline QStandardItemData(int r, const QVariant &v) : role(r), value(v) {}
- inline QStandardItemData(const std::pair<const int&, const QVariant&> &p) : role(p.first), value(p.second) {}
+ inline QStandardItemData(int r, const QVariant &v) :
+ role(r == Qt::EditRole ? Qt::DisplayRole : r), value(v) {}
+ inline QStandardItemData(const std::pair<const int&, const QVariant&> &p) :
+ role(p.first == Qt::EditRole ? Qt::DisplayRole : p.first), value(p.second) {}
int role;
QVariant value;
inline bool operator==(const QStandardItemData &other) const { return role == other.role && value == other.value; }
@@ -137,7 +105,7 @@ public:
// backwards through the children
int backwardIter = childsLastIndexInParent - 1;
int forwardIter = childsLastIndexInParent;
- Q_FOREVER {
+ for (;;) {
if (forwardIter <= lastChild) {
if (children.at(forwardIter) == child) {
childsLastIndexInParent = forwardIter;
@@ -180,7 +148,7 @@ public:
void changeFlags(bool enable, Qt::ItemFlags f);
void setItemData(const QMap<int, QVariant> &roles);
- const QMap<int, QVariant> itemData() const;
+ QMap<int, QVariant> itemData() const;
bool insertRows(int row, int count, const QList<QStandardItem*> &items);
bool insertRows(int row, const QList<QStandardItem*> &items);
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp
index 9c16123545..c67cfd53b1 100644
--- a/src/gui/kernel/qaction.cpp
+++ b/src/gui/kernel/qaction.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qaction.h"
#include "qactiongroup.h"
@@ -59,14 +23,16 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*
internal: guesses a descriptive text from a text suited for a menu entry
*/
static QString qt_strippedText(QString s)
{
- s.remove(QLatin1String("..."));
+ s.remove("..."_L1);
for (int i = 0; i < s.size(); ++i) {
- if (s.at(i) == QLatin1Char('&'))
+ if (s.at(i) == u'&')
s.remove(i, 1);
}
return s.trimmed();
@@ -115,26 +81,26 @@ void QActionPrivate::sendDataChanged()
void QActionPrivate::redoGrab(QShortcutMap &map)
{
Q_Q(QAction);
- for (int id : qAsConst(shortcutIds)) {
+ for (int id : std::as_const(shortcutIds)) {
if (id)
map.removeShortcut(id, q);
}
shortcutIds.clear();
- for (const QKeySequence &shortcut : qAsConst(shortcuts)) {
+ for (const QKeySequence &shortcut : std::as_const(shortcuts)) {
if (!shortcut.isEmpty())
shortcutIds.append(map.addShortcut(q, shortcut, shortcutContext, contextMatcher()));
else
shortcutIds.append(0);
}
if (!enabled) {
- for (int id : qAsConst(shortcutIds)) {
+ for (int id : std::as_const(shortcutIds)) {
if (id)
map.setShortcutEnabled(false, id, q);
}
}
if (!autorepeat) {
- for (int id : qAsConst(shortcutIds)) {
+ for (int id : std::as_const(shortcutIds)) {
if (id)
map.setShortcutAutoRepeat(false, id, q);
}
@@ -144,7 +110,7 @@ void QActionPrivate::redoGrab(QShortcutMap &map)
void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
{
Q_Q(QAction);
- for (int id : qAsConst(shortcutIds)) {
+ for (int id : std::as_const(shortcutIds)) {
if (id)
map.setShortcutEnabled(enable, id, q);
}
@@ -184,17 +150,18 @@ QObject *QActionPrivate::menu() const
user interface used, it is useful to represent each command as
an \e action.
- Actions can be added to menus and toolbars, and will
- automatically keep them in sync. For example, in a word processor,
- if the user presses a Bold toolbar button, the Bold menu item
+ Actions can be added to user interface elements such as menus and toolbars,
+ and will automatically keep the UI in sync. For example, in a word
+ processor, if the user presses a Bold toolbar button, the Bold menu item
will automatically be checked.
- A QAction may contain an icon, menu text, a shortcut, status text,
- "What's This?" text, and a tooltip. Most of these can be set in
- the constructor. They can also be set independently with
- setIcon(), setText(), setIconText(), setShortcut(),
- setStatusTip(), setWhatsThis(), and setToolTip(). For menu items,
- it is possible to set an individual font with setFont().
+ A QAction may contain an icon, descriptive text, icon text, a keyboard
+ shortcut, status text, "What's This?" text, and a tooltip. All properties
+ can be set independently with setIcon(), setText(), setIconText(),
+ setShortcut(), setStatusTip(), setWhatsThis(), and setToolTip(). Icon and
+ text, as the two most important properties, can also be set in the
+ constructor. It's possible to set an individual font with setFont(), which
+ e.g. menus respect when displaying the action as a menu item.
We recommend that actions are created as children of the window
they are used in. In most cases actions will be children of
@@ -204,9 +171,7 @@ QObject *QActionPrivate::menu() const
Once a QAction has been created, it should be added to the relevant
menu and toolbar, then connected to the slot which will perform
- the action. For example:
-
- \snippet ../widgets/mainwindows/application/mainwindow.cpp 19
+ the action.
Actions are added to widgets using QWidget::addAction() or
QGraphicsWidget::addAction(). Note that an action must be added to a
@@ -219,7 +184,7 @@ QObject *QActionPrivate::menu() const
use as menu items.
- \sa QMenu, QToolBar, {Qt Widgets - Application Example}
+ \sa QMenu, QToolBar
*/
/*!
@@ -272,13 +237,11 @@ QAction::QAction(QObject *parent)
parent is an action group the action will be automatically
inserted into the group.
- The action uses a stripped version of \a text (e.g. "\&Menu
- Option..." becomes "Menu Option") as descriptive text for
- tool buttons. You can override this by setting a specific
- description with setText(). The same text will be used for
- tooltips unless you specify a different text using
- setToolTip().
+ A stripped version of \a text (for example, "\&Menu Option..." becomes
+ "Menu Option") will be used for tooltips and icon text unless you specify a
+ different text using setToolTip() or setIconText(), respectively.
+ \sa text
*/
QAction::QAction(const QString &text, QObject *parent)
: QAction(parent)
@@ -292,12 +255,11 @@ QAction::QAction(const QString &text, QObject *parent)
parent. If \a parent is an action group the action will be
automatically inserted into the group.
- The action uses a stripped version of \a text (e.g. "\&Menu
- Option..." becomes "Menu Option") as descriptive text for
- tool buttons. You can override this by setting a specific
- description with setText(). The same text will be used for
- tooltips unless you specify a different text using
- setToolTip().
+ A stripped version of \a text (for example, "\&Menu Option..." becomes
+ "Menu Option") will be used for tooltips and icon text unless you specify a
+ different text using setToolTip() or setIconText(), respectively.
+
+ \sa text, icon
*/
QAction::QAction(const QIcon &icon, const QString &text, QObject *parent)
: QAction(text, parent)
@@ -492,7 +454,7 @@ QAction::~QAction()
d->group->removeAction(this);
#if QT_CONFIG(shortcut)
if (qApp) {
- for (int id : qAsConst(d->shortcutIds)) {
+ for (int id : std::as_const(d->shortcutIds)) {
if (id)
QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this);
}
@@ -548,14 +510,14 @@ QList<QObject*> QAction::associatedObjects() const
/*!
\fn QWidget *QAction::parentWidget() const
- \deprecated Use parent() with qobject_cast() instead.
+ \deprecated [6.0] Use parent() with qobject_cast() instead.
Returns the parent widget.
*/
/*!
\fn QList<QWidget*> QAction::associatedWidgets() const
- \deprecated Use associatedObjects() with qobject_cast() instead.
+ \deprecated [6.0] Use associatedObjects() with qobject_cast() instead.
Returns a list of widgets this action has been added to.
@@ -564,7 +526,7 @@ QList<QObject*> QAction::associatedObjects() const
/*!
\fn QList<QWidget*> QAction::associatedGraphicsWidgets() const
- \deprecated Use associatedObjects() with qobject_cast() instead.
+ \deprecated [6.0] Use associatedObjects() with qobject_cast() instead.
Returns a list of graphics widgets this action has been added to.
@@ -636,6 +598,14 @@ bool QAction::isSeparator() const
by using setText(), the action's description icon text will be
used as text. There is no default text.
+ Certain UI elements, such as menus or buttons, can use '&' in front of a
+ character to automatically create a mnemonic (a shortcut) for that
+ character. For example, "&File" for a menu will create the shortcut
+ \uicontrol Alt+F, which will open the File menu. "E&xit" will create the
+ shortcut \uicontrol Alt+X for a button, or in a menu allow navigating to
+ the menu item by pressing "x". (use '&&' to display an actual ampersand).
+ The widget might consume and perform an action on a given shortcut.
+
\sa iconText
*/
void QAction::setText(const QString &text)
@@ -654,7 +624,7 @@ QString QAction::text() const
QString s = d->text;
if (s.isEmpty()) {
s = d->iconText;
- s.replace(QLatin1Char('&'), QLatin1String("&&"));
+ s.replace(u'&', "&&"_L1);
}
return s;
}
@@ -1058,7 +1028,7 @@ bool QAction::event(QEvent *e)
{
Q_D(QAction);
if (e->type() == QEvent::ActionChanged) {
- for (auto object : qAsConst(d->associatedObjects))
+ for (auto object : std::as_const(d->associatedObjects))
QCoreApplication::sendEvent(object, e);
}
@@ -1225,14 +1195,13 @@ QAction::MenuRole QAction::menuRole() const
/*!
\fn QMenu *QAction::menu() const
- \deprecated
Returns the menu contained by this action.
In widget applications, actions that contain menus can be used to create menu
items with submenus, or inserted into toolbars to create buttons with popup menus.
- \sa QMenu::addAction()
+ \sa QMenu::addAction(), QMenu::menuInAction()
*/
QObject* QAction::menuObject() const
{
@@ -1242,7 +1211,6 @@ QObject* QAction::menuObject() const
/*!
\fn void QAction::setMenu(QMenu *menu)
- \deprecated
Sets the menu contained by this action to the specified \a menu.
*/
@@ -1262,7 +1230,7 @@ void QAction::setMenuObject(QObject *object)
The default is to follow whether the Qt::AA_DontShowIconsInMenus attribute
is set for the application. Explicitly settings this property overrides
- the presence (or abscence) of the attribute.
+ the presence (or absence) of the attribute.
For example:
\snippet code/src_gui_kernel_qaction.cpp 0
diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h
index fc8b4a104f..d805599138 100644
--- a/src/gui/kernel/qaction.h
+++ b/src/gui/kernel/qaction.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QACTION_H
#define QACTION_H
@@ -47,6 +11,7 @@
#include <QtGui/qicon.h>
#include <QtCore/qstring.h>
#include <QtCore/qvariant.h>
+#include <QtCore/qobject.h>
QT_REQUIRE_CONFIG(action);
@@ -55,10 +20,10 @@ QT_BEGIN_NAMESPACE
class QActionEvent;
class QActionGroup;
class QActionPrivate;
+class QMenu;
#if QT_DEPRECATED_SINCE(6,0)
class QWidget;
class QGraphicsWidget;
-class QMenu;
#endif
class Q_GUI_EXPORT QAction : public QObject
@@ -89,7 +54,7 @@ class Q_GUI_EXPORT QAction : public QObject
NOTIFY changed)
Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu
WRITE setShortcutVisibleInContextMenu NOTIFY changed)
- Q_PROPERTY(Priority priority READ priority WRITE setPriority)
+ Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY changed)
public:
// note this is copied into qplatformmenu.h, which must stay in sync
@@ -109,7 +74,7 @@ public:
QList<QObject *> associatedObjects() const;
#if QT_DEPRECATED_SINCE(6,0)
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
QWidget *parentWidget() const;
QList<QWidget*> associatedWidgets() const;
QList<QGraphicsWidget*> associatedGraphicsWidgets() const;
@@ -119,6 +84,7 @@ public:
QWidget, QMenu, and QGraphicsWidget can be expected to be fully defined.
*/
template<typename T = QWidget*>
+ QT_DEPRECATED_VERSION_X_6_0("Use parent() with qobject_cast() instead")
T parentWidget() const
{
auto result = parent();
@@ -128,6 +94,7 @@ public:
}
template<typename T = QWidget*>
+ QT_DEPRECATED_VERSION_X_6_0("Use associatedObjects() with qobject_cast() instead")
QList<T> associatedWidgets() const
{
QList<T> result;
@@ -137,6 +104,7 @@ public:
return result;
}
template<typename T = QGraphicsWidget*>
+ QT_DEPRECATED_VERSION_X_6_0("Use associatedObjects() with qobject_cast() instead")
QList<T> associatedGraphicsWidgets() const
{
QList<T> result;
@@ -210,8 +178,7 @@ public:
void setMenuRole(MenuRole menuRole);
MenuRole menuRole() const;
-#if QT_DEPRECATED_SINCE(6,0)
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
QMenu *menu() const;
void setMenu(QMenu *menu);
#else
@@ -226,7 +193,6 @@ public:
setMenuObject(m);
}
#endif
-#endif
void setIconVisibleInMenu(bool visible);
bool isIconVisibleInMenu() const;
diff --git a/src/gui/kernel/qaction_p.h b/src/gui/kernel/qaction_p.h
index 77dc450a9f..e79cc26b4d 100644
--- a/src/gui/kernel/qaction_p.h
+++ b/src/gui/kernel/qaction_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QACTION_P_H
#define QACTION_P_H
@@ -57,6 +21,8 @@
#if QT_CONFIG(shortcut)
# include <QtGui/private/qshortcutmap_p.h>
#endif
+
+#include <QtCore/qpointer.h>
#include "private/qobject_p.h"
QT_REQUIRE_CONFIG(action);
diff --git a/src/gui/kernel/qactiongroup.cpp b/src/gui/kernel/qactiongroup.cpp
index 33f9b54ddc..7fb5b4ad46 100644
--- a/src/gui/kernel/qactiongroup.cpp
+++ b/src/gui/kernel/qactiongroup.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qactiongroup.h"
@@ -313,7 +277,7 @@ void QActionGroup::setEnabled(bool b)
{
Q_D(QActionGroup);
d->enabled = b;
- for (auto action : qAsConst(d->actions)) {
+ for (auto action : std::as_const(d->actions)) {
action->d_func()->setEnabled(b, true);
}
}
@@ -347,7 +311,7 @@ void QActionGroup::setVisible(bool b)
{
Q_D(QActionGroup);
d->visible = b;
- for (auto action : qAsConst(d->actions)) {
+ for (auto action : std::as_const(d->actions)) {
if (!action->d_func()->forceInvisible)
action->d_func()->setVisible(b);
}
@@ -360,3 +324,5 @@ bool QActionGroup::isVisible() const
}
QT_END_NAMESPACE
+
+#include "moc_qactiongroup.cpp"
diff --git a/src/gui/kernel/qactiongroup.h b/src/gui/kernel/qactiongroup.h
index 9ac8743629..d0830aeccb 100644
--- a/src/gui/kernel/qactiongroup.h
+++ b/src/gui/kernel/qactiongroup.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QACTIONGROUP_H
#define QACTIONGROUP_H
diff --git a/src/gui/kernel/qactiongroup_p.h b/src/gui/kernel/qactiongroup_p.h
index 4b503783ed..ba939a2b10 100644
--- a/src/gui/kernel/qactiongroup_p.h
+++ b/src/gui/kernel/qactiongroup_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGUIACTIONGROUP_P_H
#define QGUIACTIONGROUP_P_H
@@ -57,6 +21,8 @@
#if QT_CONFIG(shortcut)
# include <QtGui/private/qshortcutmap_p.h>
#endif
+
+#include <QtCore/qpointer.h>
#include "private/qobject_p.h"
QT_REQUIRE_CONFIG(action);
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index 52d6bef391..6a36862a04 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qclipboard.h"
@@ -54,6 +18,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QClipboard
\brief The QClipboard class provides access to the window system clipboard.
@@ -137,6 +103,10 @@ QT_BEGIN_NAMESPACE
\endlist
+ \section1 Notes for Android Users
+
+ On Android only these mime types are supported: text/plain, text/html, and text/uri-list.
+
\sa QGuiApplication
*/
@@ -270,22 +240,23 @@ QString QClipboard::text(QString &subtype, Mode mode) const
const QStringList formats = data->formats();
if (subtype.isEmpty()) {
- if (formats.contains(QLatin1String("text/plain")))
- subtype = QLatin1String("plain");
+ if (formats.contains("text/plain"_L1))
+ subtype = "plain"_L1;
else {
- for (int i = 0; i < formats.size(); ++i)
- if (formats.at(i).startsWith(QLatin1String("text/"))) {
- subtype = formats.at(i).mid(5);
+ for (const auto &format : formats) {
+ if (format.startsWith("text/"_L1)) {
+ subtype = format.sliced(5);
break;
}
+ }
if (subtype.isEmpty())
return QString();
}
- } else if (!formats.contains(QLatin1String("text/") + subtype)) {
+ } else if (!formats.contains("text/"_L1 + subtype)) {
return QString();
}
- const QByteArray rawData = data->data(QLatin1String("text/") + subtype);
+ const QByteArray rawData = data->data("text/"_L1 + subtype);
auto encoding = QStringConverter::encodingForData(rawData);
if (!encoding)
encoding = QStringConverter::Utf8;
@@ -589,4 +560,6 @@ void QClipboard::emitChanged(Mode mode)
QT_END_NAMESPACE
+#include "moc_qclipboard.cpp"
+
#endif // QT_NO_CLIPBOARD
diff --git a/src/gui/kernel/qclipboard.h b/src/gui/kernel/qclipboard.h
index e91444d3dc..42b8bad026 100644
--- a/src/gui/kernel/qclipboard.h
+++ b/src/gui/kernel/qclipboard.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCLIPBOARD_H
#define QCLIPBOARD_H
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index 20511ef8e6..8e7747559a 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcursor.h"
@@ -150,7 +114,7 @@ QT_BEGIN_NAMESPACE
\li Qt::DragLinkCursor \li \c dnd-link or \c link
\endtable
- \sa QWidget, {fowler}{GUI Design Handbook: Cursors}
+ \sa QWidget
*/
/*!
@@ -251,7 +215,8 @@ void QCursor::setPos(QScreen *screen, int x, int y)
{
if (screen) {
if (QPlatformCursor *cursor = screen->handle()->cursor()) {
- const QPoint devicePos = QHighDpi::toNativePixels(QPoint(x, y), screen);
+ const QPoint pos(x, y);
+ const QPoint devicePos = QHighDpi::toNativePixels(pos, screen->virtualSiblingAt(pos));
// Need to check, since some X servers generate null mouse move
// events, causing looping in applications which call setPos() on
// every mouse move event.
@@ -325,7 +290,7 @@ QDataStream &operator<<(QDataStream &s, const QCursor &c)
if (isPixmap)
s << c.pixmap();
else
- s << c.bitmap(Qt::ReturnByValue) << c.mask(Qt::ReturnByValue);
+ s << c.bitmap() << c.mask();
s << c.hotSpot();
}
return s;
@@ -474,8 +439,7 @@ QCursor::QCursor()
QCursor::QCursor(Qt::CursorShape shape)
: d(nullptr)
{
- if (!QCursorData::initialized)
- QCursorData::initialize();
+ QCursorData::initialize();
setShape(shape);
}
@@ -533,8 +497,7 @@ bool operator==(const QCursor &lhs, const QCursor &rhs) noexcept
*/
Qt::CursorShape QCursor::shape() const
{
- if (!QCursorData::initialized)
- QCursorData::initialize();
+ QCursorData::initialize();
return d->cshape;
}
@@ -547,8 +510,7 @@ Qt::CursorShape QCursor::shape() const
*/
void QCursor::setShape(Qt::CursorShape shape)
{
- if (!QCursorData::initialized)
- QCursorData::initialize();
+ QCursorData::initialize();
QCursorData *c = uint(shape) <= Qt::LastCursor ? qt_cursorTable[shape] : nullptr;
if (!c)
c = qt_cursorTable[0];
@@ -582,8 +544,7 @@ void QCursor::setShape(Qt::CursorShape shape)
*/
QBitmap QCursor::bitmap() const
{
- if (!QCursorData::initialized)
- QCursorData::initialize();
+ QCursorData::initialize();
if (d->bm)
return *(d->bm);
return QBitmap();
@@ -609,8 +570,7 @@ QBitmap QCursor::bitmap() const
*/
QBitmap QCursor::mask() const
{
- if (!QCursorData::initialized)
- QCursorData::initialize();
+ QCursorData::initialize();
if (d->bmm)
return *(d->bmm);
return QBitmap();
@@ -623,8 +583,7 @@ QBitmap QCursor::mask() const
QPixmap QCursor::pixmap() const
{
- if (!QCursorData::initialized)
- QCursorData::initialize();
+ QCursorData::initialize();
return d->pixmap;
}
@@ -635,8 +594,7 @@ QPixmap QCursor::pixmap() const
QPoint QCursor::hotSpot() const
{
- if (!QCursorData::initialized)
- QCursorData::initialize();
+ QCursorData::initialize();
return QPoint(d->hx, d->hy);
}
@@ -646,8 +604,7 @@ QPoint QCursor::hotSpot() const
QCursor::QCursor(const QCursor &c)
{
- if (!QCursorData::initialized)
- QCursorData::initialize();
+ QCursorData::initialize();
d = c.d;
d->ref.ref();
}
@@ -670,8 +627,7 @@ QCursor::~QCursor()
QCursor &QCursor::operator=(const QCursor &c)
{
- if (!QCursorData::initialized)
- QCursorData::initialize();
+ QCursorData::initialize();
if (c.d)
c.d->ref.ref();
if (d && !d->ref.deref())
@@ -742,8 +698,7 @@ void QCursorData::initialize()
QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY, qreal devicePixelRatio)
{
- if (!QCursorData::initialized)
- QCursorData::initialize();
+ QCursorData::initialize();
if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) {
qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)");
QCursorData *c = qt_cursorTable[0];
diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h
index c1d45cc41b..3aeef52094 100644
--- a/src/gui/kernel/qcursor.h
+++ b/src/gui/kernel/qcursor.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCURSOR_H
#define QCURSOR_H
@@ -87,10 +51,10 @@ public:
QCursor(const QCursor &cursor);
~QCursor();
QCursor &operator=(const QCursor &cursor);
- QCursor(QCursor &&other) noexcept : d(qExchange(other.d, nullptr)) {}
+ QCursor(QCursor &&other) noexcept : d(std::exchange(other.d, nullptr)) {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QCursor)
- void swap(QCursor &other) noexcept { qSwap(d, other.d); }
+ void swap(QCursor &other) noexcept { qt_ptr_swap(d, other.d); }
operator QVariant() const;
@@ -98,7 +62,9 @@ public:
void setShape(Qt::CursorShape newShape);
#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_VERSION_X_6_0("Use the overload without argument instead.")
QBitmap bitmap(Qt::ReturnByValueConstant) const { return bitmap(); }
+ QT_DEPRECATED_VERSION_X_6_0("Use the overload without argument instead.")
QBitmap mask(Qt::ReturnByValueConstant) const { return mask(); }
#endif // QT_DEPRECATED_SINCE(6, 0)
QBitmap bitmap() const;
diff --git a/src/gui/kernel/qcursor_p.h b/src/gui/kernel/qcursor_p.h
index 37245a793f..52ea15b59a 100644
--- a/src/gui/kernel/qcursor_p.h
+++ b/src/gui/kernel/qcursor_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCURSOR_P_H
#define QCURSOR_P_H
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
index fe766c900e..248a1e83ed 100644
--- a/src/gui/kernel/qdnd.cpp
+++ b/src/gui/kernel/qdnd.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdnd_p.h"
@@ -123,3 +87,5 @@ Qt::DropAction QDragManager::drag(QDrag *o)
}
QT_END_NAMESPACE
+
+#include "moc_qdnd_p.cpp"
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index abb30986a5..b5a2e015f4 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDND_P_H
#define QDND_P_H
@@ -63,6 +27,8 @@
#include "private/qobject_p.h"
#include "QtGui/qbackingstore.h"
+#include <QtCore/qpointer.h>
+
QT_REQUIRE_CONFIG(draganddrop);
QT_BEGIN_NAMESPACE
diff --git a/src/gui/kernel/qdrag.cpp b/src/gui/kernel/qdrag.cpp
index 330be0ac8a..4e707e4915 100644
--- a/src/gui/kernel/qdrag.cpp
+++ b/src/gui/kernel/qdrag.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qdrag.h>
#include "private/qguiapplication_p.h"
@@ -45,6 +9,8 @@
#include <qpoint.h>
#include "qdnd_p.h"
+#include <QtCore/qpointer.h>
+
QT_BEGIN_NAMESPACE
/*!
@@ -100,7 +66,7 @@ QT_BEGIN_NAMESPACE
required.
\sa {Drag and Drop}, QClipboard, QMimeData, {Draggable Icons Example},
- {Draggable Text Example}, {Drop Site Example}, {Fridge Magnets Example}
+ {Draggable Text Example}, {Drop Site Example}
*/
/*!
@@ -392,3 +358,5 @@ void QDrag::cancel()
*/
QT_END_NAMESPACE
+
+#include "moc_qdrag.cpp"
diff --git a/src/gui/kernel/qdrag.h b/src/gui/kernel/qdrag.h
index eaa677b50d..65314fd20c 100644
--- a/src/gui/kernel/qdrag.h
+++ b/src/gui/kernel/qdrag.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDRAG_H
#define QDRAG_H
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 73a591f34c..d8c11d72a6 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -1,49 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qevent.h"
+
#include "qcursor.h"
#include "private/qguiapplication_p.h"
#include "private/qinputdevice_p.h"
#include "private/qpointingdevice_p.h"
#include "qpa/qplatformintegration.h"
#include "private/qevent_p.h"
+#include "private/qeventpoint_p.h"
+
#include "qfile.h"
#include "qhashfunctions.h"
#include "qmetaobject.h"
@@ -51,14 +18,35 @@
#include "qevent_p.h"
#include "qmath.h"
#include "qloggingcategory.h"
+#include "qpointer.h"
#if QT_CONFIG(draganddrop)
#include <qpa/qplatformdrag.h>
#include <private/qdnd_p.h>
#endif
+#if QT_CONFIG(shortcut)
+#include <private/qshortcut_p.h>
+#endif
+
#include <private/qdebug_p.h>
+#define Q_IMPL_POINTER_EVENT(Class) \
+ Class::Class(const Class &) = default; \
+ Class::~Class() = default; \
+ Class* Class::clone() const \
+ { \
+ auto c = new Class(*this); \
+ for (auto &point : c->m_points) \
+ QMutableEventPoint::detach(point); \
+ QEvent *e = c; \
+ /* check that covariant return is safe to add */ \
+ Q_ASSERT(reinterpret_cast<quintptr>(c) == reinterpret_cast<quintptr>(e)); \
+ return c; \
+ }
+
+
+
QT_BEGIN_NAMESPACE
static_assert(sizeof(QMutableTouchEvent) == sizeof(QTouchEvent));
@@ -90,55 +78,59 @@ QEnterEvent::QEnterEvent(const QPointF &localPos, const QPointF &scenePos, const
{
}
-/*!
- \internal
-*/
-QEnterEvent::~QEnterEvent()
-{
-}
+Q_IMPL_POINTER_EVENT(QEnterEvent)
/*!
\fn QPoint QEnterEvent::globalPos() const
+ \deprecated [6.0] Use globalPosition() instead.
Returns the global position of the mouse cursor \e{at the time of the event}.
*/
/*!
\fn int QEnterEvent::globalX() const
+ \deprecated [6.0] Use globalPosition().x() instead.
Returns the global position on the X-axis of the mouse cursor \e{at the time of the event}.
*/
/*!
\fn int QEnterEvent::globalY() const
+ \deprecated [6.0] Use globalPosition().y() instead.
Returns the global position on the Y-axis of the mouse cursor \e{at the time of the event}.
*/
/*!
\fn QPointF QEnterEvent::localPos() const
+ \deprecated [6.0] Use position() instead.
Returns the mouse cursor's position relative to the receiving widget.
*/
/*!
\fn QPoint QEnterEvent::pos() const
+ \deprecated [6.0] Use position().toPoint() instead.
Returns the position of the mouse cursor relative to the receiving widget.
*/
/*!
\fn QPointF QEnterEvent::screenPos() const
+ \deprecated [6.0] Use globalPosition() instead.
Returns the position of the mouse cursor relative to the receiving screen.
*/
/*!
\fn QPointF QEnterEvent::windowPos() const
+ \deprecated [6.0] Use scenePosition() instead.
Returns the position of the mouse cursor relative to the receiving window.
*/
/*!
\fn int QEnterEvent::x() const
+ \deprecated [6.0] Use position().x() instead.
Returns the x position of the mouse cursor relative to the receiving widget.
*/
/*!
\fn int QEnterEvent::y() const
+ \deprecated [6.0] Use position().y() instead.
Returns the y position of the mouse cursor relative to the receiving widget.
*/
@@ -173,12 +165,7 @@ QInputEvent::QInputEvent(QEvent::Type type, QEvent::SinglePointEventTag, const Q
: QEvent(type, QEvent::SinglePointEventTag{}), m_dev(dev), m_modState(modifiers), m_reserved(0)
{}
-/*!
- \internal
-*/
-QInputEvent::~QInputEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QInputEvent)
/*!
\fn QInputDevice *QInputEvent::device() const
@@ -248,10 +235,12 @@ QInputEvent::~QInputEvent()
*/
/*!
- \fn QEventPoint &QPointerEvent::point(qsizetype i)
-
Returns a QEventPoint reference for the point at index \a i.
*/
+QEventPoint &QPointerEvent::point(qsizetype i)
+{
+ return m_points[i];
+}
/*!
\fn const QList<QEventPoint> &QPointerEvent::points() const
@@ -282,9 +271,7 @@ QPointerEvent::QPointerEvent(QEvent::Type type, QEvent::SinglePointEventTag, con
{
}
-QPointerEvent::~QPointerEvent()
-{
-}
+Q_IMPL_POINTER_EVENT(QPointerEvent);
/*!
Returns the point whose \l {QEventPoint::id()}{id} matches the given \a id,
@@ -300,12 +287,13 @@ QEventPoint *QPointerEvent::pointById(int id)
}
/*!
- Returns \c true if every point in points() has an exclusiveGrabber().
+ Returns \c true if every point in points() has either an exclusiveGrabber()
+ or one or more passiveGrabbers().
*/
bool QPointerEvent::allPointsGrabbed() const
{
for (const auto &p : points()) {
- if (exclusiveGrabber(p) && passiveGrabbers(p).isEmpty())
+ if (!exclusiveGrabber(p) && passiveGrabbers(p).isEmpty())
return false;
}
return true;
@@ -351,7 +339,7 @@ void QPointerEvent::setTimestamp(quint64 timestamp)
{
QInputEvent::setTimestamp(timestamp);
for (auto &p : m_points)
- QMutableEventPoint::from(p).setTimestamp(timestamp);
+ QMutableEventPoint::setTimestamp(p, timestamp);
}
/*!
@@ -389,7 +377,7 @@ void QPointerEvent::setExclusiveGrabber(const QEventPoint &point, QObject *exclu
Returns the list of objects that have been requested to receive all
future update events and the release event containing the given \a point.
- It's mainly for use in Qt Quick at this time.
+ It's only for use by \l {Qt Quick Input Handlers}.
\sa QPointerEvent::addPassiveGrabber()
*/
@@ -409,7 +397,7 @@ QList<QPointer<QObject> > QPointerEvent::passiveGrabbers(const QEventPoint &poin
future update events and the release event containing the given \a point,
regardless where else those events may be delivered.
- It's mainly for use in Qt Quick at this time.
+ It's only for use by \l {Qt Quick Input Handlers}.
Returns \c false if \a grabber was already added, \c true otherwise.
*/
@@ -424,7 +412,7 @@ bool QPointerEvent::addPassiveGrabber(const QEventPoint &point, QObject *grabber
Removes the passive \a grabber from the given \a point if it was previously added.
Returns \c true if it had been a passive grabber before, \c false if not.
- It's mainly for use in Qt Quick at this time.
+ It's only for use by \l {Qt Quick Input Handlers}.
\sa QPointerEvent::addPassiveGrabber()
*/
@@ -438,7 +426,7 @@ bool QPointerEvent::removePassiveGrabber(const QEventPoint &point, QObject *grab
/*!
Removes all passive grabbers from the given \a point.
- It's mainly for use in Qt Quick at this time.
+ It's only for use by \l {Qt Quick Input Handlers}.
\sa QPointerEvent::addPassiveGrabber()
*/
@@ -539,30 +527,30 @@ QSinglePointEvent::QSinglePointEvent(QEvent::Type type, const QPointingDevice *d
bool isWheel = (type == QEvent::Type::Wheel);
auto devPriv = QPointingDevicePrivate::get(const_cast<QPointingDevice *>(pointingDevice()));
auto epd = devPriv->pointById(0);
- QMutableEventPoint &mut = QMutableEventPoint::from(epd->eventPoint);
- Q_ASSERT(mut.device() == dev);
- // mut is now a reference to a non-detached instance that lives in QPointingDevicePrivate::activePoints.
+ QEventPoint &p = epd->eventPoint;
+ Q_ASSERT(p.device() == dev);
+ // p is a reference to a non-detached instance that lives in QPointingDevicePrivate::activePoints.
// Update persistent info in that instance.
if (isPress || isWheel)
- mut.setGlobalLastPosition(globalPos);
+ QMutableEventPoint::setGlobalLastPosition(p, globalPos);
else
- mut.setGlobalLastPosition(mut.globalPosition());
- mut.setGlobalPosition(globalPos);
- if (isWheel && mut.state() != QEventPoint::State::Updated)
- mut.setGlobalPressPosition(globalPos);
+ QMutableEventPoint::setGlobalLastPosition(p, p.globalPosition());
+ QMutableEventPoint::setGlobalPosition(p, globalPos);
+ if (isWheel && p.state() != QEventPoint::State::Updated)
+ QMutableEventPoint::setGlobalPressPosition(p, globalPos);
if (type == MouseButtonDblClick)
- mut.setState(QEventPoint::State::Stationary);
+ QMutableEventPoint::setState(p, QEventPoint::State::Stationary);
else if (button == Qt::NoButton || isWheel)
- mut.setState(QEventPoint::State::Updated);
+ QMutableEventPoint::setState(p, QEventPoint::State::Updated);
else if (isPress)
- mut.setState(QEventPoint::State::Pressed);
+ QMutableEventPoint::setState(p, QEventPoint::State::Pressed);
else
- mut.setState(QEventPoint::State::Released);
- mut.setScenePosition(scenePos);
+ QMutableEventPoint::setState(p, QEventPoint::State::Released);
+ QMutableEventPoint::setScenePosition(p, scenePos);
// Now detach, and update the detached instance with ephemeral state.
- mut.detach();
- mut.setPosition(localPos);
- m_points.append(mut);
+ QMutableEventPoint::detach(p);
+ QMutableEventPoint::setPosition(p, localPos);
+ m_points.append(p);
}
/*! \internal
@@ -586,6 +574,8 @@ QSinglePointEvent::QSinglePointEvent(QEvent::Type type, const QPointingDevice *d
m_points << point;
}
+Q_IMPL_POINTER_EVENT(QSinglePointEvent)
+
/*!
Returns \c true if this event represents a \l {button()}{button} being pressed.
*/
@@ -630,7 +620,6 @@ bool QSinglePointEvent::isEndEvent() const
\endcode
*/
-
/*!
\class QMouseEvent
\ingroup events
@@ -680,7 +669,10 @@ bool QSinglePointEvent::isEndEvent() const
QCursor::pos()
*/
+#if QT_DEPRECATED_SINCE(6, 4)
/*!
+ \deprecated [6.4] Use another constructor instead (global position is required).
+
Constructs a mouse event object originating from \a device.
The \a type parameter must be one of QEvent::MouseButtonPress,
@@ -711,6 +703,7 @@ QMouseEvent::QMouseEvent(Type type, const QPointF &localPos, Qt::MouseButton but
button, buttons, modifiers)
{
}
+#endif
/*!
Constructs a mouse event object originating from \a device.
@@ -770,16 +763,12 @@ QMouseEvent::QMouseEvent(QEvent::Type type, const QPointF &localPos, const QPoin
{
}
-/*!
- \internal
-*/
-QMouseEvent::~QMouseEvent()
-{
-}
+Q_IMPL_POINTER_EVENT(QMouseEvent)
/*!
+ \fn Qt::MouseEventSource QMouseEvent::source() const
\since 5.3
- \deprecated in 6.0: use pointingDevice()
+ \deprecated [6.0] Use pointingDevice() instead.
Returns information about the mouse event source.
@@ -795,7 +784,20 @@ QMouseEvent::~QMouseEvent()
\sa Qt::MouseEventSource
\sa QGraphicsSceneMouseEvent::source()
-*/
+
+ \note In Qt 5-based code, source() was often used to attempt to distinguish
+ mouse events from an actual mouse vs. those that were synthesized because
+ some legacy QQuickItem or QWidget subclass did not react to a QTouchEvent.
+ However, you could not tell whether it was synthesized from a QTouchEvent
+ or a QTabletEvent, and other information was lost. pointingDevice()
+ tells you the specific device that it came from, so you might check
+ \c {pointingDevice()->type()} or \c {pointingDevice()->capabilities()} to
+ decide how to react to this event. But it's even better to react to the
+ original event rather than handling only mouse events.
+*/
+// Note: the docs mention 6.0 as a deprecation version. That is correct and
+// intended, because we want our users to stop using it! Internally we will
+// deprecate it when we port our code away from using it.
Qt::MouseEventSource QMouseEvent::source() const
{
return Qt::MouseEventSource(m_source);
@@ -818,6 +820,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn QPointF QMouseEvent::localPos() const
+ \deprecated [6.0] Use position() instead.
\since 5.0
@@ -845,6 +848,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn QPointF QMouseEvent::windowPos() const
+ \deprecated [6.0] Use scenePosition() instead.
\since 5.0
@@ -860,6 +864,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn QPointF QMouseEvent::screenPos() const
+ \deprecated [6.0] Use globalPosition() instead.
\since 5.0
@@ -871,6 +876,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn QPoint QMouseEvent::pos() const
+ \deprecated [6.0] Use position() instead.
Returns the position of the mouse cursor, relative to the widget
that received the event.
@@ -884,6 +890,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn QPoint QMouseEvent::globalPos() const
+ \deprecated [6.0] Use globalPosition().toPoint() instead.
Returns the global position of the mouse cursor \e{at the time
of the event}. This is important on asynchronous window systems
@@ -897,6 +904,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn int QMouseEvent::x() const
+ \deprecated [6.0] Use position().x() instead.
Returns the x position of the mouse cursor, relative to the
widget that received the event.
@@ -906,6 +914,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn int QMouseEvent::y() const
+ \deprecated [6.0] Use position().y() instead.
Returns the y position of the mouse cursor, relative to the
widget that received the event.
@@ -915,6 +924,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn int QMouseEvent::globalX() const
+ \deprecated [6.0] Use globalPosition().x() instead.
Returns the global x position of the mouse cursor at the time of
the event.
@@ -924,6 +934,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn int QMouseEvent::globalY() const
+ \deprecated [6.0] Use globalPosition().y() instead.
Returns the global y position of the mouse cursor at the time of
the event.
@@ -981,6 +992,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn QPoint QHoverEvent::pos() const
+ \deprecated [6.0] Use position().toPoint() instead.
Returns the position of the mouse cursor, relative to the widget
that received the event.
@@ -1006,6 +1018,7 @@ Qt::MouseEventFlags QMouseEvent::flags() const
/*!
\fn const QPointF &QHoverEvent::posF() const
+ \deprecated [6.0] Use position() instead.
Returns the position of the mouse cursor, relative to the widget
that received the event.
@@ -1035,23 +1048,40 @@ Qt::MouseEventFlags QMouseEvent::flags() const
The \a type parameter must be QEvent::HoverEnter,
QEvent::HoverLeave, or QEvent::HoverMove.
- The \a pos is the current mouse cursor's position relative to the
- receiving widget, while \a oldPos is its previous such position.
+ The \a scenePos is the current mouse cursor's position relative to the
+ receiving window or scene, \a oldPos is its previous such position, and
+ \a globalPos is the mouse position in absolute coordinates.
\a modifiers hold the state of all keyboard modifiers at the time
of the event.
*/
-QHoverEvent::QHoverEvent(Type type, const QPointF &pos, const QPointF &oldPos,
+QHoverEvent::QHoverEvent(Type type, const QPointF &scenePos, const QPointF &globalPos, const QPointF &oldPos,
Qt::KeyboardModifiers modifiers, const QPointingDevice *device)
- : QSinglePointEvent(type, device, pos, pos, pos, Qt::NoButton, Qt::NoButton, modifiers), m_oldPos(oldPos)
+ : QSinglePointEvent(type, device, scenePos, scenePos, globalPos, Qt::NoButton, Qt::NoButton, modifiers), m_oldPos(oldPos)
{
}
+#if QT_DEPRECATED_SINCE(6, 3)
/*!
- \internal
+ \deprecated [6.3] Use the other constructor instead (global position is required).
+
+ Constructs a hover event object originating from \a device.
+
+ The \a type parameter must be QEvent::HoverEnter,
+ QEvent::HoverLeave, or QEvent::HoverMove.
+
+ The \a pos is the current mouse cursor's position relative to the
+ receiving widget, while \a oldPos is its previous such position.
+ \a modifiers hold the state of all keyboard modifiers at the time
+ of the event.
*/
-QHoverEvent::~QHoverEvent()
+QHoverEvent::QHoverEvent(Type type, const QPointF &pos, const QPointF &oldPos,
+ Qt::KeyboardModifiers modifiers, const QPointingDevice *device)
+ : QSinglePointEvent(type, device, pos, pos, pos, Qt::NoButton, Qt::NoButton, modifiers), m_oldPos(oldPos)
{
}
+#endif
+
+Q_IMPL_POINTER_EVENT(QHoverEvent)
#if QT_CONFIG(wheelevent)
/*!
@@ -1097,7 +1127,7 @@ QHoverEvent::~QHoverEvent()
/*!
\fn Qt::MouseEventSource QWheelEvent::source() const
\since 5.5
- \deprecated in 6.0: use pointingDevice()
+ \deprecated [6.0] Use pointingDevice() instead.
Returns information about the wheel event source.
@@ -1176,12 +1206,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF &globalPos, QPoint pi
m_invertedScrolling = inverted;
}
-/*!
- \internal
-*/
-QWheelEvent::~QWheelEvent()
-{
-}
+Q_IMPL_POINTER_EVENT(QWheelEvent)
/*!
Returns \c true if this event's phase() is Qt::ScrollBegin.
@@ -1226,7 +1251,7 @@ bool QWheelEvent::isEndEvent() const
\li scrolling is about to begin, but the distance did not yet change (Qt::ScrollBegin),
\li or scrolling has ended and the distance did not change anymore (Qt::ScrollEnd).
\endlist
- \note On X11 this value is driver specific and unreliable, use angleDelta() instead
+ \note On X11 this value is driver-specific and unreliable, use angleDelta() instead.
*/
/*!
@@ -1361,22 +1386,17 @@ QKeyEvent::QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers,
}
-/*!
- \internal
-*/
-QKeyEvent::~QKeyEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QKeyEvent)
/*!
- \fn quint32 QKeyEvent::nativeScanCode() const
- \since 4.2
+ \fn quint32 QKeyEvent::nativeScanCode() const
+ \since 4.2
- Returns the native scan code of the key event. If the key event
- does not contain this data 0 is returned.
+ Returns the native scan code of the key event. If the key event
+ does not contain this data 0 is returned.
- Note: The native scan code may be 0, even if the key event contains
- extended information.
+ \note The native scan code may be 0, even if the key event contains
+ extended information.
*/
/*!
@@ -1386,7 +1406,7 @@ QKeyEvent::~QKeyEvent()
Returns the native virtual key, or key sym of the key event.
If the key event does not contain this data 0 is returned.
- Note: The native virtual key may be 0, even if the key event contains extended information.
+ \note The native virtual key may be 0, even if the key event contains extended information.
*/
/*!
@@ -1396,7 +1416,7 @@ QKeyEvent::~QKeyEvent()
Returns the native modifiers of a key event.
If the key event does not contain this data 0 is returned.
- Note: The native modifiers may be 0, even if the key event contains extended information.
+ \note The native modifiers may be 0, even if the key event contains extended information.
*/
/*!
@@ -1423,12 +1443,13 @@ QKeyEvent::~QKeyEvent()
Returns the Unicode text that this key generated.
- Return values when modifier keys such as
- Shift, Control, Alt, and Meta are pressed
- differ among platforms and could return an empty string.
+ The text is not limited to the printable range of Unicode
+ code points, and may include control characters or characters
+ from other Unicode categories, including QChar::Other_PrivateUse.
- \note \l key() will always return a valid value,
- independent of modifier keys.
+ The text may also be empty, for example when modifier keys such as
+ Shift, Control, Alt, and Meta are pressed (depending on the platform).
+ The key() function will always return a valid value.
\sa Qt::WA_KeyCompression
*/
@@ -1540,12 +1561,7 @@ QFocusEvent::QFocusEvent(Type type, Qt::FocusReason reason)
: QEvent(type), m_reason(reason)
{}
-/*!
- \internal
-*/
-QFocusEvent::~QFocusEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QFocusEvent)
/*!
Returns the reason for this focus event.
@@ -1618,12 +1634,7 @@ QPaintEvent::QPaintEvent(const QRect &paintRect)
{}
-/*!
- \internal
-*/
-QPaintEvent::~QPaintEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QPaintEvent)
/*!
\fn const QRect &QPaintEvent::rect() const
@@ -1665,12 +1676,7 @@ QMoveEvent::QMoveEvent(const QPoint &pos, const QPoint &oldPos)
: QEvent(Move), m_pos(pos), m_oldPos(oldPos)
{}
-/*!
- \internal
-*/
-QMoveEvent::~QMoveEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QMoveEvent)
/*!
\fn const QPoint &QMoveEvent::pos() const
@@ -1717,12 +1723,7 @@ QExposeEvent::QExposeEvent(const QRegion &exposeRegion)
{
}
-/*!
- \internal
-*/
-QExposeEvent::~QExposeEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QExposeEvent)
/*!
\class QPlatformSurfaceEvent
@@ -1766,15 +1767,11 @@ QPlatformSurfaceEvent::QPlatformSurfaceEvent(SurfaceEventType surfaceEventType)
{
}
-/*!
- \internal
-*/
-QPlatformSurfaceEvent::~QPlatformSurfaceEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QPlatformSurfaceEvent)
/*!
\fn const QRegion &QExposeEvent::region() const
+ \deprecated [6.0] Use QPaintEvent instead.
Returns the window area that has been exposed. The region is given in local coordinates.
*/
@@ -1801,12 +1798,7 @@ QResizeEvent::QResizeEvent(const QSize &size, const QSize &oldSize)
: QEvent(Resize), m_size(size), m_oldSize(oldSize)
{}
-/*!
- \internal
-*/
-QResizeEvent::~QResizeEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QResizeEvent)
/*!
\fn const QSize &QResizeEvent::size() const
@@ -1848,10 +1840,6 @@ QResizeEvent::~QResizeEvent()
special handling, you should reimplement the event handler and
ignore() the event.
- The \l{mainwindows/application#close event handler}{closeEvent() in the
- Application example} shows a close event handler that
- asks whether to save a document before closing.
-
If you want the widget to be deleted when it is closed, create it
with the Qt::WA_DeleteOnClose flag. This is very useful for
independent top-level windows in a multi-window application.
@@ -1881,11 +1869,7 @@ QCloseEvent::QCloseEvent()
: QEvent(Close)
{}
-/*! \internal
-*/
-QCloseEvent::~QCloseEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QCloseEvent)
/*!
\class QIconDragEvent
@@ -1914,10 +1898,7 @@ QIconDragEvent::QIconDragEvent()
: QEvent(IconDrag)
{ ignore(); }
-/*! \internal */
-QIconDragEvent::~QIconDragEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QIconDragEvent)
/*!
\class QContextMenuEvent
@@ -1953,12 +1934,12 @@ QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos, const QPo
: QInputEvent(ContextMenu, QPointingDevice::primaryPointingDevice(), modifiers), m_pos(pos), m_globalPos(globalPos), m_reason(reason)
{}
+Q_IMPL_EVENT_COMMON(QContextMenuEvent)
-/*! \internal */
-QContextMenuEvent::~QContextMenuEvent()
-{
-}
+#if QT_DEPRECATED_SINCE(6, 4)
/*!
+ \deprecated [6.4] Use the other constructor instead (global position is required).
+
Constructs a context menu event object with the accept parameter
flag set to false.
@@ -1979,6 +1960,7 @@ QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos)
m_globalPos = QCursor::pos();
#endif
}
+#endif
/*!
\fn const QPoint &QContextMenuEvent::pos() const
@@ -2113,7 +2095,7 @@ QContextMenuEvent::QContextMenuEvent(Reason reason, const QPoint &pos)
has to be inserted to the widgets text directly before the preedit
string.
- If the commitString() should replace parts of the of the text in
+ If the commitString() should replace parts of the text in
the editor, replacementLength() will contain the number of
characters to be replaced. replacementStart() contains the position
at which characters are to be replaced relative from the start of
@@ -2269,9 +2251,7 @@ QInputMethodEvent::QInputMethodEvent(const QString &preeditText, const QList<Att
{
}
-QInputMethodEvent::~QInputMethodEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QInputMethodEvent)
/*!
Sets the commit string to \a commitString.
@@ -2281,7 +2261,7 @@ QInputMethodEvent::~QInputMethodEvent()
result of the input operations and has to be inserted to the
widgets text directly before the preedit string.
- If the commit string should replace parts of the of the text in
+ If the commit string should replace parts of the text in
the editor, \a replaceLength specifies the number of
characters to be replaced. \a replaceFrom specifies the position
at which characters are to be replaced relative from the start of
@@ -2378,12 +2358,7 @@ QInputMethodQueryEvent::QInputMethodQueryEvent(Qt::InputMethodQueries queries)
{
}
-/*!
- \internal
- */
-QInputMethodQueryEvent::~QInputMethodQueryEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QInputMethodQueryEvent)
/*!
Sets property \a query to \a value.
@@ -2530,17 +2505,12 @@ QTabletEvent::QTabletEvent(Type type, const QPointingDevice *dev, const QPointF
m_yTilt(yTilt),
m_z(z)
{
- QMutableEventPoint &mut = QMutableEventPoint::from(point(0));
- mut.setPressure(pressure);
- mut.setRotation(rotation);
+ QEventPoint &p = point(0);
+ QMutableEventPoint::setPressure(p, pressure);
+ QMutableEventPoint::setRotation(p, rotation);
}
-/*!
- \internal
-*/
-QTabletEvent::~QTabletEvent()
-{
-}
+Q_IMPL_POINTER_EVENT(QTabletEvent)
/*!
\fn qreal QTabletEvent::tangentialPressure() const
@@ -2606,6 +2576,7 @@ QTabletEvent::~QTabletEvent()
/*!
\fn QPoint QTabletEvent::pos() const
+ \deprecated [6.0] Use position().toPoint() instead.
Returns the position of the device, relative to the widget that
received the event.
@@ -2618,6 +2589,7 @@ QTabletEvent::~QTabletEvent()
/*!
\fn int QTabletEvent::x() const
+ \deprecated [6.0] Use position().x() instead.
Returns the x position of the device, relative to the widget that
received the event.
@@ -2627,6 +2599,7 @@ QTabletEvent::~QTabletEvent()
/*!
\fn int QTabletEvent::y() const
+ \deprecated [6.0] Use position().y() instead.
Returns the y position of the device, relative to the widget that
received the event.
@@ -2648,6 +2621,7 @@ QTabletEvent::~QTabletEvent()
/*!
\fn QPoint QTabletEvent::globalPos() const
+ \deprecated [6.0] Use globalPosition().toPoint() instead.
Returns the global position of the device \e{at the time of the
event}. This is important on asynchronous windows systems like X11;
@@ -2660,6 +2634,7 @@ QTabletEvent::~QTabletEvent()
/*!
\fn int QTabletEvent::globalX() const
+ \deprecated [6.0] Use globalPosition().x() instead.
Returns the global x position of the mouse pointer at the time of
the event.
@@ -2669,6 +2644,7 @@ QTabletEvent::~QTabletEvent()
/*!
\fn int QTabletEvent::globalY() const
+ \deprecated [6.0] Use globalPosition().y() instead.
Returns the global y position of the tablet device at the time of
the event.
@@ -2678,6 +2654,7 @@ QTabletEvent::~QTabletEvent()
/*!
\fn qint64 QTabletEvent::uniqueId() const
+ \deprecated [6.0] Use pointingDevice().uniqueId() instead.
Returns a unique ID for the current device, making it possible
to differentiate between multiple devices being used at the same
@@ -2701,6 +2678,7 @@ QTabletEvent::~QTabletEvent()
/*!
\fn const QPointF &QTabletEvent::posF() const
+ \deprecated [6.0] Use position() instead.
Returns the position of the device, relative to the widget that
received the event.
@@ -2713,7 +2691,7 @@ QTabletEvent::~QTabletEvent()
/*!
\fn const QPointF &QTabletEvent::globalPosF() const
-
+ \deprecated [6.0] Use globalPosition() instead.
Returns the global position of the device \e{at the time of the
event}. This is important on asynchronous windows systems like X11;
whenever you move your widgets around in response to mouse events,
@@ -2791,9 +2769,9 @@ QTabletEvent::~QTabletEvent()
\sa Qt::NativeGestureType, QGestureEvent, QWheelEvent
*/
+#if QT_DEPRECATED_SINCE(6, 2)
/*!
- \deprecated
- Use the other constructor, because \a intValue is no longer stored separately.
+ \deprecated [6.2] Use the other constructor, because \a intValue is no longer stored separately.
Constructs a native gesture event of type \a type originating from \a device.
@@ -2809,7 +2787,6 @@ QTabletEvent::~QTabletEvent()
it is stored in the same variable, such that value() returns the value
given as \a intValue.
*/
-#if QT_DEPRECATED_SINCE(6, 2)
QNativeGestureEvent::QNativeGestureEvent(Qt::NativeGestureType type, const QPointingDevice *device,
const QPointF &localPos, const QPointF &scenePos,
const QPointF &globalPos, qreal realValue, quint64 sequenceId,
@@ -2857,7 +2834,7 @@ QNativeGestureEvent::QNativeGestureEvent(Qt::NativeGestureType type, const QPoin
Q_ASSERT(fingerCount < 16); // we store it in 4 bits unsigned
}
-QNativeGestureEvent::~QNativeGestureEvent() = default;
+Q_IMPL_POINTER_EVENT(QNativeGestureEvent)
/*!
\fn QNativeGestureEvent::gestureType() const
@@ -2900,6 +2877,7 @@ QNativeGestureEvent::~QNativeGestureEvent() = default;
/*!
\fn QPoint QNativeGestureEvent::globalPos() const
\since 5.2
+ \deprecated [6.0] Use globalPosition().toPoint() instead.
Returns the position of the gesture as a QPointF in screen coordinates
*/
@@ -2907,6 +2885,7 @@ QNativeGestureEvent::~QNativeGestureEvent() = default;
/*!
\fn QPoint QNativeGestureEvent::pos() const
\since 5.2
+ \deprecated [6.0] Use position().toPoint() instead.
Returns the position of the mouse cursor, relative to the widget
or item that received the event.
@@ -2915,6 +2894,7 @@ QNativeGestureEvent::~QNativeGestureEvent() = default;
/*!
\fn QPointF QNativeGestureEvent::localPos() const
\since 5.2
+ \deprecated [6.0] Use position() instead.
Returns the position of the gesture as a QPointF, relative to the
widget or item that received the event.
@@ -2923,6 +2903,7 @@ QNativeGestureEvent::~QNativeGestureEvent() = default;
/*!
\fn QPointF QNativeGestureEvent::screenPos() const
\since 5.2
+ \deprecated [6.0] Use globalPosition() instead.
Returns the position of the gesture as a QPointF in screen coordinates.
*/
@@ -2930,6 +2911,7 @@ QNativeGestureEvent::~QNativeGestureEvent() = default;
/*!
\fn QPointF QNativeGestureEvent::windowPos() const
\since 5.2
+ \deprecated [6.0] Use scenePosition() instead.
Returns the position of the gesture as a QPointF, relative to the
window that received the event.
@@ -2955,12 +2937,7 @@ QDragMoveEvent::QDragMoveEvent(const QPoint& pos, Qt::DropActions actions, const
, m_rect(pos, QSize(1, 1))
{}
-/*!
- Destroys the event.
-*/
-QDragMoveEvent::~QDragMoveEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QDragMoveEvent)
/*!
\fn void QDragMoveEvent::accept(const QRect &rectangle)
@@ -3073,10 +3050,7 @@ QDropEvent::QDropEvent(const QPointF& pos, Qt::DropActions actions, const QMimeD
ignore();
}
-/*! \internal */
-QDropEvent::~QDropEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QDropEvent)
/*!
@@ -3107,24 +3081,49 @@ void QDropEvent::setDropAction(Qt::DropAction action)
/*!
\fn QPoint QDropEvent::pos() const
+ \deprecated [6.0] Use position().toPoint() instead.
Returns the position where the drop was made.
*/
/*!
\fn const QPointF& QDropEvent::posF() const
+ \deprecated [6.0] Use position() instead.
+
+ Returns the position where the drop was made.
+*/
+
+/*!
+ \fn QPointF QDropEvent::position() const
+ \since 6.0
Returns the position where the drop was made.
*/
/*!
\fn Qt::MouseButtons QDropEvent::mouseButtons() const
+ \deprecated [6.0] Use buttons() instead.
+
+ Returns the mouse buttons that are pressed.
+*/
+
+/*!
+ \fn Qt::MouseButtons QDropEvent::buttons() const
+ \since 6.0
- Returns the mouse buttons that are pressed..
+ Returns the mouse buttons that are pressed.
*/
/*!
\fn Qt::KeyboardModifiers QDropEvent::keyboardModifiers() const
+ \deprecated [6.0] Use modifiers() instead.
+
+ Returns the modifier keys that are pressed.
+*/
+
+/*!
+ \fn Qt::KeyboardModifiers QDropEvent::modifiers() const
+ \since 6.0
Returns the modifier keys that are pressed.
*/
@@ -3217,11 +3216,7 @@ QDragEnterEvent::QDragEnterEvent(const QPoint& point, Qt::DropActions actions, c
: QDragMoveEvent(point, actions, data, buttons, modifiers, DragEnter)
{}
-/*! \internal
-*/
-QDragEnterEvent::~QDragEnterEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QDragEnterEvent)
/*!
\class QDragMoveEvent
@@ -3275,11 +3270,8 @@ QDragLeaveEvent::QDragLeaveEvent()
: QEvent(DragLeave)
{}
-/*! \internal
-*/
-QDragLeaveEvent::~QDragLeaveEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QDragLeaveEvent)
+
#endif // QT_CONFIG(draganddrop)
/*!
@@ -3361,11 +3353,7 @@ QHelpEvent::QHelpEvent(Type type, const QPoint &pos, const QPoint &globalPos)
\sa pos(), globalX(), globalY()
*/
-/*! \internal
-*/
-QHelpEvent::~QHelpEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QHelpEvent)
#ifndef QT_NO_STATUSTIP
@@ -3420,11 +3408,7 @@ QStatusTipEvent::QStatusTipEvent(const QString &tip)
: QEvent(StatusTip), m_tip(tip)
{}
-/*! \internal
-*/
-QStatusTipEvent::~QStatusTipEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QStatusTipEvent)
/*!
\fn QString QStatusTipEvent::tip() const
@@ -3460,11 +3444,7 @@ QWhatsThisClickedEvent::QWhatsThisClickedEvent(const QString &href)
: QEvent(WhatsThisClicked), m_href(href)
{}
-/*! \internal
-*/
-QWhatsThisClickedEvent::~QWhatsThisClickedEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QWhatsThisClickedEvent)
/*!
\fn QString QWhatsThisClickedEvent::href() const
@@ -3506,11 +3486,7 @@ QActionEvent::QActionEvent(int type, QAction *action, QAction *before)
: QEvent(static_cast<QEvent::Type>(type)), m_action(action), m_before(before)
{}
-/*! \internal
-*/
-QActionEvent::~QActionEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QActionEvent)
/*!
\fn QAction *QActionEvent::action() const
@@ -3560,11 +3536,7 @@ QHideEvent::QHideEvent()
: QEvent(Hide)
{}
-/*! \internal
-*/
-QHideEvent::~QHideEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QHideEvent)
/*!
\class QShowEvent
@@ -3590,11 +3562,7 @@ QShowEvent::QShowEvent()
: QEvent(Show)
{}
-/*! \internal
-*/
-QShowEvent::~QShowEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QShowEvent)
/*!
\class QFileOpenEvent
@@ -3625,10 +3593,15 @@ QShowEvent::~QShowEvent()
\snippet qfileopenevent/Info.plist Custom Info.plist
- The following implementation of a QApplication subclass prints the path to
- the file that was, for example, dropped on the Dock icon of the application.
+ The following implementation of a QApplication subclass shows how to handle
+ QFileOpenEvent to open the file that was, for example, dropped on the Dock
+ icon of the application.
\snippet qfileopenevent/main.cpp QApplication subclass
+
+ Note how \c{QFileOpenEvent::file()} is not guaranteed to be the name of a
+ local file that can be opened using QFile. The contents of the string depend
+ on the source application.
*/
/*!
@@ -3651,29 +3624,28 @@ QFileOpenEvent::QFileOpenEvent(const QUrl &url)
{
}
-
-/*! \internal
-*/
-QFileOpenEvent::~QFileOpenEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QFileOpenEvent)
/*!
\fn QString QFileOpenEvent::file() const
- Returns the file that is being opened.
+ Returns the name of the file that the application should open.
+
+ This is not guaranteed to be the path to a local file.
*/
/*!
\fn QUrl QFileOpenEvent::url() const
- Returns the url that is being opened.
+ Returns the url that the application should open.
\since 4.6
*/
+#if QT_DEPRECATED_SINCE(6, 6)
/*!
\fn bool QFileOpenEvent::openFile(QFile &file, QIODevice::OpenMode flags) const
+ \deprecated [6.6] interpret the string returned by file()
Opens a QFile on the \a file referenced by this event in the mode specified
by \a flags. Returns \c true if successful; otherwise returns \c false.
@@ -3688,6 +3660,7 @@ bool QFileOpenEvent::openFile(QFile &file, QIODevice::OpenMode flags) const
file.setFileName(m_file);
return file.open(flags);
}
+#endif
#ifndef QT_NO_TOOLBAR
/*!
@@ -3714,11 +3687,7 @@ QToolBarChangeEvent::QToolBarChangeEvent(bool t)
: QEvent(ToolBarChange), m_toggle(t)
{}
-/*! \internal
-*/
-QToolBarChangeEvent::~QToolBarChangeEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QToolBarChangeEvent)
/*!
\fn bool QToolBarChangeEvent::toggle() const
@@ -3743,6 +3712,8 @@ QToolBarChangeEvent::~QToolBarChangeEvent()
Constructs a shortcut event for the given \a key press,
associated with the QShortcut ID \a id.
+ \deprecated use the other constructor
+
\a ambiguous specifies whether there is more than one QShortcut
for the same key sequence.
*/
@@ -3752,12 +3723,29 @@ QShortcutEvent::QShortcutEvent(const QKeySequence &key, int id, bool ambiguous)
}
/*!
- Destroys the event object.
+ Constructs a shortcut event for the given \a key press,
+ associated with the QShortcut \a shortcut.
+ \since 6.5
+
+ \a ambiguous specifies whether there is more than one QShortcut
+ for the same key sequence.
*/
-QShortcutEvent::~QShortcutEvent()
+QShortcutEvent::QShortcutEvent(const QKeySequence &key, const QShortcut *shortcut, bool ambiguous)
+ : QEvent(Shortcut), m_sequence(key), m_shortcutId(0), m_ambiguous(ambiguous)
{
+ if (shortcut) {
+ auto priv = static_cast<const QShortcutPrivate *>(QShortcutPrivate::get(shortcut));
+ auto index = priv->sc_sequences.indexOf(key);
+ if (index < 0) {
+ qWarning() << "Given QShortcut does not contain key-sequence " << key;
+ return;
+ }
+ m_shortcutId = priv->sc_ids[index];
+ }
}
+Q_IMPL_EVENT_COMMON(QShortcutEvent)
+
#endif // QT_CONFIG(shortcut)
#ifndef QT_NO_DEBUG_STREAM
@@ -3783,6 +3771,13 @@ static void formatUnicodeString(QDebug d, const QString &s)
d << Qt::dec << '"';
}
+static QDebug operator<<(QDebug dbg, const QInputMethodEvent::Attribute &attr)
+{
+ dbg << "[type= " << attr.type << ", start=" << attr.start << ", length=" << attr.length
+ << ", value=" << attr.value << ']';
+ return dbg;
+}
+
static inline void formatInputMethodEvent(QDebug d, const QInputMethodEvent *e)
{
d << "QInputMethodEvent(";
@@ -3798,15 +3793,15 @@ static inline void formatInputMethodEvent(QDebug d, const QInputMethodEvent *e)
d << ", replacementStart=" << e->replacementStart() << ", replacementLength="
<< e->replacementLength();
}
- if (const int attributeCount = e->attributes().size()) {
+ const auto attributes = e->attributes();
+ auto it = attributes.cbegin();
+ const auto end = attributes.cend();
+ if (it != end) {
d << ", attributes= {";
- for (int a = 0; a < attributeCount; ++a) {
- const QInputMethodEvent::Attribute &at = e->attributes().at(a);
- if (a)
- d << ',';
- d << "[type= " << at.type << ", start=" << at.start << ", length=" << at.length
- << ", value=" << at.value << ']';
- }
+ d << *it;
+ ++it;
+ for (; it != end; ++it)
+ d << ',' << *it;
d << '}';
}
d << ')';
@@ -4058,10 +4053,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
bool isMouse = false;
switch (type) {
case QEvent::Expose:
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
- dbg << "QExposeEvent(" << static_cast<const QExposeEvent *>(e)->region() << ')';
-QT_WARNING_POP
+ dbg << "QExposeEvent()";
break;
case QEvent::Paint:
dbg << "QPaintEvent(" << static_cast<const QPaintEvent *>(e)->region() << ')';
@@ -4136,6 +4128,10 @@ QT_WARNING_POP
dbg << ", text=" << ke->text();
if (ke->isAutoRepeat())
dbg << ", autorepeat, count=" << ke->count();
+ if (dbg.verbosity() > QDebug::DefaultVerbosity) {
+ dbg << ", nativeScanCode=" << ke->nativeScanCode();
+ dbg << ", nativeVirtualKey=" << ke->nativeVirtualKey();
+ }
dbg << ')';
}
break;
@@ -4302,6 +4298,8 @@ QT_WARNING_POP
/*!
\fn int QShortcutEvent::shortcutId() const
+ \deprecated
+
Returns the ID of the QShortcut object for which this event was
generated.
@@ -4345,11 +4343,7 @@ bool QWindowStateChangeEvent::isOverride() const
return m_override;
}
-/*! \internal
-*/
-QWindowStateChangeEvent::~QWindowStateChangeEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QWindowStateChangeEvent)
/*!
@@ -4404,7 +4398,7 @@ QWindowStateChangeEvent::~QWindowStateChangeEvent()
describes the different states that a touch point may have.
\note The list of points() will never be partial: A touch event will always contain a touch
- point for each existing physical touch contacts targetting the window or widget to which the
+ point for each existing physical touch contacts targeting the window or widget to which the
event is sent. For instance, assuming that all touches target the same window or widget, an
event with a condition of points().count()==2 is guaranteed to imply that the number of
fingers touching the touchscreen or touchpad is exactly two.
@@ -4497,14 +4491,13 @@ QTouchEvent::QTouchEvent(QEvent::Type eventType,
{
for (QEventPoint &point : m_points) {
m_touchPointStates |= point.state();
- QMutableEventPoint::from(point).setDevice(device);
+ QMutableEventPoint::setDevice(point, device);
}
}
+#if QT_DEPRECATED_SINCE(6, 0)
/*!
- \deprecated
- Try to use another constructor, because \a touchPointStates
- can be calculated from the given \a touchPoints.
+ \deprecated [6.0] Use another constructor.
Constructs a QTouchEvent with the given \a eventType, \a device, and
\a touchPoints. The \a touchPointStates and \a modifiers are the current
@@ -4520,14 +4513,11 @@ QTouchEvent::QTouchEvent(QEvent::Type eventType,
m_touchPointStates(touchPointStates)
{
for (QEventPoint &point : m_points)
- QMutableEventPoint::from(point).setDevice(device);
+ QMutableEventPoint::setDevice(point, device);
}
+#endif // QT_DEPRECATED_SINCE(6, 0)
-/*!
- Destroys the QTouchEvent.
-*/
-QTouchEvent::~QTouchEvent()
-{ }
+Q_IMPL_POINTER_EVENT(QTouchEvent)
/*!
Returns true if this event includes at least one newly-pressed touchpoint.
@@ -4567,8 +4557,7 @@ bool QTouchEvent::isEndEvent() const
*/
/*! \fn const QList<QEventPoint> &QTouchEvent::touchPoints() const
- \deprecated
- Deprecated since Qt 6.0. Use points() instead.
+ \deprecated [6.0] Use points() instead.
Returns a reference to the list of touch points contained in the touch event.
@@ -4602,12 +4591,7 @@ QScrollPrepareEvent::QScrollPrepareEvent(const QPointF &startPos)
{
}
-/*!
- Destroys QScrollEvent.
-*/
-QScrollPrepareEvent::~QScrollPrepareEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QScrollPrepareEvent)
/*!
\fn QPointF QScrollPrepareEvent::startPos() const
@@ -4705,12 +4689,7 @@ QScrollEvent::QScrollEvent(const QPointF &contentPos, const QPointF &overshootDi
{
}
-/*!
- Destroys QScrollEvent.
-*/
-QScrollEvent::~QScrollEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QScrollEvent)
/*!
\fn QPointF QScrollEvent::contentPos() const
@@ -4747,12 +4726,7 @@ QScreenOrientationChangeEvent::QScreenOrientationChangeEvent(QScreen *screen, Qt
{
}
-/*!
- Destroys QScreenOrientationChangeEvent.
-*/
-QScreenOrientationChangeEvent::~QScreenOrientationChangeEvent()
-{
-}
+Q_IMPL_EVENT_COMMON(QScreenOrientationChangeEvent)
/*!
\fn QScreen *QScreenOrientationChangeEvent::screen() const
@@ -4775,12 +4749,57 @@ QApplicationStateChangeEvent::QApplicationStateChangeEvent(Qt::ApplicationState
{
}
+Q_IMPL_EVENT_COMMON(QApplicationStateChangeEvent)
+
/*!
\fn Qt::ApplicationState QApplicationStateChangeEvent::applicationState() const
Returns the state of the application.
*/
+/*!
+ \class QChildWindowEvent
+ \inmodule QtGui
+ \since 6.7
+ \brief The QChildWindowEvent class contains event parameters for
+ child window changes.
+
+ \ingroup events
+
+ Child window events are sent to windows when children are
+ added or removed.
+
+ In both cases you can only rely on the child being a QWindow
+ — not any subclass thereof. This is because in the
+ QEvent::ChildWindowAdded case the subclass is not yet fully
+ constructed, and in the QEvent::ChildWindowRemoved case it
+ might have already been destructed.
+*/
+
+/*!
+ Constructs a child window event object of a particular \a type
+ for the \a childWindow.
+
+ \a type can be QEvent::ChildWindowAdded or QEvent::ChildWindowRemoved.
+
+ \sa child()
+*/
+QChildWindowEvent::QChildWindowEvent(Type type, QWindow *childWindow)
+ : QEvent(type), c(childWindow)
+{
+}
+
+Q_IMPL_EVENT_COMMON(QChildWindowEvent)
+
+/*!
+ \fn QWindow *QChildWindowEvent::child() const
+
+ Returns the child window that was added or removed.
+*/
+
+QMutableTouchEvent::~QMutableTouchEvent()
+ = default;
+
/*! \internal
Add the given \a point.
*/
@@ -4789,10 +4808,14 @@ void QMutableTouchEvent::addPoint(const QEventPoint &point)
m_points.append(point);
auto &added = m_points.last();
if (!added.device())
- QMutableEventPoint::from(added).setDevice(pointingDevice());
+ QMutableEventPoint::setDevice(added, pointingDevice());
m_touchPointStates |= point.state();
}
+QMutableSinglePointEvent::~QMutableSinglePointEvent()
+ = default;
QT_END_NAMESPACE
+
+#include "moc_qevent.cpp"
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 9c53f7ce92..a24f0c471c 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -1,52 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEVENT_H
#define QEVENT_H
+#if 0
+#pragma qt_class(QtEvents)
+#endif
+
#include <QtGui/qtguiglobal.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qlist.h>
#include <QtCore/qnamespace.h>
-#include <QtCore/qpointer.h>
#include <QtCore/qstring.h>
#include <QtCore/qurl.h>
#include <QtCore/qvariant.h>
@@ -59,13 +26,19 @@
# include <QtGui/qkeysequence.h>
#endif
+class tst_QEvent;
+
QT_BEGIN_NAMESPACE
class QFile;
class QAction;
class QMouseEvent;
+template <typename T> class QPointer;
class QPointerEvent;
class QScreen;
+#if QT_CONFIG(shortcut)
+class QShortcut;
+#endif
class QTabletEvent;
class QTouchEvent;
#if QT_CONFIG(gestures)
@@ -74,11 +47,9 @@ class QGesture;
class Q_GUI_EXPORT QInputEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QInputEvent);
+ Q_DECL_EVENT_COMMON(QInputEvent)
public:
explicit QInputEvent(Type type, const QInputDevice *m_dev, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
- ~QInputEvent();
- QInputEvent *clone() const override { return new QInputEvent(*this); }
const QInputDevice *device() const { return m_dev; }
QInputDevice::DeviceType deviceType() const { return m_dev ? m_dev->type() : QInputDevice::DeviceType::Unknown; }
@@ -100,21 +71,19 @@ protected:
class Q_GUI_EXPORT QPointerEvent : public QInputEvent
{
- Q_EVENT_DISABLE_COPY(QPointerEvent);
+ Q_GADGET
+ Q_DECL_EVENT_COMMON(QPointerEvent)
public:
explicit QPointerEvent(Type type, const QPointingDevice *dev,
Qt::KeyboardModifiers modifiers = Qt::NoModifier, const QList<QEventPoint> &points = {});
- ~QPointerEvent();
-
- QPointerEvent *clone() const override { return new QPointerEvent(*this); }
const QPointingDevice *pointingDevice() const;
QPointingDevice::PointerType pointerType() const {
return pointingDevice() ? pointingDevice()->pointerType() : QPointingDevice::PointerType::Unknown;
}
void setTimestamp(quint64 timestamp) override;
- qsizetype pointCount() const { return m_points.count(); }
- QEventPoint &point(qsizetype i) { return m_points[i]; }
+ qsizetype pointCount() const { return m_points.size(); }
+ QEventPoint &point(qsizetype i);
const QList<QEventPoint> &points() const { return m_points; }
QEventPoint *pointById(int id);
bool allPointsGrabbed() const;
@@ -142,7 +111,7 @@ class Q_GUI_EXPORT QSinglePointEvent : public QPointerEvent
Q_PROPERTY(QObject *exclusivePointGrabber READ exclusivePointGrabber
WRITE setExclusivePointGrabber)
- Q_EVENT_DISABLE_COPY(QSinglePointEvent);
+ Q_DECL_EVENT_COMMON(QSinglePointEvent)
public:
inline Qt::MouseButton button() const { return m_button; }
inline Qt::MouseButtons buttons() const { return m_mouseState; }
@@ -163,9 +132,8 @@ public:
void setExclusivePointGrabber(QObject *exclusiveGrabber)
{ QPointerEvent::setExclusiveGrabber(points().first(), exclusiveGrabber); }
- QSinglePointEvent *clone() const override { return new QSinglePointEvent(*this); }
-
protected:
+ friend class ::tst_QEvent;
QSinglePointEvent(Type type, const QPointingDevice *dev, const QEventPoint &point,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source);
@@ -195,13 +163,10 @@ protected:
class Q_GUI_EXPORT QEnterEvent : public QSinglePointEvent
{
- Q_EVENT_DISABLE_COPY(QEnterEvent);
+ Q_DECL_EVENT_COMMON(QEnterEvent)
public:
QEnterEvent(const QPointF &localPos, const QPointF &scenePos, const QPointF &globalPos,
const QPointingDevice *device = QPointingDevice::primaryPointingDevice());
- ~QEnterEvent();
-
- QEnterEvent *clone() const override { return new QEnterEvent(*this); }
#if QT_DEPRECATED_SINCE(6, 0)
#ifndef QT_NO_INTEGER_EVENT_COORDINATES
@@ -229,11 +194,14 @@ public:
class Q_GUI_EXPORT QMouseEvent : public QSinglePointEvent
{
- Q_EVENT_DISABLE_COPY(QMouseEvent);
+ Q_DECL_EVENT_COMMON(QMouseEvent)
public:
+#if QT_DEPRECATED_SINCE(6, 4)
+ QT_DEPRECATED_VERSION_X_6_4("Use another constructor")
QMouseEvent(Type type, const QPointF &localPos, Qt::MouseButton button,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers,
const QPointingDevice *device = QPointingDevice::primaryPointingDevice());
+#endif
QMouseEvent(Type type, const QPointF &localPos, const QPointF &globalPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers,
@@ -246,9 +214,6 @@ public:
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source,
const QPointingDevice *device = QPointingDevice::primaryPointingDevice());
- ~QMouseEvent();
-
- QMouseEvent *clone() const override { return new QMouseEvent(*this); }
#ifndef QT_NO_INTEGER_EVENT_COORDINATES
inline QPoint pos() const { return position().toPoint(); }
@@ -272,21 +237,24 @@ public:
QPointF windowPos() const { return scenePosition(); }
QT_DEPRECATED_VERSION_X_6_0("Use globalPosition()")
QPointF screenPos() const { return globalPosition(); }
+#endif // QT_DEPRECATED_SINCE(6, 0)
Qt::MouseEventSource source() const;
Qt::MouseEventFlags flags() const;
-#endif // QT_DEPRECATED_SINCE(6, 0)
};
class Q_GUI_EXPORT QHoverEvent : public QSinglePointEvent
{
- Q_EVENT_DISABLE_COPY(QHoverEvent);
+ Q_DECL_EVENT_COMMON(QHoverEvent)
public:
+ QHoverEvent(Type type, const QPointF &scenePos, const QPointF &globalPos, const QPointF &oldPos,
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier,
+ const QPointingDevice *device = QPointingDevice::primaryPointingDevice());
+#if QT_DEPRECATED_SINCE(6, 3)
+ QT_DEPRECATED_VERSION_X_6_3("Use the other constructor")
QHoverEvent(Type type, const QPointF &pos, const QPointF &oldPos,
Qt::KeyboardModifiers modifiers = Qt::NoModifier,
const QPointingDevice *device = QPointingDevice::primaryPointingDevice());
- ~QHoverEvent();
-
- QHoverEvent *clone() const override { return new QHoverEvent(*this); }
+#endif
#if QT_DEPRECATED_SINCE(6, 0)
#ifndef QT_NO_INTEGER_EVENT_COORDINATES
@@ -318,7 +286,7 @@ class Q_GUI_EXPORT QWheelEvent : public QSinglePointEvent
Q_PROPERTY(Qt::ScrollPhase phase READ phase)
Q_PROPERTY(bool inverted READ inverted)
- Q_EVENT_DISABLE_COPY(QWheelEvent);
+ Q_DECL_EVENT_COMMON(QWheelEvent)
public:
enum { DefaultDeltasPerStep = 120 };
@@ -326,9 +294,6 @@ public:
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase,
bool inverted, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized,
const QPointingDevice *device = QPointingDevice::primaryPointingDevice());
- ~QWheelEvent();
-
- QWheelEvent *clone() const override { return new QWheelEvent(*this); }
inline QPoint pixelDelta() const { return m_pixelDelta; }
inline QPoint angleDelta() const { return m_angleDelta; }
@@ -352,7 +317,7 @@ protected:
#if QT_CONFIG(tabletevent)
class Q_GUI_EXPORT QTabletEvent : public QSinglePointEvent
{
- Q_EVENT_DISABLE_COPY(QTabletEvent);
+ Q_DECL_EVENT_COMMON(QTabletEvent)
public:
QTabletEvent(Type t, const QPointingDevice *device,
const QPointF &pos, const QPointF &globalPos,
@@ -360,9 +325,6 @@ public:
float tangentialPressure, qreal rotation, float z,
Qt::KeyboardModifiers keyState,
Qt::MouseButton button, Qt::MouseButtons buttons);
- ~QTabletEvent();
-
- QTabletEvent *clone() const override { return new QTabletEvent(*this); }
#if QT_DEPRECATED_SINCE(6, 0)
QT_DEPRECATED_VERSION_X_6_0("Use position()")
@@ -407,7 +369,7 @@ protected:
#if QT_CONFIG(gestures)
class Q_GUI_EXPORT QNativeGestureEvent : public QSinglePointEvent
{
- Q_EVENT_DISABLE_COPY(QNativeGestureEvent);
+ Q_DECL_EVENT_COMMON(QNativeGestureEvent)
public:
#if QT_DEPRECATED_SINCE(6, 2)
QT_DEPRECATED_VERSION_X_6_2("Use the other constructor")
@@ -417,9 +379,6 @@ public:
QNativeGestureEvent(Qt::NativeGestureType type, const QPointingDevice *dev, int fingerCount,
const QPointF &localPos, const QPointF &scenePos, const QPointF &globalPos,
qreal value, const QPointF &delta, quint64 sequenceId = UINT64_MAX);
- ~QNativeGestureEvent();
-
- QNativeGestureEvent *clone() const override { return new QNativeGestureEvent(*this); }
Qt::NativeGestureType gestureType() const { return m_gestureType; }
int fingerCount() const { return m_fingerCount; }
@@ -463,7 +422,7 @@ protected:
class Q_GUI_EXPORT QKeyEvent : public QInputEvent
{
- Q_EVENT_DISABLE_COPY(QKeyEvent);
+ Q_DECL_EVENT_COMMON(QKeyEvent)
public:
QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text = QString(),
bool autorep = false, quint16 count = 1);
@@ -471,9 +430,6 @@ public:
quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
const QString &text = QString(), bool autorep = false, quint16 count = 1,
const QInputDevice *device = QInputDevice::primaryKeyboard());
- ~QKeyEvent();
-
- QKeyEvent *clone() const override { return new QKeyEvent(*this); }
int key() const { return m_key; }
#if QT_CONFIG(shortcut)
@@ -512,12 +468,9 @@ protected:
class Q_GUI_EXPORT QFocusEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QFocusEvent);
+ Q_DECL_EVENT_COMMON(QFocusEvent)
public:
explicit QFocusEvent(Type type, Qt::FocusReason reason=Qt::OtherFocusReason);
- ~QFocusEvent();
-
- QFocusEvent *clone() const override { return new QFocusEvent(*this); }
inline bool gotFocus() const { return type() == FocusIn; }
inline bool lostFocus() const { return type() == FocusOut; }
@@ -531,13 +484,10 @@ private:
class Q_GUI_EXPORT QPaintEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QPaintEvent);
+ Q_DECL_EVENT_COMMON(QPaintEvent)
public:
explicit QPaintEvent(const QRegion& paintRegion);
explicit QPaintEvent(const QRect &paintRect);
- ~QPaintEvent();
-
- QPaintEvent *clone() const override { return new QPaintEvent(*this); }
inline const QRect &rect() const { return m_rect; }
inline const QRegion &region() const { return m_region; }
@@ -550,12 +500,9 @@ protected:
class Q_GUI_EXPORT QMoveEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QMoveEvent);
+ Q_DECL_EVENT_COMMON(QMoveEvent)
public:
QMoveEvent(const QPoint &pos, const QPoint &oldPos);
- ~QMoveEvent();
-
- QMoveEvent *clone() const override { return new QMoveEvent(*this); }
inline const QPoint &pos() const { return m_pos; }
inline const QPoint &oldPos() const { return m_oldPos;}
@@ -566,12 +513,9 @@ protected:
class Q_GUI_EXPORT QExposeEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QExposeEvent);
+ Q_DECL_EVENT_COMMON(QExposeEvent)
public:
explicit QExposeEvent(const QRegion &m_region);
- ~QExposeEvent();
-
- QExposeEvent *clone() const override { return new QExposeEvent(*this); }
#if QT_DEPRECATED_SINCE(6, 0)
QT_DEPRECATED_VERSION_X_6_0("Handle QPaintEvent instead")
@@ -580,11 +524,12 @@ public:
protected:
QRegion m_region;
+ friend class QWidgetWindow;
};
class Q_GUI_EXPORT QPlatformSurfaceEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QPlatformSurfaceEvent);
+ Q_DECL_EVENT_COMMON(QPlatformSurfaceEvent)
public:
enum SurfaceEventType {
SurfaceCreated,
@@ -592,9 +537,6 @@ public:
};
explicit QPlatformSurfaceEvent(SurfaceEventType surfaceEventType);
- ~QPlatformSurfaceEvent();
-
- QPlatformSurfaceEvent *clone() const override { return new QPlatformSurfaceEvent(*this); }
inline SurfaceEventType surfaceEventType() const { return m_surfaceEventType; }
@@ -604,12 +546,9 @@ protected:
class Q_GUI_EXPORT QResizeEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QResizeEvent);
+ Q_DECL_EVENT_COMMON(QResizeEvent)
public:
QResizeEvent(const QSize &size, const QSize &oldSize);
- ~QResizeEvent();
-
- QResizeEvent *clone() const override { return new QResizeEvent(*this); }
inline const QSize &size() const { return m_size; }
inline const QSize &oldSize()const { return m_oldSize;}
@@ -621,52 +560,48 @@ protected:
class Q_GUI_EXPORT QCloseEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QCloseEvent);
+ Q_DECL_EVENT_COMMON(QCloseEvent)
public:
QCloseEvent();
- ~QCloseEvent();
};
class Q_GUI_EXPORT QIconDragEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QIconDragEvent);
+ Q_DECL_EVENT_COMMON(QIconDragEvent)
public:
QIconDragEvent();
- ~QIconDragEvent();
};
class Q_GUI_EXPORT QShowEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QShowEvent);
+ Q_DECL_EVENT_COMMON(QShowEvent)
public:
QShowEvent();
- ~QShowEvent();
};
class Q_GUI_EXPORT QHideEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QHideEvent);
+ Q_DECL_EVENT_COMMON(QHideEvent)
public:
QHideEvent();
- ~QHideEvent();
};
#ifndef QT_NO_CONTEXTMENU
class Q_GUI_EXPORT QContextMenuEvent : public QInputEvent
{
- Q_EVENT_DISABLE_COPY(QContextMenuEvent);
+ Q_DECL_EVENT_COMMON(QContextMenuEvent)
public:
enum Reason { Mouse, Keyboard, Other };
QContextMenuEvent(Reason reason, const QPoint &pos, const QPoint &globalPos,
Qt::KeyboardModifiers modifiers = Qt::NoModifier);
+#if QT_DEPRECATED_SINCE(6, 4)
+ QT_DEPRECATED_VERSION_X_6_4("Use the other constructor")
QContextMenuEvent(Reason reason, const QPoint &pos);
- ~QContextMenuEvent();
-
- QContextMenuEvent *clone() const override { return new QContextMenuEvent(*this); }
+#endif
inline int x() const { return m_pos.x(); }
inline int y() const { return m_pos.y(); }
@@ -688,7 +623,7 @@ protected:
#ifndef QT_NO_INPUTMETHOD
class Q_GUI_EXPORT QInputMethodEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QInputMethodEvent);
+ Q_DECL_EVENT_COMMON(QInputMethodEvent)
public:
enum AttributeType {
TextFormat,
@@ -709,9 +644,6 @@ public:
};
QInputMethodEvent();
QInputMethodEvent(const QString &preeditText, const QList<Attribute> &attributes);
- ~QInputMethodEvent();
-
- QInputMethodEvent *clone() const override { return new QInputMethodEvent(*this); }
void setCommitString(const QString &commitString, int replaceFrom = 0, int replaceLength = 0);
inline const QList<Attribute> &attributes() const { return m_attributes; }
@@ -745,12 +677,9 @@ Q_DECLARE_TYPEINFO(QInputMethodEvent::Attribute, Q_RELOCATABLE_TYPE);
class Q_GUI_EXPORT QInputMethodQueryEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QInputMethodQueryEvent);
+ Q_DECL_EVENT_COMMON(QInputMethodQueryEvent)
public:
explicit QInputMethodQueryEvent(Qt::InputMethodQueries queries);
- ~QInputMethodQueryEvent();
-
- QInputMethodQueryEvent *clone() const override { return new QInputMethodQueryEvent(*this); }
Qt::InputMethodQueries queries() const { return m_queries; }
@@ -775,13 +704,10 @@ class QMimeData;
class Q_GUI_EXPORT QDropEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QDropEvent);
+ Q_DECL_EVENT_COMMON(QDropEvent)
public:
QDropEvent(const QPointF& pos, Qt::DropActions actions, const QMimeData *data,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Type type = Drop);
- ~QDropEvent();
-
- QDropEvent *clone() const override { return new QDropEvent(*this); }
#if QT_DEPRECATED_SINCE(6, 0)
QT_DEPRECATED_VERSION_X_6_0("Use position().toPoint()")
@@ -822,13 +748,10 @@ protected:
class Q_GUI_EXPORT QDragMoveEvent : public QDropEvent
{
- Q_EVENT_DISABLE_COPY(QDragMoveEvent);
+ Q_DECL_EVENT_COMMON(QDragMoveEvent)
public:
QDragMoveEvent(const QPoint &pos, Qt::DropActions actions, const QMimeData *data,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Type type = DragMove);
- ~QDragMoveEvent();
-
- QDragMoveEvent *clone() const override { return new QDragMoveEvent(*this); }
inline QRect answerRect() const { return m_rect; }
@@ -845,32 +768,27 @@ protected:
class Q_GUI_EXPORT QDragEnterEvent : public QDragMoveEvent
{
- Q_EVENT_DISABLE_COPY(QDragEnterEvent);
+ Q_DECL_EVENT_COMMON(QDragEnterEvent)
public:
QDragEnterEvent(const QPoint &pos, Qt::DropActions actions, const QMimeData *data,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers);
- ~QDragEnterEvent();
};
class Q_GUI_EXPORT QDragLeaveEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QDragLeaveEvent);
+ Q_DECL_EVENT_COMMON(QDragLeaveEvent)
public:
QDragLeaveEvent();
- ~QDragLeaveEvent();
};
#endif // QT_CONFIG(draganddrop)
class Q_GUI_EXPORT QHelpEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QHelpEvent);
+ Q_DECL_EVENT_COMMON(QHelpEvent)
public:
QHelpEvent(Type type, const QPoint &pos, const QPoint &globalPos);
- ~QHelpEvent();
-
- QHelpEvent *clone() const override { return new QHelpEvent(*this); }
inline int x() const { return m_pos.x(); }
inline int y() const { return m_pos.y(); }
@@ -888,12 +806,9 @@ private:
#ifndef QT_NO_STATUSTIP
class Q_GUI_EXPORT QStatusTipEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QStatusTipEvent);
+ Q_DECL_EVENT_COMMON(QStatusTipEvent)
public:
explicit QStatusTipEvent(const QString &tip);
- ~QStatusTipEvent();
-
- QStatusTipEvent *clone() const override { return new QStatusTipEvent(*this); }
inline QString tip() const { return m_tip; }
private:
@@ -904,12 +819,9 @@ private:
#if QT_CONFIG(whatsthis)
class Q_GUI_EXPORT QWhatsThisClickedEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QWhatsThisClickedEvent);
+ Q_DECL_EVENT_COMMON(QWhatsThisClickedEvent)
public:
explicit QWhatsThisClickedEvent(const QString &href);
- ~QWhatsThisClickedEvent();
-
- QWhatsThisClickedEvent *clone() const override { return new QWhatsThisClickedEvent(*this); }
inline QString href() const { return m_href; }
private:
@@ -920,12 +832,9 @@ private:
#if QT_CONFIG(action)
class Q_GUI_EXPORT QActionEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QActionEvent);
+ Q_DECL_EVENT_COMMON(QActionEvent)
public:
QActionEvent(int type, QAction *action, QAction *before = nullptr);
- ~QActionEvent();
-
- QActionEvent *clone() const override { return new QActionEvent(*this); }
inline QAction *action() const { return m_action; }
inline QAction *before() const { return m_before; }
@@ -937,17 +846,17 @@ private:
class Q_GUI_EXPORT QFileOpenEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QFileOpenEvent);
+ Q_DECL_EVENT_COMMON(QFileOpenEvent)
public:
explicit QFileOpenEvent(const QString &file);
explicit QFileOpenEvent(const QUrl &url);
- ~QFileOpenEvent();
-
- QFileOpenEvent *clone() const override { return new QFileOpenEvent(*this); }
inline QString file() const { return m_file; }
QUrl url() const { return m_url; }
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Interpret the string returned by file()")
bool openFile(QFile &file, QIODevice::OpenMode flags) const;
+#endif
private:
QString m_file;
QUrl m_url;
@@ -956,12 +865,9 @@ private:
#ifndef QT_NO_TOOLBAR
class Q_GUI_EXPORT QToolBarChangeEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QToolBarChangeEvent);
+ Q_DECL_EVENT_COMMON(QToolBarChangeEvent)
public:
explicit QToolBarChangeEvent(bool t);
- ~QToolBarChangeEvent();
-
- QToolBarChangeEvent *clone() const override { return new QToolBarChangeEvent(*this); }
inline bool toggle() const { return m_toggle; }
private:
@@ -972,14 +878,14 @@ private:
#if QT_CONFIG(shortcut)
class Q_GUI_EXPORT QShortcutEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QShortcutEvent);
+ Q_DECL_EVENT_COMMON(QShortcutEvent)
public:
+ // Note this is publicly deprecated, but should remain as internal constructor:
QShortcutEvent(const QKeySequence &key, int id, bool ambiguous = false);
- ~QShortcutEvent();
-
- QShortcutEvent *clone() const override { return new QShortcutEvent(*this); }
+ QShortcutEvent(const QKeySequence &key, const QShortcut *shortcut = nullptr, bool ambiguous = false);
inline const QKeySequence &key() const { return m_sequence; }
+ // Note this is publicly deprecated, but should remain as internal getter:
inline int shortcutId() const { return m_shortcutId; }
inline bool isAmbiguous() const { return m_ambiguous; }
protected:
@@ -991,12 +897,9 @@ protected:
class Q_GUI_EXPORT QWindowStateChangeEvent: public QEvent
{
- Q_EVENT_DISABLE_COPY(QWindowStateChangeEvent);
+ Q_DECL_EVENT_COMMON(QWindowStateChangeEvent)
public:
explicit QWindowStateChangeEvent(Qt::WindowStates oldState, bool isOverride = false);
- ~QWindowStateChangeEvent();
-
- QWindowStateChangeEvent *clone() const override { return new QWindowStateChangeEvent(*this); }
inline Qt::WindowStates oldState() const { return m_oldStates; }
bool isOverride() const;
@@ -1012,7 +915,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug, const QEvent *);
class Q_GUI_EXPORT QTouchEvent : public QPointerEvent
{
- Q_EVENT_DISABLE_COPY(QTouchEvent);
+ Q_DECL_EVENT_COMMON(QTouchEvent)
public:
using TouchPoint = QEventPoint; // source compat
@@ -1028,9 +931,6 @@ public:
QEventPoint::States touchPointStates,
const QList<QEventPoint> &touchPoints = {});
#endif
- ~QTouchEvent();
-
- QTouchEvent *clone() const override { return new QTouchEvent(*this); }
inline QObject *target() const { return m_target; }
inline QEventPoint::States touchPointStates() const { return m_touchPointStates; }
@@ -1050,12 +950,9 @@ protected:
class Q_GUI_EXPORT QScrollPrepareEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QScrollPrepareEvent);
+ Q_DECL_EVENT_COMMON(QScrollPrepareEvent)
public:
explicit QScrollPrepareEvent(const QPointF &startPos);
- ~QScrollPrepareEvent();
-
- QScrollPrepareEvent *clone() const override { return new QScrollPrepareEvent(*this); }
QPointF startPos() const { return m_startPos; }
@@ -1077,7 +974,7 @@ private:
class Q_GUI_EXPORT QScrollEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QScrollEvent);
+ Q_DECL_EVENT_COMMON(QScrollEvent)
public:
enum ScrollState
{
@@ -1087,9 +984,6 @@ public:
};
QScrollEvent(const QPointF &contentPos, const QPointF &overshoot, ScrollState scrollState);
- ~QScrollEvent();
-
- QScrollEvent *clone() const override { return new QScrollEvent(*this); }
QPointF contentPos() const { return m_contentPos; }
QPointF overshootDistance() const { return m_overshoot; }
@@ -1103,12 +997,9 @@ private:
class Q_GUI_EXPORT QScreenOrientationChangeEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QScreenOrientationChangeEvent);
+ Q_DECL_EVENT_COMMON(QScreenOrientationChangeEvent)
public:
QScreenOrientationChangeEvent(QScreen *screen, Qt::ScreenOrientation orientation);
- ~QScreenOrientationChangeEvent();
-
- QScreenOrientationChangeEvent *clone() const override { return new QScreenOrientationChangeEvent(*this); }
QScreen *screen() const { return m_screen; }
Qt::ScreenOrientation orientation() const { return m_orientation; }
@@ -1120,18 +1011,27 @@ private:
class Q_GUI_EXPORT QApplicationStateChangeEvent : public QEvent
{
- Q_EVENT_DISABLE_COPY(QApplicationStateChangeEvent);
+ Q_DECL_EVENT_COMMON(QApplicationStateChangeEvent)
public:
explicit QApplicationStateChangeEvent(Qt::ApplicationState state);
- QApplicationStateChangeEvent *clone() const override { return new QApplicationStateChangeEvent(*this); }
-
Qt::ApplicationState applicationState() const { return m_applicationState; }
private:
Qt::ApplicationState m_applicationState;
};
+class Q_GUI_EXPORT QChildWindowEvent : public QEvent
+{
+ Q_DECL_EVENT_COMMON(QChildWindowEvent)
+public:
+ explicit QChildWindowEvent(Type type, QWindow *childWindow);
+ QWindow *child() const { return c; }
+
+private:
+ QWindow *c;
+};
+
QT_END_NAMESPACE
#endif // QEVENT_H
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 227b1a4303..96ef8f123e 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEVENT_P_H
#define QEVENT_P_H
@@ -52,7 +16,6 @@
//
#include <QtGui/private/qtguiglobal_p.h>
-#include <QtGui/private/qeventpoint_p.h>
#include <QtCore/qurl.h>
#include <QtGui/qevent.h>
#include <QtGui/qwindow.h>
@@ -69,6 +32,7 @@ public:
Qt::KeyboardModifiers modifiers = Qt::NoModifier,
const QList<QEventPoint> &touchPoints = QList<QEventPoint>()) :
QTouchEvent(eventType, device, modifiers, touchPoints) { }
+ ~QMutableTouchEvent() override;
static QMutableTouchEvent *from(QTouchEvent *e) { return static_cast<QMutableTouchEvent *>(e); }
@@ -88,13 +52,12 @@ public:
Qt::KeyboardModifiers modifiers = Qt::NoModifier,
Qt::MouseEventSource source = Qt::MouseEventSynthesizedByQt) :
QSinglePointEvent(type, device, point, button, buttons, modifiers, source) { }
+ ~QMutableSinglePointEvent() override;
static QMutableSinglePointEvent *from(QSinglePointEvent *e) { return static_cast<QMutableSinglePointEvent *>(e); }
static QMutableSinglePointEvent &from(QSinglePointEvent &e) { return static_cast<QMutableSinglePointEvent &>(e); }
- QMutableEventPoint &mutablePoint() { return QMutableEventPoint::from(point(0)); }
-
void setSource(Qt::MouseEventSource s) { m_source = s; }
bool isDoubleClick() { return m_doubleClick; }
diff --git a/src/gui/kernel/qeventpoint.cpp b/src/gui/kernel/qeventpoint.cpp
index 0c8428286a..66d4f44ea0 100644
--- a/src/gui/kernel/qeventpoint.cpp
+++ b/src/gui/kernel/qeventpoint.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qeventpoint.h"
#include "private/qeventpoint_p.h"
@@ -142,8 +106,7 @@ bool QEventPoint::operator==(const QEventPoint &other) const noexcept
QEventPoint::~QEventPoint() = default;
/*! \fn QPointF QEventPoint::pos() const
- \deprecated
- Deprecated since Qt 6.0. Use position() instead.
+ \deprecated [6.0] Use position() instead.
Returns the position of this point, relative to the widget
or item that received the event.
@@ -376,7 +339,7 @@ ulong QEventPoint::pressTimestamp() const
/*!
\property QEventPoint::timeHeld
- \brief the duration, in milliseconds, since this point was pressed and not released.
+ \brief the duration, in seconds, since this point was pressed and not released.
\sa pressTimestamp, timestamp
*/
@@ -443,10 +406,8 @@ bool QEventPoint::isAccepted() const
/*!
- \deprecated
\fn QPointF QEventPoint::normalizedPos() const
-
- Deprecated since Qt 6.0. Use normalizedPosition() instead.
+ \deprecated [6.0] Use normalizedPosition() instead.
*/
/*!
@@ -469,9 +430,9 @@ QPointF QEventPoint::normalizedPosition() const
return (globalPosition() - geom.topLeft()) / geom.width();
}
+#if QT_DEPRECATED_SINCE(6, 0)
/*!
- \deprecated
- Deprecated since Qt 6.0. Use globalPressPosition() instead.
+ \deprecated [6.0] Use globalPressPosition() instead.
Returns the normalized press position of this point.
*/
@@ -487,8 +448,7 @@ QPointF QEventPoint::startNormalizedPos() const
}
/*!
- \deprecated
- Deprecated since Qt 6.0. Use globalLastPosition() instead.
+ \deprecated [6.0] Use globalLastPosition() instead.
Returns the normalized position of this point from the previous press or
move event.
@@ -496,7 +456,7 @@ QPointF QEventPoint::startNormalizedPos() const
The coordinates are normalized to QInputDevice::availableVirtualGeometry(),
i.e. \c (0, 0) is the top-left corner and \c (1, 1) is the bottom-right corner.
- \sa normalizedPos(), startNormalizedPos()
+ \sa normalizedPosition(), globalPressPosition()
*/
QPointF QEventPoint::lastNormalizedPos() const
{
@@ -508,7 +468,7 @@ QPointF QEventPoint::lastNormalizedPos() const
return QPointF();
return (globalLastPosition() - geom.topLeft()) / geom.width();
}
-
+#endif // QT_DEPRECATED_SINCE(6, 0)
/*! \internal
This class is explicitly shared, which means if you construct an event and
@@ -520,17 +480,17 @@ QPointF QEventPoint::lastNormalizedPos() const
modify an independent copy. (The independent copy can then be used in a
subsequent event.)
*/
-void QMutableEventPoint::detach()
+void QMutableEventPoint::detach(QEventPoint &p)
{
- if (d)
- d.detach();
+ if (p.d)
+ p.d.detach();
else
- d.reset(new QEventPointPrivate(-1, nullptr));
+ p.d.reset(new QEventPointPrivate(-1, nullptr));
}
/*! \internal
- Update current state from the given \a other point, assuming that this
- instance contains state from the previous event and \a other contains new
+ Update \a target state from the \a other point, assuming that \a target
+ contains state from the previous event and \a other contains new
values that came in from a device.
That is: global position and other valuators will be updated, but
@@ -542,40 +502,41 @@ void QMutableEventPoint::detach()
\li properties that should be persistent between events (such as grabbers)
\endlist
*/
-void QMutableEventPoint::updateFrom(const QEventPoint &other)
+void QMutableEventPoint::update(const QEventPoint &other, QEventPoint &target)
{
- detach();
- setPressure(other.pressure());
+ detach(target);
+ setPressure(target, other.pressure());
switch (other.state()) {
case QEventPoint::State::Pressed:
- setGlobalPressPosition(other.globalPosition());
- setGlobalLastPosition(other.globalPosition());
- if (pressure() < 0)
- setPressure(1);
+ setGlobalPressPosition(target, other.globalPosition());
+ setGlobalLastPosition(target, other.globalPosition());
+ if (target.pressure() < 0)
+ setPressure(target, 1);
break;
case QEventPoint::State::Released:
- if (globalPosition() != other.globalPosition())
- setGlobalLastPosition(globalPosition());
- setPressure(0);
+ if (target.globalPosition() != other.globalPosition())
+ setGlobalLastPosition(target, target.globalPosition());
+ setPressure(target, 0);
break;
default: // update or stationary
- if (globalPosition() != other.globalPosition())
- setGlobalLastPosition(globalPosition());
- if (pressure() < 0)
- setPressure(1);
+ if (target.globalPosition() != other.globalPosition())
+ setGlobalLastPosition(target, target.globalPosition());
+ if (target.pressure() < 0)
+ setPressure(target, 1);
break;
}
- setState(other.state());
- setPosition(other.position());
- setScenePosition(other.scenePosition());
- setGlobalPosition(other.globalPosition());
- setEllipseDiameters(other.ellipseDiameters());
- setRotation(other.rotation());
- setVelocity(other.velocity());
+ setState(target, other.state());
+ setPosition(target, other.position());
+ setScenePosition(target, other.scenePosition());
+ setGlobalPosition(target, other.globalPosition());
+ setEllipseDiameters(target, other.ellipseDiameters());
+ setRotation(target, other.rotation());
+ setVelocity(target, other.velocity());
+ setUniqueId(target, other.uniqueId()); // for TUIO
}
/*! \internal
@@ -596,33 +557,33 @@ void QMutableEventPoint::updateFrom(const QEventPoint &other)
The velocity calculation is skipped if the platform has promised to
provide velocities already by setting the QInputDevice::Velocity capability.
*/
-void QMutableEventPoint::setTimestamp(const ulong t)
+void QMutableEventPoint::setTimestamp(QEventPoint &p, ulong t)
{
// On mouse press, if the mouse has moved from its last-known location,
// QGuiApplicationPrivate::processMouseEvent() sends first a mouse move and
// then a press. Both events will get the same timestamp. So we need to set
// the press timestamp and position even when the timestamp isn't advancing,
// but skip setting lastTimestamp and velocity because those need a time delta.
- if (d) {
- if (state() == QEventPoint::State::Pressed) {
- d->pressTimestamp = t;
- d->globalPressPos = d->globalPos;
+ if (p.d) {
+ if (p.state() == QEventPoint::State::Pressed) {
+ p.d->pressTimestamp = t;
+ p.d->globalPressPos = p.d->globalPos;
}
- if (d->timestamp == t)
+ if (p.d->timestamp == t)
return;
}
- detach();
- if (device()) {
+ detach(p);
+ if (p.device()) {
// get the persistent instance out of QPointingDevicePrivate::activePoints
// (which sometimes might be the same as this instance)
QEventPointPrivate *pd = QPointingDevicePrivate::get(
- const_cast<QPointingDevice *>(d->device))->pointById(id())->eventPoint.d.get();
+ const_cast<QPointingDevice *>(p.d->device))->pointById(p.id())->eventPoint.d.get();
if (t > pd->timestamp) {
pd->lastTimestamp = pd->timestamp;
pd->timestamp = t;
- if (state() == QEventPoint::State::Pressed)
+ if (p.state() == QEventPoint::State::Pressed)
pd->pressTimestamp = t;
- if (pd->lastTimestamp > 0 && !device()->capabilities().testFlag(QInputDevice::Capability::Velocity)) {
+ if (pd->lastTimestamp > 0 && !p.device()->capabilities().testFlag(QInputDevice::Capability::Velocity)) {
// calculate instantaneous velocity according to time and distance moved since the previous point
QVector2D newVelocity = QVector2D(pd->globalPos - pd->globalLastPos) / (t - pd->lastTimestamp) * 1000;
// VERY simple kalman filter: does a weighted average
@@ -633,17 +594,17 @@ void QMutableEventPoint::setTimestamp(const ulong t)
"based on movement" << pd->globalLastPos << "->" << pd->globalPos <<
"over time" << pd->lastTimestamp << "->" << pd->timestamp;
}
- if (d != pd) {
- d->lastTimestamp = pd->lastTimestamp;
- d->velocity = pd->velocity;
+ if (p.d != pd) {
+ p.d->lastTimestamp = pd->lastTimestamp;
+ p.d->velocity = pd->velocity;
}
}
}
- d->timestamp = t;
+ p.d->timestamp = t;
}
/*!
- \fn void QMutableEventPoint::setPosition(const QPointF &pos)
+ \fn void QMutableEventPoint::setPosition(QPointF pos)
\internal
Sets the localized position.
@@ -654,3 +615,5 @@ void QMutableEventPoint::setTimestamp(const ulong t)
*/
QT_END_NAMESPACE
+
+#include "moc_qeventpoint.cpp"
diff --git a/src/gui/kernel/qeventpoint.h b/src/gui/kernel/qeventpoint.h
index 52b5c26039..518faecee2 100644
--- a/src/gui/kernel/qeventpoint.h
+++ b/src/gui/kernel/qeventpoint.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEVENTPOINT_H
#define QEVENTPOINT_H
@@ -50,12 +14,12 @@ QT_BEGIN_NAMESPACE
class QEventPointPrivate;
QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QEventPointPrivate, Q_GUI_EXPORT)
+class QMutableEventPoint;
class Q_GUI_EXPORT QEventPoint
{
Q_GADGET
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
- QDOC_PROPERTY(QPointingDevice *device READ device CONSTANT) // qdoc doesn't know const
Q_PROPERTY(const QPointingDevice *device READ device CONSTANT)
Q_PROPERTY(int id READ id CONSTANT)
Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId CONSTANT)
@@ -101,7 +65,7 @@ public:
bool operator!=(const QEventPoint &other) const noexcept { return !operator==(other); }
~QEventPoint();
inline void swap(QEventPoint &other) noexcept
- { qSwap(d, other.d); }
+ { d.swap(other.d); }
QPointF position() const;
QPointF pressPosition() const;
diff --git a/src/gui/kernel/qeventpoint_p.h b/src/gui/kernel/qeventpoint_p.h
index f10739343f..c339c7e3e1 100644
--- a/src/gui/kernel/qeventpoint_p.h
+++ b/src/gui/kernel/qeventpoint_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEVENTPOINT_P_H
#define QEVENTPOINT_P_H
@@ -53,7 +17,9 @@
#include <QtGui/private/qtguiglobal_p.h>
#include <QtGui/qevent.h>
+
#include <QtCore/qloggingcategory.h>
+#include <QtCore/qpointer.h>
QT_BEGIN_NAMESPACE
@@ -118,84 +84,58 @@ public:
// Private subclasses to allow accessing and modifying protected variables.
// These should NOT hold any extra state.
-class Q_GUI_EXPORT QMutableEventPoint : public QEventPoint
+class QMutableEventPoint
{
public:
- QMutableEventPoint(int pointId = -1, State state = QEventPoint::State::Stationary,
- const QPointF &scenePosition = QPointF(), const QPointF &globalPosition = QPointF()) :
- QEventPoint(pointId, state, scenePosition, globalPosition) {}
-
- QMutableEventPoint(ulong timestamp, int pointId, State state,
- const QPointF &position, const QPointF &scenePosition, const QPointF &globalPosition) :
- QEventPoint(pointId, state, scenePosition, globalPosition)
+ static QEventPoint withTimeStamp(ulong timestamp, int pointId, QEventPoint::State state,
+ QPointF position, QPointF scenePosition, QPointF globalPosition)
{
- d->timestamp = timestamp;
- d->pos = position;
+ QEventPoint p(pointId, state, scenePosition, globalPosition);
+ p.d->timestamp = timestamp;
+ p.d->pos = position;
+ return p;
}
- void updateFrom(const QEventPoint &other);
-
- static QMutableEventPoint *from(QEventPoint *me) { return static_cast<QMutableEventPoint *>(me); }
-
- static QMutableEventPoint &from(QEventPoint &me) { return static_cast<QMutableEventPoint &>(me); }
-
- static const QMutableEventPoint &constFrom(const QEventPoint &me) { return static_cast<const QMutableEventPoint &>(me); }
-
- void detach();
-
- void setId(int pointId) { d->pointId = pointId; }
-
- void setDevice(const QPointingDevice *device) { d->device = device; }
-
- void setTimestamp(const ulong t);
+ static Q_GUI_EXPORT void update(const QEventPoint &from, QEventPoint &to);
- void setPressTimestamp(const ulong t) { d->pressTimestamp = t; }
+ static Q_GUI_EXPORT void detach(QEventPoint &p);
- void setState(QEventPoint::State state) { d->state = state; }
+#define TRIVIAL_SETTER(type, field, Field) \
+ static void set##Field (QEventPoint &p, type arg) { p.d->field = std::move(arg); } \
+ /* end */
- void setUniqueId(const QPointingDeviceUniqueId &uid) { d->uniqueId = uid; }
+ TRIVIAL_SETTER(int, pointId, Id)
+ TRIVIAL_SETTER(const QPointingDevice *, device, Device)
- void setPosition(const QPointF &pos) { d->pos = pos; }
+ // not trivial:
+ static Q_GUI_EXPORT void setTimestamp(QEventPoint &p, ulong t);
- void setScenePosition(const QPointF &pos) { d->scenePos = pos; }
+ TRIVIAL_SETTER(ulong, pressTimestamp, PressTimestamp)
+ TRIVIAL_SETTER(QEventPoint::State, state, State)
+ TRIVIAL_SETTER(QPointingDeviceUniqueId, uniqueId, UniqueId)
+ TRIVIAL_SETTER(QPointF, pos, Position)
+ TRIVIAL_SETTER(QPointF, scenePos, ScenePosition)
+ TRIVIAL_SETTER(QPointF, globalPos, GlobalPosition)
- void setGlobalPosition(const QPointF &pos) { d->globalPos = pos; }
+ TRIVIAL_SETTER(QPointF, globalPressPos, GlobalPressPosition)
+ TRIVIAL_SETTER(QPointF, globalGrabPos, GlobalGrabPosition)
+ TRIVIAL_SETTER(QPointF, globalLastPos, GlobalLastPosition)
+ TRIVIAL_SETTER(QSizeF, ellipseDiameters, EllipseDiameters)
+ TRIVIAL_SETTER(qreal, pressure, Pressure)
+ TRIVIAL_SETTER(qreal, rotation, Rotation)
+ TRIVIAL_SETTER(QVector2D, velocity, Velocity)
-#if QT_DEPRECATED_SINCE(6, 0)
- // temporary replacements for QTouchEvent::TouchPoint setters, mainly to make porting easier
- QT_DEPRECATED_VERSION_X_6_0("Use setPosition()")
- void setPos(const QPointF &pos) { d->pos = pos; }
- QT_DEPRECATED_VERSION_X_6_0("Use setScenePosition()")
- void setScenePos(const QPointF &pos) { d->scenePos = pos; }
- QT_DEPRECATED_VERSION_X_6_0("Use setGlobalPosition()")
- void setScreenPos(const QPointF &pos) { d->globalPos = pos; }
-#endif
+ static QWindow *window(const QEventPoint &p) { return p.d->window.data(); }
- void setGlobalPressPosition(const QPointF &pos) { d->globalPressPos = pos; }
+ TRIVIAL_SETTER(QWindow *, window, Window)
- void setGlobalGrabPosition(const QPointF &pos) { d->globalGrabPos = pos; }
+ static QObject *target(const QEventPoint &p) { return p.d->target.data(); }
- void setGlobalLastPosition(const QPointF &pos) { d->globalLastPos = pos; }
+ TRIVIAL_SETTER(QObject *, target, Target)
- void setEllipseDiameters(const QSizeF &diams) { d->ellipseDiameters = diams; }
-
- void setPressure(qreal v) { d->pressure = v; }
-
- void setRotation(qreal v) { d->rotation = v; }
-
- void setVelocity(const QVector2D &v) { d->velocity = v; }
-
- QWindow *window() const { return d->window.data(); }
-
- void setWindow(const QPointer<QWindow> &w) { d->window = w; }
-
- QObject *target() const { return d->target.data(); }
-
- void setTarget(const QPointer<QObject> &t) { d->target = t; }
+#undef TRIVIAL_SETTER
};
-static_assert(sizeof(QMutableEventPoint) == sizeof(QEventPoint));
-
QT_END_NAMESPACE
#endif // QEVENTPOINT_P_H
diff --git a/src/gui/kernel/qgenericplugin.cpp b/src/gui/kernel/qgenericplugin.cpp
index a53b60b008..8411faeb1f 100644
--- a/src/gui/kernel/qgenericplugin.cpp
+++ b/src/gui/kernel/qgenericplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgenericplugin.h"
@@ -94,3 +58,5 @@ QGenericPlugin::~QGenericPlugin()
*/
QT_END_NAMESPACE
+
+#include "moc_qgenericplugin.cpp"
diff --git a/src/gui/kernel/qgenericplugin.h b/src/gui/kernel/qgenericplugin.h
index 69b4f29854..f76228dc8a 100644
--- a/src/gui/kernel/qgenericplugin.h
+++ b/src/gui/kernel/qgenericplugin.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGENERICPLUGIN_H
#define QGENERICPLUGIN_H
diff --git a/src/gui/kernel/qgenericpluginfactory.cpp b/src/gui/kernel/qgenericpluginfactory.cpp
index 9f41b948c0..5ce13ad5e1 100644
--- a/src/gui/kernel/qgenericpluginfactory.cpp
+++ b/src/gui/kernel/qgenericpluginfactory.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgenericpluginfactory.h"
@@ -46,9 +10,10 @@
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QGenericPluginFactoryInterface_iid,
- QLatin1String("/generic"), Qt::CaseInsensitive))
+using namespace Qt::StringLiterals;
+
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, gpLoader,
+ (QGenericPluginFactoryInterface_iid, "/generic"_L1, Qt::CaseInsensitive))
/*!
\class QGenericPluginFactory
@@ -69,7 +34,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
*/
QObject *QGenericPluginFactory::create(const QString& key, const QString &specification)
{
- return qLoadPlugin<QObject, QGenericPlugin>(loader(), key.toLower(), specification);
+ return qLoadPlugin<QObject, QGenericPlugin>(gpLoader(), key.toLower(), specification);
}
/*!
@@ -84,7 +49,7 @@ QStringList QGenericPluginFactory::keys()
typedef QMultiMap<int, QString> PluginKeyMap;
typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator;
- const PluginKeyMap keyMap = loader()->keyMap();
+ const PluginKeyMap keyMap = gpLoader()->keyMap();
const PluginKeyMapConstIterator cend = keyMap.constEnd();
for (PluginKeyMapConstIterator it = keyMap.constBegin(); it != cend; ++it)
if (!list.contains(it.value()))
diff --git a/src/gui/kernel/qgenericpluginfactory.h b/src/gui/kernel/qgenericpluginfactory.h
index 9cc77a0590..710c983310 100644
--- a/src/gui/kernel/qgenericpluginfactory.h
+++ b/src/gui/kernel/qgenericpluginfactory.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGENERICPLUGINFACTORY_H
#define QGENERICPLUGINFACTORY_H
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index c93e483438..444091afef 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qguiapplication.h"
@@ -44,6 +8,8 @@
#include "private/qabstractfileiconprovider_p.h"
#include <qpa/qplatformintegrationfactory_p.h>
#include "private/qevent_p.h"
+#include "private/qeventpoint_p.h"
+#include "private/qiconloader_p.h"
#include "qfont.h"
#include "qpointingdevice.h"
#include <qpa/qplatformfontdatabase.h>
@@ -51,21 +17,24 @@
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatformtheme.h>
#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformkeymapper.h>
#include <QtCore/QAbstractEventDispatcher>
+#include <QtCore/QFileInfo>
#include <QtCore/QStandardPaths>
#include <QtCore/QVariant>
#include <QtCore/private/qcoreapplication_p.h>
#include <QtCore/private/qabstracteventdispatcher_p.h>
+#include <QtCore/private/qminimalflatset_p.h>
#include <QtCore/qmutex.h>
#include <QtCore/private/qthread_p.h>
#include <QtCore/private/qlocking_p.h>
#include <QtCore/private/qflatmap_p.h>
#include <QtCore/qdir.h>
#include <QtCore/qlibraryinfo.h>
-#include <QtCore/qnumeric.h>
+#include <QtCore/private/qnumeric_p.h>
#include <QtDebug>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include "qaccessible.h"
#endif
#include <qpalette.h>
@@ -76,6 +45,7 @@
#include <QtGui/qgenericpluginfactory.h>
#include <QtGui/qstylehints.h>
+#include <QtGui/private/qstylehints_p.h>
#include <QtGui/qinputmethod.h>
#include <QtGui/qpixmapcache.h>
#include <qpa/qplatforminputcontext.h>
@@ -84,8 +54,11 @@
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qwindowsysteminterface_p.h>
#include "private/qwindow_p.h"
+#include "private/qicon_p.h"
#include "private/qcursor_p.h"
-#include "private/qopenglcontext_p.h"
+#if QT_CONFIG(opengl)
+# include "private/qopenglcontext_p.h"
+#endif
#include "private/qinputdevicemanager_p.h"
#include "private/qinputmethod_p.h"
#include "private/qpointingdevice_p.h"
@@ -122,12 +95,21 @@
#include <emscripten.h>
#endif
+#if QT_CONFIG(vulkan)
+#include <private/qvulkandefaultinstance_p.h>
+#endif
+
#include <qtgui_tracepoints_p.h>
-#include <ctype.h>
+#include <private/qtools_p.h>
+
+#include <limits>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+using namespace QtMiscUtils;
+
// Helper macro for static functions to check on the existence of the application class.
#define CHECK_QAPP_INSTANCE(...) \
if (Q_LIKELY(QCoreApplication::instance())) { \
@@ -137,78 +119,81 @@ QT_BEGIN_NAMESPACE
}
Q_CORE_EXPORT void qt_call_post_routines();
-Q_GUI_EXPORT bool qt_is_gui_used = true;
+Q_CONSTINIT Q_GUI_EXPORT bool qt_is_tty_app = false;
-Qt::MouseButtons QGuiApplicationPrivate::mouse_buttons = Qt::NoButton;
-Qt::KeyboardModifiers QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
+Q_CONSTINIT Qt::MouseButtons QGuiApplicationPrivate::mouse_buttons = Qt::NoButton;
+Q_CONSTINIT Qt::KeyboardModifiers QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
-QPointF QGuiApplicationPrivate::lastCursorPosition(qInf(), qInf());
+Q_CONSTINIT QGuiApplicationPrivate::QLastCursorPosition QGuiApplicationPrivate::lastCursorPosition;
-QWindow *QGuiApplicationPrivate::currentMouseWindow = nullptr;
+Q_CONSTINIT QWindow *QGuiApplicationPrivate::currentMouseWindow = nullptr;
-QString QGuiApplicationPrivate::styleOverride;
+Q_CONSTINIT QString QGuiApplicationPrivate::styleOverride;
-Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
+Q_CONSTINIT Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
-Qt::HighDpiScaleFactorRoundingPolicy QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy =
+Q_CONSTINIT Qt::HighDpiScaleFactorRoundingPolicy QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy =
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough;
-QPointer<QWindow> QGuiApplicationPrivate::currentDragWindow;
+Q_CONSTINIT QPointer<QWindow> QGuiApplicationPrivate::currentDragWindow;
-QList<QGuiApplicationPrivate::TabletPointData> QGuiApplicationPrivate::tabletDevicePoints; // TODO remove
+Q_CONSTINIT QList<QGuiApplicationPrivate::TabletPointData> QGuiApplicationPrivate::tabletDevicePoints; // TODO remove
-QPlatformIntegration *QGuiApplicationPrivate::platform_integration = nullptr;
-QPlatformTheme *QGuiApplicationPrivate::platform_theme = nullptr;
+Q_CONSTINIT QPlatformIntegration *QGuiApplicationPrivate::platform_integration = nullptr;
+Q_CONSTINIT QPlatformTheme *QGuiApplicationPrivate::platform_theme = nullptr;
-QList<QObject *> QGuiApplicationPrivate::generic_plugin_list;
+Q_CONSTINIT QList<QObject *> QGuiApplicationPrivate::generic_plugin_list;
enum ApplicationResourceFlags
{
ApplicationFontExplicitlySet = 0x2
};
-static unsigned applicationResourceFlags = 0;
+Q_CONSTINIT static unsigned applicationResourceFlags = 0;
-QIcon *QGuiApplicationPrivate::app_icon = nullptr;
+Q_CONSTINIT QIcon *QGuiApplicationPrivate::app_icon = nullptr;
-QString *QGuiApplicationPrivate::platform_name = nullptr;
-QString *QGuiApplicationPrivate::displayName = nullptr;
-QString *QGuiApplicationPrivate::desktopFileName = nullptr;
+Q_CONSTINIT QString *QGuiApplicationPrivate::platform_name = nullptr;
+Q_CONSTINIT QString *QGuiApplicationPrivate::displayName = nullptr;
+Q_CONSTINIT QString *QGuiApplicationPrivate::desktopFileName = nullptr;
-QPalette *QGuiApplicationPrivate::app_pal = nullptr; // default application palette
+Q_CONSTINIT QPalette *QGuiApplicationPrivate::app_pal = nullptr; // default application palette
-Qt::MouseButton QGuiApplicationPrivate::mousePressButton = Qt::NoButton;
+Q_CONSTINIT Qt::MouseButton QGuiApplicationPrivate::mousePressButton = Qt::NoButton;
-static int mouseDoubleClickDistance = -1;
-static int touchDoubleTapDistance = -1;
+Q_CONSTINIT static int mouseDoubleClickDistance = 0;
+Q_CONSTINIT static int touchDoubleTapDistance = 0;
-QWindow *QGuiApplicationPrivate::currentMousePressWindow = nullptr;
+Q_CONSTINIT QWindow *QGuiApplicationPrivate::currentMousePressWindow = nullptr;
-static Qt::LayoutDirection layout_direction = Qt::LayoutDirectionAuto;
-static bool force_reverse = false;
+Q_CONSTINIT static Qt::LayoutDirection layout_direction = Qt::LayoutDirectionAuto;
+Q_CONSTINIT static Qt::LayoutDirection effective_layout_direction = Qt::LeftToRight;
+Q_CONSTINIT static bool force_reverse = false;
-QGuiApplicationPrivate *QGuiApplicationPrivate::self = nullptr;
-int QGuiApplicationPrivate::m_fakeMouseSourcePointId = -1;
+Q_CONSTINIT QGuiApplicationPrivate *QGuiApplicationPrivate::self = nullptr;
+Q_CONSTINIT int QGuiApplicationPrivate::m_fakeMouseSourcePointId = -1;
#ifndef QT_NO_CLIPBOARD
-QClipboard *QGuiApplicationPrivate::qt_clipboard = nullptr;
+Q_CONSTINIT QClipboard *QGuiApplicationPrivate::qt_clipboard = nullptr;
#endif
-QList<QScreen *> QGuiApplicationPrivate::screen_list;
+Q_CONSTINIT QList<QScreen *> QGuiApplicationPrivate::screen_list;
+
+Q_CONSTINIT QWindowList QGuiApplicationPrivate::window_list;
+Q_CONSTINIT QWindow *QGuiApplicationPrivate::focus_window = nullptr;
-QWindowList QGuiApplicationPrivate::window_list;
-QWindow *QGuiApplicationPrivate::focus_window = nullptr;
+Q_CONSTINIT static QBasicMutex applicationFontMutex;
+Q_CONSTINIT QFont *QGuiApplicationPrivate::app_font = nullptr;
+Q_CONSTINIT QStyleHints *QGuiApplicationPrivate::styleHints = nullptr;
+Q_CONSTINIT bool QGuiApplicationPrivate::obey_desktop_settings = true;
-static QBasicMutex applicationFontMutex;
-QFont *QGuiApplicationPrivate::app_font = nullptr;
-QStyleHints *QGuiApplicationPrivate::styleHints = nullptr;
-bool QGuiApplicationPrivate::obey_desktop_settings = true;
+Q_CONSTINIT QInputDeviceManager *QGuiApplicationPrivate::m_inputDeviceManager = nullptr;
-QInputDeviceManager *QGuiApplicationPrivate::m_inputDeviceManager = nullptr;
+Q_CONSTINIT qreal QGuiApplicationPrivate::m_maxDevicePixelRatio = 0.0;
-qreal QGuiApplicationPrivate::m_maxDevicePixelRatio = 0.0;
+Q_CONSTINIT static qreal fontSmoothingGamma = 1.7;
-static qreal fontSmoothingGamma = 1.7;
+Q_CONSTINIT bool QGuiApplicationPrivate::quitOnLastWindowClosed = true;
extern void qRegisterGuiVariant();
#if QT_CONFIG(animation)
@@ -221,7 +206,7 @@ static bool qt_detectRTLLanguage()
(QGuiApplication::tr("QT_LAYOUT_DIRECTION",
"Translate this string to the string 'LTR' in left-to-right"
" languages or to 'RTL' in right-to-left languages (such as Hebrew"
- " and Arabic) to get proper widget layout.") == QLatin1String("RTL"));
+ " and Arabic) to get proper widget layout.") == "RTL"_L1);
}
static void initFontUnlocked()
@@ -251,7 +236,7 @@ static void initThemeHints()
static bool checkNeedPortalSupport()
{
#if QT_CONFIG(dbus)
- return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty() || qEnvironmentVariableIsSet("SNAP");
+ return QFileInfo::exists("/.flatpak-info"_L1) || qEnvironmentVariableIsSet("SNAP");
#else
return false;
#endif // QT_CONFIG(dbus)
@@ -278,20 +263,20 @@ struct QWindowGeometrySpecification
static inline int nextGeometryToken(const QByteArray &a, int &pos, char *op)
{
*op = 0;
- const int size = a.size();
+ const qsizetype size = a.size();
if (pos >= size)
return -1;
*op = a.at(pos);
if (*op == '+' || *op == '-' || *op == 'x')
pos++;
- else if (isdigit(*op))
+ else if (isAsciiDigit(*op))
*op = 'x'; // If it starts with a digit, it is supposed to be a width specification.
else
return -1;
const int numberPos = pos;
- for ( ; pos < size && isdigit(a.at(pos)); ++pos) ;
+ for ( ; pos < size && isAsciiDigit(a.at(pos)); ++pos) ;
bool ok;
const int result = a.mid(numberPos, pos - numberPos).toInt(&ok);
@@ -579,10 +564,12 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME
\list
\li \c {altgr}, detect the key \c {AltGr} found on some keyboards as
Qt::GroupSwitchModifier (since Qt 5.12).
- \li \c {darkmode=[1|2]} controls how Qt responds to the activation
+ \li \c {darkmode=[0|1|2]} controls how Qt responds to the activation
of the \e{Dark Mode for applications} introduced in Windows 10
1903 (since Qt 5.15).
+ A value of 0 disables dark mode support.
+
A value of 1 causes Qt to switch the window borders to black
when \e{Dark Mode for applications} is activated and no High
Contrast Theme is in use. This is intended for applications
@@ -594,17 +581,17 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME
experimental pending the introduction of new style that
properly adapts to dark mode.
+ As of Qt 6.5, the default value is 2; to disable dark mode
+ support, set the value to 0 or 1.
+
\li \c {dialogs=[xp|none]}, \c xp uses XP-style native dialogs and
\c none disables them.
\li \c {fontengine=freetype}, uses the FreeType font engine.
- \li \c {fontengine=directwrite}, uses the experimental DirectWrite
- font database and defaults to using the DirectWrite font
+ \li \c {fontengine=gdi}, uses the legacy GDI-based
+ font database and defaults to using the GDI font
engine (which is otherwise only used for some font types
- or font properties.) This affects font selection and aims
- to provide font naming more consistent with other platforms,
- but does not support all font formats, such as Postscript
- Type-1 or Microsoft FNT fonts.
+ or font properties.) (Since Qt 6.8).
\li \c {menus=[native|none]}, controls the use of native menus.
Native menus are implemented using Win32 API and are simpler than
@@ -618,7 +605,8 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME
\li \c {nocolorfonts} Turn off DirectWrite Color fonts
(since Qt 5.8).
- \li \c {nodirectwrite} Turn off DirectWrite fonts (since Qt 5.8).
+ \li \c {nodirectwrite} Turn off DirectWrite fonts (since Qt 5.8). This implicitly
+ also selects the GDI font engine.
\li \c {nomousefromtouch} Ignores mouse events synthesized
from touch events by the operating system.
@@ -646,9 +634,9 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME
#ifdef Q_QDOC
QGuiApplication::QGuiApplication(int &argc, char **argv)
#else
-QGuiApplication::QGuiApplication(int &argc, char **argv, int flags)
+QGuiApplication::QGuiApplication(int &argc, char **argv, int)
#endif
- : QCoreApplication(*new QGuiApplicationPrivate(argc, argv, flags))
+ : QCoreApplication(*new QGuiApplicationPrivate(argc, argv))
{
d_func()->init();
@@ -704,15 +692,16 @@ QGuiApplication::~QGuiApplication()
QGuiApplicationPrivate::desktopFileName = nullptr;
QGuiApplicationPrivate::mouse_buttons = Qt::NoButton;
QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
- QGuiApplicationPrivate::lastCursorPosition = {qreal(qInf()), qreal(qInf())};
+ QGuiApplicationPrivate::lastCursorPosition.reset();
QGuiApplicationPrivate::currentMousePressWindow = QGuiApplicationPrivate::currentMouseWindow = nullptr;
QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
+ QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy = Qt::HighDpiScaleFactorRoundingPolicy::PassThrough;
QGuiApplicationPrivate::currentDragWindow = nullptr;
QGuiApplicationPrivate::tabletDevicePoints.clear();
}
-QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv, int flags)
- : QCoreApplicationPrivate(argc, argv, flags),
+QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv)
+ : QCoreApplicationPrivate(argc, argv),
inputMethod(nullptr),
lastTouchType(QEvent::TouchEnd),
ownGlobalShareContext(false)
@@ -761,13 +750,37 @@ QString QGuiApplication::applicationDisplayName()
}
/*!
+ Sets the application's badge to \a number.
+
+ Useful for providing feedback to the user about the number
+ of unread messages or similar.
+
+ The badge will be overlaid on the application's icon in the Dock
+ on \macos, the home screen icon on iOS, or the task bar on Windows
+ and Linux.
+
+ If the number is outside the range supported by the platform, the
+ number will be clamped to the supported range. If the number does
+ not fit within the badge, the number may be visually elided.
+
+ Setting the number to 0 will clear the badge.
+
+ \since 6.5
+ \sa applicationName
+*/
+void QGuiApplication::setBadgeNumber(qint64 number)
+{
+ QGuiApplicationPrivate::platformIntegration()->setApplicationBadge(number);
+}
+
+/*!
\property QGuiApplication::desktopFileName
\brief the base name of the desktop entry for this application
\since 5.7
- This is the file name, without the full path, of the desktop entry
- that represents this application according to the freedesktop desktop
- entry specification.
+ This is the file name, without the full path or the trailing ".desktop"
+ extension of the desktop entry that represents this application
+ according to the freedesktop desktop entry specification.
This property gives a precise indication of what desktop entry represents
the application and it is needed by the windowing system to retrieve
@@ -781,6 +794,15 @@ void QGuiApplication::setDesktopFileName(const QString &name)
if (!QGuiApplicationPrivate::desktopFileName)
QGuiApplicationPrivate::desktopFileName = new QString;
*QGuiApplicationPrivate::desktopFileName = name;
+ if (name.endsWith(QLatin1String(".desktop"))) { // ### Qt 7: remove
+ const QString filePath = QStandardPaths::locate(QStandardPaths::ApplicationsLocation, name);
+ if (!filePath.isEmpty()) {
+ qWarning("QGuiApplication::setDesktopFileName: the specified desktop file name "
+ "ends with .desktop. For compatibility reasons, the .desktop suffix will "
+ "be removed. Please specify a desktop file name without .desktop suffix");
+ (*QGuiApplicationPrivate::desktopFileName).chop(8);
+ }
+ }
}
QString QGuiApplication::desktopFileName()
@@ -807,7 +829,7 @@ QWindow *QGuiApplication::modalWindow()
CHECK_QAPP_INSTANCE(nullptr)
if (QGuiApplicationPrivate::self->modalWindowList.isEmpty())
return nullptr;
- return QGuiApplicationPrivate::self->modalWindowList.first();
+ return QGuiApplicationPrivate::self->modalWindowList.constFirst();
}
static void updateBlockedStatusRecursion(QWindow *window, bool shouldBeBlocked)
@@ -858,7 +880,7 @@ void QGuiApplicationPrivate::showModalWindow(QWindow *modal)
}
}
- for (QWindow *window : qAsConst(QGuiApplicationPrivate::window_list)) {
+ for (QWindow *window : std::as_const(QGuiApplicationPrivate::window_list)) {
if (needsWindowBlockedEvent(window) && !window->d_func()->blockedByModalWindow)
updateBlockedStatus(window);
}
@@ -870,12 +892,23 @@ void QGuiApplicationPrivate::hideModalWindow(QWindow *window)
{
self->modalWindowList.removeAll(window);
- for (QWindow *window : qAsConst(QGuiApplicationPrivate::window_list)) {
+ for (QWindow *window : std::as_const(QGuiApplicationPrivate::window_list)) {
if (needsWindowBlockedEvent(window) && window->d_func()->blockedByModalWindow)
updateBlockedStatus(window);
}
}
+Qt::WindowModality QGuiApplicationPrivate::defaultModality() const
+{
+ return Qt::NonModal;
+}
+
+bool QGuiApplicationPrivate::windowNeverBlocked(QWindow *window) const
+{
+ Q_UNUSED(window);
+ return false;
+}
+
/*
Returns \c true if \a window is blocked by a modal window. If \a
blockingWindow is non-zero, *blockingWindow will be set to the blocking
@@ -883,55 +916,40 @@ void QGuiApplicationPrivate::hideModalWindow(QWindow *window)
*/
bool QGuiApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWindow) const
{
+ Q_ASSERT_X(window, Q_FUNC_INFO, "The window must not be null");
+
QWindow *unused = nullptr;
if (!blockingWindow)
blockingWindow = &unused;
+ *blockingWindow = nullptr;
- if (modalWindowList.isEmpty()) {
- *blockingWindow = nullptr;
+ if (modalWindowList.isEmpty() || windowNeverBlocked(window))
return false;
- }
- for (int i = 0; i < modalWindowList.count(); ++i) {
+ for (int i = 0; i < modalWindowList.size(); ++i) {
QWindow *modalWindow = modalWindowList.at(i);
// A window is not blocked by another modal window if the two are
// the same, or if the window is a child of the modal window.
- if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients)) {
- *blockingWindow = nullptr;
+ if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients))
return false;
- }
- Qt::WindowModality windowModality = modalWindow->modality();
- switch (windowModality) {
+ switch (modalWindow->modality() == Qt::NonModal ? defaultModality()
+ : modalWindow->modality()) {
case Qt::ApplicationModal:
- {
- if (modalWindow != window) {
- *blockingWindow = modalWindow;
- return true;
- }
- break;
- }
- case Qt::WindowModal:
- {
- QWindow *w = window;
+ *blockingWindow = modalWindow;
+ return true;
+ case Qt::WindowModal: {
+ // Find the nearest ancestor of window which is also an ancestor of modal window to
+ // determine if the modal window blocks the window.
+ auto *current = window;
do {
- QWindow *m = modalWindow;
- do {
- if (m == w) {
- *blockingWindow = m;
- return true;
- }
- QWindow *p = m->parent();
- if (!p)
- p = m->transientParent();
- m = p;
- } while (m);
- QWindow *p = w->parent();
- if (!p)
- p = w->transientParent();
- w = p;
- } while (w);
+ if (current->isAncestorOf(modalWindow, QWindow::IncludeTransients)) {
+ *blockingWindow = modalWindow;
+ return true;
+ }
+ current = current->parent(QWindow::IncludeTransients);
+ } while (current);
break;
}
default:
@@ -939,13 +957,14 @@ bool QGuiApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blocking
break;
}
}
- *blockingWindow = nullptr;
return false;
}
/*!
Returns the QWindow that receives events tied to focus,
such as key events.
+
+ \sa QWindow::requestActivate()
*/
QWindow *QGuiApplication::focusWindow()
{
@@ -1123,7 +1142,7 @@ qreal QGuiApplication::devicePixelRatio() const
return QGuiApplicationPrivate::m_maxDevicePixelRatio;
QGuiApplicationPrivate::m_maxDevicePixelRatio = 1.0; // make sure we never return 0.
- for (QScreen *screen : qAsConst(QGuiApplicationPrivate::screen_list))
+ for (QScreen *screen : std::as_const(QGuiApplicationPrivate::screen_list))
QGuiApplicationPrivate::m_maxDevicePixelRatio = qMax(QGuiApplicationPrivate::m_maxDevicePixelRatio, screen->devicePixelRatio());
return QGuiApplicationPrivate::m_maxDevicePixelRatio;
@@ -1170,32 +1189,50 @@ QWindow *QGuiApplication::topLevelAt(const QPoint &pos)
\li \c offscreen
\li \c qnx
\li \c windows
- \li \c wayland is a platform plugin for modern Linux desktops and some
- embedded systems.
- \li \c xcb is the X11 plugin used on regular desktop Linux platforms.
+ \li \c wayland is a platform plugin for the Wayland display server protocol,
+ used on some Linux desktops and embedded systems.
+ \li \c xcb is a plugin for the X11 window system, used on some desktop Linux platforms.
\endlist
+ \note Calling this function without a QGuiApplication will return the default
+ platform name, if available. The default platform name is not affected by the
+ \c{-platform} command line option, or the \c QT_QPA_PLATFORM environment variable.
+
For more information about the platform plugins for embedded Linux devices,
see \l{Qt for Embedded Linux}.
*/
QString QGuiApplication::platformName()
{
- return QGuiApplicationPrivate::platform_name ?
- *QGuiApplicationPrivate::platform_name : QString();
+ if (!QGuiApplication::instance()) {
+#ifdef QT_QPA_DEFAULT_PLATFORM_NAME
+ return QStringLiteral(QT_QPA_DEFAULT_PLATFORM_NAME);
+#else
+ return QString();
+#endif
+ } else {
+ return QGuiApplicationPrivate::platform_name ?
+ *QGuiApplicationPrivate::platform_name : QString();
+ }
}
Q_LOGGING_CATEGORY(lcQpaPluginLoading, "qt.qpa.plugin");
+Q_LOGGING_CATEGORY(lcQpaTheme, "qt.qpa.theme");
Q_LOGGING_CATEGORY(lcPtrDispatch, "qt.pointer.dispatch");
static void init_platform(const QString &pluginNamesWithArguments, const QString &platformPluginPath, const QString &platformThemeName, int &argc, char **argv)
{
- QStringList plugins = pluginNamesWithArguments.split(QLatin1Char(';'), Qt::SkipEmptyParts);
+ qCDebug(lcQpaPluginLoading) << "init_platform called with"
+ << "pluginNamesWithArguments" << pluginNamesWithArguments
+ << "platformPluginPath" << platformPluginPath
+ << "platformThemeName" << platformThemeName;
+
+ QStringList plugins = pluginNamesWithArguments.split(u';', Qt::SkipEmptyParts);
QStringList platformArguments;
QStringList availablePlugins = QPlatformIntegrationFactory::keys(platformPluginPath);
for (const auto &pluginArgument : plugins) {
// Split into platform name and arguments
- QStringList arguments = pluginArgument.split(QLatin1Char(':'), Qt::SkipEmptyParts);
+ QStringList arguments = pluginArgument.split(u':', Qt::SkipEmptyParts);
if (arguments.isEmpty())
continue;
const QString name = arguments.takeFirst().toLower();
@@ -1205,10 +1242,16 @@ static void init_platform(const QString &pluginNamesWithArguments, const QString
argumentsKey[0] = argumentsKey.at(0).toUpper();
arguments.append(QLibraryInfo::platformPluginArguments(argumentsKey));
+ qCDebug(lcQpaPluginLoading) << "Attempting to load Qt platform plugin" << name << "with arguments" << arguments;
+
// Create the platform integration.
QGuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, arguments, argc, argv, platformPluginPath);
if (Q_UNLIKELY(!QGuiApplicationPrivate::platform_integration)) {
if (availablePlugins.contains(name)) {
+ if (name == QStringLiteral("xcb") && QVersionNumber::compare(QLibraryInfo::version(), QVersionNumber(6, 5, 0)) >= 0) {
+ qCWarning(lcQpaPluginLoading).nospace().noquote()
+ << "From 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platform plugin.";
+ }
qCInfo(lcQpaPluginLoading).nospace().noquote()
<< "Could not load the Qt platform plugin \"" << name << "\" in \""
<< QDir::toNativeSeparators(platformPluginPath) << "\" even though it was found.";
@@ -1218,6 +1261,7 @@ static void init_platform(const QString &pluginNamesWithArguments, const QString
<< QDir::toNativeSeparators(platformPluginPath) << "\"";
}
} else {
+ qCDebug(lcQpaPluginLoading) << "Successfully loaded Qt platform plugin" << name;
QGuiApplicationPrivate::platform_name = new QString(name);
platformArguments = arguments;
break;
@@ -1229,7 +1273,7 @@ static void init_platform(const QString &pluginNamesWithArguments, const QString
"Reinstalling the application may fix this problem.\n");
if (!availablePlugins.isEmpty())
- fatalMessage += QStringLiteral("\nAvailable platform plugins are: %1.\n").arg(availablePlugins.join(QLatin1String(", ")));
+ fatalMessage += "\nAvailable platform plugins are: %1.\n"_L1.arg(availablePlugins.join(", "_L1));
#if defined(Q_OS_WIN)
// Windows: Display message box unless it is a console application
@@ -1246,45 +1290,57 @@ static void init_platform(const QString &pluginNamesWithArguments, const QString
// 1) Fetch the platform name from the environment if present.
QStringList themeNames;
- if (!platformThemeName.isEmpty())
+ if (!platformThemeName.isEmpty()) {
+ qCDebug(lcQpaTheme) << "Adding" << platformThemeName << "from environment to list of theme names";
themeNames.append(platformThemeName);
+ }
// 2) Special case - check whether it's a flatpak or snap app to use xdg-desktop-portal platform theme for portals support
if (checkNeedPortalSupport()) {
+ qCDebug(lcQpaTheme) << "Adding xdgdesktopportal to list of theme names";
themeNames.append(QStringLiteral("xdgdesktopportal"));
}
// 3) Ask the platform integration for a list of theme names
- themeNames += QGuiApplicationPrivate::platform_integration->themeNames();
+ const auto platformIntegrationThemeNames = QGuiApplicationPrivate::platform_integration->themeNames();
+ qCDebug(lcQpaTheme) << "Adding platform integration's theme names to list of theme names:" << platformIntegrationThemeNames;
+ themeNames += platformIntegrationThemeNames;
// 4) Look for a theme plugin.
- for (const QString &themeName : qAsConst(themeNames)) {
+ for (const QString &themeName : std::as_const(themeNames)) {
+ qCDebug(lcQpaTheme) << "Attempting to create platform theme" << themeName << "via QPlatformThemeFactory::create";
QGuiApplicationPrivate::platform_theme = QPlatformThemeFactory::create(themeName, platformPluginPath);
- if (QGuiApplicationPrivate::platform_theme)
+ if (QGuiApplicationPrivate::platform_theme) {
+ qCDebug(lcQpaTheme) << "Successfully created platform theme" << themeName;
break;
+ }
}
// 5) If no theme plugin was found ask the platform integration to
// create a theme
if (!QGuiApplicationPrivate::platform_theme) {
- for (const QString &themeName : qAsConst(themeNames)) {
+ for (const QString &themeName : std::as_const(themeNames)) {
+ qCDebug(lcQpaTheme) << "Attempting to create platform theme" << themeName << "via createPlatformTheme";
QGuiApplicationPrivate::platform_theme = QGuiApplicationPrivate::platform_integration->createPlatformTheme(themeName);
- if (QGuiApplicationPrivate::platform_theme)
+ if (QGuiApplicationPrivate::platform_theme) {
+ qCDebug(lcQpaTheme) << "Successfully created platform theme" << themeName;
break;
+ }
}
// No error message; not having a theme plugin is allowed.
}
// 6) Fall back on the built-in "null" platform theme.
- if (!QGuiApplicationPrivate::platform_theme)
+ if (!QGuiApplicationPrivate::platform_theme) {
+ qCDebug(lcQpaTheme) << "Failed to create platform theme; using \"null\" platform theme";
QGuiApplicationPrivate::platform_theme = new QPlatformTheme;
+ }
-#ifndef QT_NO_PROPERTIES
// Set arguments as dynamic properties on the native interface as
// boolean 'foo' or strings: 'foo=bar'
if (!platformArguments.isEmpty()) {
if (QObject *nativeInterface = QGuiApplicationPrivate::platform_integration->nativeInterface()) {
- for (const QString &argument : qAsConst(platformArguments)) {
- const int equalsPos = argument.indexOf(QLatin1Char('='));
+ for (const QString &argument : std::as_const(platformArguments)) {
+ const qsizetype equalsPos = argument.indexOf(u'=');
const QByteArray name =
equalsPos != -1 ? argument.left(equalsPos).toUtf8() : argument.toUtf8();
const QVariant value =
@@ -1293,25 +1349,24 @@ static void init_platform(const QString &pluginNamesWithArguments, const QString
}
}
}
-#endif
const auto platformIntegration = QGuiApplicationPrivate::platformIntegration();
fontSmoothingGamma = platformIntegration->styleHint(QPlatformIntegration::FontSmoothingGamma).toReal();
QCoreApplication::setAttribute(Qt::AA_DontShowShortcutsInContextMenus,
- !platformIntegration->styleHint(QPlatformIntegration::ShowShortcutsInContextMenus).toBool());
+ !QGuiApplication::styleHints()->showShortcutsInContextMenus());
}
static void init_plugins(const QList<QByteArray> &pluginList)
{
- for (int i = 0; i < pluginList.count(); ++i) {
+ for (int i = 0; i < pluginList.size(); ++i) {
QByteArray pluginSpec = pluginList.at(i);
- int colonPos = pluginSpec.indexOf(':');
+ qsizetype colonPos = pluginSpec.indexOf(':');
QObject *plugin;
if (colonPos < 0)
- plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec), QString());
+ plugin = QGenericPluginFactory::create(QLatin1StringView(pluginSpec), QString());
else
- plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec.mid(0, colonPos)),
- QLatin1String(pluginSpec.mid(colonPos+1)));
+ plugin = QGenericPluginFactory::create(QLatin1StringView(pluginSpec.mid(0, colonPos)),
+ QLatin1StringView(pluginSpec.mid(colonPos+1)));
if (plugin)
QGuiApplicationPrivate::generic_plugin_list.append(plugin);
else
@@ -1364,11 +1419,11 @@ void QGuiApplicationPrivate::addQtOptions(QList<QCommandLineOption> *options)
QGuiApplication::tr("ID of the X11 Visual to use."), QStringLiteral("id")));
// Not using the "QStringList names" solution for those aliases, because it makes the first column too wide
options->append(QCommandLineOption(QStringLiteral("geometry"),
- QGuiApplication::tr("Alias for --windowgeometry."), QStringLiteral("geometry")));
+ QGuiApplication::tr("Alias for --qwindowgeometry."), QStringLiteral("geometry")));
options->append(QCommandLineOption(QStringLiteral("icon"),
- QGuiApplication::tr("Alias for --windowicon."), QStringLiteral("icon")));
+ QGuiApplication::tr("Alias for --qwindowicon."), QStringLiteral("icon")));
options->append(QCommandLineOption(QStringLiteral("title"),
- QGuiApplication::tr("Alias for --windowtitle."), QStringLiteral("title")));
+ QGuiApplication::tr("Alias for --qwindowtitle."), QStringLiteral("title")));
}
}
#endif // QT_CONFIG(commandlineparser)
@@ -1402,16 +1457,9 @@ void QGuiApplicationPrivate::createPlatformIntegration()
}
const bool defaultIsWayland = !defaultIsXcb && platformPluginBase.startsWith("wayland");
- bool isGnome = false;
const QByteArray waylandPlatformName = defaultIsWayland ? platformName : "wayland";
if (hasWaylandDisplay || isWaylandSessionType) {
- const QByteArray currentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toLower();
- const QByteArray sessionDesktop = qgetenv("XDG_SESSION_DESKTOP").toLower();
- isGnome = currentDesktop.contains("gnome") || sessionDesktop.contains("gnome");
- if (isGnome)
- preferredPlatformOrder.append(waylandPlatformName);
- else
- preferredPlatformOrder.prepend(waylandPlatformName);
+ preferredPlatformOrder.prepend(waylandPlatformName);
if (defaultIsWayland)
platformName.clear();
@@ -1450,7 +1498,7 @@ void QGuiApplicationPrivate::createPlatformIntegration()
++arg;
if (strcmp(arg, "-platformpluginpath") == 0) {
if (++i < argc)
- platformPluginPath = QString::fromLocal8Bit(argv[i]);
+ platformPluginPath = QFile::decodeName(argv[i]);
} else if (strcmp(arg, "-platform") == 0) {
if (++i < argc) {
platformExplicitlySelected = true;
@@ -1467,7 +1515,7 @@ void QGuiApplicationPrivate::createPlatformIntegration()
firstWindowTitle = QString::fromLocal8Bit(argv[i]);
} else if (strcmp(arg, "-qwindowicon") == 0 || (xcbIsDefault && strcmp(arg, "-icon") == 0)) {
if (++i < argc) {
- icon = QString::fromLocal8Bit(argv[i]);
+ icon = QFile::decodeName(argv[i]);
}
} else {
argv[j++] = argv[i];
@@ -1479,16 +1527,11 @@ void QGuiApplicationPrivate::createPlatformIntegration()
argc = j;
}
-#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
- if ((hasWaylandDisplay || isWaylandSessionType) && isGnome && !platformExplicitlySelected) {
- qInfo() << "Warning: Ignoring WAYLAND_DISPLAY on Gnome."
- << "Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.";
- }
-#else
Q_UNUSED(platformExplicitlySelected);
-#endif
- init_platform(QLatin1String(platformName), platformPluginPath, platformThemeName, argc, argv);
+ init_platform(QLatin1StringView(platformName), platformPluginPath, platformThemeName, argc, argv);
+ if (const QPlatformTheme *theme = platformTheme())
+ QStyleHintsPrivate::get(QGuiApplication::styleHints())->updateColorScheme(theme->colorScheme());
if (!icon.isEmpty())
forcedWindowIcon = QDir::isAbsolutePath(icon) ? QIcon(icon) : QIcon::fromTheme(icon);
@@ -1507,7 +1550,11 @@ void QGuiApplicationPrivate::createEventDispatcher()
if (platform_integration == nullptr)
createPlatformIntegration();
- // The platform integration should not mess with the event dispatcher
+ // The platform integration should not result in creating an event dispatcher
+ Q_ASSERT_X(!threadData.loadRelaxed()->eventDispatcher, "QGuiApplication",
+ "Creating the platform integration resulted in creating an event dispatcher");
+
+ // Nor should it mess with the QCoreApplication's event dispatcher
Q_ASSERT(!eventDispatcher);
eventDispatcher = platform_integration->createEventDispatcher();
@@ -1521,7 +1568,7 @@ void QGuiApplicationPrivate::eventDispatcherReady()
platform_integration->initialize();
}
-void QGuiApplicationPrivate::init()
+void Q_TRACE_INSTRUMENT(qtgui) QGuiApplicationPrivate::init()
{
Q_TRACE_SCOPE(QGuiApplicationPrivate_init);
@@ -1571,12 +1618,12 @@ void QGuiApplicationPrivate::init()
} else if (strncmp(arg, "-psn_", 5) == 0) {
// eat "-psn_xxxx" on Mac, which is passed when starting an app from Finder.
// special hack to change working directory (for an app bundle) when running from finder
- if (QDir::currentPath() == QLatin1String("/")) {
+ if (QDir::currentPath() == "/"_L1) {
QCFType<CFURLRef> bundleURL(CFBundleCopyBundleURL(CFBundleGetMainBundle()));
QString qbundlePath = QCFString(CFURLCopyFileSystemPath(bundleURL,
kCFURLPOSIXPathStyle));
- if (qbundlePath.endsWith(QLatin1String(".app")))
- QDir::setCurrent(qbundlePath.section(QLatin1Char('/'), 0, -2));
+ if (qbundlePath.endsWith(".app"_L1))
+ QDir::setCurrent(qbundlePath.section(u'/', 0, -2));
}
#endif
#ifndef QT_NO_SESSIONMANAGER
@@ -1584,7 +1631,7 @@ void QGuiApplicationPrivate::init()
++i;
if (argv[i] && *argv[i]) {
session_id = QString::fromLatin1(argv[i]);
- int p = session_id.indexOf(QLatin1Char('_'));
+ qsizetype p = session_id.indexOf(u'_');
if (p >= 0) {
session_key = session_id.mid(p +1);
session_id = session_id.left(p);
@@ -1680,8 +1727,8 @@ void QGuiApplicationPrivate::init()
Q_UNUSED(loadTestability);
#endif // QT_CONFIG(library)
- if (layout_direction == Qt::LayoutDirectionAuto || force_reverse)
- QGuiApplication::setLayoutDirection(qt_detectRTLLanguage() ? Qt::RightToLeft : Qt::LeftToRight);
+ // trigger changed signal and event delivery
+ QGuiApplication::setLayoutDirection(layout_direction);
if (!QGuiApplicationPrivate::displayName)
QObject::connect(q, &QGuiApplication::applicationNameChanged,
@@ -1695,7 +1742,7 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
is_app_closing = true;
is_app_running = false;
- for (int i = 0; i < generic_plugin_list.count(); ++i)
+ for (int i = 0; i < generic_plugin_list.size(); ++i)
delete generic_plugin_list.at(i);
generic_plugin_list.clear();
@@ -1707,7 +1754,7 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
QCursorData::cleanup();
#endif
- layout_direction = Qt::LeftToRight;
+ layout_direction = Qt::LayoutDirectionAuto;
cleanupThreadData();
@@ -1726,6 +1773,10 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate()
}
#endif
+#if QT_CONFIG(vulkan)
+ QVulkanDefaultInstance::cleanup();
+#endif
+
platform_integration->destroy();
delete platform_theme;
@@ -1760,7 +1811,7 @@ static QClipboard *clipboard();
/*!
Returns the current state of the modifier keys on the keyboard. The current
- state is updated sychronously as the event queue is emptied of events that
+ state is updated synchronously as the event queue is emptied of events that
will spontaneously change the keyboard state (QEvent::KeyPress and
QEvent::KeyRelease events).
@@ -1796,7 +1847,7 @@ Qt::KeyboardModifiers QGuiApplication::queryKeyboardModifiers()
{
CHECK_QAPP_INSTANCE(Qt::KeyboardModifiers{})
QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
- return pi->queryKeyboardModifiers();
+ return pi->keyMapper()->queryKeyboardModifiers();
}
/*!
@@ -1854,9 +1905,10 @@ QFunctionPointer QGuiApplication::platformFunction(const QByteArray &function)
Generally, no user interaction can take place before calling exec().
- To make your application perform idle processing, e.g., executing a special
- function whenever there are no pending events, use a QTimer with 0 timeout.
- More advanced idle processing schemes can be achieved using processEvents().
+ To make your application perform idle processing, e.g., executing a
+ special function whenever there are no pending events, use a QChronoTimer
+ with 0ns timeout. More advanced idle processing schemes can be achieved
+ using processEvents().
We recommend that you connect clean-up code to the
\l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your
@@ -1868,7 +1920,7 @@ QFunctionPointer QGuiApplication::platformFunction(const QByteArray &function)
*/
int QGuiApplication::exec()
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::setRootObject(qApp);
#endif
return QCoreApplication::exec();
@@ -1946,19 +1998,24 @@ bool QGuiApplication::notify(QObject *object, QEvent *event)
*/
bool QGuiApplication::event(QEvent *e)
{
- if (e->type() == QEvent::LanguageChange) {
- setLayoutDirection(qt_detectRTLLanguage()?Qt::RightToLeft:Qt::LeftToRight);
+ switch (e->type()) {
+ case QEvent::LanguageChange:
+ // if the layout direction was set explicitly, then don't override it here
+ if (layout_direction == Qt::LayoutDirectionAuto)
+ setLayoutDirection(layout_direction);
for (auto *topLevelWindow : QGuiApplication::topLevelWindows()) {
if (topLevelWindow->flags() != Qt::Desktop)
postEvent(topLevelWindow, new QEvent(QEvent::LanguageChange));
}
- } else if (e->type() == QEvent::ApplicationFontChange ||
- e->type() == QEvent::ApplicationPaletteChange) {
+ break;
+ case QEvent::ApplicationFontChange:
+ case QEvent::ApplicationPaletteChange:
for (auto *topLevelWindow : QGuiApplication::topLevelWindows()) {
if (topLevelWindow->flags() != Qt::Desktop)
postEvent(topLevelWindow, new QEvent(e->type()));
}
- } else if (e->type() == QEvent::Quit) {
+ break;
+ case QEvent::Quit:
// Close open windows. This is done in order to deliver de-expose
// events while the event loop is still running.
for (QWindow *topLevelWindow : QGuiApplication::topLevelWindows()) {
@@ -1970,8 +2027,10 @@ bool QGuiApplication::event(QEvent *e)
return true;
}
}
+ break;
+ default:
+ break;
}
-
return QCoreApplication::event(e);
}
@@ -2002,8 +2061,9 @@ bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArra
return window->nativeEvent(eventType, message, result);
}
-void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
+void Q_TRACE_INSTRUMENT(qtgui) QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
{
+ Q_TRACE_PARAM_REPLACE(QWindowSystemInterfacePrivate::WindowSystemEvent *, int);
Q_TRACE_SCOPE(QGuiApplicationPrivate_processWindowSystemEvent, e->type);
switch(e->type) {
@@ -2028,8 +2088,8 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
case QWindowSystemInterfacePrivate::Leave:
QGuiApplicationPrivate::processLeaveEvent(static_cast<QWindowSystemInterfacePrivate::LeaveEvent *>(e));
break;
- case QWindowSystemInterfacePrivate::ActivatedWindow:
- QGuiApplicationPrivate::processActivatedEvent(static_cast<QWindowSystemInterfacePrivate::ActivatedWindowEvent *>(e));
+ case QWindowSystemInterfacePrivate::FocusWindow:
+ QGuiApplicationPrivate::processFocusWindowEvent(static_cast<QWindowSystemInterfacePrivate::FocusWindowEvent *>(e));
break;
case QWindowSystemInterfacePrivate::WindowStateChanged:
QGuiApplicationPrivate::processWindowStateChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowStateChangedEvent *>(e));
@@ -2037,6 +2097,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
case QWindowSystemInterfacePrivate::WindowScreenChanged:
QGuiApplicationPrivate::processWindowScreenChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowScreenChangedEvent *>(e));
break;
+ case QWindowSystemInterfacePrivate::WindowDevicePixelRatioChanged:
+ QGuiApplicationPrivate::processWindowDevicePixelRatioChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent *>(e));
+ break;
case QWindowSystemInterfacePrivate::SafeAreaMarginsChanged:
QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(static_cast<QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *>(e));
break;
@@ -2184,22 +2247,24 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
QPointF localPoint = e->localPos;
bool doubleClick = false;
auto persistentEPD = devPriv->pointById(0);
- const auto &persistentPoint = QMutableEventPoint::from(persistentEPD->eventPoint);
if (mouseMove) {
QGuiApplicationPrivate::lastCursorPosition = globalPoint;
const auto doubleClickDistance = (e->device && e->device->type() == QInputDevice::DeviceType::Mouse ?
mouseDoubleClickDistance : touchDoubleTapDistance);
- const auto pressPos = persistentPoint.globalPressPosition();
+ const auto pressPos = persistentEPD->eventPoint.globalPressPosition();
if (qAbs(globalPoint.x() - pressPos.x()) > doubleClickDistance ||
qAbs(globalPoint.y() - pressPos.y()) > doubleClickDistance)
mousePressButton = Qt::NoButton;
} else {
+ static unsigned long lastPressTimestamp = 0;
mouse_buttons = e->buttons;
if (mousePress) {
ulong doubleClickInterval = static_cast<ulong>(QGuiApplication::styleHints()->mouseDoubleClickInterval());
- doubleClick = e->timestamp - persistentPoint.pressTimestamp() < doubleClickInterval && button == mousePressButton;
+ doubleClick = e->timestamp - lastPressTimestamp
+ < doubleClickInterval && button == mousePressButton;
mousePressButton = button;
+ lastPressTimestamp = e ->timestamp;
}
}
@@ -2242,9 +2307,11 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
#endif
QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, e->buttons, e->modifiers, e->source, device);
+ Q_ASSERT(devPriv->pointById(0) == persistentEPD); // we don't expect reallocation in QPlatformCursor::pointerEvenmt()
// restore globalLastPosition to avoid invalidating the velocity calculations,
// because the QPlatformCursor mouse event above was in native coordinates
- QMutableEventPoint::from(persistentEPD->eventPoint).setGlobalLastPosition(lastGlobalPosition);
+ QMutableEventPoint::setGlobalLastPosition(persistentEPD->eventPoint, lastGlobalPosition);
+ persistentEPD = nullptr; // incoming and synth events can cause reallocation during delivery, so don't use this again
// ev now contains a detached copy of the QEventPoint from QPointingDevicePrivate::activePoints
ev.setTimestamp(e->timestamp);
if (window->d_func()->blockedByModalWindow && !qApp->d_func()->popupActive()) {
@@ -2301,8 +2368,10 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
}
}
if (type == QEvent::MouseButtonRelease && e->buttons == Qt::NoButton) {
- ev.setExclusiveGrabber(persistentPoint, nullptr);
- ev.clearPassiveGrabbers(persistentPoint);
+ if (auto *persistentEPD = devPriv->queryPointById(0)) {
+ ev.setExclusiveGrabber(persistentEPD->eventPoint, nullptr);
+ ev.clearPassiveGrabbers(persistentEPD->eventPoint);
+ }
}
}
@@ -2335,6 +2404,7 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh
mouse_buttons, e->modifiers, e->phase, e->inverted, e->source, device);
ev.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(window, &ev);
+ e->eventAccepted = ev.isAccepted();
#else
Q_UNUSED(e);
#endif // QT_CONFIG(wheelevent)
@@ -2345,7 +2415,7 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE
QWindow *window = e->window.data();
modifier_buttons = e->modifiers;
if (e->nullWindow()
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#ifdef Q_OS_ANDROID
|| e->key == Qt::Key_Back || e->key == Qt::Key_Menu
#endif
) {
@@ -2381,7 +2451,7 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE
if (window && !window->d_func()->blockedByModalWindow)
QGuiApplication::sendSpontaneousEvent(window, &ev);
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#ifdef Q_OS_ANDROID
else
ev.setAccepted(false);
@@ -2422,7 +2492,7 @@ void QGuiApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::En
const QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(event.pointingDevice());
auto epd = devPriv->queryPointById(event.points().first().id());
Q_ASSERT(epd);
- QMutableEventPoint::from(epd->eventPoint).setVelocity({});
+ QMutableEventPoint::setVelocity(epd->eventPoint, {});
QCoreApplication::sendSpontaneousEvent(e->enter.data(), &event);
}
@@ -2442,10 +2512,10 @@ void QGuiApplicationPrivate::processLeaveEvent(QWindowSystemInterfacePrivate::Le
QCoreApplication::sendSpontaneousEvent(e->leave.data(), &event);
}
-void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent *e)
+void QGuiApplicationPrivate::processFocusWindowEvent(QWindowSystemInterfacePrivate::FocusWindowEvent *e)
{
QWindow *previous = QGuiApplicationPrivate::focus_window;
- QWindow *newFocus = e->activated.data();
+ QWindow *newFocus = e->focused.data();
if (previous == newFocus)
return;
@@ -2495,8 +2565,15 @@ void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate
if (self) {
self->notifyActiveWindowChange(previous);
- if (previousFocusObject != qApp->focusObject())
+ if (previousFocusObject != qApp->focusObject() ||
+ // We are getting an activation change but there is no new focusObject, and we also
+ // don't have a previousFocusObject in the previously active window anymore. This can
+ // happen when window gets destroyed (see QWidgetWindow::focusObject returning nullptr
+ // when already in the QWidget destructor), so update the focusObject to avoid dangling
+ // pointers. See also QWidget::clearFocus(), which tries to cover for this as well.
+ (previous && previousFocusObject == nullptr && qApp->focusObject() == nullptr)) {
self->_q_updateFocusObject(qApp->focusObject());
+ }
}
emit qApp->focusWindowChanged(newFocus);
@@ -2508,32 +2585,46 @@ void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate
void QGuiApplicationPrivate::processWindowStateChangedEvent(QWindowSystemInterfacePrivate::WindowStateChangedEvent *wse)
{
- if (QWindow *window = wse->window.data()) {
+ if (QWindow *window = wse->window.data()) {
+ QWindowPrivate *windowPrivate = qt_window_private(window);
+ const auto originalEffectiveState = QWindowPrivate::effectiveState(windowPrivate->windowState);
+
+ windowPrivate->windowState = wse->newState;
+ const auto newEffectiveState = QWindowPrivate::effectiveState(windowPrivate->windowState);
+ if (newEffectiveState != originalEffectiveState)
+ emit window->windowStateChanged(newEffectiveState);
+
+ windowPrivate->updateVisibility();
+
QWindowStateChangeEvent e(wse->oldState);
- window->d_func()->windowState = wse->newState;
QGuiApplication::sendSpontaneousEvent(window, &e);
}
}
void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterfacePrivate::WindowScreenChangedEvent *wse)
{
- if (QWindow *window = wse->window.data()) {
- if (window->screen() == wse->screen.data())
- return;
- if (QWindow *topLevelWindow = window->d_func()->topLevelWindow(QWindow::ExcludeTransients)) {
- if (QScreen *screen = wse->screen.data())
- topLevelWindow->d_func()->setTopLevelScreen(screen, false /* recreate */);
- else // Fall back to default behavior, and try to find some appropriate screen
- topLevelWindow->setScreen(nullptr);
- }
- // we may have changed scaling, so trigger resize event if needed
- if (window->handle()) {
- QWindowSystemInterfacePrivate::GeometryChangeEvent gce(window, QHighDpi::fromNativePixels(window->handle()->geometry(), window));
- processGeometryChangeEvent(&gce);
- }
+ QWindow *window = wse->window.data();
+ if (!window)
+ return;
+
+ if (window->screen() == wse->screen.data())
+ return;
+
+ if (QWindow *topLevelWindow = window->d_func()->topLevelWindow(QWindow::ExcludeTransients)) {
+ if (QScreen *screen = wse->screen.data())
+ topLevelWindow->d_func()->setTopLevelScreen(screen, false /* recreate */);
+ else // Fall back to default behavior, and try to find some appropriate screen
+ topLevelWindow->setScreen(nullptr);
}
}
+void QGuiApplicationPrivate::processWindowDevicePixelRatioChangedEvent(QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent *wde)
+{
+ if (wde->window.isNull())
+ return;
+ QWindowPrivate::get(wde->window)->updateDevicePixelRatio();
+}
+
void QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *wse)
{
if (wse->window.isNull())
@@ -2548,11 +2639,43 @@ void QGuiApplicationPrivate::processSafeAreaMarginsChangedEvent(QWindowSystemInt
void QGuiApplicationPrivate::processThemeChanged(QWindowSystemInterfacePrivate::ThemeChangeEvent *tce)
{
if (self)
- self->notifyThemeChanged();
- if (QWindow *window = tce->window.data()) {
- QEvent e(QEvent::ThemeChange);
- QGuiApplication::sendSpontaneousEvent(window, &e);
+ self->handleThemeChanged();
+
+ QIconPrivate::clearIconCache();
+
+ QStyleHintsPrivate::get(QGuiApplication::styleHints())->updateColorScheme(colorScheme());
+
+ QEvent themeChangeEvent(QEvent::ThemeChange);
+ const QWindowList windows = tce->window ? QWindowList{tce->window} : window_list;
+ for (auto *window : windows)
+ QGuiApplication::sendSpontaneousEvent(window, &themeChangeEvent);
+}
+
+/*!
+ \internal
+ \brief QGuiApplicationPrivate::colorScheme
+ \return the platform theme's color scheme
+ or Qt::ColorScheme::Unknown if a platform theme cannot be established
+ */
+Qt::ColorScheme QGuiApplicationPrivate::colorScheme()
+{
+ return platformTheme() ? platformTheme()->colorScheme()
+ : Qt::ColorScheme::Unknown;
+}
+
+void QGuiApplicationPrivate::handleThemeChanged()
+{
+ updatePalette();
+
+ QIconLoader::instance()->updateSystemTheme();
+ QAbstractFileIconProviderPrivate::clearIconTypeCache();
+
+ if (!(applicationResourceFlags & ApplicationFontExplicitlySet)) {
+ const auto locker = qt_scoped_lock(applicationFontMutex);
+ clearFontUnlocked();
+ initFontUnlocked();
}
+ initThemeHints();
}
void QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e)
@@ -2611,8 +2734,10 @@ void QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::Cl
{
if (e->window.isNull())
return;
- if (e->window.data()->d_func()->blockedByModalWindow) {
- // a modal window is blocking this window, don't allow close events through
+ if (e->window.data()->d_func()->blockedByModalWindow && !e->window.data()->d_func()->inClose) {
+ // a modal window is blocking this window, don't allow close events through, unless they
+ // originate from a call to QWindow::close.
+ e->eventAccepted = false;
return;
}
@@ -2717,6 +2842,8 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T
QWindowSystemInterfacePrivate::MouseEvent mouseEvent(window, e->timestamp, e->local,
e->global, e->buttons, e->modifiers, button, mouseType, Qt::MouseEventNotSynthesized, false, device);
mouseEvent.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
+ qCDebug(lcPtrDispatch) << "synthesizing mouse from tablet event" << mouseType
+ << e->local << button << e->buttons << e->modifiers;
processMouseEvent(&mouseEvent);
}
#else
@@ -2795,6 +2922,9 @@ void QGuiApplicationPrivate::processContextMenuEvent(QWindowSystemInterfacePriva
void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e)
{
+ if (!QInputDevicePrivate::isRegistered(e->device))
+ return;
+
modifier_buttons = e->modifiers;
QPointingDevice *device = const_cast<QPointingDevice *>(static_cast<const QPointingDevice *>(e->device));
QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(device);
@@ -2804,19 +2934,17 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
// Send the TouchCancel to all windows with active touches and clean up.
QTouchEvent touchEvent(QEvent::TouchCancel, device, e->modifiers);
touchEvent.setTimestamp(e->timestamp);
- QSet<QWindow *> windowsNeedingCancel;
+ constexpr qsizetype Prealloc = decltype(devPriv->activePoints)::mapped_container_type::PreallocatedSize;
+ QMinimalVarLengthFlatSet<QWindow *, Prealloc> windowsNeedingCancel;
for (auto &epd : devPriv->activePoints.values()) {
- auto &mut = QMutableEventPoint::from(const_cast<QEventPoint &>(epd.eventPoint));
- QWindow *w = mut.window();
- if (w)
+ if (QWindow *w = QMutableEventPoint::window(epd.eventPoint))
windowsNeedingCancel.insert(w);
}
- for (QSet<QWindow *>::const_iterator winIt = windowsNeedingCancel.constBegin(),
- winItEnd = windowsNeedingCancel.constEnd(); winIt != winItEnd; ++winIt) {
- QGuiApplication::sendSpontaneousEvent(*winIt, &touchEvent);
- }
+ for (QWindow *w : windowsNeedingCancel)
+ QGuiApplication::sendSpontaneousEvent(w, &touchEvent);
+
if (!self->synthesizedMousePoints.isEmpty() && !e->synthetic()) {
for (QHash<QWindow *, SynthesizedMouseData>::const_iterator synthIt = self->synthesizedMousePoints.constBegin(),
synthItEnd = self->synthesizedMousePoints.constEnd(); synthIt != synthItEnd; ++synthIt) {
@@ -2858,7 +2986,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
for (auto &tempPt : e->points) {
// update state
auto epd = devPriv->pointById(tempPt.id());
- auto &mut = QMutableEventPoint::from(const_cast<QEventPoint &>(epd->eventPoint));
+ auto &ep = epd->eventPoint;
epd->eventPoint.setAccepted(false);
switch (tempPt.state()) {
case QEventPoint::State::Pressed:
@@ -2868,19 +2996,21 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
// If the QPA event didn't tell us which window, find the one under the touchpoint position.
if (!window)
window = QGuiApplication::topLevelAt(tempPt.globalPosition().toPoint());
- mut.setWindow(window);
+ QMutableEventPoint::setWindow(ep, window);
break;
case QEventPoint::State::Released:
- if (Q_UNLIKELY(!window.isNull() && window != mut.window()))
- qCWarning(lcPtrDispatch) << "delivering touch release to same window" << mut.window() << "not" << window.data();
- window = mut.window();
+ if (Q_UNLIKELY(!window.isNull() && window != QMutableEventPoint::window(ep)))
+ qCDebug(lcPtrDispatch) << "delivering touch release to same window"
+ << QMutableEventPoint::window(ep) << "not" << window.data();
+ window = QMutableEventPoint::window(ep);
break;
default: // update or stationary
- if (Q_UNLIKELY(!window.isNull() && window != mut.window()))
- qCWarning(lcPtrDispatch) << "delivering touch update to same window" << mut.window() << "not" << window.data();
- window = mut.window();
+ if (Q_UNLIKELY(!window.isNull() && window != QMutableEventPoint::window(ep)))
+ qCDebug(lcPtrDispatch) << "delivering touch update to same window"
+ << QMutableEventPoint::window(ep) << "not" << window.data();
+ window = QMutableEventPoint::window(ep);
break;
}
// If we somehow still don't have a window, we can't deliver this touchpoint. (should never happen)
@@ -2888,30 +3018,30 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
qCWarning(lcPtrDispatch) << "skipping" << &tempPt << ": no target window";
continue;
}
- mut.updateFrom(tempPt);
+ QMutableEventPoint::update(tempPt, ep);
Q_ASSERT(window.data() != nullptr);
// make the *scene* position the same as the *global* position
- mut.setScenePosition(tempPt.globalPosition());
+ QMutableEventPoint::setScenePosition(ep, tempPt.globalPosition());
// store the scene position as local position, for now
- mut.setPosition(window->mapFromGlobal(tempPt.globalPosition()));
+ QMutableEventPoint::setPosition(ep, window->mapFromGlobal(tempPt.globalPosition()));
// setTimeStamp has side effects, so we do it last
- mut.setTimestamp(e->timestamp);
+ QMutableEventPoint::setTimestamp(ep, e->timestamp);
// add the touchpoint to the event that will be delivered to the window
bool added = false;
for (QMutableTouchEvent &ev : touchEvents) {
if (ev.target() == window.data()) {
- ev.addPoint(mut);
+ ev.addPoint(ep);
added = true;
break;
}
}
if (!added) {
- QMutableTouchEvent mte(e->touchType, device, e->modifiers, {mut});
+ QMutableTouchEvent mte(e->touchType, device, e->modifiers, {ep});
mte.setTimestamp(e->timestamp);
mte.setTarget(window.data());
touchEvents.append(mte);
@@ -2963,7 +3093,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
QEvent::Type mouseEventType = QEvent::MouseMove;
Qt::MouseButton button = Qt::NoButton;
Qt::MouseButtons buttons = Qt::LeftButton;
- if (eventType == QEvent::TouchBegin && m_fakeMouseSourcePointId < 0) {
+ if (eventType == QEvent::TouchBegin || m_fakeMouseSourcePointId < 0) {
m_fakeMouseSourcePointId = touchEvent.point(0).id();
qCDebug(lcPtrDispatch) << "synthesizing mouse events from touchpoint" << m_fakeMouseSourcePointId;
}
@@ -3047,26 +3177,16 @@ void QGuiApplicationPrivate::processScreenGeometryChange(QWindowSystemInterfaceP
if (!e->screen)
return;
- QScreen *s = e->screen.data();
-
- bool geometryChanged = e->geometry != s->d_func()->geometry;
- s->d_func()->geometry = e->geometry;
+ {
+ QScreen *s = e->screen.data();
+ QScreenPrivate::UpdateEmitter updateEmitter(s);
- bool availableGeometryChanged = e->availableGeometry != s->d_func()->availableGeometry;
- s->d_func()->availableGeometry = e->availableGeometry;
+ // Note: The incoming geometries have already been scaled by QHighDpi
+ // in the QWSI layer, so we don't need to call updateGeometry() here.
+ s->d_func()->geometry = e->geometry;
+ s->d_func()->availableGeometry = e->availableGeometry;
- const Qt::ScreenOrientation primaryOrientation = s->primaryOrientation();
- if (geometryChanged)
s->d_func()->updatePrimaryOrientation();
-
- s->d_func()->emitGeometryChangeSignals(geometryChanged, availableGeometryChanged);
-
- if (geometryChanged) {
- emit s->physicalSizeChanged(s->physicalSize());
- emit s->logicalDotsPerInchChanged(s->logicalDotsPerInch());
-
- if (s->primaryOrientation() != primaryOrientation)
- emit s->primaryOrientationChanged(s->primaryOrientation());
}
resetCachedDevicePixelRatio();
@@ -3083,11 +3203,16 @@ void QGuiApplicationPrivate::processScreenLogicalDotsPerInchChange(QWindowSystem
if (!e->screen)
return;
- QScreen *s = e->screen.data();
- s->d_func()->logicalDpi = QDpi(e->dpiX, e->dpiY);
+ {
+ QScreen *s = e->screen.data();
+ QScreenPrivate::UpdateEmitter updateEmitter(s);
+ s->d_func()->logicalDpi = QDpi(e->dpiX, e->dpiY);
+ s->d_func()->updateGeometry();
+ }
- emit s->logicalDotsPerInchChanged(s->logicalDotsPerInch());
- s->d_func()->updateGeometriesWithSignals();
+ for (QWindow *window : QGuiApplication::allWindows())
+ if (window->screen() == e->screen)
+ QWindowPrivate::get(window)->updateDevicePixelRatio();
resetCachedDevicePixelRatio();
}
@@ -3147,6 +3272,16 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E
const bool wasExposed = p->exposed;
p->exposed = e->isExposed && window->screen();
+ // We expect that the platform plugins send DevicePixelRatioChange events.
+ // As a fail-safe make a final check here to make sure the cached DPR value is
+ // always up to date before sending the expose event.
+ if (e->isExposed && !e->region.isEmpty()) {
+ const bool dprWasChanged = QWindowPrivate::get(window)->updateDevicePixelRatio();
+ if (dprWasChanged)
+ qWarning() << "The cached device pixel ratio value was stale on window expose. "
+ << "Please file a QTBUG which explains how to reproduce.";
+ }
+
// We treat expose events for an already exposed window as paint events
if (wasExposed && p->exposed && shouldSynthesizePaintEvents) {
QPaintEvent paintEvent(e->region);
@@ -3288,7 +3423,7 @@ QClipboard * QGuiApplication::clipboard()
/*!
\since 5.4
\fn void QGuiApplication::paletteChanged(const QPalette &palette)
- \deprecated
+ \deprecated [6.0] Handle QEvent::ApplicationPaletteChange instead.
This signal is emitted when the \a palette of the application changes. Use
QEvent::ApplicationPaletteChanged instead.
@@ -3372,11 +3507,13 @@ bool QGuiApplicationPrivate::setPalette(const QPalette &palette)
*/
QPalette QGuiApplicationPrivate::basePalette() const
{
- return platformTheme() ? *platformTheme()->palette() : Qt::gray;
+ const auto pf = platformTheme();
+ return pf && pf->palette() ? *pf->palette() : Qt::gray;
}
void QGuiApplicationPrivate::handlePaletteChanged(const char *className)
{
+#if QT_DEPRECATED_SINCE(6, 0)
if (!className) {
Q_ASSERT(app_pal);
QT_WARNING_PUSH
@@ -3384,6 +3521,9 @@ QT_WARNING_DISABLE_DEPRECATED
emit qGuiApp->paletteChanged(*QGuiApplicationPrivate::app_pal);
QT_WARNING_POP
}
+#else
+ Q_UNUSED(className);
+#endif // QT_DEPRECATED_SINCE(6, 0)
if (is_app_running && !is_app_closing) {
QEvent event(QEvent::ApplicationPaletteChange);
@@ -3399,7 +3539,7 @@ void QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(QWindow *window)
/*!
\since 5.11
\fn void QGuiApplication::fontChanged(const QFont &font)
- \deprecated
+ \deprecated [6.0] Handle QEvent::ApplicationFontChange instead.
This signal is emitted when the \a font of the application changes. Use
QEvent::ApplicationFontChanged instead.
@@ -3442,10 +3582,14 @@ void QGuiApplication::setFont(const QFont &font)
if (emitChange && qGuiApp) {
auto font = *QGuiApplicationPrivate::app_font;
locker.unlock();
+#if QT_DEPRECATED_SINCE(6, 0)
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
emit qGuiApp->fontChanged(font);
QT_WARNING_POP
+#else
+ Q_UNUSED(font);
+#endif // QT_DEPRECATED_SINCE(6, 0)
QEvent event(QEvent::ApplicationFontChange);
QGuiApplication::sendEvent(qGuiApp, &event);
}
@@ -3532,61 +3676,67 @@ void QGuiApplicationPrivate::notifyWindowIconChanged()
The default is \c true.
If this property is \c true, the applications quits when the last visible
- primary window (i.e. window with no parent) is closed.
+ \l{Primary and Secondary Windows}{primary window} (i.e. top level window
+ with no transient parent) is closed.
\sa quit(), QWindow::close()
*/
void QGuiApplication::setQuitOnLastWindowClosed(bool quit)
{
- QCoreApplication::setQuitLockEnabled(quit);
+ QGuiApplicationPrivate::quitOnLastWindowClosed = quit;
}
-
-
bool QGuiApplication::quitOnLastWindowClosed()
{
- return QCoreApplication::isQuitLockEnabled();
+ return QGuiApplicationPrivate::quitOnLastWindowClosed;
}
+void QGuiApplicationPrivate::maybeLastWindowClosed()
+{
+ if (!lastWindowClosed())
+ return;
+
+ if (in_exec)
+ emit q_func()->lastWindowClosed();
+
+ if (quitOnLastWindowClosed && canQuitAutomatically())
+ quitAutomatically();
+}
/*!
\fn void QGuiApplication::lastWindowClosed()
This signal is emitted from exec() when the last visible
- primary window (i.e. window with no parent) is closed.
+ \l{Primary and Secondary Windows}{primary window} (i.e.
+ top level window with no transient parent) is closed.
By default, QGuiApplication quits after this signal is emitted. This feature
can be turned off by setting \l quitOnLastWindowClosed to \c false.
- \sa QWindow::close(), QWindow::isTopLevel()
+ \sa QWindow::close(), QWindow::isTopLevel(), QWindow::transientParent()
*/
-void QGuiApplicationPrivate::emitLastWindowClosed()
+bool QGuiApplicationPrivate::lastWindowClosed() const
{
- if (qGuiApp && qGuiApp->d_func()->in_exec) {
- emit qGuiApp->lastWindowClosed();
- }
-}
+ for (auto *window : QGuiApplication::topLevelWindows()) {
+ auto *windowPrivate = qt_window_private(window);
+ if (!windowPrivate->participatesInLastWindowClosed())
+ continue;
-bool QGuiApplicationPrivate::shouldQuit()
-{
- const QWindowList processedWindows;
- return shouldQuitInternal(processedWindows);
+ if (windowPrivate->treatAsVisible())
+ return false;
+ }
+
+ return true;
}
-bool QGuiApplicationPrivate::shouldQuitInternal(const QWindowList &processedWindows)
+bool QGuiApplicationPrivate::canQuitAutomatically()
{
- /* if there is no visible top-level window left, we allow the quit */
- QWindowList list = QGuiApplication::topLevelWindows();
- for (int i = 0; i < list.size(); ++i) {
- QWindow *w = list.at(i);
- if (processedWindows.contains(w))
- continue;
- if (w->isVisible() && !w->transientParent())
- return false;
- }
- return true;
+ if (quitOnLastWindowClosed && !lastWindowClosed())
+ return false;
+
+ return QCoreApplicationPrivate::canQuitAutomatically();
}
void QGuiApplicationPrivate::quit()
@@ -3647,6 +3797,8 @@ Qt::ApplicationState QGuiApplication::applicationState()
*/
void QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy policy)
{
+ if (qApp)
+ qWarning("setHighDpiScaleFactorRoundingPolicy must be called before creating the QGuiApplication instance");
QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy = policy;
}
@@ -3867,7 +4019,8 @@ void QGuiApplication::sync()
\property QGuiApplication::layoutDirection
\brief the default layout direction for this application
- On system start-up, the default layout direction depends on the
+ On system start-up, or when the direction is explicitly set to
+ Qt::LayoutDirectionAuto, the default layout direction depends on the
application's language.
The notifier signal was introduced in Qt 5.4.
@@ -3877,11 +4030,15 @@ void QGuiApplication::sync()
void QGuiApplication::setLayoutDirection(Qt::LayoutDirection direction)
{
- if (layout_direction == direction || direction == Qt::LayoutDirectionAuto)
- return;
-
layout_direction = direction;
+ if (direction == Qt::LayoutDirectionAuto)
+ direction = qt_detectRTLLanguage() ? Qt::RightToLeft : Qt::LeftToRight;
+ // no change to the explicitly set or auto-detected layout direction
+ if (direction == effective_layout_direction)
+ return;
+
+ effective_layout_direction = direction;
if (qGuiApp) {
emit qGuiApp->layoutDirectionChanged(direction);
QGuiApplicationPrivate::self->notifyLayoutDirectionChange();
@@ -3890,10 +4047,15 @@ void QGuiApplication::setLayoutDirection(Qt::LayoutDirection direction)
Qt::LayoutDirection QGuiApplication::layoutDirection()
{
- // layout_direction is only ever Qt::LayoutDirectionAuto if setLayoutDirection
- // was never called, or called with Qt::LayoutDirectionAuto (which is a no-op).
- // In that case we return the default LeftToRight.
- return layout_direction == Qt::LayoutDirectionAuto ? Qt::LeftToRight : layout_direction;
+ /*
+ effective_layout_direction defaults to Qt::LeftToRight, and is updated with what is
+ auto-detected by a call to setLayoutDirection(Qt::LayoutDirectionAuto). This happens in
+ QGuiApplicationPrivate::init and when the language changes (or before if the application
+ calls the static function, but then no translators are installed so the auto-detection
+ always yields Qt::LeftToRight).
+ So we can be certain that it's always the right value.
+ */
+ return effective_layout_direction;
}
/*!
@@ -4000,7 +4162,7 @@ static inline void applyWindowCursor(const QList<QWindow *> &l)
Application cursors are stored on an internal stack. setOverrideCursor()
pushes the cursor onto the stack, and restoreOverrideCursor() pops the
- active cursor off the stack. changeOverrideCursor() changes the curently
+ active cursor off the stack. changeOverrideCursor() changes the currently
active application override cursor.
Every setOverrideCursor() must eventually be followed by a corresponding
@@ -4117,7 +4279,10 @@ QInputMethod *QGuiApplication::inputMethod()
/*!
\fn void QGuiApplication::fontDatabaseChanged()
- This signal is emitted when application fonts are loaded or removed.
+ This signal is emitted when the available fonts have changed.
+
+ This can happen when application fonts are added or removed, or when the
+ system fonts change.
\sa QFontDatabase::addApplicationFont(),
QFontDatabase::addApplicationFontFromData(),
@@ -4131,18 +4296,12 @@ QPixmap QGuiApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape)
return QPixmap();
}
-void QGuiApplicationPrivate::notifyThemeChanged()
+QPoint QGuiApplicationPrivate::QLastCursorPosition::toPoint() const noexcept
{
- updatePalette();
-
- QAbstractFileIconProviderPrivate::clearIconTypeCache();
-
- if (!(applicationResourceFlags & ApplicationFontExplicitlySet)) {
- const auto locker = qt_scoped_lock(applicationFontMutex);
- clearFontUnlocked();
- initFontUnlocked();
- }
- initThemeHints();
+ // Guard against the default initialization of qInf() (avoid UB or SIGFPE in conversion).
+ if (Q_UNLIKELY(qIsInf(thePoint.x())))
+ return QPoint(std::numeric_limits<int>::max(), std::numeric_limits<int>::max());
+ return thePoint.toPoint();
}
#if QT_CONFIG(draganddrop)
@@ -4203,8 +4362,22 @@ QInputDeviceManager *QGuiApplicationPrivate::inputDeviceManager()
return m_inputDeviceManager;
}
+/*!
+ \fn template <typename QNativeInterface> QNativeInterface *QGuiApplication::nativeInterface() const
+
+ Returns a native interface of the given type for the application.
+
+ This function provides access to platform specific functionality
+ of QGuiApplication, as defined in the QNativeInterface namespace:
+
+ \annotatedlist native-interfaces-qguiapplication
+
+ If the requested interface is not available a \nullptr is returned.
+ */
+
void *QGuiApplication::resolveInterface(const char *name, int revision) const
{
+ using namespace QNativeInterface;
using namespace QNativeInterface::Private;
auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
@@ -4213,10 +4386,16 @@ void *QGuiApplication::resolveInterface(const char *name, int revision) const
#if defined(Q_OS_WIN)
QT_NATIVE_INTERFACE_RETURN_IF(QWindowsApplication, platformIntegration);
#endif
+#if QT_CONFIG(xcb)
+ QT_NATIVE_INTERFACE_RETURN_IF(QX11Application, platformNativeInterface());
+#endif
+#if QT_CONFIG(wayland)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWaylandApplication, platformNativeInterface());
+#endif
return QCoreApplication::resolveInterface(name, revision);
}
-#include "moc_qguiapplication.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qguiapplication.cpp"
diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h
index 795a88f2b0..14bce88c62 100644
--- a/src/gui/kernel/qguiapplication.h
+++ b/src/gui/kernel/qguiapplication.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGUIAPPLICATION_H
#define QGUIAPPLICATION_H
@@ -94,6 +58,8 @@ public:
static void setApplicationDisplayName(const QString &name);
static QString applicationDisplayName();
+ Q_SLOT void setBadgeNumber(qint64 number);
+
static void setDesktopFileName(const QString &name);
static QString desktopFileName();
@@ -219,4 +185,6 @@ private:
QT_END_NAMESPACE
+#include <QtGui/qguiapplication_platform.h>
+
#endif // QGUIAPPLICATION_H
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index b98a1b9ecf..58c3f33394 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGUIAPPLICATION_P_H
#define QGUIAPPLICATION_P_H
@@ -55,10 +19,13 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/qicon.h>
+#include <QtCore/QHash>
#include <QtCore/QPointF>
#include <QtCore/private/qcoreapplication_p.h>
#include <QtCore/qnativeinterface.h>
+#include <QtCore/private/qnativeinterface_p.h>
+#include <QtCore/private/qnumeric_p.h>
#include <QtCore/private/qthread_p.h>
#include <qpa/qwindowsysteminterface.h>
@@ -67,6 +34,8 @@
# include "private/qshortcutmap_p.h"
#endif
+#include <QtCore/qpointer.h>
+
#include <memory>
QT_BEGIN_NAMESPACE
@@ -90,7 +59,7 @@ class Q_GUI_EXPORT QGuiApplicationPrivate : public QCoreApplicationPrivate
{
Q_DECLARE_PUBLIC(QGuiApplication)
public:
- QGuiApplicationPrivate(int &argc, char **argv, int flags);
+ QGuiApplicationPrivate(int &argc, char **argv);
~QGuiApplicationPrivate();
void init();
@@ -105,10 +74,12 @@ public:
#if QT_CONFIG(commandlineparser)
void addQtOptions(QList<QCommandLineOption> *options) override;
#endif
- virtual bool shouldQuit() override;
+ bool canQuitAutomatically() override;
void quit() override;
- bool shouldQuitInternal(const QWindowList &processedWindows);
+ void maybeLastWindowClosed();
+ bool lastWindowClosed() const;
+ static bool quitOnLastWindowClosed;
static void captureGlobalModifierState(QEvent *e);
static Qt::KeyboardModifiers modifier_buttons;
@@ -144,9 +115,11 @@ public:
static void processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e);
static void processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e);
- static void processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent *e);
+ static void processFocusWindowEvent(QWindowSystemInterfacePrivate::FocusWindowEvent *e);
+
static void processWindowStateChangedEvent(QWindowSystemInterfacePrivate::WindowStateChangedEvent *e);
static void processWindowScreenChangedEvent(QWindowSystemInterfacePrivate::WindowScreenChangedEvent *e);
+ static void processWindowDevicePixelRatioChangedEvent(QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent *e);
static void processSafeAreaMarginsChangedEvent(QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *e);
@@ -204,8 +177,6 @@ public:
return alignment;
}
- static void emitLastWindowClosed();
-
QPixmap getPixmapCursor(Qt::CursorShape cshape);
void _q_updateFocusObject(QObject *object);
@@ -221,11 +192,49 @@ public:
static void showModalWindow(QWindow *window);
static void hideModalWindow(QWindow *window);
static void updateBlockedStatus(QWindow *window);
- virtual bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = nullptr) const;
+
+ virtual Qt::WindowModality defaultModality() const;
+ virtual bool windowNeverBlocked(QWindow *window) const;
+ bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = nullptr) const;
virtual bool popupActive() { return false; }
+ virtual bool closeAllPopups() { return false; }
static Qt::MouseButton mousePressButton;
- static QPointF lastCursorPosition;
+ static struct QLastCursorPosition {
+ constexpr inline QLastCursorPosition() noexcept : thePoint(qt_inf(), qt_inf()) {}
+ constexpr inline Q_IMPLICIT QLastCursorPosition(QPointF p) noexcept : thePoint(p) {}
+ constexpr inline Q_IMPLICIT operator QPointF() const noexcept { return thePoint; }
+ constexpr inline qreal x() const noexcept{ return thePoint.x(); }
+ constexpr inline qreal y() const noexcept{ return thePoint.y(); }
+ Q_GUI_EXPORT QPoint toPoint() const noexcept;
+
+ constexpr void reset() noexcept { *this = QLastCursorPosition{}; }
+
+ // QGuiApplicationPrivate::lastCursorPosition is used for mouse-move detection
+ // but even QPointF's qFuzzCompare on doubles is too precise, and causes move-noise
+ // e.g. on macOS (see QTBUG-111170). So we specialize the equality operators here
+ // to use single-point precision.
+ friend constexpr bool operator==(const QLastCursorPosition &p1, const QPointF &p2) noexcept
+ {
+ return qFuzzyCompare(float(p1.x()), float(p2.x()))
+ && qFuzzyCompare(float(p1.y()), float(p2.y()));
+ }
+ friend constexpr bool operator!=(const QLastCursorPosition &p1, const QPointF &p2) noexcept
+ {
+ return !(p1 == p2);
+ }
+ friend constexpr bool operator==(const QPointF &p1, const QLastCursorPosition &p2) noexcept
+ {
+ return p2 == p1;
+ }
+ friend constexpr bool operator!=(const QPointF &p1, const QLastCursorPosition &p2) noexcept
+ {
+ return !(p2 == p1);
+ }
+
+ private:
+ QPointF thePoint;
+ } lastCursorPosition;
static QWindow *currentMouseWindow;
static QWindow *currentMousePressWindow;
static Qt::ApplicationState applicationState;
@@ -314,8 +323,10 @@ public:
static void updatePalette();
+ static Qt::ColorScheme colorScheme();
+
protected:
- virtual void notifyThemeChanged();
+ virtual void handleThemeChanged();
static bool setPalette(const QPalette &palette);
virtual QPalette basePalette() const;
@@ -348,11 +359,12 @@ private:
// ----------------- QNativeInterface -----------------
+class QWindowsMimeConverter;
+
namespace QNativeInterface::Private {
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
-class QWindowsMime;
struct Q_GUI_EXPORT QWindowsApplication
{
@@ -384,6 +396,8 @@ struct Q_GUI_EXPORT QWindowsApplication
virtual WindowActivationBehavior windowActivationBehavior() const = 0;
virtual void setWindowActivationBehavior(WindowActivationBehavior behavior) = 0;
+ virtual void setHasBorderInFullScreenDefault(bool border) = 0;
+
virtual bool isTabletMode() const = 0;
virtual bool isWinTabEnabled() const = 0;
@@ -394,8 +408,8 @@ struct Q_GUI_EXPORT QWindowsApplication
virtual DarkModeHandling darkModeHandling() const = 0;
virtual void setDarkModeHandling(DarkModeHandling handling) = 0;
- virtual void registerMime(QWindowsMime *mime) = 0;
- virtual void unregisterMime(QWindowsMime *mime) = 0;
+ virtual void registerMime(QWindowsMimeConverter *mime) = 0;
+ virtual void unregisterMime(QWindowsMimeConverter *mime) = 0;
virtual int registerMimeType(const QString &mime) = 0;
@@ -408,6 +422,8 @@ struct Q_GUI_EXPORT QWindowsApplication
virtual QVariant gpu() const = 0; // internal, used by qtdiag
virtual QVariant gpuList() const = 0;
+
+ virtual void populateLightSystemPalette(QPalette &pal) const = 0;
};
#endif // Q_OS_WIN
diff --git a/src/gui/kernel/qguiapplication_platform.h b/src/gui/kernel/qguiapplication_platform.h
new file mode 100644
index 0000000000..545bf75c84
--- /dev/null
+++ b/src/gui/kernel/qguiapplication_platform.h
@@ -0,0 +1,68 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QGUIAPPLICATION_PLATFORM_H
+#define QGUIAPPLICATION_PLATFORM_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the native interface APIs. Usage of
+// this API may make your code source and binary incompatible
+// with future versions of Qt.
+//
+
+#include <QtGui/qtguiglobal.h>
+
+#include <QtCore/qnativeinterface.h>
+#include <QtGui/qguiapplication.h>
+
+#if QT_CONFIG(xcb)
+typedef struct _XDisplay Display;
+struct xcb_connection_t;
+#endif
+
+#if QT_CONFIG(wayland)
+struct wl_display;
+struct wl_compositor;
+struct wl_seat;
+struct wl_keyboard;
+struct wl_pointer;
+struct wl_touch;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QNativeInterface
+{
+
+#if QT_CONFIG(xcb) || defined(Q_QDOC)
+struct Q_GUI_EXPORT QX11Application
+{
+ QT_DECLARE_NATIVE_INTERFACE(QX11Application, 1, QGuiApplication)
+ virtual Display *display() const = 0;
+ virtual xcb_connection_t *connection() const = 0;
+};
+#endif
+
+#if QT_CONFIG(wayland) || defined(Q_QDOC)
+struct Q_GUI_EXPORT QWaylandApplication
+{
+ QT_DECLARE_NATIVE_INTERFACE(QWaylandApplication, 1, QGuiApplication)
+ virtual wl_display *display() const = 0;
+ virtual wl_compositor *compositor() const = 0;
+ virtual wl_seat *seat() const = 0;
+ virtual wl_keyboard *keyboard() const = 0;
+ virtual wl_pointer *pointer() const = 0;
+ virtual wl_touch *touch() const = 0;
+ virtual uint lastInputSerial() const = 0;
+ virtual wl_seat *lastInputSeat() const = 0;
+};
+#endif
+
+} // QNativeInterface
+
+QT_END_NAMESPACE
+
+#endif // QGUIAPPLICATION_PLATFORM_H
diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp
index 1b455a57bf..fe72e7782f 100644
--- a/src/gui/kernel/qguivariant.cpp
+++ b/src/gui/kernel/qguivariant.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Gui types
#include "qbitmap.h"
@@ -86,20 +50,14 @@
#include <float.h>
-#include "private/qvariant_p.h"
#include <private/qmetatype_p.h>
QT_BEGIN_NAMESPACE
namespace {
-struct GuiTypesFilter {
- template<typename T>
- struct Acceptor {
- static const bool IsAccepted = QModulesPrivate::QTypeModuleInfo<T>::IsGui && QtMetaTypePrivate::TypeDefinition<T>::IsAvailable;
- };
-};
-static const struct : QMetaTypeModuleHelper
+// NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor): this is not a base class
+static constexpr struct : QMetaTypeModuleHelper
{
#define QT_IMPL_METATYPEINTERFACE_GUI_TYPES(MetaTypeName, MetaTypeId, RealName) \
QT_METATYPE_INTERFACE_INIT(RealName),
@@ -128,7 +86,7 @@ static const struct : QMetaTypeModuleHelper
return true;
);
QMETATYPE_CONVERTER(QColor, QByteArray,
- result.setNamedColor(QLatin1String(source));
+ result = QColor::fromString(QLatin1StringView(source));
return result.isValid();
);
QMETATYPE_CONVERTER(QString, QColor,
@@ -137,7 +95,7 @@ static const struct : QMetaTypeModuleHelper
return true;
);
QMETATYPE_CONVERTER(QColor, QString,
- result.setNamedColor(source);
+ result = QColor::fromString(source);
return result.isValid();
);
#if QT_CONFIG(shortcut)
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index 1ce5f84ed8..a0e1b48dcb 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qhighdpiscaling_p.h"
#include "qguiapplication.h"
@@ -183,7 +147,7 @@ static std::optional<qreal> qEnvironmentVariableOptionalReal(const char *name)
is always enabled. The Qt scale factor value is typically determined by the
QPlatformScreen implementation - see below.
- There is one environment variable based opt-out option: set QT_ENABLE_HIGH_DPI_SCALING=0.
+ There is one environment variable based opt-out option: set QT_ENABLE_HIGHDPI_SCALING=0.
Keep in mind that this does not affect the OS scale factor, which is controlled by
the operating system.
@@ -437,6 +401,8 @@ QDpi QHighDpiScaling::effectiveLogicalDpi(const QPlatformScreen *screen, qreal r
*/
void QHighDpiScaling::initHighDpiScaling()
{
+ qCDebug(lcHighDpi) << "Initializing high-DPI scaling";
+
// Read environment variables
static const char* envDebugStr = "environment variable set:";
std::optional<int> envEnableHighDpiScaling = qEnvironmentVariableOptionalInt(enableHighDpiScalingEnvVar);
@@ -496,7 +462,7 @@ void QHighDpiScaling::initHighDpiScaling()
// Resolve DpiAdjustmentPolicy to m_dpiAdjustmentPolicy
if (envDpiAdjustmentPolicy.has_value()) {
- QByteArray policyText = envScaleFactorRoundingPolicy.value();
+ QByteArray policyText = envDpiAdjustmentPolicy.value();
auto policyEnumValue = lookupDpiAdjustmentPolicy(policyText);
if (policyEnumValue != DpiAdjustmentPolicy::Unset) {
QHighDpiScaling::m_dpiAdjustmentPolicy = policyEnumValue;
@@ -510,6 +476,9 @@ void QHighDpiScaling::initHighDpiScaling()
// Set initial active state
m_active = m_globalScalingActive || m_usePlatformPluginDpi;
+
+ qCDebug(lcHighDpi) << "Initialization done, high-DPI scaling is"
+ << (m_active ? "active" : "inactive");
}
/*
@@ -518,14 +487,18 @@ void QHighDpiScaling::initHighDpiScaling()
*/
void QHighDpiScaling::updateHighDpiScaling()
{
+ qCDebug(lcHighDpi) << "Updating high-DPI scaling";
+
// Apply screen factors from environment
if (m_screenFactors.size() > 0) {
+ qCDebug(lcHighDpi) << "Applying screen factors" << m_screenFactors;
int i = -1;
const auto screens = QGuiApplication::screens();
- for (const auto &[name, factor] : m_screenFactors) {
+ for (const auto &[name, rawFactor]: m_screenFactors) {
+ const qreal factor = roundScaleFactor(rawFactor);
++i;
if (name.isNull()) {
- if (i < screens.count())
+ if (i < screens.size())
setScreenFactor(screens.at(i), factor);
} else {
for (QScreen *screen : screens) {
@@ -551,6 +524,9 @@ void QHighDpiScaling::updateHighDpiScaling()
}
m_active = m_globalScalingActive || m_screenFactorSet || m_platformPluginDpiScalingActive;
+
+ qCDebug(lcHighDpi) << "Update done, high-DPI scaling is"
+ << (m_active ? "active" : "inactive");
}
/*
@@ -558,17 +534,24 @@ void QHighDpiScaling::updateHighDpiScaling()
*/
void QHighDpiScaling::setGlobalFactor(qreal factor)
{
+ qCDebug(lcHighDpi) << "Setting global scale factor to" << factor;
+
if (qFuzzyCompare(factor, m_factor))
return;
if (!QGuiApplication::allWindows().isEmpty())
qWarning("QHighDpiScaling::setFactor: Should only be called when no windows exist.");
+ const auto screens = QGuiApplication::screens();
+
+ std::vector<QScreenPrivate::UpdateEmitter> updateEmitters;
+ for (QScreen *screen : screens)
+ updateEmitters.emplace_back(screen);
+
m_globalScalingActive = !qFuzzyCompare(factor, qreal(1));
m_factor = m_globalScalingActive ? factor : qreal(1);
m_active = m_globalScalingActive || m_screenFactorSet || m_platformPluginDpiScalingActive ;
- const auto screens = QGuiApplication::screens();
for (QScreen *screen : screens)
- screen->d_func()->updateHighDpi();
+ screen->d_func()->updateGeometry();
}
static const char scaleFactorProperty[] = "_q_scaleFactor";
@@ -578,11 +561,15 @@ static const char scaleFactorProperty[] = "_q_scaleFactor";
*/
void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor)
{
+ qCDebug(lcHighDpi) << "Setting screen scale factor for" << screen << "to" << factor;
+
if (!qFuzzyCompare(factor, qreal(1))) {
m_screenFactorSet = true;
m_active = true;
}
+ QScreenPrivate::UpdateEmitter updateEmitter(screen);
+
// Prefer associating the factor with screen name over the object
// since the screen object may be deleted on screen disconnects.
const QString name = screen->name();
@@ -591,9 +578,7 @@ void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor)
else
QHighDpiScaling::m_namedScreenScaleFactors.insert(name, factor);
- // hack to force re-evaluation of screen geometry
- if (screen->handle())
- screen->d_func()->setPlatformScreen(screen->handle()); // updates geometries based on scale factor
+ screen->d_func()->updateGeometry();
}
QPoint QHighDpiScaling::mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen)
@@ -714,7 +699,7 @@ QVector<QHighDpiScaling::ScreenFactor> QHighDpiScaling::parseScreenScaleFactorsS
// - a semicolon-separated name=factor list: "foo=1.5;bar=2;baz=3"
const auto specs = screenScaleFactors.split(u';');
for (const auto &spec : specs) {
- const int equalsPos = spec.lastIndexOf(QLatin1Char('='));
+ const qsizetype equalsPos = spec.lastIndexOf(u'=');
if (equalsPos == -1) {
// screens in order
bool ok;
@@ -768,7 +753,20 @@ QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QWindow *w
return scaleAndOrigin(targetScreen, position);
}
-#else
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QHighDpiScaling::ScreenFactor &factor)
+{
+ const QDebugStateSaver saver(debug);
+ debug.nospace();
+ if (!factor.name.isEmpty())
+ debug << factor.name << "=";
+ debug << factor.factor;
+ return debug;
+}
+#endif
+
+#else // QT_NO_HIGHDPISCALING
+
QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QPlatformScreen *, QPoint *)
{
return { qreal(1), QPoint() };
@@ -783,5 +781,9 @@ QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QWindow *,
{
return { qreal(1), QPoint() };
}
-#endif //QT_NO_HIGHDPISCALING
+
+#endif // QT_NO_HIGHDPISCALING
+
QT_END_NAMESPACE
+
+#include "moc_qhighdpiscaling_p.cpp"
diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index 8460b3ec2e..189f31fd0a 100644
--- a/src/gui/kernel/qhighdpiscaling_p.h
+++ b/src/gui/kernel/qhighdpiscaling_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QHIGHDPISCALING_P_H
#define QHIGHDPISCALING_P_H
@@ -124,6 +88,7 @@ public:
static QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen);
static QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen);
static QDpi logicalDpi(const QScreen *screen);
+ static qreal roundScaleFactor(qreal rawFactor);
private:
struct ScreenFactor {
@@ -134,7 +99,6 @@ private:
};
static qreal rawScaleFactor(const QPlatformScreen *screen);
- static qreal roundScaleFactor(qreal rawFactor);
static QDpi effectiveLogicalDpi(const QPlatformScreen *screen, qreal rawFactor, qreal roundedFactor);
static qreal screenSubfactor(const QPlatformScreen *screen);
static QScreen *screenForPosition(Point position, QScreen *guess);
@@ -150,6 +114,10 @@ private:
static QVector<ScreenFactor> m_screenFactors;
static DpiAdjustmentPolicy m_dpiAdjustmentPolicy;
static QHash<QString, qreal> m_namedScreenScaleFactors;
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const ScreenFactor &);
+#endif
};
namespace QHighDpi {
@@ -219,10 +187,9 @@ inline QRegion scale(const QRegion &region, qreal scaleFactor, QPoint origin = Q
if (!QHighDpiScaling::isActive())
return region;
- QRegion scaled;
- for (const QRect &rect : region)
- scaled += scale(QRectF(rect), scaleFactor, origin).toRect();
- return scaled;
+ QRegion scaled = region.translated(-origin);
+ scaled = QTransform::fromScale(scaleFactor, scaleFactor).map(scaled);
+ return scaled.translated(origin);
}
template <typename T>
@@ -381,6 +348,9 @@ public:
namespace QHighDpi {
template <typename T> inline
+ T scale(const T &value, ...) { return value; }
+
+ template <typename T> inline
T toNative(const T &value, ...) { return value; }
template <typename T> inline
T fromNative(const T &value, ...) { return value; }
diff --git a/src/gui/kernel/qinputdevice.cpp b/src/gui/kernel/qinputdevice.cpp
index 9dcf288d00..f7b216dcf0 100644
--- a/src/gui/kernel/qinputdevice.cpp
+++ b/src/gui/kernel/qinputdevice.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qinputdevice.h"
#include "qinputdevice_p.h"
@@ -48,6 +12,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QInputDevice
\brief The QInputDevice class describes a device from which a QInputEvent originates.
@@ -101,6 +67,11 @@ QT_BEGIN_NAMESPACE
\value Scroll
Indicates that the device has a scroll capability.
+ \value [since 6.2] PixelScroll
+ Indicates that the device (usually a
+ \l {QInputDevice::DeviceType::TouchPad}{touchpad})
+ scrolls with \l {QWheelEvent::pixelDelta()}{pixel precision}.
+
\value Hover
Indicates that the device has a hover capability.
@@ -259,11 +230,18 @@ QString QInputDevice::seatName() const
using InputDevicesList = QList<const QInputDevice *>;
Q_GLOBAL_STATIC(InputDevicesList, deviceList)
-static QBasicMutex devicesMutex;
+Q_CONSTINIT static QBasicMutex devicesMutex;
/*!
Returns a list of all registered input devices (keyboards and pointing devices).
+ \note The list of devices is not always complete on all platforms. So far,
+ the most-complete information is available on the \l {Qt for Linux/X11}{X11}
+ platform, at startup and in response to hot-plugging. Most other platforms
+ are only able to provide generic devices of various types, only after receiving
+ events from them; and most platforms do not tell Qt when a device is plugged in,
+ or when it is unplugged at runtime.
+
\note The returned list cannot be used to add new devices. To add a simulated
touch screen for an autotest, QTest::createTouchDevice() can be used.
Platform plugins should call QWindowSystemInterface::registerInputDevice()
@@ -276,16 +254,37 @@ QList<const QInputDevice *> QInputDevice::devices()
}
/*!
+ \since 6.3
+
+ Returns a list of seat names for all registered input devices (keyboards and pointing devices).
+*/
+QStringList QInputDevice::seatNames()
+{
+ QMutexLocker locker(&devicesMutex);
+ const InputDevicesList devices = *deviceList();
+ locker.unlock();
+ QStringList result;
+ for (const QInputDevice *d : devices) {
+ if (!result.contains(d->seatName()))
+ result.append(d->seatName());
+ }
+
+ return result;
+}
+
+/*!
Returns the core or master keyboard on the given seat \a seatName.
*/
const QInputDevice *QInputDevice::primaryKeyboard(const QString& seatName)
{
QMutexLocker locker(&devicesMutex);
- InputDevicesList v = *deviceList();
+ const InputDevicesList devices = *deviceList();
locker.unlock();
const QInputDevice *ret = nullptr;
- for (const QInputDevice *d : v) {
- if (d->type() == DeviceType::Keyboard && d->seatName() == seatName) {
+ for (const QInputDevice *d : devices) {
+ if (d->type() != DeviceType::Keyboard)
+ continue;
+ if (seatName.isNull() || d->seatName() == seatName) {
// the master keyboard's parent is not another input device
if (!d->parent() || !qobject_cast<const QInputDevice *>(d->parent()))
return d;
@@ -297,7 +296,7 @@ const QInputDevice *QInputDevice::primaryKeyboard(const QString& seatName)
qCDebug(lcQpaInputDevices) << "no keyboards registered for seat" << seatName
<< "The platform plugin should have provided one via "
"QWindowSystemInterface::registerInputDevice(). Creating a default one for now.";
- ret = new QInputDevice(QLatin1String("core keyboard"), 0, DeviceType::Keyboard, seatName, QCoreApplication::instance());
+ ret = new QInputDevice("core keyboard"_L1, 0, DeviceType::Keyboard, seatName, QCoreApplication::instance());
QInputDevicePrivate::registerDevice(ret);
return ret;
}
@@ -305,6 +304,9 @@ const QInputDevice *QInputDevice::primaryKeyboard(const QString& seatName)
return ret;
}
+QInputDevicePrivate::~QInputDevicePrivate()
+ = default;
+
/*!
\internal
Checks whether a matching device is already registered
@@ -365,22 +367,29 @@ bool QInputDevice::operator==(const QInputDevice &other) const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QInputDevice *device)
{
- const QInputDevicePrivate *d = QInputDevicePrivate::get(device);
- if (d->pointingDeviceType)
- return operator<<(debug, static_cast<const QPointingDevice *>(device));
QDebugStateSaver saver(debug);
debug.nospace();
debug.noquote();
+
debug << "QInputDevice(";
- if (device) {
- debug << '"' << device->name() << "\", type=" << device->type()
- << Qt::hex << ", ID=" << device->systemId() << ", seat='" << device->seatName() << "'";
- } else {
- debug << '0';
+ if (!device) {
+ debug << "0)";
+ return debug;
}
+
+ const QInputDevicePrivate *d = QInputDevicePrivate::get(device);
+
+ if (d->pointingDeviceType)
+ return operator<<(debug, static_cast<const QPointingDevice *>(device));
+
+ debug << "QInputDevice(";
+ debug << '"' << device->name() << "\", type=" << device->type()
+ << ", ID=" << device->systemId() << ", seat='" << device->seatName() << "'";
debug << ')';
return debug;
}
#endif // !QT_NO_DEBUG_STREAM
QT_END_NAMESPACE
+
+#include "moc_qinputdevice.cpp"
diff --git a/src/gui/kernel/qinputdevice.h b/src/gui/kernel/qinputdevice.h
index 2fe69943bf..2b7ce32d86 100644
--- a/src/gui/kernel/qinputdevice.h
+++ b/src/gui/kernel/qinputdevice.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QINPUTDEVICE_H
#define QINPUTDEVICE_H
@@ -84,6 +48,7 @@ public:
Velocity = 0x0008,
NormalizedPosition = 0x0020,
MouseEmulation = 0x0040,
+ PixelScroll = 0x0080,
Scroll = 0x0100,
Hover = 0x0200,
Rotation = 0x0400,
@@ -109,6 +74,7 @@ public:
QString seatName() const;
QRect availableVirtualGeometry() const;
+ static QStringList seatNames();
static QList<const QInputDevice *> devices();
static const QInputDevice *primaryKeyboard(const QString& seatName = QString());
diff --git a/src/gui/kernel/qinputdevice_p.h b/src/gui/kernel/qinputdevice_p.h
index 41150d055d..7f6ee258be 100644
--- a/src/gui/kernel/qinputdevice_p.h
+++ b/src/gui/kernel/qinputdevice_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QINPUTDEVICE_P_H
#define QINPUTDEVICE_P_H
@@ -73,6 +37,7 @@ public:
if (!systemId)
systemId = nextId++;
}
+ ~QInputDevicePrivate() override;
QString name;
QString seatName;
diff --git a/src/gui/kernel/qinputdevicemanager.cpp b/src/gui/kernel/qinputdevicemanager.cpp
index 11442407e1..72af92cf17 100644
--- a/src/gui/kernel/qinputdevicemanager.cpp
+++ b/src/gui/kernel/qinputdevicemanager.cpp
@@ -1,47 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qinputdevicemanager_p.h"
#include "qinputdevicemanager_p_p.h"
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN_TAGGED(QInputDeviceManager::DeviceType, QInputDeviceManager__DeviceType)
+
/*!
\class QInputDeviceManager
\internal
@@ -67,6 +33,8 @@ QInputDeviceManager::QInputDeviceManager(QObject *parent)
qRegisterMetaType<DeviceType>();
}
+QInputDeviceManager::~QInputDeviceManager() = default;
+
int QInputDeviceManager::deviceCount(DeviceType type) const
{
Q_D(const QInputDeviceManager);
@@ -116,3 +84,5 @@ void QInputDeviceManager::setKeyboardModifiers(Qt::KeyboardModifiers mods)
}
QT_END_NAMESPACE
+
+#include "moc_qinputdevicemanager_p.cpp"
diff --git a/src/gui/kernel/qinputdevicemanager_p.h b/src/gui/kernel/qinputdevicemanager_p.h
index 1d20b102e3..9c34ece555 100644
--- a/src/gui/kernel/qinputdevicemanager_p.h
+++ b/src/gui/kernel/qinputdevicemanager_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QINPUTDEVICEMANAGER_P_H
#define QINPUTDEVICEMANAGER_P_H
@@ -74,7 +38,8 @@ public:
NumDeviceTypes
};
- QInputDeviceManager(QObject *parent = nullptr);
+ explicit QInputDeviceManager(QObject *parent = nullptr);
+ ~QInputDeviceManager() override;
int deviceCount(DeviceType type) const;
@@ -83,13 +48,14 @@ public:
Qt::KeyboardModifiers keyboardModifiers() const;
void setKeyboardModifiers(Qt::KeyboardModifiers mods);
-signals:
+Q_SIGNALS:
void deviceListChanged(QInputDeviceManager::DeviceType type);
void cursorPositionChangeRequested(const QPoint &pos);
};
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QInputDeviceManager::DeviceType)
+QT_DECL_METATYPE_EXTERN_TAGGED(QInputDeviceManager::DeviceType,
+ QInputDeviceManager__DeviceType, Q_GUI_EXPORT)
#endif // QINPUTDEVICEMANAGER_P_H
diff --git a/src/gui/kernel/qinputdevicemanager_p_p.h b/src/gui/kernel/qinputdevicemanager_p_p.h
index 82a86446a0..b43904aa67 100644
--- a/src/gui/kernel/qinputdevicemanager_p_p.h
+++ b/src/gui/kernel/qinputdevicemanager_p_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QINPUTDEVICEMANAGER_P_P_H
#define QINPUTDEVICEMANAGER_P_P_H
diff --git a/src/gui/kernel/qinputmethod.cpp b/src/gui/kernel/qinputmethod.cpp
index f5de06aea1..e37e85e246 100644
--- a/src/gui/kernel/qinputmethod.cpp
+++ b/src/gui/kernel/qinputmethod.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qinputmethod.h>
#include <private/qinputmethod_p.h>
@@ -426,13 +390,21 @@ QVariant QInputMethod::queryFocusObject(Qt::InputMethodQuery query, const QVaria
if (!focusObject)
return retval;
- bool newMethodWorks = QMetaObject::invokeMethod(focusObject, "inputMethodQuery",
- Qt::DirectConnection,
- Q_RETURN_ARG(QVariant, retval),
- Q_ARG(Qt::InputMethodQuery, query),
- Q_ARG(QVariant, argument));
- if (newMethodWorks)
- return retval;
+ static const char *signature = "inputMethodQuery(Qt::InputMethodQuery,QVariant)";
+ const bool newMethodSupported = focusObject->metaObject()->indexOfMethod(signature) != -1;
+ if (newMethodSupported) {
+ const bool ok = QMetaObject::invokeMethod(focusObject, "inputMethodQuery",
+ Qt::DirectConnection,
+ Q_RETURN_ARG(QVariant, retval),
+ Q_ARG(Qt::InputMethodQuery, query),
+ Q_ARG(QVariant, argument));
+ Q_ASSERT(ok);
+ if (retval.isValid())
+ return retval;
+
+ // If the new API didn't have an answer to the query, we fall
+ // back to use the old event-based API.
+ }
QInputMethodQueryEvent queryEvent(query);
QCoreApplication::sendEvent(focusObject, &queryEvent);
diff --git a/src/gui/kernel/qinputmethod.h b/src/gui/kernel/qinputmethod.h
index 32831573a4..dfddc9b7c7 100644
--- a/src/gui/kernel/qinputmethod.h
+++ b/src/gui/kernel/qinputmethod.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QINPUTMETHOD_H
#define QINPUTMETHOD_H
diff --git a/src/gui/kernel/qinputmethod_p.h b/src/gui/kernel/qinputmethod_p.h
index 5657edeb4e..9191813b44 100644
--- a/src/gui/kernel/qinputmethod_p.h
+++ b/src/gui/kernel/qinputmethod_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QINPUTMETHOD_P_H
#define QINPUTMETHOD_P_H
diff --git a/src/gui/kernel/qinternalmimedata.cpp b/src/gui/kernel/qinternalmimedata.cpp
index 5dc296cd01..d33402703e 100644
--- a/src/gui/kernel/qinternalmimedata.cpp
+++ b/src/gui/kernel/qinternalmimedata.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qinternalmimedata_p.h"
@@ -46,15 +10,17 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static QStringList imageMimeFormats(const QList<QByteArray> &imageFormats)
{
QStringList formats;
formats.reserve(imageFormats.size());
for (const auto &format : imageFormats)
- formats.append(QLatin1String("image/") + QLatin1String(format.toLower()));
+ formats.append("image/"_L1 + QLatin1StringView(format.toLower()));
//put png at the front because it is best
- int pngIndex = formats.indexOf(QLatin1String("image/png"));
+ const qsizetype pngIndex = formats.indexOf("image/png"_L1);
if (pngIndex != -1 && pngIndex != 0)
formats.move(pngIndex, 0);
@@ -83,7 +49,7 @@ QInternalMimeData::~QInternalMimeData()
bool QInternalMimeData::hasFormat(const QString &mimeType) const
{
bool foundFormat = hasFormat_sys(mimeType);
- if (!foundFormat && mimeType == QLatin1String("application/x-qt-image")) {
+ if (!foundFormat && mimeType == "application/x-qt-image"_L1) {
QStringList imageFormats = imageReadMimeFormats();
for (int i = 0; i < imageFormats.size(); ++i) {
if ((foundFormat = hasFormat_sys(imageFormats.at(i))))
@@ -96,11 +62,11 @@ bool QInternalMimeData::hasFormat(const QString &mimeType) const
QStringList QInternalMimeData::formats() const
{
QStringList realFormats = formats_sys();
- if (!realFormats.contains(QLatin1String("application/x-qt-image"))) {
+ if (!realFormats.contains("application/x-qt-image"_L1)) {
QStringList imageFormats = imageReadMimeFormats();
for (int i = 0; i < imageFormats.size(); ++i) {
if (realFormats.contains(imageFormats.at(i))) {
- realFormats += QLatin1String("application/x-qt-image");
+ realFormats += "application/x-qt-image"_L1;
break;
}
}
@@ -111,7 +77,7 @@ QStringList QInternalMimeData::formats() const
QVariant QInternalMimeData::retrieveData(const QString &mimeType, QMetaType type) const
{
QVariant data = retrieveData_sys(mimeType, type);
- if (mimeType == QLatin1String("application/x-qt-image")) {
+ if (mimeType == "application/x-qt-image"_L1) {
if (data.isNull() || (data.metaType().id() == QMetaType::QByteArray && data.toByteArray().isEmpty())) {
// try to find an image
QStringList imageFormats = imageReadMimeFormats();
@@ -128,7 +94,7 @@ QVariant QInternalMimeData::retrieveData(const QString &mimeType, QMetaType type
&& (typeId == QMetaType::QImage || typeId == QMetaType::QPixmap || typeId == QMetaType::QBitmap))
data = QImage::fromData(data.toByteArray());
- } else if (mimeType == QLatin1String("application/x-color") && data.metaType().id() == QMetaType::QByteArray) {
+ } else if (mimeType == "application/x-color"_L1 && data.metaType().id() == QMetaType::QByteArray) {
QColor c;
QByteArray ba = data.toByteArray();
if (ba.size() == 8) {
@@ -160,7 +126,7 @@ bool QInternalMimeData::canReadData(const QString &mimeType)
QStringList QInternalMimeData::formatsHelper(const QMimeData *data)
{
QStringList realFormats = data->formats();
- if (realFormats.contains(QLatin1String("application/x-qt-image"))) {
+ if (realFormats.contains("application/x-qt-image"_L1)) {
// add all supported image formats
QStringList imageFormats = imageWriteMimeFormats();
for (int i = 0; i < imageFormats.size(); ++i) {
@@ -176,14 +142,14 @@ bool QInternalMimeData::hasFormatHelper(const QString &mimeType, const QMimeData
bool foundFormat = data->hasFormat(mimeType);
if (!foundFormat) {
- if (mimeType == QLatin1String("application/x-qt-image")) {
+ if (mimeType == "application/x-qt-image"_L1) {
// check all supported image formats
QStringList imageFormats = imageWriteMimeFormats();
for (int i = 0; i < imageFormats.size(); ++i) {
if ((foundFormat = data->hasFormat(imageFormats.at(i))))
break;
}
- } else if (mimeType.startsWith(QLatin1String("image/"))) {
+ } else if (mimeType.startsWith("image/"_L1)) {
return data->hasImage() && imageWriteMimeFormats().contains(mimeType);
}
}
@@ -193,7 +159,7 @@ bool QInternalMimeData::hasFormatHelper(const QString &mimeType, const QMimeData
QByteArray QInternalMimeData::renderDataHelper(const QString &mimeType, const QMimeData *data)
{
QByteArray ba;
- if (mimeType == QLatin1String("application/x-color")) {
+ if (mimeType == "application/x-color"_L1) {
/* QMimeData can only provide colors as QColor or the name
of a color as a QByteArray or a QString. So we need to do
the conversion to application/x-color here.
@@ -215,17 +181,17 @@ QByteArray QInternalMimeData::renderDataHelper(const QString &mimeType, const QM
} else {
ba = data->data(mimeType);
if (ba.isEmpty()) {
- if (mimeType == QLatin1String("application/x-qt-image") && data->hasImage()) {
+ if (mimeType == "application/x-qt-image"_L1 && data->hasImage()) {
QImage image = qvariant_cast<QImage>(data->imageData());
QBuffer buf(&ba);
buf.open(QBuffer::WriteOnly);
// would there not be PNG ??
image.save(&buf, "PNG");
- } else if (mimeType.startsWith(QLatin1String("image/")) && data->hasImage()) {
+ } else if (mimeType.startsWith("image/"_L1) && data->hasImage()) {
QImage image = qvariant_cast<QImage>(data->imageData());
QBuffer buf(&ba);
buf.open(QBuffer::WriteOnly);
- image.save(&buf, mimeType.mid(mimeType.indexOf(QLatin1Char('/')) + 1).toLatin1().toUpper());
+ image.save(&buf, mimeType.mid(mimeType.indexOf(u'/') + 1).toLatin1().toUpper());
}
}
}
@@ -233,3 +199,5 @@ QByteArray QInternalMimeData::renderDataHelper(const QString &mimeType, const QM
}
QT_END_NAMESPACE
+
+#include "moc_qinternalmimedata_p.cpp"
diff --git a/src/gui/kernel/qinternalmimedata_p.h b/src/gui/kernel/qinternalmimedata_p.h
index 5c61370360..ce4cfaa72d 100644
--- a/src/gui/kernel/qinternalmimedata_p.h
+++ b/src/gui/kernel/qinternalmimedata_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QINTERNALMIMEDATA_P_H
#define QINTERNALMIMEDATA_P_H
diff --git a/src/gui/kernel/qkeymapper.cpp b/src/gui/kernel/qkeymapper.cpp
index 054d850dbb..4ceb508465 100644
--- a/src/gui/kernel/qkeymapper.cpp
+++ b/src/gui/kernel/qkeymapper.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qguiapplication.h"
@@ -45,6 +9,7 @@
#include <private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformkeymapper.h>
QT_BEGIN_NAMESPACE
@@ -59,8 +24,7 @@ QT_BEGIN_NAMESPACE
/*!
Constructs a new key mapper.
*/
-QKeyMapper::QKeyMapper()
- : QObject(*new QKeyMapperPrivate, nullptr)
+QKeyMapper::QKeyMapper() : QObject()
{
}
@@ -71,34 +35,34 @@ QKeyMapper::~QKeyMapper()
{
}
-static QList<int> extractKeyFromEvent(QKeyEvent *e)
+QList<QKeyCombination> QKeyMapper::possibleKeys(const QKeyEvent *e)
{
- QList<int> result;
- if (e->key() && (e->key() != Qt::Key_unknown))
- result << e->keyCombination().toCombined();
- else if (!e->text().isEmpty())
- result << int(e->text().at(0).unicode() + (int)e->modifiers());
- return result;
-}
+ qCDebug(lcQpaKeyMapper).verbosity(3) << "Computing possible key combinations for" << e;
-QList<int> QKeyMapper::possibleKeys(QKeyEvent *e)
-{
- return instance()->d_func()->possibleKeys(e);
-}
+ const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
+ const auto *platformKeyMapper = platformIntegration->keyMapper();
+ QList<QKeyCombination> result = platformKeyMapper->possibleKeyCombinations(e);
-extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // in qapplication_*.cpp
-void QKeyMapper::changeKeyboard()
-{
- // ## TODO: Support KeyboardLayoutChange on QPA
-#if 0
- // inform all toplevel widgets of the change
- QEvent e(QEvent::KeyboardLayoutChange);
- QWidgetList list = QApplication::topLevelWidgets();
- for (int i = 0; i < list.size(); ++i) {
- QWidget *w = list.at(i);
- qt_sendSpontaneousEvent(w, &e);
+ if (result.isEmpty()) {
+ if (e->key() && (e->key() != Qt::Key_unknown))
+ result << e->keyCombination();
+ else if (!e->text().isEmpty())
+ result << (Qt::Key(e->text().at(0).unicode()) | e->modifiers());
+ }
+
+#if QT_CONFIG(shortcut)
+ if (lcQpaKeyMapper().isDebugEnabled()) {
+ qCDebug(lcQpaKeyMapper) << "Resulting possible key combinations:";
+ for (auto keyCombination : result) {
+ auto keySequence = QKeySequence(keyCombination);
+ qCDebug(lcQpaKeyMapper).verbosity(0) << "\t-"
+ << keyCombination << "/" << keySequence << "/"
+ << qUtf8Printable(keySequence.toString(QKeySequence::NativeText));
+ }
}
#endif
+
+ return result;
}
Q_GLOBAL_STATIC(QKeyMapper, keymapper)
@@ -111,30 +75,6 @@ QKeyMapper *QKeyMapper::instance()
return keymapper();
}
-QKeyMapperPrivate *qt_keymapper_private()
-{
- return QKeyMapper::instance()->d_func();
-}
-
-QKeyMapperPrivate::QKeyMapperPrivate()
-{
- keyboardInputLocale = QLocale::system();
- keyboardInputDirection = keyboardInputLocale.textDirection();
-}
-
-QKeyMapperPrivate::~QKeyMapperPrivate()
-{
-}
-
-QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
-{
- QList<int> result = QGuiApplicationPrivate::platformIntegration()->possibleKeys(e);
- if (!result.isEmpty())
- return result;
-
- return extractKeyFromEvent(e);
-}
-
void *QKeyMapper::resolveInterface(const char *name, int revision) const
{
Q_UNUSED(name); Q_UNUSED(revision);
@@ -148,3 +88,5 @@ void *QKeyMapper::resolveInterface(const char *name, int revision) const
}
QT_END_NAMESPACE
+
+#include "moc_qkeymapper_p.cpp"
diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h
index 0297a69e28..1a6a9a608f 100644
--- a/src/gui/kernel/qkeymapper_p.h
+++ b/src/gui/kernel/qkeymapper_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QKEYMAPPER_P_H
#define QKEYMAPPER_P_H
@@ -61,7 +25,6 @@
QT_BEGIN_NAMESPACE
-class QKeyMapperPrivate;
class Q_GUI_EXPORT QKeyMapper : public QObject
{
Q_OBJECT
@@ -70,40 +33,19 @@ public:
~QKeyMapper();
static QKeyMapper *instance();
- static void changeKeyboard();
- static QList<int> possibleKeys(QKeyEvent *e);
+ static QList<QKeyCombination> possibleKeys(const QKeyEvent *e);
QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(QKeyMapper)
private:
- friend QKeyMapperPrivate *qt_keymapper_private();
- Q_DECLARE_PRIVATE(QKeyMapper)
Q_DISABLE_COPY_MOVE(QKeyMapper)
};
-struct KeyboardLayoutItem;
-class QKeyEvent;
-
-class QKeyMapperPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QKeyMapper)
-public:
- QKeyMapperPrivate();
- ~QKeyMapperPrivate();
-
- QList<int> possibleKeys(QKeyEvent *e);
-
- QLocale keyboardInputLocale;
- Qt::LayoutDirection keyboardInputDirection;
-};
-
-QKeyMapperPrivate *qt_keymapper_private(); // from qkeymapper.cpp
-
// ----------------- QNativeInterface -----------------
namespace QNativeInterface::Private {
-#if QT_CONFIG(evdev) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(evdev) || defined(Q_QDOC)
struct Q_GUI_EXPORT QEvdevKeyMapper
{
QT_DECLARE_NATIVE_INTERFACE(QEvdevKeyMapper, 1, QKeyMapper)
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index c10ba93954..0529d940d2 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qkeysequence.h"
#include "qkeysequence_p.h"
@@ -49,30 +13,32 @@
#endif
#include "qvariant.h"
-#if defined(Q_OS_MACOS)
+#if defined(Q_OS_APPLE)
#include <QtCore/private/qcore_mac_p.h>
#endif
#include <algorithm>
+#include <q20algorithm.h>
QT_BEGIN_NAMESPACE
-#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
-static bool qt_sequence_no_mnemonics = true;
-struct MacSpecialKey {
+using namespace Qt::StringLiterals;
+
+#if defined(Q_OS_APPLE) || defined(Q_QDOC)
+Q_CONSTINIT static bool qt_sequence_no_mnemonics = true;
+struct AppleSpecialKey {
int key;
- ushort macSymbol;
+ ushort appleSymbol;
};
// Unicode code points for the glyphs associated with these keys
// Defined by Carbon headers but not anywhere in Cocoa
-static const int kShiftUnicode = 0x21E7;
-static const int kControlUnicode = 0x2303;
-static const int kOptionUnicode = 0x2325;
-static const int kCommandUnicode = 0x2318;
+static constexpr int kShiftUnicode = 0x21E7;
+static constexpr int kControlUnicode = 0x2303;
+static constexpr int kOptionUnicode = 0x2325;
+static constexpr int kCommandUnicode = 0x2318;
-static const int NumEntries = 21;
-static const MacSpecialKey entries[NumEntries] = {
+static constexpr AppleSpecialKey entries[] = {
{ Qt::Key_Escape, 0x238B },
{ Qt::Key_Tab, 0x21E5 },
{ Qt::Key_Backtab, 0x21E4 },
@@ -80,6 +46,7 @@ static const MacSpecialKey entries[NumEntries] = {
{ Qt::Key_Return, 0x21B5 },
{ Qt::Key_Enter, 0x2324 },
{ Qt::Key_Delete, 0x2326 },
+ { Qt::Key_Clear, 0x2327 },
{ Qt::Key_Home, 0x2196 },
{ Qt::Key_End, 0x2198 },
{ Qt::Key_Left, 0x2190 },
@@ -93,43 +60,48 @@ static const MacSpecialKey entries[NumEntries] = {
{ Qt::Key_Meta, kControlUnicode },
{ Qt::Key_Alt, kOptionUnicode },
{ Qt::Key_CapsLock, 0x21EA },
+ { Qt::Key_Eject, 0x23CF },
};
-static bool operator<(const MacSpecialKey &entry, int key)
+static constexpr bool operator<(const AppleSpecialKey &lhs, const AppleSpecialKey &rhs)
{
- return entry.key < key;
+ return lhs.key < rhs.key;
}
-static bool operator<(int key, const MacSpecialKey &entry)
+static constexpr bool operator<(const AppleSpecialKey &lhs, int rhs)
{
- return key < entry.key;
+ return lhs.key < rhs;
}
-static const MacSpecialKey * const MacSpecialKeyEntriesEnd = entries + NumEntries;
+static constexpr bool operator<(int lhs, const AppleSpecialKey &rhs)
+{
+ return lhs < rhs.key;
+}
-QChar qt_macSymbolForQtKey(int key)
+static_assert(q20::is_sorted(std::begin(entries), std::end(entries)));
+
+static QChar appleSymbolForQtKey(int key)
{
- const MacSpecialKey *i = std::lower_bound(entries, MacSpecialKeyEntriesEnd, key);
- if ((i == MacSpecialKeyEntriesEnd) || (key < *i))
+ const auto i = std::lower_bound(std::begin(entries), std::end(entries), key);
+ if (i == std::end(entries) || key < *i)
return QChar();
- ushort macSymbol = i->macSymbol;
+ ushort appleSymbol = i->appleSymbol;
if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)
- && (macSymbol == kControlUnicode || macSymbol == kCommandUnicode)) {
- if (macSymbol == kControlUnicode)
- macSymbol = kCommandUnicode;
+ && (appleSymbol == kControlUnicode || appleSymbol == kCommandUnicode)) {
+ if (appleSymbol == kControlUnicode)
+ appleSymbol = kCommandUnicode;
else
- macSymbol = kControlUnicode;
+ appleSymbol = kControlUnicode;
}
- return QChar(macSymbol);
+ return QChar(appleSymbol);
}
-static int qtkeyForMacSymbol(const QChar ch)
+static int qtkeyForAppleSymbol(const QChar ch)
{
const ushort unicode = ch.unicode();
- for (int i = 0; i < NumEntries; ++i) {
- const MacSpecialKey &entry = entries[i];
- if (entry.macSymbol == unicode) {
+ for (const AppleSpecialKey &entry : entries) {
+ if (entry.appleSymbol == unicode) {
int key = entry.key;
if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)
&& (unicode == kControlUnicode || unicode == kCommandUnicode)) {
@@ -145,7 +117,7 @@ static int qtkeyForMacSymbol(const QChar ch)
}
#else
-static bool qt_sequence_no_mnemonics = false;
+Q_CONSTINIT static bool qt_sequence_no_mnemonics = false;
#endif
/*!
@@ -192,9 +164,10 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
for users of different languages. Translations are made in the
"QShortcut" context.
\li For hard-coded shortcuts, integer key codes can be specified with
- a combination of values defined by the Qt::Key and Qt::Modifier enum
- values. Each key code consists of a single Qt::Key value and zero or
- more modifiers, such as Qt::SHIFT, Qt::CTRL, Qt::ALT and Qt::META.
+ a combination of values defined by the Qt::Key and Qt::KeyboardModifier
+ enum values. Each key code consists of a single Qt::Key value and zero
+ or more modifiers, such as Qt::ShiftModifier, Qt::ControlModifier,
+ Qt::AltModifier and Qt::MetaModifier.
\endlist
For example, \uicontrol{Ctrl P} might be a sequence used as a shortcut for
@@ -218,7 +191,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
QKeySequence objects can be cast to a QString to obtain a human-readable
translated version of the sequence. Similarly, the toString() function
- produces human-readable strings for use in menus. On \macos, the
+ produces human-readable strings for use in menus. On Apple platforms, the
appropriate symbols are used to describe keyboard shortcuts using special
keys on the Macintosh keyboard.
@@ -226,12 +199,12 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
code point of the character; for example, 'A' gives the same key sequence
as Qt::Key_A.
- \note On \macos, references to "Ctrl", Qt::CTRL, Qt::Key_Control
+ \note On Apple platforms, references to "Ctrl", Qt::CTRL, Qt::Key_Control
and Qt::ControlModifier correspond to the \uicontrol Command keys on the
Macintosh keyboard, and references to "Meta", Qt::META, Qt::Key_Meta and
- Qt::MetaModifier correspond to the \uicontrol Control keys. Developers on
- \macos can use the same shortcut descriptions across all platforms,
- and their applications will automatically work as expected on \macos.
+ Qt::MetaModifier correspond to the \uicontrol Control keys. In effect,
+ developers can use the same shortcut descriptions across all platforms,
+ and their applications will automatically work as expected on Apple platforms.
\section1 Standard Shortcuts
@@ -240,21 +213,21 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
setting up actions in a typical application. The table below shows
some common key sequences that are often used for these standard
shortcuts by applications on four widely-used platforms. Note
- that on \macos, the \uicontrol Ctrl value corresponds to the \uicontrol
+ that on Apple platforms, the \uicontrol Ctrl value corresponds to the \uicontrol
Command keys on the Macintosh keyboard, and the \uicontrol Meta value
corresponds to the \uicontrol Control keys.
\table
- \header \li StandardKey \li Windows \li \macos \li KDE Plasma \li GNOME
+ \header \li StandardKey \li Windows \li Apple platforms \li KDE Plasma \li GNOME
\row \li HelpContents \li F1 \li Ctrl+? \li F1 \li F1
\row \li WhatsThis \li Shift+F1 \li Shift+F1 \li Shift+F1 \li Shift+F1
\row \li Open \li Ctrl+O \li Ctrl+O \li Ctrl+O \li Ctrl+O
\row \li Close \li Ctrl+F4, Ctrl+W \li Ctrl+W, Ctrl+F4 \li Ctrl+W \li Ctrl+W
\row \li Save \li Ctrl+S \li Ctrl+S \li Ctrl+S \li Ctrl+S
\row \li Quit \li \li Ctrl+Q \li Ctrl+Q \li Ctrl+Q
- \row \li SaveAs \li \li Ctrl+Shift+S \li \li Ctrl+Shift+S
+ \row \li SaveAs \li Ctrl+Shift+S \li Ctrl+Shift+S \li Ctrl+Shift+S \li Ctrl+Shift+S
\row \li New \li Ctrl+N \li Ctrl+N \li Ctrl+N \li Ctrl+N
- \row \li Delete \li Del \li Del, Meta+D \li Del, Ctrl+D \li Del, Ctrl+D
+ \row \li Delete \li Del \li Forward Delete, Meta+D \li Del, Ctrl+D \li Del, Ctrl+D
\row \li Cut \li Ctrl+X, Shift+Del \li Ctrl+X, Meta+K \li Ctrl+X, F20, Shift+Del \li Ctrl+X, F20, Shift+Del
\row \li Copy \li Ctrl+C, Ctrl+Ins \li Ctrl+C \li Ctrl+C, F16, Ctrl+Ins \li Ctrl+C, F16, Ctrl+Ins
\row \li Paste \li Ctrl+V, Shift+Ins \li Ctrl+V, Meta+Y \li Ctrl+V, F18, Shift+Ins \li Ctrl+V, F18, Shift+Ins
@@ -314,7 +287,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
\row \li DeleteCompleteLine \li (none) \li (none) \li Ctrl+U \li Ctrl+U
\row \li InsertParagraphSeparator \li Enter \li Enter \li Enter \li Enter
\row \li InsertLineSeparator \li Shift+Enter \li Meta+Enter, Meta+O \li Shift+Enter \li Shift+Enter
- \row \li Backspace \li (none) \li Meta+H \li (none) \li (none)
+ \row \li Backspace \li (none) \li Delete, Meta+H \li (none) \li (none)
\row \li Cancel \li Escape \li Escape, Ctrl+. \li Escape \li Escape
\endtable
@@ -401,7 +374,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
\enum QKeySequence::SequenceFormat
\value NativeText The key sequence as a platform specific string.
- This means that it will be shown translated and on the Mac it will
+ This means that it will be shown translated and on Apple platforms it will
resemble a key sequence from the menu bar. This enum is best used when you
want to display the string to the user.
@@ -410,7 +383,7 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
similar to the native text on Windows and X11.
*/
-static const struct {
+static constexpr struct {
int key;
const char name[25];
} keyname[] = {
@@ -699,6 +672,10 @@ static const struct {
{ Qt::Key_TouchpadToggle, QT_TRANSLATE_NOOP("QShortcut", "Touchpad Toggle") },
{ Qt::Key_TouchpadOn, QT_TRANSLATE_NOOP("QShortcut", "Touchpad On") },
{ Qt::Key_TouchpadOff, QT_TRANSLATE_NOOP("QShortcut", "Touchpad Off") },
+ { Qt::Key_Shift, QT_TRANSLATE_NOOP("QShortcut", "Shift") },
+ { Qt::Key_Control, QT_TRANSLATE_NOOP("QShortcut", "Control") },
+ { Qt::Key_Alt, QT_TRANSLATE_NOOP("QShortcut", "Alt") },
+ { Qt::Key_Meta, QT_TRANSLATE_NOOP("QShortcut", "Meta") },
};
static constexpr int numKeyNames = sizeof keyname / sizeof *keyname;
@@ -733,7 +710,7 @@ static constexpr int numKeyNames = sizeof keyname / sizeof *keyname;
\value InsertLineSeparator Insert a new line.
\value InsertParagraphSeparator Insert a new paragraph.
\value Italic Italic text.
- \value MoveToEndOfBlock Move cursor to end of block. This shortcut is only used on the \macos.
+ \value MoveToEndOfBlock Move cursor to end of block. This shortcut is only used on Apple platforms.
\value MoveToEndOfDocument Move cursor to end of document.
\value MoveToEndOfLine Move cursor to end of line.
\value MoveToNextChar Move cursor to next character.
@@ -744,7 +721,7 @@ static constexpr int numKeyNames = sizeof keyname / sizeof *keyname;
\value MoveToPreviousLine Move cursor to previous line.
\value MoveToPreviousPage Move cursor to previous page.
\value MoveToPreviousWord Move cursor to previous word.
- \value MoveToStartOfBlock Move cursor to start of a block. This shortcut is only used on \macos.
+ \value MoveToStartOfBlock Move cursor to start of a block. This shortcut is only used on Apple platforms.
\value MoveToStartOfDocument Move cursor to start of document.
\value MoveToStartOfLine Move cursor to start of line.
\value New Create new document.
@@ -762,7 +739,7 @@ static constexpr int numKeyNames = sizeof keyname / sizeof *keyname;
\value Save Save document.
\value SelectAll Select all text.
\value Deselect Deselect text. Since 5.1
- \value SelectEndOfBlock Extend selection to the end of a text block. This shortcut is only used on \macos.
+ \value SelectEndOfBlock Extend selection to the end of a text block. This shortcut is only used on Apple platforms.
\value SelectEndOfDocument Extend selection to end of document.
\value SelectEndOfLine Extend selection to end of line.
\value SelectNextChar Extend selection to next character.
@@ -773,7 +750,7 @@ static constexpr int numKeyNames = sizeof keyname / sizeof *keyname;
\value SelectPreviousLine Extend selection to previous line.
\value SelectPreviousPage Extend selection to previous page.
\value SelectPreviousWord Extend selection to previous word.
- \value SelectStartOfBlock Extend selection to the start of a text block. This shortcut is only used on \macos.
+ \value SelectStartOfBlock Extend selection to the start of a text block. This shortcut is only used on Apple platforms.
\value SelectStartOfDocument Extend selection to start of document.
\value SelectStartOfLine Extend selection to start of line.
\value Underline Underline text.
@@ -807,8 +784,8 @@ QKeySequence::QKeySequence(StandardKey key)
{
const QList <QKeySequence> bindings = keyBindings(key);
//pick only the first/primary shortcut from current bindings
- if (bindings.size() > 0) {
- d = bindings.first().d;
+ if (!bindings.isEmpty()) {
+ d = bindings.constFirst().d;
d->ref.ref();
}
else
@@ -821,7 +798,7 @@ QKeySequence::QKeySequence(StandardKey key)
*/
QKeySequence::QKeySequence()
{
- static QKeySequencePrivate shared_empty;
+ Q_CONSTINIT static QKeySequencePrivate shared_empty;
d = &shared_empty;
d->ref.ref();
}
@@ -857,8 +834,8 @@ static_assert(QKeySequencePrivate::MaxKeyCount == 4, "Change docs and ctor impl
\a k3 and \a k4.
The key codes are listed in Qt::Key and can be combined with
- modifiers (see Qt::Modifier) such as Qt::SHIFT, Qt::CTRL,
- Qt::ALT, or Qt::META.
+ modifiers (see Qt::KeyboardModifier) such as Qt::ShiftModifier,
+ Qt::ControlModifier, Qt::AltModifier, or Qt::MetaModifier.
*/
QKeySequence::QKeySequence(int k1, int k2, int k3, int k4)
{
@@ -954,11 +931,6 @@ bool QKeySequence::isEmpty() const
For example, mnemonic("E&xit") returns \c{Qt::ALT+Qt::Key_X},
mnemonic("&Quit") returns \c{ALT+Key_Q}, and mnemonic("Quit")
returns an empty QKeySequence.
-
- We provide a \l{accelerators.html}{list of common mnemonics}
- in English. At the time of writing, Microsoft and Open Group do
- not appear to have issued equivalent recommendations for other
- languages.
*/
QKeySequence QKeySequence::mnemonic(const QString &text)
{
@@ -968,12 +940,12 @@ QKeySequence QKeySequence::mnemonic(const QString &text)
return ret;
bool found = false;
- int p = 0;
+ qsizetype p = 0;
while (p >= 0) {
- p = text.indexOf(QLatin1Char('&'), p) + 1;
- if (p <= 0 || p >= (int)text.length())
+ p = text.indexOf(u'&', p) + 1;
+ if (p <= 0 || p >= (int)text.size())
break;
- if (text.at(p) != QLatin1Char('&')) {
+ if (text.at(p) != u'&') {
QChar c = text.at(p);
if (c.isPrint()) {
if (!found) {
@@ -1021,22 +993,22 @@ int QKeySequence::assign(const QString &ks, QKeySequence::SequenceFormat format)
{
QString keyseq = ks;
int n = 0;
- int p = 0, diff = 0;
+ qsizetype p = 0, diff = 0;
// Run through the whole string, but stop
// if we have MaxKeyCount keys before the end.
- while (keyseq.length() && n < QKeySequencePrivate::MaxKeyCount) {
+ while (keyseq.size() && n < QKeySequencePrivate::MaxKeyCount) {
// We MUST use something to separate each sequence, and space
// does not cut it, since some of the key names have space
// in them.. (Let's hope no one translate with a comma in it:)
- p = keyseq.indexOf(QLatin1Char(','));
+ p = keyseq.indexOf(u',');
if (-1 != p) {
- if (p == keyseq.count() - 1) { // Last comma 'Ctrl+,'
+ if (p == keyseq.size() - 1) { // Last comma 'Ctrl+,'
p = -1;
} else {
- if (QLatin1Char(',') == keyseq.at(p+1)) // e.g. 'Ctrl+,, Shift+,,'
+ if (u',' == keyseq.at(p+1)) // e.g. 'Ctrl+,, Shift+,,'
p++;
- if (QLatin1Char(' ') == keyseq.at(p+1)) { // Space after comma
+ if (u' ' == keyseq.at(p+1)) { // Space after comma
diff = 1;
p++;
} else {
@@ -1044,9 +1016,9 @@ int QKeySequence::assign(const QString &ks, QKeySequence::SequenceFormat format)
}
}
}
- QString part = keyseq.left(-1 == p ? keyseq.length() : p - diff);
- keyseq = keyseq.right(-1 == p ? 0 : keyseq.length() - (p + 1));
- d->key[n] = QKeySequencePrivate::decodeString(std::move(part), format);
+ QString part = keyseq.left(-1 == p ? keyseq.size() : p - diff);
+ keyseq = keyseq.right(-1 == p ? 0 : keyseq.size() - (p + 1));
+ d->key[n] = QKeySequencePrivate::decodeString(std::move(part), format).toCombined();
++n;
}
return n;
@@ -1064,15 +1036,7 @@ Q_DECLARE_TYPEINFO(QModifKeyName, Q_RELOCATABLE_TYPE);
Q_GLOBAL_STATIC(QList<QModifKeyName>, globalModifs)
Q_GLOBAL_STATIC(QList<QModifKeyName>, globalPortableModifs)
-/*!
- Constructs a single key from the string \a str.
-*/
-int QKeySequence::decodeString(const QString &str)
-{
- return QKeySequencePrivate::decodeString(str, NativeText);
-}
-
-int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceFormat format)
+QKeyCombination QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceFormat format)
{
Q_ASSERT(!accel.isEmpty());
@@ -1084,7 +1048,7 @@ int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceForma
if (nativeText) {
gmodifs = globalModifs();
if (gmodifs->isEmpty()) {
-#if defined(Q_OS_MACOS)
+#if defined(Q_OS_APPLE)
const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
if (dontSwap)
*gmodifs << QModifKeyName(Qt::META, QChar(kCommandUnicode));
@@ -1097,36 +1061,36 @@ int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceForma
*gmodifs << QModifKeyName(Qt::META, QChar(kControlUnicode));
*gmodifs << QModifKeyName(Qt::SHIFT, QChar(kShiftUnicode));
#endif
- *gmodifs << QModifKeyName(Qt::CTRL, QLatin1String("ctrl+"))
- << QModifKeyName(Qt::SHIFT, QLatin1String("shift+"))
- << QModifKeyName(Qt::ALT, QLatin1String("alt+"))
- << QModifKeyName(Qt::META, QLatin1String("meta+"))
- << QModifKeyName(Qt::KeypadModifier, QLatin1String("num+"));
+ *gmodifs << QModifKeyName(Qt::CTRL, u"ctrl+"_s)
+ << QModifKeyName(Qt::SHIFT, u"shift+"_s)
+ << QModifKeyName(Qt::ALT, u"alt+"_s)
+ << QModifKeyName(Qt::META, u"meta+"_s)
+ << QModifKeyName(Qt::KeypadModifier, u"num+"_s);
}
} else {
gmodifs = globalPortableModifs();
if (gmodifs->isEmpty()) {
- *gmodifs << QModifKeyName(Qt::CTRL, QLatin1String("ctrl+"))
- << QModifKeyName(Qt::SHIFT, QLatin1String("shift+"))
- << QModifKeyName(Qt::ALT, QLatin1String("alt+"))
- << QModifKeyName(Qt::META, QLatin1String("meta+"))
- << QModifKeyName(Qt::KeypadModifier, QLatin1String("num+"));
+ *gmodifs << QModifKeyName(Qt::CTRL, u"ctrl+"_s)
+ << QModifKeyName(Qt::SHIFT, u"shift+"_s)
+ << QModifKeyName(Qt::ALT, u"alt+"_s)
+ << QModifKeyName(Qt::META, u"meta+"_s)
+ << QModifKeyName(Qt::KeypadModifier, u"num+"_s);
}
}
QList<QModifKeyName> modifs;
if (nativeText) {
- modifs << QModifKeyName(Qt::CTRL, QCoreApplication::translate("QShortcut", "Ctrl").toLower().append(QLatin1Char('+')))
- << QModifKeyName(Qt::SHIFT, QCoreApplication::translate("QShortcut", "Shift").toLower().append(QLatin1Char('+')))
- << QModifKeyName(Qt::ALT, QCoreApplication::translate("QShortcut", "Alt").toLower().append(QLatin1Char('+')))
- << QModifKeyName(Qt::META, QCoreApplication::translate("QShortcut", "Meta").toLower().append(QLatin1Char('+')))
- << QModifKeyName(Qt::KeypadModifier, QCoreApplication::translate("QShortcut", "Num").toLower().append(QLatin1Char('+')));
+ modifs << QModifKeyName(Qt::CTRL, QCoreApplication::translate("QShortcut", "Ctrl").toLower().append(u'+'))
+ << QModifKeyName(Qt::SHIFT, QCoreApplication::translate("QShortcut", "Shift").toLower().append(u'+'))
+ << QModifKeyName(Qt::ALT, QCoreApplication::translate("QShortcut", "Alt").toLower().append(u'+'))
+ << QModifKeyName(Qt::META, QCoreApplication::translate("QShortcut", "Meta").toLower().append(u'+'))
+ << QModifKeyName(Qt::KeypadModifier, QCoreApplication::translate("QShortcut", "Num").toLower().append(u'+'));
}
modifs += *gmodifs; // Test non-translated ones last
QString sl = accel;
-#if defined(Q_OS_MACOS)
+#if defined(Q_OS_APPLE)
for (int i = 0; i < modifs.size(); ++i) {
const QModifKeyName &mkf = modifs.at(i);
if (sl.contains(mkf.name)) {
@@ -1139,9 +1103,9 @@ int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceForma
return Qt::Key_unknown;
#endif
- int i = 0;
- int lastI = 0;
- while ((i = sl.indexOf(QLatin1Char('+'), i + 1)) != -1) {
+ qsizetype i = 0;
+ qsizetype lastI = 0;
+ while ((i = sl.indexOf(u'+', i + 1)) != -1) {
const QStringView sub = QStringView{sl}.mid(lastI, i - lastI + 1);
// If we get here the shortcuts contains at least one '+'. We break up
// along the following strategy:
@@ -1152,9 +1116,9 @@ int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceForma
// except for a single '+' at the end of the string.
// Only '+' can have length 1.
- if (sub.length() == 1) {
+ if (sub.size() == 1) {
// Make sure we only encounter a single '+' at the end of the accel
- if (accel.lastIndexOf(QLatin1Char('+')) != accel.length()-1)
+ if (accel.lastIndexOf(u'+') != accel.size()-1)
return Qt::Key_unknown;
} else {
// Identify the modifier
@@ -1174,15 +1138,15 @@ int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceForma
lastI = i + 1;
}
- int p = accel.lastIndexOf(QLatin1Char('+'), accel.length() - 2); // -2 so that Ctrl++ works
+ qsizetype p = accel.lastIndexOf(u'+', accel.size() - 2); // -2 so that Ctrl++ works
QStringView accelRef(accel);
if (p > 0)
accelRef = accelRef.mid(p + 1);
int fnum = 0;
- if (accelRef.length() == 1) {
-#if defined(Q_OS_MACOS)
- int qtKey = qtkeyForMacSymbol(accelRef.at(0));
+ if (accelRef.size() == 1) {
+#if defined(Q_OS_APPLE)
+ int qtKey = qtkeyForAppleSymbol(accelRef.at(0));
if (qtKey != -1) {
ret |= qtKey;
} else
@@ -1190,10 +1154,10 @@ int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceForma
{
ret |= accelRef.at(0).toUpper().unicode();
}
- } else if (accelRef.at(0) == QLatin1Char('f') && (fnum = accelRef.mid(1).toInt()) >= 1 && fnum <= 35) {
+ } else if (accelRef.at(0) == u'f' && (fnum = accelRef.mid(1).toInt()) >= 1 && fnum <= 35) {
ret |= Qt::Key_F1 + fnum - 1;
} else {
- // For NativeText, check the traslation table first,
+ // For NativeText, check the translation table first,
// if we don't find anything then try it out with just the untranlated stuff.
// PortableText will only try the untranlated table.
bool found = false;
@@ -1217,17 +1181,7 @@ int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceForma
if (!found)
return Qt::Key_unknown;
}
- return ret;
-}
-
-/*!
- Creates a shortcut string for \a key. For example,
- Qt::CTRL+Qt::Key_O gives "Ctrl+O". The strings, "Ctrl", "Shift", etc. are
- translated (using QObject::tr()) in the "QShortcut" context.
- */
-QString QKeySequence::encodeString(int key)
-{
- return QKeySequencePrivate::encodeString(key, NativeText);
+ return QKeyCombination::fromCombined(ret);
}
static inline void addKey(QString &str, const QString &theKey, QKeySequence::SequenceFormat format)
@@ -1237,34 +1191,38 @@ static inline void addKey(QString &str, const QString &theKey, QKeySequence::Seq
//: Key separator in shortcut string
str += QCoreApplication::translate("QShortcut", "+");
} else {
- str += QLatin1Char('+');
+ str += u'+';
}
}
str += theKey;
}
-QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat format)
+QString QKeySequencePrivate::encodeString(QKeyCombination keyCombination, QKeySequence::SequenceFormat format)
{
bool nativeText = (format == QKeySequence::NativeText);
QString s;
+ const auto key = keyCombination.key();
+
// Handle -1 (Invalid Key) and Qt::Key_unknown gracefully
- if (key == -1 || key == Qt::Key_unknown)
+ if (keyCombination.toCombined() == -1 || key == Qt::Key_unknown)
return s;
-#if defined(Q_OS_MACOS)
+ const auto modifiers = keyCombination.keyboardModifiers();
+
+#if defined(Q_OS_APPLE)
if (nativeText) {
- // On OS X the order (by default) is Meta, Alt, Shift, Control.
+ // On Apple platforms the order (by default) is Meta, Alt, Shift, Control.
// If the AA_MacDontSwapCtrlAndMeta is enabled, then the order
- // is Ctrl, Alt, Shift, Meta. The macSymbolForQtKey does this swap
+ // is Ctrl, Alt, Shift, Meta. The appleSymbolForQtKey helper does this swap
// for us, which means that we have to adjust our order here.
// The upshot is a lot more infrastructure to keep the number of
// if tests down and the code relatively clean.
- static const int ModifierOrder[] = { Qt::META, Qt::ALT, Qt::SHIFT, Qt::CTRL, 0 };
- static const int QtKeyOrder[] = { Qt::Key_Meta, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Control, 0 };
- static const int DontSwapModifierOrder[] = { Qt::CTRL, Qt::ALT, Qt::SHIFT, Qt::META, 0 };
- static const int DontSwapQtKeyOrder[] = { Qt::Key_Control, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Meta, 0 };
+ static constexpr int ModifierOrder[] = { Qt::META, Qt::ALT, Qt::SHIFT, Qt::CTRL, 0 };
+ static constexpr int QtKeyOrder[] = { Qt::Key_Meta, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Control, 0 };
+ static constexpr int DontSwapModifierOrder[] = { Qt::CTRL, Qt::ALT, Qt::SHIFT, Qt::META, 0 };
+ static constexpr int DontSwapQtKeyOrder[] = { Qt::Key_Control, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Meta, 0 };
const int *modifierOrder;
const int *qtkeyOrder;
if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
@@ -1276,33 +1234,33 @@ QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat
}
for (int i = 0; modifierOrder[i] != 0; ++i) {
- if (key & modifierOrder[i])
- s += qt_macSymbolForQtKey(qtkeyOrder[i]);
+ if (modifiers & modifierOrder[i])
+ s += appleSymbolForQtKey(qtkeyOrder[i]);
}
} else
#endif
{
// On other systems the order is Meta, Control, Alt, Shift
- if ((key & Qt::META) == Qt::META)
+ if (modifiers & Qt::MetaModifier)
s = nativeText ? QCoreApplication::translate("QShortcut", "Meta") : QString::fromLatin1("Meta");
- if ((key & Qt::CTRL) == Qt::CTRL)
+ if (modifiers & Qt::ControlModifier)
addKey(s, nativeText ? QCoreApplication::translate("QShortcut", "Ctrl") : QString::fromLatin1("Ctrl"), format);
- if ((key & Qt::ALT) == Qt::ALT)
+ if (modifiers & Qt::AltModifier)
addKey(s, nativeText ? QCoreApplication::translate("QShortcut", "Alt") : QString::fromLatin1("Alt"), format);
- if ((key & Qt::SHIFT) == Qt::SHIFT)
+ if (modifiers & Qt::ShiftModifier)
addKey(s, nativeText ? QCoreApplication::translate("QShortcut", "Shift") : QString::fromLatin1("Shift"), format);
}
- if ((key & Qt::KeypadModifier) == Qt::KeypadModifier)
+ if (modifiers & Qt::KeypadModifier)
addKey(s, nativeText ? QCoreApplication::translate("QShortcut", "Num") : QString::fromLatin1("Num"), format);
- QString p = keyName(key, format);
+ QString keyName = QKeySequencePrivate::keyName(key, format);
-#if defined(Q_OS_MACOS)
+#if defined(Q_OS_APPLE)
if (nativeText)
- s += p;
+ s += keyName;
else
#endif
- addKey(s, p, format);
+ addKey(s, keyName, format);
return s;
}
@@ -1314,10 +1272,9 @@ QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat
This static method is used by encodeString() and by the D-Bus menu exporter.
*/
-QString QKeySequencePrivate::keyName(int key, QKeySequence::SequenceFormat format)
+QString QKeySequencePrivate::keyName(Qt::Key key, QKeySequence::SequenceFormat format)
{
bool nativeText = (format == QKeySequence::NativeText);
- key &= ~(Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier);
QString p;
if (key && key < Qt::Key_Escape && key != Qt::Key_Space) {
@@ -1332,9 +1289,9 @@ QString QKeySequencePrivate::keyName(int key, QKeySequence::SequenceFormat forma
: QString::fromLatin1("F%1").arg(key - Qt::Key_F1 + 1);
} else if (key) {
int i=0;
-#if defined(Q_OS_MACOS)
+#if defined(Q_OS_APPLE)
if (nativeText) {
- QChar ch = qt_macSymbolForQtKey(key);
+ QChar ch = appleSymbolForQtKey(key);
if (!ch.isNull())
p = ch;
else
@@ -1342,7 +1299,7 @@ QString QKeySequencePrivate::keyName(int key, QKeySequence::SequenceFormat forma
} else
#endif
{
-#if defined(Q_OS_MACOS)
+#if defined(Q_OS_APPLE)
NonSymbol:
#endif
while (i < numKeyNames) {
@@ -1455,6 +1412,7 @@ bool QKeySequence::operator==(const QKeySequence &other) const
/*!
\since 5.6
+ \relates QKeySequence
Calculates the hash value of \a key, using
\a seed to seed the calculation.
@@ -1531,7 +1489,7 @@ bool QKeySequence::isDetached() const
If the key sequence has no keys, an empty string is returned.
- On \macos, the string returned resembles the sequence that is
+ On Apple platforms, the string returned resembles the sequence that is
shown in the menu bar if \a format is
QKeySequence::NativeText; otherwise, the string uses the
"portable" format, suitable for writing to a file.
@@ -1545,10 +1503,10 @@ QString QKeySequence::toString(SequenceFormat format) const
// look like our latin case on Windows and X11
int end = count();
for (int i = 0; i < end; ++i) {
- finalString += d->encodeString(d->key[i], format);
- finalString += QLatin1String(", ");
+ finalString += d->encodeString(QKeyCombination::fromCombined(d->key[i]), format);
+ finalString += ", "_L1;
}
- finalString.truncate(finalString.length() - 2);
+ finalString.truncate(finalString.size() - 2);
return finalString;
}
@@ -1576,8 +1534,8 @@ QList<QKeySequence> QKeySequence::listFromString(const QString &str, SequenceFor
{
QList<QKeySequence> result;
- const QStringList strings = str.split(QLatin1String("; "));
- result.reserve(strings.count());
+ const QStringList strings = str.split("; "_L1);
+ result.reserve(strings.size());
for (const QString &string : strings) {
result << fromString(string, format);
}
@@ -1599,9 +1557,9 @@ QString QKeySequence::listToString(const QList<QKeySequence> &list, SequenceForm
for (const QKeySequence &sequence : list) {
result += sequence.toString(format);
- result += QLatin1String("; ");
+ result += "; "_L1;
}
- result.truncate(result.length() - 2);
+ result.truncate(result.size() - 2);
return result;
}
@@ -1680,3 +1638,5 @@ QDebug operator<<(QDebug dbg, const QKeySequence &p)
*/
QT_END_NAMESPACE
+
+#include "moc_qkeysequence.cpp"
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
index 61001dddbc..4dae26a755 100644
--- a/src/gui/kernel/qkeysequence.h
+++ b/src/gui/kernel/qkeysequence.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QKEYSEQUENCE_H
#define QKEYSEQUENCE_H
@@ -53,12 +17,12 @@ class QKeySequence;
/*****************************************************************************
QKeySequence stream functions
*****************************************************************************/
-#if !defined(QT_NO_DATASTREAM) || defined(Q_CLANG_QDOC)
+#if !defined(QT_NO_DATASTREAM) || defined(Q_QDOC)
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QKeySequence &ks);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &out, QKeySequence &ks);
#endif
-#if defined(Q_CLANG_QDOC)
+#if defined(Q_QDOC)
void qt_set_sequence_auto_mnemonic(bool b);
#endif
@@ -151,6 +115,7 @@ public:
NativeText,
PortableText
};
+ Q_ENUM(SequenceFormat)
QKeySequence();
QKeySequence(const QString &key, SequenceFormat format = NativeText);
@@ -171,6 +136,7 @@ public:
PartialMatch,
ExactMatch
};
+ Q_ENUM(SequenceMatch);
QString toString(SequenceFormat format = PortableText) const;
static QKeySequence fromString(const QString &str, SequenceFormat format = PortableText);
@@ -186,7 +152,7 @@ public:
QKeyCombination operator[](uint i) const;
QKeySequence &operator=(const QKeySequence &other);
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QKeySequence)
- void swap(QKeySequence &other) noexcept { qSwap(d, other.d); }
+ void swap(QKeySequence &other) noexcept { qt_ptr_swap(d, other.d); }
bool operator==(const QKeySequence &other) const;
inline bool operator!= (const QKeySequence &other) const
@@ -201,8 +167,6 @@ public:
bool isDetached() const;
private:
- static int decodeString(const QString &ks);
- static QString encodeString(int key);
int assign(const QString &str);
int assign(const QString &str, SequenceFormat format);
void setKey(QKeyCombination key, int index);
@@ -222,7 +186,7 @@ public:
Q_DECLARE_SHARED(QKeySequence)
-#if !defined(QT_NO_DEBUG_STREAM) || defined(Q_CLANG_QDOC)
+#if !defined(QT_NO_DEBUG_STREAM) || defined(Q_QDOC)
Q_GUI_EXPORT QDebug operator<<(QDebug, const QKeySequence &);
#endif
diff --git a/src/gui/kernel/qkeysequence_p.h b/src/gui/kernel/qkeysequence_p.h
index 99d17e98d1..8b98e3778a 100644
--- a/src/gui/kernel/qkeysequence_p.h
+++ b/src/gui/kernel/qkeysequence_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QKEYSEQUENCE_P_H
#define QKEYSEQUENCE_P_H
@@ -71,11 +35,8 @@ struct QKeyBinding
class QKeySequencePrivate
{
public:
- enum { MaxKeyCount = 4 }; // also used in QKeySequenceEdit
- inline QKeySequencePrivate() : ref(1)
- {
- std::fill_n(key, uint(MaxKeyCount), 0);
- }
+ static constexpr int MaxKeyCount = 4 ; // also used in QKeySequenceEdit
+ constexpr QKeySequencePrivate() : ref(1), key{} {}
inline QKeySequencePrivate(const QKeySequencePrivate &copy) : ref(1)
{
std::copy(copy.key, copy.key + MaxKeyCount,
@@ -83,10 +44,10 @@ public:
}
QAtomicInt ref;
int key[MaxKeyCount];
- static QString encodeString(int key, QKeySequence::SequenceFormat format);
+ static QString encodeString(QKeyCombination keyCombination, QKeySequence::SequenceFormat format);
// used in dbusmenu
- Q_GUI_EXPORT static QString keyName(int key, QKeySequence::SequenceFormat format);
- static int decodeString(QString accel, QKeySequence::SequenceFormat format);
+ Q_GUI_EXPORT static QString keyName(Qt::Key key, QKeySequence::SequenceFormat format);
+ static QKeyCombination decodeString(QString accel, QKeySequence::SequenceFormat format);
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index 8fbb188bd1..02e606658a 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qoffscreensurface.h"
@@ -50,6 +14,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QOffscreenSurface
\inmodule QtGui
@@ -162,7 +128,7 @@ void QOffscreenSurface::create()
// violate the minimum title bar width on the platform.
d->offscreenWindow->setFlags(d->offscreenWindow->flags()
| Qt::CustomizeWindowHint | Qt::FramelessWindowHint);
- d->offscreenWindow->setObjectName(QLatin1String("QOffscreenSurface"));
+ d->offscreenWindow->setObjectName("QOffscreenSurface"_L1);
// Remove this window from the global list since we do not want it to be destroyed when closing the app.
// The QOffscreenSurface has to be usable even after exiting the event loop.
QGuiApplicationPrivate::window_list.removeOne(d->offscreenWindow);
@@ -203,7 +169,7 @@ void QOffscreenSurface::destroy()
/*!
Returns \c true if this offscreen surface is valid; otherwise returns \c false.
- The offscreen surface is valid if the platform resources have been successfuly allocated.
+ The offscreen surface is valid if the platform resources have been successfully allocated.
\sa create()
*/
@@ -386,3 +352,5 @@ void *QOffscreenSurface::resolveInterface(const char *name, int revision) const
}
QT_END_NAMESPACE
+
+#include "moc_qoffscreensurface.cpp"
diff --git a/src/gui/kernel/qoffscreensurface.h b/src/gui/kernel/qoffscreensurface.h
index 6ed063b8c9..410b6d2b61 100644
--- a/src/gui/kernel/qoffscreensurface.h
+++ b/src/gui/kernel/qoffscreensurface.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOFFSCREENSURFACE_H
#define QOFFSCREENSURFACE_H
@@ -44,7 +8,7 @@
#include <QtCore/QObject>
#include <QtCore/qnativeinterface.h>
#include <QtGui/qsurface.h>
-Q_MOC_INCLUDE(<QScreen>)
+Q_MOC_INCLUDE(<QtGui/qscreen.h>)
QT_BEGIN_NAMESPACE
diff --git a/src/gui/kernel/qoffscreensurface_p.h b/src/gui/kernel/qoffscreensurface_p.h
index 5b41e71c29..3de4b5e17a 100644
--- a/src/gui/kernel/qoffscreensurface_p.h
+++ b/src/gui/kernel/qoffscreensurface_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOFFSCREENSURFACE_P_H
#define QOFFSCREENSURFACE_P_H
diff --git a/src/gui/kernel/qoffscreensurface_platform.h b/src/gui/kernel/qoffscreensurface_platform.h
index b6d77491d5..33e72c7e17 100644
--- a/src/gui/kernel/qoffscreensurface_platform.h
+++ b/src/gui/kernel/qoffscreensurface_platform.h
@@ -1,45 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOFFSCREENSURFACE_PLATFORM_H
#define QOFFSCREENSURFACE_PLATFORM_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the native interface APIs. Usage of
+// this API may make your code source and binary incompatible
+// with future versions of Qt.
+//
+
#include <QtGui/qtguiglobal.h>
#include <QtGui/qoffscreensurface.h>
#include <QtCore/qnativeinterface.h>
@@ -52,7 +25,7 @@ QT_BEGIN_NAMESPACE
namespace QNativeInterface {
-#if defined(Q_OS_ANDROID) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_ANDROID) || defined(Q_QDOC)
struct Q_GUI_EXPORT QAndroidOffscreenSurface
{
QT_DECLARE_NATIVE_INTERFACE(QAndroidOffscreenSurface, 1, QOffscreenSurface)
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index bdbd18f771..dd41318f72 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qpa/qplatformopenglcontext.h>
#include <qpa/qplatformintegration.h>
@@ -78,7 +42,7 @@ static QOpenGLContext *global_share_context = nullptr;
#ifndef QT_NO_DEBUG
QHash<QOpenGLContext *, bool> QOpenGLContextPrivate::makeCurrentTracker;
-QMutex QOpenGLContextPrivate::makeCurrentTrackerMutex;
+Q_CONSTINIT QMutex QOpenGLContextPrivate::makeCurrentTrackerMutex;
#endif
/*!
@@ -105,6 +69,7 @@ QOpenGLContext *qt_gl_global_share_context()
/*!
\class QOpenGLContext
+ \ingroup painting-3D
\inmodule QtGui
\since 5.0
\brief The QOpenGLContext class represents a native OpenGL context, enabling
@@ -173,6 +138,22 @@ QOpenGLContext *qt_gl_global_share_context()
application is portable between different platforms. However, if you use
QOpenGLFunctions::glBindFramebuffer(), this is done automatically for you.
+ \warning WebAssembly
+
+ We recommend that only one QOpenGLContext is made current with a QSurface,
+ for the entire lifetime of the QSurface. Should more than once context be used,
+ it is important to understand that multiple QOpenGLContext instances may be
+ backed by the same native context underneath with the WebAssembly platform.
+ Therefore, calling makeCurrent() with the same QSurface on two QOpenGLContext
+ objects may not switch to a different native context in the second call. As
+ a result, any OpenGL state changes done after the second makeCurrent() may
+ alter the state of the first QOpenGLContext as well, as they are all backed
+ by the same native context.
+
+ \note This means that when targeting WebAssembly with existing OpenGL-based
+ Qt code, some porting may be required to cater to these limitations.
+
+
\sa QOpenGLFunctions, QOpenGLBuffer, QOpenGLShaderProgram, QOpenGLFramebufferObject
*/
@@ -189,6 +170,9 @@ QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context
qWarning("No QTLS available. currentContext won't work");
return nullptr;
}
+ if (!context)
+ return nullptr;
+
threadContext = new QGuiGLThreadContext;
qwindow_context_storage()->setLocalData(threadContext);
}
@@ -396,6 +380,10 @@ bool QOpenGLContext::create()
return isValid();
}
+QOpenGLContextPrivate::~QOpenGLContextPrivate()
+{
+}
+
void QOpenGLContextPrivate::adopt(QPlatformOpenGLContext *context)
{
Q_Q(QOpenGLContext);
@@ -431,30 +419,47 @@ void QOpenGLContextPrivate::adopt(QPlatformOpenGLContext *context)
void QOpenGLContext::destroy()
{
Q_D(QOpenGLContext);
+
+ // Notify that the native context and the QPlatformOpenGLContext are going
+ // to go away.
if (d->platformGLContext)
emit aboutToBeDestroyed();
- if (QOpenGLContext::currentContext() == this)
- doneCurrent();
- if (d->shareGroup)
- d->shareGroup->d_func()->removeContext(this);
- d->shareGroup = nullptr;
- delete d->platformGLContext;
- d->platformGLContext = nullptr;
- delete d->functions;
- d->functions = nullptr;
+ // Invoke callbacks for helpers and invalidate.
if (d->textureFunctionsDestroyCallback) {
d->textureFunctionsDestroyCallback();
d->textureFunctionsDestroyCallback = nullptr;
}
d->textureFunctions = nullptr;
+ delete d->versionFunctions;
+ d->versionFunctions = nullptr;
+
if (d->vaoHelperDestroyCallback) {
Q_ASSERT(d->vaoHelper);
d->vaoHelperDestroyCallback(d->vaoHelper);
d->vaoHelperDestroyCallback = nullptr;
}
d->vaoHelper = nullptr;
+
+ // Tear down function wrappers.
+ delete d->versionFunctions;
+ d->versionFunctions = nullptr;
+
+ delete d->functions;
+ d->functions = nullptr;
+
+ // Clean up and destroy the native context machinery.
+ if (QOpenGLContext::currentContext() == this)
+ doneCurrent();
+
+ if (d->shareGroup)
+ d->shareGroup->d_func()->removeContext(this);
+
+ d->shareGroup = nullptr;
+
+ delete d->platformGLContext;
+ d->platformGLContext = nullptr;
}
/*!
@@ -466,6 +471,11 @@ void QOpenGLContext::destroy()
If you wish to make the context current in order to do clean-up, make sure
to only connect to the signal using a direct connection.
+
+ \note In Qt for Python, this signal will not be received when emitted
+ from the destructor of QOpenGLWidget or QOpenGLWindow due to the Python
+ instance already being destroyed. We recommend doing cleanups
+ in QWidget::hideEvent() instead.
*/
/*!
@@ -1031,6 +1041,9 @@ QOpenGLContextGroup *QOpenGLContextGroup::currentContextGroup()
return current ? current->shareGroup() : nullptr;
}
+QOpenGLContextGroupPrivate::~QOpenGLContextGroupPrivate()
+ = default;
+
void QOpenGLContextGroupPrivate::addContext(QOpenGLContext *ctx)
{
const auto locker = qt_scoped_lock(m_mutex);
@@ -1172,6 +1185,10 @@ void QOpenGLSharedResource::free()
\inmodule QtGui
*/
+
+QOpenGLSharedResourceGuard::~QOpenGLSharedResourceGuard()
+ = default;
+
void QOpenGLSharedResourceGuard::freeResource(QOpenGLContext *context)
{
if (m_id) {
@@ -1271,6 +1288,9 @@ void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContextGroup *group, QOpenG
m_groups.removeOne(group);
}
+QOpenGLContextVersionFunctionHelper::~QOpenGLContextVersionFunctionHelper()
+ = default;
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QOpenGLContext *ctx)
{
@@ -1335,6 +1355,6 @@ void *QOpenGLContext::resolveInterface(const char *name, int revision) const
return nullptr;
}
-#include "moc_qopenglcontext.cpp"
-
QT_END_NAMESPACE
+
+#include "moc_qopenglcontext.cpp"
diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h
index 36c3ed3a67..ca2d4a8903 100644
--- a/src/gui/kernel/qopenglcontext.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPENGLCONTEXT_H
#define QOPENGLCONTEXT_H
@@ -45,8 +9,9 @@
#ifndef QT_NO_OPENGL
#include <QtCore/qnamespace.h>
-#include <QtCore/QObject>
-#include <QtCore/QScopedPointer>
+#include <QtCore/qobject.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qset.h>
#include <QtCore/qnativeinterface.h>
#include <QtGui/QSurfaceFormat>
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index 7bba323120..a0e8eda679 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPENGLCONTEXT_P_H
#define QOPENGLCONTEXT_P_H
@@ -110,6 +74,7 @@ public:
, m_func(func)
{
}
+ ~QOpenGLSharedResourceGuard() override;
GLuint id() const { return m_id; }
@@ -135,6 +100,7 @@ public:
, m_refs(0)
{
}
+ ~QOpenGLContextGroupPrivate() override;
void addContext(QOpenGLContext *ctx);
void removeContext(QOpenGLContext *ctx);
@@ -196,7 +162,7 @@ class QOpenGLVertexArrayObjectHelper;
class Q_GUI_EXPORT QOpenGLContextVersionFunctionHelper
{
public:
- virtual ~QOpenGLContextVersionFunctionHelper() {}
+ virtual ~QOpenGLContextVersionFunctionHelper();
};
class Q_GUI_EXPORT QOpenGLContextPrivate : public QObjectPrivate
@@ -226,13 +192,7 @@ public:
requestedFormat = QSurfaceFormat::defaultFormat();
}
- ~QOpenGLContextPrivate()
- {
- //do not delete the QOpenGLContext handle here as it is deleted in
- //QWidgetPrivate::deleteTLSysExtra()
-
- delete versionFunctions;
- }
+ ~QOpenGLContextPrivate() override;
void adopt(QPlatformOpenGLContext *);
diff --git a/src/gui/kernel/qopenglcontext_platform.h b/src/gui/kernel/qopenglcontext_platform.h
index 7627e34c20..1f84cf6ce3 100644
--- a/src/gui/kernel/qopenglcontext_platform.h
+++ b/src/gui/kernel/qopenglcontext_platform.h
@@ -1,45 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPENGLCONTEXT_PLATFORM_H
#define QOPENGLCONTEXT_PLATFORM_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the native interface APIs. Usage of
+// this API may make your code source and binary incompatible
+// with future versions of Qt.
+//
+
#ifndef QT_NO_OPENGL
#include <QtGui/qtguiglobal.h>
@@ -58,9 +31,10 @@ struct __GLXcontextRec; typedef struct __GLXcontextRec *GLXContext;
#if QT_CONFIG(egl)
typedef void *EGLContext;
typedef void *EGLDisplay;
+typedef void *EGLConfig;
#endif
-#if !defined(Q_OS_MACOS) && defined(Q_CLANG_QDOC)
+#if !defined(Q_OS_MACOS) && defined(Q_QDOC)
typedef void *NSOpenGLContext;
#endif
@@ -68,7 +42,7 @@ QT_BEGIN_NAMESPACE
namespace QNativeInterface {
-#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_MACOS) || defined(Q_QDOC)
struct Q_GUI_EXPORT QCocoaGLContext
{
QT_DECLARE_NATIVE_INTERFACE(QCocoaGLContext, 1, QOpenGLContext)
@@ -77,7 +51,7 @@ struct Q_GUI_EXPORT QCocoaGLContext
};
#endif
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
struct Q_GUI_EXPORT QWGLContext
{
QT_DECLARE_NATIVE_INTERFACE(QWGLContext, 1, QOpenGLContext)
@@ -87,7 +61,7 @@ struct Q_GUI_EXPORT QWGLContext
};
#endif
-#if QT_CONFIG(xcb_glx_plugin) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(xcb_glx_plugin) || defined(Q_QDOC)
struct Q_GUI_EXPORT QGLXContext
{
QT_DECLARE_NATIVE_INTERFACE(QGLXContext, 1, QOpenGLContext)
@@ -97,12 +71,16 @@ struct Q_GUI_EXPORT QGLXContext
};
#endif
-#if QT_CONFIG(egl) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(egl) || defined(Q_QDOC)
struct Q_GUI_EXPORT QEGLContext
{
QT_DECLARE_NATIVE_INTERFACE(QEGLContext, 1, QOpenGLContext)
static QOpenGLContext *fromNative(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext = nullptr);
virtual EGLContext nativeContext() const = 0;
+ virtual EGLConfig config() const = 0;
+ virtual EGLDisplay display() const = 0;
+
+ virtual void invalidateContext() = 0;
};
#endif
diff --git a/src/gui/kernel/qpaintdevicewindow.cpp b/src/gui/kernel/qpaintdevicewindow.cpp
index ebacc727f9..9e8c6ae5a8 100644
--- a/src/gui/kernel/qpaintdevicewindow.cpp
+++ b/src/gui/kernel/qpaintdevicewindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpaintdevicewindow_p.h"
@@ -44,6 +8,12 @@
QT_BEGIN_NAMESPACE
+QPaintDeviceWindowPrivate::QPaintDeviceWindowPrivate()
+ = default;
+
+QPaintDeviceWindowPrivate::~QPaintDeviceWindowPrivate()
+ = default;
+
/*!
\class QPaintDeviceWindow
\inmodule QtGui
@@ -201,6 +171,8 @@ bool QPaintDeviceWindow::event(QEvent *event)
auto region = QRect(QPoint(0, 0), size());
d->doFlush(region); // Will end up calling paintEvent
return true;
+ } else if (event->type() == QEvent::Resize) {
+ d->handleResizeEvent();
}
return QWindow::event(event);
@@ -223,3 +195,5 @@ QPaintEngine *QPaintDeviceWindow::paintEngine() const
}
QT_END_NAMESPACE
+
+#include "moc_qpaintdevicewindow.cpp"
diff --git a/src/gui/kernel/qpaintdevicewindow.h b/src/gui/kernel/qpaintdevicewindow.h
index 69e56ea842..d6b70298a6 100644
--- a/src/gui/kernel/qpaintdevicewindow.h
+++ b/src/gui/kernel/qpaintdevicewindow.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTDEVICEWINDOW_H
#define QPAINTDEVICEWINDOW_H
diff --git a/src/gui/kernel/qpaintdevicewindow_p.h b/src/gui/kernel/qpaintdevicewindow_p.h
index a16b83689e..85c11cbf91 100644
--- a/src/gui/kernel/qpaintdevicewindow_p.h
+++ b/src/gui/kernel/qpaintdevicewindow_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTDEVICEWINDOW_P_H
#define QPAINTDEVICEWINDOW_P_H
@@ -64,6 +28,11 @@ class Q_GUI_EXPORT QPaintDeviceWindowPrivate : public QWindowPrivate
Q_DECLARE_PUBLIC(QPaintDeviceWindow)
public:
+ QPaintDeviceWindowPrivate();
+ ~QPaintDeviceWindowPrivate() override;
+
+ virtual void handleResizeEvent() {}
+
virtual void beginPaint(const QRegion &region)
{
Q_UNUSED(region);
@@ -115,7 +84,7 @@ public:
void markWindowAsDirty()
{
Q_Q(QPaintDeviceWindow);
- dirtyRegion += QRect(QPoint(0, 0), q->size());
+ dirtyRegion = QRect(QPoint(0, 0), q->size());
}
private:
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index b313d545a5..256ea52f01 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -1,44 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qpalette.h"
-#include "qguiapplication.h"
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qpalette_p.h"
#include "qguiapplication_p.h"
#include "qdatastream.h"
#include "qvariant.h"
@@ -48,39 +11,61 @@
QT_BEGIN_NAMESPACE
-static int qt_palette_count = 1;
+static_assert(QPalettePrivate::bitPosition(QPalette::ColorGroup(QPalette::NColorGroups - 1),
+ QPalette::ColorRole(QPalette::NColorRoles - 1))
+ < sizeof(QPalette::ResolveMask) * CHAR_BIT,
+ "The resolve mask type is not wide enough to fit the entire bit mask.");
-static constexpr QPalette::ResolveMask colorRoleOffset(QPalette::ColorGroup colorGroup)
+static QColor qt_mix_colors(QColor a, QColor b)
{
- return qToUnderlying(QPalette::NColorRoles) * qToUnderlying(colorGroup);
+ return QColor((a.red() + b.red()) / 2, (a.green() + b.green()) / 2,
+ (a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2);
}
-static constexpr QPalette::ResolveMask bitPosition(QPalette::ColorGroup colorGroup,
- QPalette::ColorRole colorRole)
-{
- return colorRole + colorRoleOffset(colorGroup);
-}
+/*!
+ \internal
-static_assert(bitPosition(QPalette::ColorGroup(QPalette::NColorGroups - 1),
- QPalette::ColorRole(QPalette::NColorRoles - 1))
- < sizeof(QPalette::ResolveMask) * CHAR_BIT,
- "The resolve mask type is not wide enough to fit the entire bit mask.");
+ Derive undefined \l PlaceholderText colors from \l Text colors.
+ Unless already set, PlaceholderText colors will be derived from their Text pendents.
+ Colors of existing PlaceHolderText brushes will not be replaced.
-class QPalettePrivate
+ \a alpha represents the dim factor as a percentage. By default, a PlaceHolderText color
+ becomes a 50% more transparent version of the corresponding Text color.
+*/
+static void qt_placeholder_from_text(QPalette &pal, int alpha = 50)
{
-public:
- QPalettePrivate() : ref(1), ser_no(qt_palette_count++), detach_no(0) { }
- QAtomicInt ref;
- QBrush br[QPalette::NColorGroups][QPalette::NColorRoles];
- QPalette::ResolveMask resolveMask = {0};
- int ser_no;
- int detach_no;
-};
+ if (alpha < 0 or alpha > 100)
+ return;
-static QColor qt_mix_colors(QColor a, QColor b)
+ for (int cg = 0; cg < int(QPalette::NColorGroups); ++cg) {
+ const QPalette::ColorGroup group = QPalette::ColorGroup(cg);
+
+ // skip if the brush has been set already
+ if (!pal.isBrushSet(group, QPalette::PlaceholderText)) {
+ QColor c = pal.color(group, QPalette::Text);
+ const int a = (c.alpha() * alpha) / 100;
+ c.setAlpha(a);
+ pal.setColor(group, QPalette::PlaceholderText, c);
+ }
+ }
+}
+
+static void qt_ensure_default_accent_color(QPalette &pal)
{
- return QColor((a.red() + b.red()) / 2, (a.green() + b.green()) / 2,
- (a.blue() + b.blue()) / 2, (a.alpha() + b.alpha()) / 2);
+ // have a lighter/darker factor handy, depending on dark/light heuristics
+ const int lighter = pal.base().color().lightness() > pal.text().color().lightness() ? 130 : 70;
+
+ // Act only for color groups where no accent color is set
+ for (int i = 0; i < QPalette::NColorGroups; ++i) {
+ const QPalette::ColorGroup group = static_cast<QPalette::ColorGroup>(i);
+ if (!pal.isBrushSet(group, QPalette::Accent)) {
+ // Default to highlight if available, otherwise use a shade of base
+ const QBrush accentBrush = pal.isBrushSet(group, QPalette::Highlight)
+ ? pal.brush(group, QPalette::Highlight)
+ : pal.brush(group, QPalette::Base).color().lighter(lighter);
+ pal.setBrush(group, QPalette::Accent, accentBrush);
+ }
+ }
}
static void qt_palette_from_color(QPalette &pal, const QColor &button)
@@ -105,6 +90,9 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button)
pal.setColorGroup(QPalette::Disabled, buttonBrushDark, buttonBrush, buttonBrushLight150,
buttonBrushDark, buttonBrushDark150, buttonBrushDark,
whiteBrush, buttonBrush, buttonBrush);
+
+ qt_placeholder_from_text(pal);
+ qt_ensure_default_accent_color(pal);
}
/*!
@@ -306,6 +294,15 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button)
*/
/*!
+ \fn const QBrush & QPalette::accent() const
+ \since 6.6
+
+ Returns the accent brush of the current color group.
+
+ \sa ColorRole, brush()
+*/
+
+/*!
\fn const QBrush & QPalette::link() const
Returns the unvisited link text brush of the current color group.
@@ -505,6 +502,13 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button)
item. By default, the highlight color is
Qt::darkBlue.
+ \value [since 6.6] Accent
+ A color that typically contrasts or complements
+ Base, Window and Button colors. It usually represents
+ the users' choice of desktop personalisation.
+ Styling of interactive components is a typical use case.
+ Unless explicitly set, it defaults to Highlight.
+
\value HighlightedText A text color that contrasts with \c Highlight.
By default, the highlighted text color is Qt::white.
@@ -592,6 +596,9 @@ QPalette::QPalette(const QBrush &windowText, const QBrush &button,
init();
setColorGroup(All, windowText, button, light, dark, mid, text, bright_text,
base, window);
+
+ qt_placeholder_from_text(*this);
+ qt_ensure_default_accent_color(*this);
}
@@ -647,6 +654,9 @@ QPalette::QPalette(const QColor &button, const QColor &window)
setColorGroup(Disabled, disabledForeground, buttonBrush, buttonBrushLight150,
buttonBrushDark, buttonBrushDark150, disabledForeground,
whiteBrush, baseBrush, windowBrush);
+
+ qt_placeholder_from_text(*this);
+ qt_ensure_default_accent_color(*this);
}
/*!
@@ -746,7 +756,7 @@ const QBrush &QPalette::brush(ColorGroup gr, ColorRole cr) const
gr = Active;
}
}
- return d->br[gr][cr];
+ return d->data->br[gr][cr];
}
/*!
@@ -784,12 +794,18 @@ void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b)
cg = Active;
}
- if (d->br[cg][cr] != b) {
+ const auto newResolveMask = d->resolveMask | ResolveMask(1) << QPalettePrivate::bitPosition(cg, cr);
+ const auto valueChanged = d->data->br[cg][cr] != b;
+
+ if (valueChanged) {
+ detach();
+ d->data.detach();
+ d->data->br[cg][cr] = b;
+ } else if (d->resolveMask != newResolveMask) {
detach();
- d->br[cg][cr] = b;
}
- d->resolveMask |= ResolveMask(1) << bitPosition(cg, cr);
+ d->resolveMask = newResolveMask;
}
/*!
@@ -808,6 +824,10 @@ void QPalette::setBrush(ColorGroup cg, ColorRole cr, const QBrush &b)
*/
bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const
{
+ // NoRole has no resolve mask and should never be set anyway
+ if (cr == NoRole)
+ return false;
+
if (cg == Current)
cg = currentGroup;
@@ -821,7 +841,7 @@ bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const
return false;
}
- return d->resolveMask & (ResolveMask(1) << bitPosition(cg, cr));
+ return d->resolveMask & (ResolveMask(1) << QPalettePrivate::bitPosition(cg, cr));
}
/*!
@@ -830,17 +850,14 @@ bool QPalette::isBrushSet(ColorGroup cg, ColorRole cr) const
void QPalette::detach()
{
if (d->ref.loadRelaxed() != 1) {
- QPalettePrivate *x = new QPalettePrivate;
- for(int grp = 0; grp < (int)NColorGroups; grp++) {
- for(int role = 0; role < (int)NColorRoles; role++)
- x->br[grp][role] = d->br[grp][role];
- }
+ QPalettePrivate *x = new QPalettePrivate(d->data);
x->resolveMask = d->resolveMask;
if (!d->ref.deref())
delete d;
d = x;
+ } else {
+ d->detach_no = ++QPalettePrivate::qt_palette_private_count;
}
- ++d->detach_no;
}
/*!
@@ -859,18 +876,24 @@ void QPalette::detach()
Returns \c true (usually quickly) if this palette is equal to \a p;
otherwise returns \c false (slowly).
- \note The current ColorGroup is not taken into account when
- comparing palettes
+ \note The following is not taken into account when comparing palettes:
+ \list
+ \li the \c current ColorGroup
+ \li ColorRole NoRole \since 6.6
+ \endlist
\sa operator!=()
*/
bool QPalette::operator==(const QPalette &p) const
{
- if (isCopyOf(p))
+ if (isCopyOf(p) || d->data == p.d->data)
return true;
for(int grp = 0; grp < (int)NColorGroups; grp++) {
for(int role = 0; role < (int)NColorRoles; role++) {
- if (d->br[grp][role] != p.d->br[grp][role])
+ // Dont't verify NoRole, because it has no resolve bit
+ if (role == NoRole)
+ continue;
+ if (d->data->br[grp][role] != p.d->data->br[grp][role])
return false;
}
}
@@ -904,7 +927,7 @@ bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2)
if (group1 == group2)
return true;
for(int role = 0; role < (int)NColorRoles; role++) {
- if (d->br[group1][role] != d->br[group2][role])
+ if (d->data->br[group1][role] != d->data->br[group2][role])
return false;
}
return true;
@@ -919,7 +942,18 @@ bool QPalette::isEqual(QPalette::ColorGroup group1, QPalette::ColorGroup group2)
*/
qint64 QPalette::cacheKey() const
{
- return (((qint64) d->ser_no) << 32) | ((qint64) (d->detach_no));
+ return (((qint64) d->data->ser_no) << 32) | ((qint64) (d->detach_no));
+}
+
+static constexpr QPalette::ResolveMask allResolveMask()
+{
+ QPalette::ResolveMask mask = {0};
+ for (int role = 0; role < int(QPalette::NColorRoles); ++role) {
+ for (int grp = 0; grp < int(QPalette::NColorGroups); ++grp) {
+ mask |= (QPalette::ResolveMask(1) << QPalettePrivate::bitPosition(QPalette::ColorGroup(grp), QPalette::ColorRole(role)));
+ }
+ }
+ return mask;
}
/*!
@@ -931,17 +965,25 @@ QPalette QPalette::resolve(const QPalette &other) const
if ((*this == other && d->resolveMask == other.d->resolveMask)
|| d->resolveMask == 0) {
QPalette o = other;
- o.d->resolveMask = d->resolveMask;
+ o.setResolveMask(d->resolveMask);
return o;
}
+ if (d->resolveMask == allResolveMask())
+ return *this;
+
QPalette palette(*this);
palette.detach();
for (int role = 0; role < int(NColorRoles); ++role) {
+ // Don't resolve NoRole, its bits are needed for Accent (see bitPosition)
+ if (role == NoRole)
+ continue;
+
for (int grp = 0; grp < int(NColorGroups); ++grp) {
- if (!(d->resolveMask & (ResolveMask(1) << bitPosition(ColorGroup(grp), ColorRole(role))))) {
- palette.d->br[grp][role] = other.d->br[grp][role];
+ if (!(d->resolveMask & (ResolveMask(1) << QPalettePrivate::bitPosition(ColorGroup(grp), ColorRole(role))))) {
+ palette.d->data.detach();
+ palette.d->data->br[grp][role] = other.d->data->br[grp][role];
}
}
}
@@ -1004,7 +1046,7 @@ QDataStream &operator<<(QDataStream &s, const QPalette &p)
if (s.version() == 1) {
// Qt 1.x
for (int i = 0; i < NumOldRoles; ++i)
- s << p.d->br[grp][oldRoles[i]].color();
+ s << p.d->data->br[grp][oldRoles[i]].color();
} else {
int max = (int)QPalette::NColorRoles;
if (s.version() <= QDataStream::Qt_2_1)
@@ -1013,8 +1055,11 @@ QDataStream &operator<<(QDataStream &s, const QPalette &p)
max = QPalette::AlternateBase + 1;
else if (s.version() <= QDataStream::Qt_5_11)
max = QPalette::ToolTipText + 1;
+ else if (s.version() <= QDataStream::Qt_6_5)
+ max = QPalette::PlaceholderText + 1;
+
for (int r = 0; r < max; r++)
- s << p.d->br[grp][r];
+ s << p.d->data->br[grp][r];
}
}
return s;
@@ -1056,15 +1101,25 @@ QDataStream &operator>>(QDataStream &s, QPalette &p)
} else if (s.version() <= QDataStream::Qt_5_11) {
p = QPalette();
max = QPalette::ToolTipText + 1;
+ } else if (s.version() <= QDataStream::Qt_6_5) {
+ p = QPalette();
+ max = QPalette::PlaceholderText + 1;
}
+
QBrush tmp;
for(int grp = 0; grp < (int)QPalette::NColorGroups; ++grp) {
+ const QPalette::ColorGroup group = static_cast<QPalette::ColorGroup>(grp);
for(int role = 0; role < max; ++role) {
s >> tmp;
- p.setBrush((QPalette::ColorGroup)grp, (QPalette::ColorRole)role, tmp);
+ p.setBrush(group, (QPalette::ColorRole)role, tmp);
}
+
+ // Accent defaults to Highlight for stream versions that don't have it.
+ if (s.version() < QDataStream::Qt_6_6)
+ p.setBrush(group, QPalette::Accent, p.brush(group, QPalette::Highlight));
}
+
}
return s;
}
@@ -1111,10 +1166,10 @@ void QPalette::setColorGroup(ColorGroup cg, const QBrush &windowText, const QBru
for (int cr = Highlight; cr <= LinkVisited; ++cr) {
if (cg == All) {
for (int group = Active; group < NColorGroups; ++group) {
- d->resolveMask &= ~(ResolveMask(1) << bitPosition(ColorGroup(group), ColorRole(cr)));
+ d->resolveMask &= ~(ResolveMask(1) << QPalettePrivate::bitPosition(ColorGroup(group), ColorRole(cr)));
}
} else {
- d->resolveMask &= ~(ResolveMask(1) << bitPosition(ColorGroup(cg), ColorRole(cr)));
+ d->resolveMask &= ~(ResolveMask(1) << QPalettePrivate::bitPosition(ColorGroup(cg), ColorRole(cr)));
}
}
}
@@ -1169,47 +1224,6 @@ void QPalette::setColorGroup(ColorGroup cg, const QBrush &foreground, const QBru
setBrush(cg, ToolTipText, toolTipText);
}
-Q_GUI_EXPORT QPalette qt_fusionPalette()
-{
- QColor backGround(239, 239, 239);
- QColor light = backGround.lighter(150);
- QColor mid(backGround.darker(130));
- QColor midLight = mid.lighter(110);
- QColor base = Qt::white;
- QColor disabledBase(backGround);
- QColor dark = backGround.darker(150);
- QColor darkDisabled = QColor(209, 209, 209).darker(110);
- QColor text = Qt::black;
- QColor hightlightedText = Qt::white;
- QColor disabledText = QColor(190, 190, 190);
- QColor button = backGround;
- QColor shadow = dark.darker(135);
- QColor disabledShadow = shadow.lighter(150);
- QColor placeholder = text;
- placeholder.setAlpha(128);
-
- QPalette fusionPalette(Qt::black,backGround,light,dark,mid,text,base);
- fusionPalette.setBrush(QPalette::Midlight, midLight);
- fusionPalette.setBrush(QPalette::Button, button);
- fusionPalette.setBrush(QPalette::Shadow, shadow);
- fusionPalette.setBrush(QPalette::HighlightedText, hightlightedText);
-
- fusionPalette.setBrush(QPalette::Disabled, QPalette::Text, disabledText);
- fusionPalette.setBrush(QPalette::Disabled, QPalette::WindowText, disabledText);
- fusionPalette.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledText);
- fusionPalette.setBrush(QPalette::Disabled, QPalette::Base, disabledBase);
- fusionPalette.setBrush(QPalette::Disabled, QPalette::Dark, darkDisabled);
- fusionPalette.setBrush(QPalette::Disabled, QPalette::Shadow, disabledShadow);
-
- fusionPalette.setBrush(QPalette::Active, QPalette::Highlight, QColor(48, 140, 198));
- fusionPalette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(48, 140, 198));
- fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 145, 145));
-
- fusionPalette.setBrush(QPalette::PlaceholderText, placeholder);
-
- return fusionPalette;
-}
-
#ifndef QT_NO_DEBUG_STREAM
static QString groupsToString(const QPalette &p, QPalette::ColorRole cr)
{
@@ -1221,8 +1235,8 @@ static QString groupsToString(const QPalette &p, QPalette::ColorRole cr)
if (p.isBrushSet(cg, cr)) {
const auto &color = p.color(cg, cr);
- groupString += QString::fromUtf8(groupEnum.valueToKey(cg)) + QLatin1Char(':') +
- color.name(QColor::HexArgb) + QLatin1Char(',');
+ groupString += QString::fromUtf8(groupEnum.valueToKey(cg)) + u':' +
+ color.name(QColor::HexArgb) + u',';
}
}
groupString.chop(1);
@@ -1266,3 +1280,5 @@ QDebug operator<<(QDebug dbg, const QPalette &p)
#endif
QT_END_NAMESPACE
+
+#include "moc_qpalette.cpp"
diff --git a/src/gui/kernel/qpalette.h b/src/gui/kernel/qpalette.h
index 776d489d44..a6162e1090 100644
--- a/src/gui/kernel/qpalette.h
+++ b/src/gui/kernel/qpalette.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPALETTE_H
#define QPALETTE_H
@@ -68,19 +32,20 @@ public:
~QPalette();
QPalette &operator=(const QPalette &palette);
QPalette(QPalette &&other) noexcept
- : d(qExchange(other.d, nullptr)), currentGroup(other.currentGroup)
+ : d(std::exchange(other.d, nullptr)), currentGroup(other.currentGroup)
{}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPalette)
void swap(QPalette &other) noexcept
{
- qSwap(currentGroup, other.currentGroup);
- qSwap(d, other.d);
+ std::swap(currentGroup, other.currentGroup);
+ qt_ptr_swap(d, other.d);
}
operator QVariant() const;
// Do not change the order, the serialization format depends on it
+ // Ensure these values are kept in sync with QQuickColorGroup's properties.
enum ColorGroup { Active, Disabled, Inactive, NColorGroups, Current, All, Normal = Active };
Q_ENUM(ColorGroup)
enum ColorRole { WindowText, Button, Light, Midlight, Dark, Mid,
@@ -91,7 +56,8 @@ public:
NoRole,
ToolTipBase, ToolTipText,
PlaceholderText,
- NColorRoles = PlaceholderText + 1,
+ Accent,
+ NColorRoles = Accent + 1,
};
Q_ENUM(ColorRole)
@@ -134,6 +100,7 @@ public:
inline const QBrush &link() const { return brush(Link); }
inline const QBrush &linkVisited() const { return brush(LinkVisited); }
inline const QBrush &placeholderText() const { return brush(PlaceholderText); }
+ inline const QBrush &accent() const { return brush(Accent); }
bool operator==(const QPalette &p) const;
inline bool operator!=(const QPalette &p) const { return !(operator==(p)); }
diff --git a/src/gui/kernel/qpalette_p.h b/src/gui/kernel/qpalette_p.h
new file mode 100644
index 0000000000..ce7c30d66d
--- /dev/null
+++ b/src/gui/kernel/qpalette_p.h
@@ -0,0 +1,77 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QPALETTE_P_H
+#define QPALETTE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpalette.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QPalettePrivate
+{
+public:
+ class Data : public QSharedData {
+ public:
+ // Every instance of Data has to have a unique serial number, even
+ // if it gets created by copying another - we wouldn't create a copy
+ // in the first place if the serial number should be the same!
+ Data(const Data &other)
+ : QSharedData(other)
+ {
+ for (int grp = 0; grp < int(QPalette::NColorGroups); grp++) {
+ for (int role = 0; role < int(QPalette::NColorRoles); role++)
+ br[grp][role] = other.br[grp][role];
+ }
+ }
+ Data() = default;
+
+ QBrush br[QPalette::NColorGroups][QPalette::NColorRoles];
+ const int ser_no = qt_palette_count++;
+ };
+
+ QPalettePrivate(const QExplicitlySharedDataPointer<Data> &data)
+ : ref(1), data(data)
+ { }
+ QPalettePrivate()
+ : QPalettePrivate(QExplicitlySharedDataPointer<Data>(new Data))
+ { }
+
+ static constexpr QPalette::ResolveMask colorRoleOffset(QPalette::ColorGroup colorGroup)
+ {
+ // Exclude NoRole; that bit is used for Accent
+ return (qToUnderlying(QPalette::NColorRoles) - 1) * qToUnderlying(colorGroup);
+ }
+
+ static constexpr QPalette::ResolveMask bitPosition(QPalette::ColorGroup colorGroup,
+ QPalette::ColorRole colorRole)
+ {
+ // Map Accent into NoRole for resolving purposes
+ if (colorRole == QPalette::Accent)
+ colorRole = QPalette::NoRole;
+
+ return colorRole + colorRoleOffset(colorGroup);
+ }
+
+ QAtomicInt ref;
+ QPalette::ResolveMask resolveMask = {0};
+ static inline int qt_palette_count = 0;
+ static inline int qt_palette_private_count = 0;
+ int detach_no = ++qt_palette_private_count;
+ QExplicitlySharedDataPointer<Data> data;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPALETTE_P_H
diff --git a/src/gui/kernel/qpixelformat.cpp b/src/gui/kernel/qpixelformat.cpp
index 7a47dd472c..e05192f0b2 100644
--- a/src/gui/kernel/qpixelformat.cpp
+++ b/src/gui/kernel/qpixelformat.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpixelformat.h"
@@ -186,7 +150,7 @@ QT_BEGIN_NAMESPACE
\enum QPixelFormat::YUVLayout
YUV is not represented by describing the size of the color channels. This is
- because YUV often use macro pixels, making the concept of sperate color channels
+ because YUV often use macro pixels, making the concept of separate color channels
invalid. Instead the different YUV layouts are described with this enum.
\value YUV444
diff --git a/src/gui/kernel/qpixelformat.h b/src/gui/kernel/qpixelformat.h
index 2fee7c1a9a..4954a6cd94 100644
--- a/src/gui/kernel/qpixelformat.h
+++ b/src/gui/kernel/qpixelformat.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXELFORMAT_H
#define QPIXELFORMAT_H
diff --git a/src/gui/kernel/qplatformclipboard.cpp b/src/gui/kernel/qplatformclipboard.cpp
index 34c94dca3b..7321b5065d 100644
--- a/src/gui/kernel/qplatformclipboard.cpp
+++ b/src/gui/kernel/qplatformclipboard.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformclipboard.h"
#ifndef QT_NO_CLIPBOARD
diff --git a/src/gui/kernel/qplatformclipboard.h b/src/gui/kernel/qplatformclipboard.h
index 3220201720..51b7c51abd 100644
--- a/src/gui/kernel/qplatformclipboard.h
+++ b/src/gui/kernel/qplatformclipboard.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMCLIPBOARD_H
#define QPLATFORMCLIPBOARD_H
diff --git a/src/gui/kernel/qplatformcursor.cpp b/src/gui/kernel/qplatformcursor.cpp
index 1330b5bf31..0e2fb9eba1 100644
--- a/src/gui/kernel/qplatformcursor.cpp
+++ b/src/gui/kernel/qplatformcursor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformcursor.h"
#include <QPainter>
@@ -619,7 +583,7 @@ void QPlatformCursorImage::set(const uchar *data, const uchar *mask,
int p = 0;
int d, m;
- int x = -1, w = 0;
+ int x = -1;
uchar *cursor_data = cursorImage.bits();
qsizetype bpl = cursorImage.bytesPerLine();
@@ -641,15 +605,11 @@ void QPlatformCursorImage::set(const uchar *data, const uchar *mask,
x = j*8+b;
else if (x >= 0 && !m) {
x = -1;
- w = 0;
}
- if (m)
- w++;
}
}
if (x >= 0) {
x = -1;
- w = 0;
}
cursor_data += bpl;
}
diff --git a/src/gui/kernel/qplatformcursor.h b/src/gui/kernel/qplatformcursor.h
index f3871d8780..56216d475b 100644
--- a/src/gui/kernel/qplatformcursor.h
+++ b/src/gui/kernel/qplatformcursor.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMCURSOR_H
#define QPLATFORMCURSOR_H
diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp
index 82b60b7749..93de7933d4 100644
--- a/src/gui/kernel/qplatformdialoghelper.cpp
+++ b/src/gui/kernel/qplatformdialoghelper.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdialoghelper.h"
@@ -51,11 +15,19 @@
#include <QtCore/QUrl>
#include <QtCore/QVariant>
#include <QtGui/QColor>
+#include <QtGui/QPixmap>
#include <algorithm>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+QT_IMPL_METATYPE_EXTERN_TAGGED(QPlatformDialogHelper::StandardButton,
+ QPlatformDialogHelper__StandardButton)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QPlatformDialogHelper::ButtonRole,
+ QPlatformDialogHelper__ButtonRole)
+
/*!
\class QPlatformDialogHelper
\since 5.0
@@ -294,7 +266,7 @@ void QColorDialogStaticData::readSettings()
#if QT_CONFIG(settings)
const QSettings settings(QSettings::UserScope, QStringLiteral("QtProject"));
for (int i = 0; i < int(CustomColorCount); ++i) {
- const QVariant v = settings.value(QLatin1String("Qt/customColors/") + QString::number(i));
+ const QVariant v = settings.value("Qt/customColors/"_L1 + QString::number(i));
if (v.isValid())
customRgb[i] = v.toUInt();
}
@@ -308,7 +280,7 @@ void QColorDialogStaticData::writeSettings() const
const_cast<QColorDialogStaticData*>(this)->customSet = false;
QSettings settings(QSettings::UserScope, QStringLiteral("QtProject"));
for (int i = 0; i < int(CustomColorCount); ++i)
- settings.setValue(QLatin1String("Qt/customColors/") + QString::number(i), customRgb[i]);
+ settings.setValue("Qt/customColors/"_L1 + QString::number(i), customRgb[i]);
}
#endif
}
@@ -643,7 +615,7 @@ QStringList QFileDialogOptions::mimeTypeFilters() const
void QFileDialogOptions::setDefaultSuffix(const QString &suffix)
{
d->defaultSuffix = suffix;
- if (d->defaultSuffix.size() > 1 && d->defaultSuffix.startsWith(QLatin1Char('.')))
+ if (d->defaultSuffix.size() > 1 && d->defaultSuffix.startsWith(u'.'))
d->defaultSuffix.remove(0, 1); // Silently change ".txt" -> "txt".
}
@@ -771,13 +743,13 @@ const char QPlatformFileDialogHelper::filterRegExp[] =
QStringList QPlatformFileDialogHelper::cleanFilterList(const QString &filter)
{
#if QT_CONFIG(regularexpression)
- QRegularExpression regexp(QString::fromLatin1(filterRegExp));
+ static const QRegularExpression regexp(QString::fromLatin1(filterRegExp));
Q_ASSERT(regexp.isValid());
QString f = filter;
QRegularExpressionMatch match = regexp.match(filter);
if (match.hasMatch())
f = match.captured(2);
- return f.split(QLatin1Char(' '), Qt::SkipEmptyParts);
+ return f.split(u' ', Qt::SkipEmptyParts);
#else
Q_UNUSED(filter);
return QStringList();
@@ -796,13 +768,19 @@ public:
{}
QString windowTitle;
- QMessageDialogOptions::Icon icon;
+ QMessageDialogOptions::StandardIcon icon;
QString text;
QString informativeText;
QString detailedText;
QPlatformDialogHelper::StandardButtons buttons;
QList<QMessageDialogOptions::CustomButton> customButtons;
int nextCustomButtonId;
+ QPixmap iconPixmap;
+ QString checkBoxLabel;
+ Qt::CheckState checkBoxState = Qt::Unchecked;
+ int defaultButtonId = 0;
+ int escapeButtonId = 0;
+ QMessageDialogOptions::Options options;
};
QMessageDialogOptions::QMessageDialogOptions(QMessageDialogOptionsPrivate *dd)
@@ -844,16 +822,26 @@ void QMessageDialogOptions::setWindowTitle(const QString &title)
d->windowTitle = title;
}
-QMessageDialogOptions::Icon QMessageDialogOptions::icon() const
+QMessageDialogOptions::StandardIcon QMessageDialogOptions::standardIcon() const
{
return d->icon;
}
-void QMessageDialogOptions::setIcon(Icon icon)
+void QMessageDialogOptions::setStandardIcon(StandardIcon icon)
{
d->icon = icon;
}
+void QMessageDialogOptions::setIconPixmap(const QPixmap &pixmap)
+{
+ d->iconPixmap = pixmap;
+}
+
+QPixmap QMessageDialogOptions::iconPixmap() const
+{
+ return d->iconPixmap;
+}
+
QString QMessageDialogOptions::text() const
{
return d->text;
@@ -895,9 +883,9 @@ QPlatformDialogHelper::StandardButtons QMessageDialogOptions::standardButtons()
}
int QMessageDialogOptions::addButton(const QString &label, QPlatformDialogHelper::ButtonRole role,
- void *buttonImpl)
+ void *buttonImpl, int buttonId)
{
- const CustomButton b(d->nextCustomButtonId++, label, role, buttonImpl);
+ const CustomButton b(buttonId ? buttonId : d->nextCustomButtonId++, label, role, buttonImpl);
d->customButtons.append(b);
return b.id;
}
@@ -917,12 +905,76 @@ const QList<QMessageDialogOptions::CustomButton> &QMessageDialogOptions::customB
return d->customButtons;
}
+void QMessageDialogOptions::clearCustomButtons()
+{
+ d->customButtons.clear();
+}
+
const QMessageDialogOptions::CustomButton *QMessageDialogOptions::customButton(int id)
{
- int i = d->customButtons.indexOf(CustomButton(id));
+ const int i = int(d->customButtons.indexOf(CustomButton(id)));
return (i < 0 ? nullptr : &d->customButtons.at(i));
}
+void QMessageDialogOptions::setCheckBox(const QString &label, Qt::CheckState state)
+{
+ d->checkBoxLabel = label;
+ d->checkBoxState = state;
+}
+
+QString QMessageDialogOptions::checkBoxLabel() const
+{
+ return d->checkBoxLabel;
+}
+
+Qt::CheckState QMessageDialogOptions::checkBoxState() const
+{
+ return d->checkBoxState;
+}
+
+void QMessageDialogOptions::setDefaultButton(int id)
+{
+ d->defaultButtonId = id;
+}
+
+int QMessageDialogOptions::defaultButton() const
+{
+ return d->defaultButtonId;
+}
+
+void QMessageDialogOptions::setEscapeButton(int id)
+{
+ d->escapeButtonId = id;
+}
+
+int QMessageDialogOptions::escapeButton() const
+{
+ return d->escapeButtonId;
+}
+
+void QMessageDialogOptions::setOption(QMessageDialogOptions::Option option, bool on)
+{
+ if (!(d->options & option) != !on)
+ setOptions(d->options ^ option);
+}
+
+bool QMessageDialogOptions::testOption(QMessageDialogOptions::Option option) const
+{
+ return d->options & option;
+}
+
+void QMessageDialogOptions::setOptions(QMessageDialogOptions::Options options)
+{
+ if (options != d->options)
+ d->options = options;
+}
+
+QMessageDialogOptions::Options QMessageDialogOptions::options() const
+{
+ return d->options;
+}
+
+
QPlatformDialogHelper::ButtonRole QPlatformDialogHelper::buttonRole(QPlatformDialogHelper::StandardButton button)
{
switch (button) {
@@ -1002,3 +1054,5 @@ void QPlatformMessageDialogHelper::setOptions(const QSharedPointer<QMessageDialo
}
QT_END_NAMESPACE
+
+#include "moc_qplatformdialoghelper.cpp"
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
index 5d1d25a2dd..0569a7e2f9 100644
--- a/src/gui/kernel/qplatformdialoghelper.h
+++ b/src/gui/kernel/qplatformdialoghelper.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMDIALOGHELPER_H
#define QPLATFORMDIALOGHELPER_H
@@ -176,8 +140,10 @@ Q_SIGNALS:
};
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QPlatformDialogHelper::StandardButton)
-Q_DECLARE_METATYPE(QPlatformDialogHelper::ButtonRole)
+QT_DECL_METATYPE_EXTERN_TAGGED(QPlatformDialogHelper::StandardButton,
+ QPlatformDialogHelper__StandardButton, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN_TAGGED(QPlatformDialogHelper::ButtonRole,
+ QPlatformDialogHelper__ButtonRole, Q_GUI_EXPORT)
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QColorDialogOptions
@@ -191,7 +157,8 @@ public:
enum ColorDialogOption {
ShowAlphaChannel = 0x00000001,
NoButtons = 0x00000002,
- DontUseNativeDialog = 0x00000004
+ DontUseNativeDialog = 0x00000004,
+ NoEyeDropperButton = 0x00000008
};
Q_DECLARE_FLAGS(ColorDialogOptions, ColorDialogOption)
@@ -314,15 +281,16 @@ public:
enum DialogLabel { LookIn, FileName, FileType, Accept, Reject, DialogLabelCount };
Q_ENUM(DialogLabel)
+ // keep this in sync with QFileDialog::Options
enum FileDialogOption
{
ShowDirsOnly = 0x00000001,
DontResolveSymlinks = 0x00000002,
DontConfirmOverwrite = 0x00000004,
- DontUseNativeDialog = 0x00000010,
- ReadOnly = 0x00000020,
- HideNameFilterDetails = 0x00000040,
- DontUseCustomDirectoryIcons = 0x00000080
+ DontUseNativeDialog = 0x00000008,
+ ReadOnly = 0x00000010,
+ HideNameFilterDetails = 0x00000020,
+ DontUseCustomDirectoryIcons = 0x00000040
};
Q_DECLARE_FLAGS(FileDialogOptions, FileDialogOption)
Q_FLAG(FileDialogOptions)
@@ -436,9 +404,16 @@ protected:
~QMessageDialogOptions();
public:
+ // Keep in sync with QMessageBox Option
+ enum class Option {
+ DontUseNativeDialog = 0x00000001,
+ };
+ Q_DECLARE_FLAGS(Options, Option);
+ Q_FLAG(Options);
+
// Keep in sync with QMessageBox::Icon
- enum Icon { NoIcon, Information, Warning, Critical, Question };
- Q_ENUM(Icon)
+ enum StandardIcon { NoIcon, Information, Warning, Critical, Question };
+ Q_ENUM(StandardIcon)
static QSharedPointer<QMessageDialogOptions> create();
QSharedPointer<QMessageDialogOptions> clone() const;
@@ -446,8 +421,11 @@ public:
QString windowTitle() const;
void setWindowTitle(const QString &);
- void setIcon(Icon icon);
- Icon icon() const;
+ void setStandardIcon(StandardIcon icon);
+ StandardIcon standardIcon() const;
+
+ void setIconPixmap(const QPixmap &pixmap);
+ QPixmap iconPixmap() const;
void setText(const QString &text);
QString text() const;
@@ -458,6 +436,11 @@ public:
void setDetailedText(const QString &text);
QString detailedText() const;
+ void setOption(Option option, bool on = true);
+ bool testOption(Option option) const;
+ void setOptions(Options options);
+ Options options() const;
+
void setStandardButtons(QPlatformDialogHelper::StandardButtons buttons);
QPlatformDialogHelper::StandardButtons standardButtons() const;
@@ -476,10 +459,21 @@ public:
};
int addButton(const QString &label, QPlatformDialogHelper::ButtonRole role,
- void *buttonImpl = nullptr);
+ void *buttonImpl = nullptr, int buttonId = 0);
void removeButton(int id);
const QList<CustomButton> &customButtons();
const CustomButton *customButton(int id);
+ void clearCustomButtons();
+
+ void setCheckBox(const QString &label, Qt::CheckState state);
+ QString checkBoxLabel() const;
+ Qt::CheckState checkBoxState() const;
+
+ void setEscapeButton(int id);
+ int escapeButton() const;
+
+ void setDefaultButton(int id);
+ int defaultButton() const;
private:
QMessageDialogOptionsPrivate *d;
@@ -494,6 +488,7 @@ public:
Q_SIGNALS:
void clicked(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role);
+ void checkBoxStateChanged(Qt::CheckState state);
private:
QSharedPointer<QMessageDialogOptions> m_options;
diff --git a/src/gui/kernel/qplatformdrag.cpp b/src/gui/kernel/qplatformdrag.cpp
index b40ddcbfb8..cf50587996 100644
--- a/src/gui/kernel/qplatformdrag.cpp
+++ b/src/gui/kernel/qplatformdrag.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdrag.h"
diff --git a/src/gui/kernel/qplatformdrag.h b/src/gui/kernel/qplatformdrag.h
index 0c99539357..d9e4a553b8 100644
--- a/src/gui/kernel/qplatformdrag.h
+++ b/src/gui/kernel/qplatformdrag.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMDRAG_H
#define QPLATFORMDRAG_H
diff --git a/src/gui/kernel/qplatformgraphicsbuffer.cpp b/src/gui/kernel/qplatformgraphicsbuffer.cpp
index b49aa47d41..52fc2770b4 100644
--- a/src/gui/kernel/qplatformgraphicsbuffer.cpp
+++ b/src/gui/kernel/qplatformgraphicsbuffer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformgraphicsbuffer.h"
#include <QtGui/QOpenGLContext>
@@ -270,3 +234,5 @@ QPlatformGraphicsBuffer::Origin QPlatformGraphicsBuffer::origin() const
*/
QT_END_NAMESPACE
+
+#include "moc_qplatformgraphicsbuffer.cpp"
diff --git a/src/gui/kernel/qplatformgraphicsbuffer.h b/src/gui/kernel/qplatformgraphicsbuffer.h
index 9004116ea4..6723c63f0c 100644
--- a/src/gui/kernel/qplatformgraphicsbuffer.h
+++ b/src/gui/kernel/qplatformgraphicsbuffer.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMGRAPHICSBUFFER_H
#define QPLATFORMGRAPHICSBUFFER_H
diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp
index ff72171b85..0ec2308453 100644
--- a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp
+++ b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qpa/qplatformgraphicsbuffer.h>
@@ -215,14 +179,14 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe
QRect rect = subRect;
if (rect.isNull() || rect == QRect(QPoint(0,0),size)) {
if (needsRowLength)
- funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.bytesPerLine() / 4);
+ funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, GLint(image.bytesPerLine() / 4));
funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, size.width(), size.height(), 0, GL_RGBA, pixelType, image.constBits());
if (needsRowLength)
funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
} else {
if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
// OpenGL 2.1+ or OpenGL ES/3+
- funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.bytesPerLine() / 4);
+ funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, GLint(image.bytesPerLine() / 4));
funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType,
image.constScanLine(rect.y()) + rect.x() * 4);
funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.h b/src/gui/kernel/qplatformgraphicsbufferhelper.h
index 36afd4877b..e408e4a674 100644
--- a/src/gui/kernel/qplatformgraphicsbufferhelper.h
+++ b/src/gui/kernel/qplatformgraphicsbufferhelper.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMGRAPHICSBUFFERHELPER_H
#define QPLATFORMGRAPHICSBUFFERHELPER_H
diff --git a/src/gui/kernel/qplatforminputcontext.cpp b/src/gui/kernel/qplatforminputcontext.cpp
index 0326744482..9d3ee4acb6 100644
--- a/src/gui/kernel/qplatforminputcontext.cpp
+++ b/src/gui/kernel/qplatforminputcontext.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatforminputcontext.h"
#include <qguiapplication.h>
@@ -83,6 +47,11 @@ QT_BEGIN_NAMESPACE
QPlatformInputContext::QPlatformInputContext()
: QObject(*(new QPlatformInputContextPrivate))
{
+ // Delay initialization of cached input direction
+ // until super class has finished constructing.
+ QMetaObject::invokeMethod(this, [this]{
+ m_inputDirection = inputDirection();
+ }, Qt::QueuedConnection);
}
/*!
@@ -131,7 +100,7 @@ void QPlatformInputContext::update(Qt::InputMethodQueries)
}
/*!
- Called when when the word currently being composed in input item is tapped by
+ Called when the word currently being composed in the input item is tapped by
the user. Input methods often use this information to offer more word
suggestions to the user.
*/
@@ -228,22 +197,29 @@ void QPlatformInputContext::emitInputPanelVisibleChanged()
QLocale QPlatformInputContext::locale() const
{
- return qt_keymapper_private()->keyboardInputLocale;
+ return QLocale::system();
}
void QPlatformInputContext::emitLocaleChanged()
{
emit QGuiApplication::inputMethod()->localeChanged();
+
+ // Changing the locale might have updated the input direction
+ emitInputDirectionChanged(inputDirection());
}
Qt::LayoutDirection QPlatformInputContext::inputDirection() const
{
- return qt_keymapper_private()->keyboardInputDirection;
+ return locale().textDirection();
}
void QPlatformInputContext::emitInputDirectionChanged(Qt::LayoutDirection newDirection)
{
+ if (newDirection == m_inputDirection)
+ return;
+
emit QGuiApplication::inputMethod()->inputDirectionChanged(newDirection);
+ m_inputDirection = newDirection;
}
/*!
@@ -377,3 +353,5 @@ QRectF QPlatformInputContext::keyboardRectangle()
}
QT_END_NAMESPACE
+
+#include "moc_qplatforminputcontext.cpp"
diff --git a/src/gui/kernel/qplatforminputcontext.h b/src/gui/kernel/qplatforminputcontext.h
index ea929f4a0d..481f97a065 100644
--- a/src/gui/kernel/qplatforminputcontext.h
+++ b/src/gui/kernel/qplatforminputcontext.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMINPUTCONTEXT_H
#define QPLATFORMINPUTCONTEXT_H
@@ -108,6 +72,8 @@ private:
friend class QGuiApplication;
friend class QGuiApplicationPrivate;
friend class QInputMethod;
+
+ Qt::LayoutDirection m_inputDirection;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatforminputcontext_p.h b/src/gui/kernel/qplatforminputcontext_p.h
index c4f4b97d03..d26bfe70af 100644
--- a/src/gui/kernel/qplatforminputcontext_p.h
+++ b/src/gui/kernel/qplatforminputcontext_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMINPUTCONTEXT_P_H
#define QPLATFORMINPUTCONTEXT_P_H
diff --git a/src/gui/kernel/qplatforminputcontextfactory.cpp b/src/gui/kernel/qplatforminputcontextfactory.cpp
index 749abaf27a..933d990f7c 100644
--- a/src/gui/kernel/qplatforminputcontextfactory.cpp
+++ b/src/gui/kernel/qplatforminputcontextfactory.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatforminputcontextplugin_p.h>
@@ -48,35 +12,60 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#if QT_CONFIG(settings)
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QPlatformInputContextFactoryInterface_iid, QLatin1String("/platforminputcontexts"), Qt::CaseInsensitive))
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, icLoader,
+ (QPlatformInputContextFactoryInterface_iid, "/platforminputcontexts"_L1, Qt::CaseInsensitive))
#endif
QStringList QPlatformInputContextFactory::keys()
{
#if QT_CONFIG(settings)
- return loader()->keyMap().values();
+ return icLoader()->keyMap().values();
#else
return QStringList();
#endif
}
-QString QPlatformInputContextFactory::requested()
+QStringList QPlatformInputContextFactory::requested()
{
- QByteArray env = qgetenv("QT_IM_MODULE");
- return env.isNull() ? QString() : QString::fromLocal8Bit(env);
+ QStringList imList;
+ QByteArray env = qgetenv("QT_IM_MODULES");
+
+ if (!env.isEmpty())
+ imList = QString::fromLocal8Bit(env).split(QChar::fromLatin1(';'), Qt::SkipEmptyParts);
+
+ if (!imList.isEmpty())
+ return imList;
+
+ env = qgetenv("QT_IM_MODULE");
+ if (!env.isEmpty())
+ imList = {QString::fromLocal8Bit(env)};
+
+ return imList;
+}
+
+QPlatformInputContext *QPlatformInputContextFactory::create(const QStringList& keys)
+{
+ for (const QString &key : keys) {
+ auto plugin = create(key);
+ if (plugin)
+ return plugin;
+ }
+
+ return nullptr;
}
QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key)
{
#if QT_CONFIG(settings)
if (!key.isEmpty()) {
- QStringList paramList = key.split(QLatin1Char(':'));
+ QStringList paramList = key.split(u':');
const QString platform = paramList.takeFirst().toLower();
QPlatformInputContext *ic = qLoadPlugin<QPlatformInputContext, QPlatformInputContextPlugin>
- (loader(), platform, paramList);
+ (icLoader(), platform, paramList);
if (ic && ic->isValid())
return ic;
diff --git a/src/gui/kernel/qplatforminputcontextfactory_p.h b/src/gui/kernel/qplatforminputcontextfactory_p.h
index 881421ce49..5f5881c508 100644
--- a/src/gui/kernel/qplatforminputcontextfactory_p.h
+++ b/src/gui/kernel/qplatforminputcontextfactory_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMINPUTCONTEXTFACTORY_H
#define QPLATFORMINPUTCONTEXTFACTORY_H
@@ -63,7 +27,8 @@ class Q_GUI_EXPORT QPlatformInputContextFactory
{
public:
static QStringList keys();
- static QString requested();
+ static QStringList requested();
+ static QPlatformInputContext *create(const QStringList &keys);
static QPlatformInputContext *create(const QString &key);
static QPlatformInputContext *create();
};
diff --git a/src/gui/kernel/qplatforminputcontextplugin.cpp b/src/gui/kernel/qplatforminputcontextplugin.cpp
index 53d56dbb48..fdfc8483b5 100644
--- a/src/gui/kernel/qplatforminputcontextplugin.cpp
+++ b/src/gui/kernel/qplatforminputcontextplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatforminputcontextplugin_p.h"
@@ -51,3 +15,5 @@ QPlatformInputContextPlugin::~QPlatformInputContextPlugin()
}
QT_END_NAMESPACE
+
+#include "moc_qplatforminputcontextplugin_p.cpp"
diff --git a/src/gui/kernel/qplatforminputcontextplugin_p.h b/src/gui/kernel/qplatforminputcontextplugin_p.h
index 2228d5c8d6..819955bef4 100644
--- a/src/gui/kernel/qplatforminputcontextplugin_p.h
+++ b/src/gui/kernel/qplatforminputcontextplugin_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMINPUTCONTEXTPLUGIN_H
#define QPLATFORMINPUTCONTEXTPLUGIN_H
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index a53f0d09d7..130b479c64 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformintegration.h"
#include <qpa/qplatformfontdatabase.h>
#include <qpa/qplatformclipboard.h>
#include <qpa/qplatformaccessibility.h>
+#include <qpa/qplatformkeymapper.h>
#include <qpa/qplatformtheme.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qpixmap_raster_p.h>
@@ -187,7 +152,7 @@ QPlatformServices *QPlatformIntegration::services() const
/*!
\enum QPlatformIntegration::Capability
- Capabilities are used to determing specific features of a platform integration
+ Capabilities are used to determine specific features of a platform integration
\value ThreadedPixmaps The platform uses a pixmap implementation that is reentrant
and can be used from multiple threads, like the raster paint engine and QImage based
@@ -260,6 +225,15 @@ QPlatformServices *QPlatformIntegration::services() const
where there is an alternative, such as Qt Quick with its \c software backend, an
automatic fallback to that alternative may occur, if applicable. The default
implementation of hasCapability() returns \c true.
+
+ \value ScreenWindowGrabbing The platform supports grabbing window on screen.
+ On Wayland, this capability can be reported as \c false. The default implementation
+ of hasCapability() returns \c true.
+
+ \value BackingStoreStaticContents The platform backingstore supports static contents.
+ On resize of the backingstore the static contents region is provided, and the backing
+ store is expected to propagate the static content to the resized backing store, without
+ clients needing to repaint the static content region.
*/
/*!
@@ -284,7 +258,8 @@ QPlatformServices *QPlatformIntegration::services() const
bool QPlatformIntegration::hasCapability(Capability cap) const
{
return cap == NonFullScreenWindows || cap == NativeWidgets || cap == WindowManagement
- || cap == TopStackedNativeChildWindows || cap == WindowActivation || cap == RhiBasedRendering;
+ || cap == TopStackedNativeChildWindows || cap == WindowActivation
+ || cap == RhiBasedRendering || cap == ScreenWindowGrabbing;
}
QPlatformPixmap *QPlatformIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
@@ -373,7 +348,22 @@ QPlatformInputContext *QPlatformIntegration::inputContext() const
return nullptr;
}
-#ifndef QT_NO_ACCESSIBILITY
+/*!
+ Accessor for the platform integration's key mapper.
+
+ Default implementation returns a default QPlatformKeyMapper.
+
+ \sa QPlatformKeyMapper
+*/
+QPlatformKeyMapper *QPlatformIntegration::keyMapper() const
+{
+ static QPlatformKeyMapper *keyMapper = nullptr;
+ if (!keyMapper)
+ keyMapper = new QPlatformKeyMapper;
+ return keyMapper;
+}
+
+#if QT_CONFIG(accessibility)
/*!
Returns the platforms accessibility.
@@ -424,7 +414,7 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
case UseRtlExtensions:
return QVariant(false);
case SetFocusOnTouchRelease:
- return QVariant(false);
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::SetFocusOnTouchRelease);
case MousePressAndHoldInterval:
return QPlatformTheme::defaultThemeHint(QPlatformTheme::MousePressAndHoldInterval);
case TabFocusBehavior:
@@ -439,6 +429,16 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
return QPlatformTheme::defaultThemeHint(QPlatformTheme::WheelScrollLines);
case MouseQuickSelectionThreshold:
return QPlatformTheme::defaultThemeHint(QPlatformTheme::MouseQuickSelectionThreshold);
+ case MouseDoubleClickDistance:
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::MouseDoubleClickDistance);
+ case FlickStartDistance:
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::FlickStartDistance);
+ case FlickMaximumVelocity:
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::FlickMaximumVelocity);
+ case FlickDeceleration:
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::FlickDeceleration);
+ case UnderlineShortcut:
+ return true;
}
return 0;
@@ -450,6 +450,9 @@ Qt::WindowState QPlatformIntegration::defaultWindowState(Qt::WindowFlags flags)
if (flags & Qt::Popup & ~Qt::Window)
return Qt::WindowNoState;
+ if (flags & Qt::SubWindow)
+ return Qt::WindowNoState;
+
if (styleHint(QPlatformIntegration::ShowIsFullScreen).toBool())
return Qt::WindowFullScreen;
else if (styleHint(QPlatformIntegration::ShowIsMaximized).toBool())
@@ -589,7 +592,21 @@ void QPlatformIntegration::setApplicationIcon(const QIcon &icon) const
Q_UNUSED(icon);
}
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+/*!
+ \since 6.5
+
+ Should set the application's badge to \a number.
+
+ If the number is 0 the badge should be cleared.
+
+ \sa QGuiApplication::setBadge()
+*/
+void QPlatformIntegration::setApplicationBadge(qint64 number)
+{
+ Q_UNUSED(number);
+}
+
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
/*!
Factory function for QPlatformVulkanInstance. The \a instance parameter is a
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 75b942f998..a18ae821c7 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMINTEGRATION_H
#define QPLATFORMINTEGRATION_H
@@ -69,6 +33,7 @@ class QPlatformOpenGLContext;
class QGuiGLFormat;
class QAbstractEventDispatcher;
class QPlatformInputContext;
+class QPlatformKeyMapper;
class QPlatformAccessibility;
class QPlatformTheme;
class QPlatformDialogHelper;
@@ -133,7 +98,9 @@ public:
OpenGLOnRasterSurface,
MaximizeUsingFullscreenGeometry,
PaintEvents,
- RhiBasedRendering
+ RhiBasedRendering,
+ ScreenWindowGrabbing, // whether QScreen::grabWindow() is supported
+ BackingStoreStaticContents
};
virtual ~QPlatformIntegration() { }
@@ -164,7 +131,7 @@ public:
virtual QPlatformDrag *drag() const;
#endif
virtual QPlatformInputContext *inputContext() const;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
virtual QPlatformAccessibility *accessibility() const;
#endif
@@ -195,14 +162,23 @@ public:
UiEffects,
WheelScrollLines,
ShowShortcutsInContextMenus,
- MouseQuickSelectionThreshold
+ MouseQuickSelectionThreshold,
+ MouseDoubleClickDistance,
+ FlickStartDistance,
+ FlickMaximumVelocity,
+ FlickDeceleration,
+ UnderlineShortcut,
};
virtual QVariant styleHint(StyleHint hint) const;
virtual Qt::WindowState defaultWindowState(Qt::WindowFlags) const;
+protected:
virtual Qt::KeyboardModifiers queryKeyboardModifiers() const;
virtual QList<int> possibleKeys(const QKeyEvent *) const;
+ friend class QPlatformKeyMapper;
+public:
+ virtual QPlatformKeyMapper *keyMapper() const;
virtual QStringList themeNames() const;
virtual QPlatformTheme *createPlatformTheme(const QString &name) const;
@@ -219,11 +195,12 @@ public:
virtual QOpenGLContext::OpenGLModuleType openGLModuleType();
#endif
virtual void setApplicationIcon(const QIcon &icon) const;
+ virtual void setApplicationBadge(qint64 number);
virtual void beep() const;
virtual void quit() const;
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
virtual QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const;
#endif
diff --git a/src/gui/kernel/qplatformintegrationfactory.cpp b/src/gui/kernel/qplatformintegrationfactory.cpp
index 3fcf9014a7..d0a5e8871f 100644
--- a/src/gui/kernel/qplatformintegrationfactory.cpp
+++ b/src/gui/kernel/qplatformintegrationfactory.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qpa/qplatformintegrationfactory_p.h>
#include <qpa/qplatformintegrationplugin.h>
@@ -48,27 +12,15 @@
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QPlatformIntegrationFactoryInterface_iid, QLatin1String("/platforms"), Qt::CaseInsensitive))
+using namespace Qt::StringLiterals;
-#if QT_CONFIG(library)
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader,
- (QPlatformIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
-#endif // QT_CONFIG(library)
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, piLoader,
+ (QPlatformIntegrationFactoryInterface_iid, "/platforms"_L1, Qt::CaseInsensitive))
QPlatformIntegration *QPlatformIntegrationFactory::create(const QString &platform, const QStringList &paramList, int &argc, char **argv, const QString &platformPluginPath)
{
-#if QT_CONFIG(library)
- // Try loading the plugin from platformPluginPath first:
- if (!platformPluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(platformPluginPath);
- if (QPlatformIntegration *ret = qLoadPlugin<QPlatformIntegration, QPlatformIntegrationPlugin>(directLoader(), platform, paramList, argc, argv))
- return ret;
- }
-#else
- Q_UNUSED(platformPluginPath);
-#endif
- return qLoadPlugin<QPlatformIntegration, QPlatformIntegrationPlugin>(loader(), platform, paramList, argc, argv);
+ piLoader->setExtraSearchPath(platformPluginPath);
+ return qLoadPlugin<QPlatformIntegration, QPlatformIntegrationPlugin>(piLoader(), platform, paramList, argc, argv);
}
/*!
@@ -80,25 +32,8 @@ QPlatformIntegration *QPlatformIntegrationFactory::create(const QString &platfor
QStringList QPlatformIntegrationFactory::keys(const QString &platformPluginPath)
{
- QStringList list;
-#if QT_CONFIG(library)
- if (!platformPluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(platformPluginPath);
- list = directLoader()->keyMap().values();
- if (!list.isEmpty()) {
- const QString postFix = QLatin1String(" (from ")
- + QDir::toNativeSeparators(platformPluginPath)
- + QLatin1Char(')');
- const QStringList::iterator end = list.end();
- for (QStringList::iterator it = list.begin(); it != end; ++it)
- (*it).append(postFix);
- }
- }
-#else
- Q_UNUSED(platformPluginPath);
-#endif
- list.append(loader()->keyMap().values());
- return list;
+ piLoader->setExtraSearchPath(platformPluginPath);
+ return piLoader->keyMap().values();
}
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformintegrationfactory_p.h b/src/gui/kernel/qplatformintegrationfactory_p.h
index 22c77ce8bd..0010815956 100644
--- a/src/gui/kernel/qplatformintegrationfactory_p.h
+++ b/src/gui/kernel/qplatformintegrationfactory_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMINTEGRATIONFACTORY_H
#define QPLATFORMINTEGRATIONFACTORY_H
diff --git a/src/gui/kernel/qplatformintegrationplugin.cpp b/src/gui/kernel/qplatformintegrationplugin.cpp
index e024276797..faf32887c7 100644
--- a/src/gui/kernel/qplatformintegrationplugin.cpp
+++ b/src/gui/kernel/qplatformintegrationplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformintegrationplugin.h"
@@ -65,3 +29,5 @@ QPlatformIntegration *QPlatformIntegrationPlugin::create(const QString &key, con
}
QT_END_NAMESPACE
+
+#include "moc_qplatformintegrationplugin.cpp"
diff --git a/src/gui/kernel/qplatformintegrationplugin.h b/src/gui/kernel/qplatformintegrationplugin.h
index 6a0b9dc9a7..cf4915ad83 100644
--- a/src/gui/kernel/qplatformintegrationplugin.h
+++ b/src/gui/kernel/qplatformintegrationplugin.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMINTEGRATIONPLUGIN_H
#define QPLATFORMINTEGRATIONPLUGIN_H
diff --git a/src/gui/kernel/qplatformkeymapper.cpp b/src/gui/kernel/qplatformkeymapper.cpp
new file mode 100644
index 0000000000..f54e4ff379
--- /dev/null
+++ b/src/gui/kernel/qplatformkeymapper.cpp
@@ -0,0 +1,38 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qplatformkeymapper.h"
+
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcQpaKeyMapper, "qt.qpa.keymapper")
+
+QPlatformKeyMapper::~QPlatformKeyMapper()
+{
+}
+
+/*
+ Should return a list of possible key combinations for the given key event.
+
+ For example, given a US English keyboard layout, the key event Shift+5
+ can represent both a "Shift+5" key combination, as well as just "%".
+*/
+QList<QKeyCombination> QPlatformKeyMapper::possibleKeyCombinations(const QKeyEvent *event) const
+{
+ auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
+ QList<int> possibleKeys = platformIntegration->possibleKeys(event);
+ QList<QKeyCombination> combinations;
+ for (int key : possibleKeys)
+ combinations << QKeyCombination::fromCombined(key);
+ return combinations;
+}
+
+Qt::KeyboardModifiers QPlatformKeyMapper::queryKeyboardModifiers() const
+{
+ return QGuiApplicationPrivate::platformIntegration()->queryKeyboardModifiers();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformkeymapper.h b/src/gui/kernel/qplatformkeymapper.h
new file mode 100644
index 0000000000..fb5b0cdb8b
--- /dev/null
+++ b/src/gui/kernel/qplatformkeymapper.h
@@ -0,0 +1,36 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QPLATFORMKEYMAPPER_P
+#define QPLATFORMKEYMAPPER_P
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the QPA API and is not meant to be used
+// in applications. Usage of this API may make your code
+// source and binary incompatible with future versions of Qt.
+//
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/qloggingcategory.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcQpaKeyMapper, Q_GUI_EXPORT)
+
+class QKeyEvent;
+
+class Q_GUI_EXPORT QPlatformKeyMapper
+{
+public:
+ virtual ~QPlatformKeyMapper();
+
+ virtual QList<QKeyCombination> possibleKeyCombinations(const QKeyEvent *event) const;
+ virtual Qt::KeyboardModifiers queryKeyboardModifiers() const;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPLATFORMKEYMAPPER_P
diff --git a/src/gui/kernel/qplatformmenu.cpp b/src/gui/kernel/qplatformmenu.cpp
index 0d76f2039d..d629c8b02d 100644
--- a/src/gui/kernel/qplatformmenu.cpp
+++ b/src/gui/kernel/qplatformmenu.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 Martin Graesslin <mgraesslin@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2014 Martin Graesslin <mgraesslin@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformmenu.h"
@@ -92,3 +56,5 @@ QPlatformMenu *QPlatformMenuBar::createMenu() const
}
QT_END_NAMESPACE
+
+#include "moc_qplatformmenu.cpp"
diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h
index 8e470aefd3..fbb54f2af1 100644
--- a/src/gui/kernel/qplatformmenu.h
+++ b/src/gui/kernel/qplatformmenu.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author James Turner <james.turner@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author James Turner <james.turner@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMMENU_H
#define QPLATFORMMENU_H
@@ -49,13 +13,14 @@
// source and binary incompatible with future versions of Qt.
//
+#include <QtCore/qobject.h>
#include <QtGui/qtguiglobal.h>
#include <QtCore/qpointer.h>
-#include <QtGui/QFont>
+#include <QtGui/qfont.h>
#if QT_CONFIG(shortcut)
-# include <QtGui/QKeySequence>
+# include <QtGui/qkeysequence.h>
#endif
-#include <QtGui/QIcon>
+#include <QtGui/qicon.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/kernel/qplatformmenu_p.h b/src/gui/kernel/qplatformmenu_p.h
index 38f49ef983..00e3fa56da 100644
--- a/src/gui/kernel/qplatformmenu_p.h
+++ b/src/gui/kernel/qplatformmenu_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMMENU_P_H
#define QPLATFORMMENU_P_H
@@ -59,7 +23,7 @@ QT_BEGIN_NAMESPACE
// ----------------- QNativeInterface -----------------
-#if !defined(Q_OS_MACOS) && defined(Q_CLANG_QDOC)
+#if !defined(Q_OS_MACOS) && defined(Q_QDOC)
typedef void NSMenu;
#else
QT_END_NAMESPACE
@@ -69,7 +33,7 @@ QT_BEGIN_NAMESPACE
namespace QNativeInterface::Private {
-#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_MACOS) || defined(Q_QDOC)
struct Q_GUI_EXPORT QCocoaMenu
{
QT_DECLARE_NATIVE_INTERFACE(QCocoaMenu)
diff --git a/src/gui/kernel/qplatformnativeinterface.cpp b/src/gui/kernel/qplatformnativeinterface.cpp
index 15b08e195a..d010f0b7c6 100644
--- a/src/gui/kernel/qplatformnativeinterface.cpp
+++ b/src/gui/kernel/qplatformnativeinterface.cpp
@@ -1,43 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformnativeinterface.h"
+#include <QtCore/qvariant.h>
+#include <QtCore/qmap.h>
#include <QtGui/qcursor.h>
QT_BEGIN_NAMESPACE
@@ -175,3 +141,5 @@ void QPlatformNativeInterface::setWindowProperty(QPlatformWindow *window, const
}
QT_END_NAMESPACE
+
+#include "moc_qplatformnativeinterface.cpp"
diff --git a/src/gui/kernel/qplatformnativeinterface.h b/src/gui/kernel/qplatformnativeinterface.h
index 58c8f6b414..6e721ec71c 100644
--- a/src/gui/kernel/qplatformnativeinterface.h
+++ b/src/gui/kernel/qplatformnativeinterface.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMNATIVEINTERFACE_H
#define QPLATFORMNATIVEINTERFACE_H
diff --git a/src/gui/kernel/qplatformoffscreensurface.cpp b/src/gui/kernel/qplatformoffscreensurface.cpp
index c2952e166c..653b0c762a 100644
--- a/src/gui/kernel/qplatformoffscreensurface.cpp
+++ b/src/gui/kernel/qplatformoffscreensurface.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformoffscreensurface.h"
diff --git a/src/gui/kernel/qplatformoffscreensurface.h b/src/gui/kernel/qplatformoffscreensurface.h
index 259b213f5a..227c04794a 100644
--- a/src/gui/kernel/qplatformoffscreensurface.h
+++ b/src/gui/kernel/qplatformoffscreensurface.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMOFFSCREENSURFACE_H
#define QPLATFORMOFFSCREENSURFACE_H
diff --git a/src/gui/kernel/qplatformopenglcontext.cpp b/src/gui/kernel/qplatformopenglcontext.cpp
index 839ec008aa..8391425caf 100644
--- a/src/gui/kernel/qplatformopenglcontext.cpp
+++ b/src/gui/kernel/qplatformopenglcontext.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformopenglcontext.h"
@@ -165,4 +129,20 @@ bool QPlatformOpenGLContext::parseOpenGLVersion(const QByteArray &versionString,
return (majorOk && minorOk);
}
+/*!
+ Called when the RHI begins rendering a new frame in the context. Will always be paired with a
+ call to \l endFrame().
+*/
+void QPlatformOpenGLContext::beginFrame()
+{
+}
+
+/*!
+ Called when the RHI ends rendering a in the context. Is always preceded by a call to
+ \l beginFrame().
+*/
+void QPlatformOpenGLContext::endFrame()
+{
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformopenglcontext.h b/src/gui/kernel/qplatformopenglcontext.h
index 034462e5f3..ac13c42655 100644
--- a/src/gui/kernel/qplatformopenglcontext.h
+++ b/src/gui/kernel/qplatformopenglcontext.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMOPENGLCONTEXT_H
#define QPLATFORMOPENGLCONTEXT_H
@@ -84,6 +48,9 @@ public:
virtual bool makeCurrent(QPlatformSurface *surface) = 0;
virtual void doneCurrent() = 0;
+ virtual void beginFrame();
+ virtual void endFrame();
+
virtual bool isSharing() const { return false; }
virtual bool isValid() const { return true; }
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index 0649139455..0369a0b12a 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformscreen.h"
#include <QtCore/qdebug.h>
@@ -61,10 +25,8 @@ QPlatformScreen::QPlatformScreen()
QPlatformScreen::~QPlatformScreen()
{
Q_D(QPlatformScreen);
- if (d->screen) {
- qWarning("Manually deleting a QPlatformScreen. Call QWindowSystemInterface::handleScreenRemoved instead.");
- delete d->screen;
- }
+ Q_ASSERT_X(!d->screen, "QPlatformScreen",
+ "QPlatformScreens should be removed via QWindowSystemInterface::handleScreenRemoved()");
}
/*!
@@ -92,8 +54,9 @@ QPixmap QPlatformScreen::grabWindow(WId window, int x, int y, int width, int hei
QWindow *QPlatformScreen::topLevelAt(const QPoint & pos) const
{
const QWindowList list = QGuiApplication::topLevelWindows();
- for (int i = list.size()-1; i >= 0; --i) {
- QWindow *w = list[i];
+ const auto crend = list.crend();
+ for (auto it = list.crbegin(); it != crend; ++it) {
+ QWindow *w = *it;
if (w->isVisible() && QHighDpi::toNativePixels(w->geometry(), w).contains(pos))
return w;
}
@@ -471,13 +434,6 @@ QRect QPlatformScreen::mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation
return rect;
}
-QRect QPlatformScreen::deviceIndependentGeometry() const
-{
- qreal scaleFactor = QHighDpiScaling::factor(this);
- QRect nativeGeometry = geometry();
- return QRect(nativeGeometry.topLeft(), QHighDpi::fromNative(nativeGeometry.size(), scaleFactor));
-}
-
/*!
Returns a hint about this screen's subpixel layout structure.
diff --git a/src/gui/kernel/qplatformscreen.h b/src/gui/kernel/qplatformscreen.h
index 4e1ea4b3a9..a547a635e9 100644
--- a/src/gui/kernel/qplatformscreen.h
+++ b/src/gui/kernel/qplatformscreen.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMSCREEN_H
#define QPLATFORMSCREEN_H
@@ -78,6 +42,7 @@ typedef QPair<qreal, qreal> QDpi;
class Q_GUI_EXPORT QPlatformScreen
{
+ Q_GADGET
Q_DECLARE_PRIVATE(QPlatformScreen)
public:
@@ -160,9 +125,6 @@ public:
static QTransform transformBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &target);
static QRect mapBetween(Qt::ScreenOrientation a, Qt::ScreenOrientation b, const QRect &rect);
- // The platform screen's geometry in device independent coordinates
- QRect deviceIndependentGeometry() const;
-
static QDpi overrideDpi(const QDpi &in);
protected:
@@ -171,7 +133,7 @@ protected:
QScopedPointer<QPlatformScreenPrivate> d_ptr;
private:
- friend class QScreenPrivate;
+ friend class QScreen;
};
// Qt doesn't currently support running with no platform screen
diff --git a/src/gui/kernel/qplatformscreen_p.h b/src/gui/kernel/qplatformscreen_p.h
index 35097b5d23..345a90845c 100644
--- a/src/gui/kernel/qplatformscreen_p.h
+++ b/src/gui/kernel/qplatformscreen_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMSCREEN_P_H
#define QPLATFORMSCREEN_P_H
@@ -70,7 +34,7 @@ public:
namespace QNativeInterface::Private {
-#if QT_CONFIG(xcb) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(xcb) || defined(Q_QDOC)
struct Q_GUI_EXPORT QXcbScreen
{
QT_DECLARE_NATIVE_INTERFACE(QXcbScreen, 1, QScreen)
@@ -78,7 +42,7 @@ struct Q_GUI_EXPORT QXcbScreen
};
#endif
-#if QT_CONFIG(vsp2) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vsp2) || defined(Q_QDOC)
struct Q_GUI_EXPORT QVsp2Screen
{
QT_DECLARE_NATIVE_INTERFACE(QVsp2Screen, 1, QScreen)
@@ -91,7 +55,7 @@ struct Q_GUI_EXPORT QVsp2Screen
};
#endif
-#if defined(Q_OS_WEBOS) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WEBOS) || defined(Q_QDOC)
struct Q_GUI_EXPORT QWebOSScreen
{
QT_DECLARE_NATIVE_INTERFACE(QWebOSScreen, 1, QScreen)
@@ -103,7 +67,6 @@ struct Q_GUI_EXPORT QWebOSScreen
virtual void addFlipListener(void (*callback)()) = 0;
};
#endif
-
} // QNativeInterface::Private
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformservices.cpp b/src/gui/kernel/qplatformservices.cpp
index fdc6a6c4aa..7ff2a6c2f8 100644
--- a/src/gui/kernel/qplatformservices.cpp
+++ b/src/gui/kernel/qplatformservices.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformservices.h"
@@ -55,6 +19,19 @@ QT_BEGIN_NAMESPACE
\brief The QPlatformServices provides the backend for desktop-related functionality.
*/
+/*!
+ \enum QPlatformServices::Capability
+
+ Capabilities are used to determine a specific platform service's availability.
+
+ \value ColorPickingFromScreen The platform natively supports color picking from screen.
+ This capability indicates that the platform supports "opaque" color picking, where the
+ platform implements a complete user experience for color picking and outputs a color.
+ This is in contrast to the application implementing the color picking user experience
+ (taking care of showing a cross hair, instructing the platform integration to obtain
+ the color at a given pixel, etc.). The related service function is pickColor().
+ */
+
QPlatformServices::QPlatformServices()
{ }
@@ -85,5 +62,18 @@ QByteArray QPlatformServices::desktopEnvironment() const
return QByteArray("UNKNOWN");
}
+QPlatformServiceColorPicker *QPlatformServices::colorPicker(QWindow *parent)
+{
+ Q_UNUSED(parent);
+ return nullptr;
+}
+
+bool QPlatformServices::hasCapability(Capability capability) const
+{
+ Q_UNUSED(capability)
+ return false;
+}
QT_END_NAMESPACE
+
+#include "moc_qplatformservices.cpp"
diff --git a/src/gui/kernel/qplatformservices.h b/src/gui/kernel/qplatformservices.h
index 5de96cfa7d..063247af08 100644
--- a/src/gui/kernel/qplatformservices.h
+++ b/src/gui/kernel/qplatformservices.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMSERVICES_H
#define QPLATFORMSERVICES_H
@@ -50,16 +14,32 @@
//
#include <QtGui/qtguiglobal.h>
+#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
class QUrl;
+class QWindow;
+
+class Q_GUI_EXPORT QPlatformServiceColorPicker : public QObject
+{
+ Q_OBJECT
+public:
+ using QObject::QObject;
+ virtual void pickColor() = 0;
+Q_SIGNALS:
+ void colorPicked(const QColor &color);
+};
class Q_GUI_EXPORT QPlatformServices
{
public:
Q_DISABLE_COPY_MOVE(QPlatformServices)
+ enum Capability {
+ ColorPicking,
+ };
+
QPlatformServices();
virtual ~QPlatformServices() { }
@@ -67,6 +47,10 @@ public:
virtual bool openDocument(const QUrl &url);
virtual QByteArray desktopEnvironment() const;
+
+ virtual bool hasCapability(Capability capability) const;
+
+ virtual QPlatformServiceColorPicker *colorPicker(QWindow *parent = nullptr);
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformsessionmanager.cpp b/src/gui/kernel/qplatformsessionmanager.cpp
index bc4ce22c0f..2a8e621294 100644
--- a/src/gui/kernel/qplatformsessionmanager.cpp
+++ b/src/gui/kernel/qplatformsessionmanager.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2013 Teo Mrnjavac <teo@kde.org>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2013 Teo Mrnjavac <teo@kde.org>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformsessionmanager.h"
diff --git a/src/gui/kernel/qplatformsessionmanager.h b/src/gui/kernel/qplatformsessionmanager.h
index c6c3984816..213d8dc07e 100644
--- a/src/gui/kernel/qplatformsessionmanager.h
+++ b/src/gui/kernel/qplatformsessionmanager.h
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2013 Teo Mrnjavac <teo@kde.org>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2013 Teo Mrnjavac <teo@kde.org>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMSESSIONMANAGER_H
#define QPLATFORMSESSIONMANAGER_H
diff --git a/src/gui/kernel/qplatformsharedgraphicscache.cpp b/src/gui/kernel/qplatformsharedgraphicscache.cpp
index 971fb0f848..c482a94426 100644
--- a/src/gui/kernel/qplatformsharedgraphicscache.cpp
+++ b/src/gui/kernel/qplatformsharedgraphicscache.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformsharedgraphicscache.h"
@@ -292,3 +256,5 @@ QT_BEGIN_NAMESPACE
*/
QT_END_NAMESPACE
+
+#include "moc_qplatformsharedgraphicscache.cpp"
diff --git a/src/gui/kernel/qplatformsharedgraphicscache.h b/src/gui/kernel/qplatformsharedgraphicscache.h
index 56e51188cc..4935a52bd6 100644
--- a/src/gui/kernel/qplatformsharedgraphicscache.h
+++ b/src/gui/kernel/qplatformsharedgraphicscache.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMSHAREDGRAPHICSCACHE_H
#define QPLATFORMSHAREDGRAPHICSCACHE_H
diff --git a/src/gui/kernel/qplatformsurface.cpp b/src/gui/kernel/qplatformsurface.cpp
index fdb2cf567d..39a1869de6 100644
--- a/src/gui/kernel/qplatformsurface.cpp
+++ b/src/gui/kernel/qplatformsurface.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformsurface.h"
#ifndef QT_NO_DEBUG_STREAM
@@ -68,6 +32,17 @@ QPlatformSurface::QPlatformSurface(QSurface *surface) : m_surface(surface)
{
}
+bool QPlatformSurface::isRasterSurface(QSurface *surface)
+{
+ switch (surface->surfaceType()) {
+ case QSurface::RasterSurface:
+ case QSurface::RasterGLSurface:
+ return true;
+ default:
+ return false;
+ };
+}
+
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QPlatformSurface *surface)
{
diff --git a/src/gui/kernel/qplatformsurface.h b/src/gui/kernel/qplatformsurface.h
index 475f3ef330..f867d3df1b 100644
--- a/src/gui/kernel/qplatformsurface.h
+++ b/src/gui/kernel/qplatformsurface.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMSURFACE_H
#define QPLATFORMSURFACE_H
@@ -73,6 +37,8 @@ public:
QSurface *surface() const;
virtual QPlatformScreen *screen() const = 0;
+ static bool isRasterSurface(QSurface *surface);
+
private:
explicit QPlatformSurface(QSurface *surface);
diff --git a/src/gui/kernel/qplatformsystemtrayicon.cpp b/src/gui/kernel/qplatformsystemtrayicon.cpp
index 296beda0f9..0b21fe39f7 100644
--- a/src/gui/kernel/qplatformsystemtrayicon.cpp
+++ b/src/gui/kernel/qplatformsystemtrayicon.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2012 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Christoph Schleifenbaum <christoph.schleifenbaum@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2012 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Christoph Schleifenbaum <christoph.schleifenbaum@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformsystemtrayicon.h"
diff --git a/src/gui/kernel/qplatformsystemtrayicon.h b/src/gui/kernel/qplatformsystemtrayicon.h
index bd74a2cc0a..76a7ef03d9 100644
--- a/src/gui/kernel/qplatformsystemtrayicon.h
+++ b/src/gui/kernel/qplatformsystemtrayicon.h
@@ -1,47 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2012 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Christoph Schleifenbaum <christoph.schleifenbaum@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2012 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Christoph Schleifenbaum <christoph.schleifenbaum@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMSYSTEMTRAYICON_H
#define QPLATFORMSYSTEMTRAYICON_H
#include <QtGui/qtguiglobal.h>
+#include <qpa/qplatformscreen.h>
#include "QtCore/qobject.h"
#ifndef QT_NO_SYSTEMTRAYICON
@@ -49,7 +14,6 @@
QT_BEGIN_NAMESPACE
class QPlatformMenu;
-class QPlatformScreen;
class QIcon;
class QString;
class QRect;
@@ -57,7 +21,6 @@ class QRect;
class Q_GUI_EXPORT QPlatformSystemTrayIcon : public QObject
{
Q_OBJECT
- Q_MOC_INCLUDE(<qpa/qplatformscreen.h>)
public:
enum ActivationReason {
Unknown,
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index 34f7307cd7..48978b849a 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformtheme.h"
@@ -64,6 +28,8 @@ QT_BEGIN_NAMESPACE
\ingroup qpa
\brief The QPlatformTheme class allows customizing the UI based on themes.
+ See the init_platform function in qguiapplication.cpp for the complete
+ platform initialization process.
*/
/*!
@@ -167,6 +133,26 @@ QT_BEGIN_NAMESPACE
as basis for the resize.
This enum value has been added in Qt 6.2.
+ \value ShowDirectoriesFirst (bool) Whether directories should be shown
+ first (before files) in file dialogs.
+ This enum value was added in Qt 6.3.
+
+ \value PreselectFirstFileInDirectory (bool) Whether the first file in a directory
+ should be automatically selected when a file dialog opens.
+ This enum value was added in Qt 6.3.
+
+ \value ButtonPressKeys (QList<Qt::Key>) A list of keys that can be used to press buttons via keyboard input.
+
+ \value SetFocusOnTouchRelease (bool) Whether focus objects (line edits etc) should receive
+ input focus after a touch/mouse release.
+ This enum value has been added in Qt 6.5.
+
+ \value MouseCursorTheme (QString) Name of the mouse cursor theme.
+ This enum value has been added in Qt 6.5.
+
+ \value MouseCursorSize (QSize) Size of the mouse cursor.
+ This enum value has been added in Qt 6.5.
+
\sa themeHint(), QStyle::pixelMetric()
*/
@@ -339,7 +325,7 @@ const QKeyBinding QPlatformThemePrivate::keyBindings[] = {
{QKeySequence::InsertLineSeparator, 0, Qt::SHIFT | Qt::Key_Enter, KB_All},
{QKeySequence::InsertLineSeparator, 0, Qt::SHIFT | Qt::Key_Return, KB_All},
{QKeySequence::InsertLineSeparator, 0, Qt::META | Qt::Key_O, KB_Mac},
- {QKeySequence::SaveAs, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_S, KB_Gnome | KB_Mac},
+ {QKeySequence::SaveAs, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_S, KB_All},
{QKeySequence::Preferences, 0, Qt::CTRL | Qt::Key_Comma, KB_Mac},
{QKeySequence::Quit, 0, Qt::CTRL | Qt::Key_Q, KB_X11 | KB_Gnome | KB_KDE | KB_Mac},
{QKeySequence::FullScreen, 1, Qt::META | Qt::CTRL | Qt::Key_F, KB_Mac},
@@ -349,6 +335,7 @@ const QKeyBinding QPlatformThemePrivate::keyBindings[] = {
{QKeySequence::FullScreen, 1, Qt::Key_F11, KB_Win | KB_KDE},
{QKeySequence::Deselect, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_A, KB_X11},
{QKeySequence::DeleteCompleteLine, 0, Qt::CTRL | Qt::Key_U, KB_X11},
+ {QKeySequence::Backspace, 1, Qt::Key_Backspace, KB_Mac},
{QKeySequence::Backspace, 0, Qt::META | Qt::Key_H, KB_Mac},
{QKeySequence::Cancel, 0, Qt::Key_Escape, KB_All},
{QKeySequence::Cancel, 0, Qt::CTRL | Qt::Key_Period, KB_Mac}
@@ -366,7 +353,61 @@ QPlatformThemePrivate::~QPlatformThemePrivate()
delete systemPalette;
}
-Q_GUI_EXPORT QPalette qt_fusionPalette();
+Q_GUI_EXPORT QPalette qt_fusionPalette()
+{
+ auto theme = QGuiApplicationPrivate::platformTheme();
+ const bool darkAppearance = theme
+ ? theme->colorScheme() == Qt::ColorScheme::Dark
+ : false;
+ const QColor windowText = darkAppearance ? QColor(240, 240, 240) : Qt::black;
+ const QColor backGround = darkAppearance ? QColor(50, 50, 50) : QColor(239, 239, 239);
+ const QColor light = backGround.lighter(150);
+ const QColor mid = (backGround.darker(130));
+ const QColor midLight = mid.lighter(110);
+ const QColor base = darkAppearance ? backGround.darker(140) : Qt::white;
+ const QColor disabledBase(backGround);
+ const QColor dark = backGround.darker(150);
+ const QColor darkDisabled = QColor(209, 209, 209).darker(110);
+ const QColor text = darkAppearance ? windowText : Qt::black;
+ const QColor highlight = QColor(48, 140, 198);
+ const QColor hightlightedText = darkAppearance ? windowText : Qt::white;
+ const QColor disabledText = darkAppearance ? QColor(130, 130, 130) : QColor(190, 190, 190);
+ const QColor button = backGround;
+ const QColor shadow = dark.darker(135);
+ const QColor disabledShadow = shadow.lighter(150);
+ const QColor disabledHighlight(145, 145, 145);
+ QColor placeholder = text;
+ placeholder.setAlpha(128);
+
+ QPalette fusionPalette(windowText, backGround, light, dark, mid, text, base);
+ fusionPalette.setBrush(QPalette::Midlight, midLight);
+ fusionPalette.setBrush(QPalette::Button, button);
+ fusionPalette.setBrush(QPalette::Shadow, shadow);
+ fusionPalette.setBrush(QPalette::HighlightedText, hightlightedText);
+
+ fusionPalette.setBrush(QPalette::Disabled, QPalette::Text, disabledText);
+ fusionPalette.setBrush(QPalette::Disabled, QPalette::WindowText, disabledText);
+ fusionPalette.setBrush(QPalette::Disabled, QPalette::ButtonText, disabledText);
+ fusionPalette.setBrush(QPalette::Disabled, QPalette::Base, disabledBase);
+ fusionPalette.setBrush(QPalette::Disabled, QPalette::Dark, darkDisabled);
+ fusionPalette.setBrush(QPalette::Disabled, QPalette::Shadow, disabledShadow);
+
+ fusionPalette.setBrush(QPalette::Active, QPalette::Highlight, highlight);
+ fusionPalette.setBrush(QPalette::Inactive, QPalette::Highlight, highlight);
+ fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, disabledHighlight);
+
+ fusionPalette.setBrush(QPalette::Active, QPalette::Accent, highlight);
+ fusionPalette.setBrush(QPalette::Inactive, QPalette::Accent, highlight);
+ fusionPalette.setBrush(QPalette::Disabled, QPalette::Accent, disabledHighlight);
+
+ fusionPalette.setBrush(QPalette::PlaceholderText, placeholder);
+
+ // Use a more legible light blue on dark backgrounds than the default Qt::blue.
+ if (darkAppearance)
+ fusionPalette.setBrush(QPalette::Link, highlight);
+
+ return fusionPalette;
+}
void QPlatformThemePrivate::initializeSystemPalette()
{
@@ -401,6 +442,11 @@ QPlatformDialogHelper *QPlatformTheme::createPlatformDialogHelper(DialogType typ
return nullptr;
}
+Qt::ColorScheme QPlatformTheme::colorScheme() const
+{
+ return Qt::ColorScheme::Unknown;
+}
+
const QPalette *QPlatformTheme::palette(Palette type) const
{
Q_D(const QPlatformTheme);
@@ -477,6 +523,16 @@ QVariant QPlatformTheme::themeHint(ThemeHint hint) const
return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::UiEffects);
case QPlatformTheme::ShowShortcutsInContextMenus:
return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ShowShortcutsInContextMenus);
+ case QPlatformTheme::SetFocusOnTouchRelease:
+ return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::SetFocusOnTouchRelease);
+ case QPlatformTheme::FlickStartDistance:
+ return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::FlickStartDistance);
+ case QPlatformTheme::FlickMaximumVelocity:
+ return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::FlickMaximumVelocity);
+ case QPlatformTheme::FlickDeceleration:
+ return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::FlickDeceleration);
+ case QPlatformTheme::UnderlineShortcut:
+ return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::UnderlineShortcut);
default:
return QPlatformTheme::defaultThemeHint(hint);
}
@@ -569,7 +625,30 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
return QVariant(10);
case InteractiveResizeAcrossScreens:
return true;
+ case ShowDirectoriesFirst:
+ return true;
+ case PreselectFirstFileInDirectory:
+ return false;
+ case ButtonPressKeys:
+ return QVariant::fromValue(QList<Qt::Key>({ Qt::Key_Space, Qt::Key_Select }));
+ case SetFocusOnTouchRelease:
+ return false;
+ case FlickStartDistance:
+ return QVariant(15);
+ case FlickMaximumVelocity:
+ return QVariant(2500);
+ case FlickDeceleration:
+ return QVariant(1500);
+ case MenuBarFocusOnAltPressRelease:
+ return false;
+ case MouseCursorTheme:
+ return QVariant(QString());
+ case MouseCursorSize:
+ return QVariant(QSize(16, 16));
+ case UnderlineShortcut:
+ return true;
}
+
return QVariant();
}
@@ -737,33 +816,38 @@ QString QPlatformTheme::defaultStandardButtonText(int button)
QString QPlatformTheme::removeMnemonics(const QString &original)
{
+ const auto mnemonicInParentheses = [](QStringView text) {
+ /* Format of mnemonics to remove is /\(&[^&]\)/ but accept full-width
+ forms of ( and ) as equivalent, for cross-platform compatibility with
+ MS (and consequent behavior of translators, see QTBUG-110829).
+ */
+ Q_ASSERT(text.size() == 4); // Caller's responsibility.
+ constexpr QChar wideOpen = u'\uff08', wideClose = u'\uff09';
+ if (!text.startsWith(u'(') && !text.startsWith(wideOpen))
+ return false;
+ if (text[1] != u'&' || text[2] == u'&')
+ return false;
+ return text.endsWith(u')') || text.endsWith(wideClose);
+ };
QString returnText(original.size(), u'\0');
int finalDest = 0;
- int currPos = 0;
- int l = original.length();
- while (l) {
- if (original.at(currPos) == QLatin1Char('&')) {
- ++currPos;
- --l;
- if (l == 0)
+ QStringView text(original);
+ while (!text.isEmpty()) {
+ if (text.startsWith(u'&')) {
+ text = text.sliced(1);
+ if (text.isEmpty())
break;
- } else if (original.at(currPos) == QLatin1Char('(') && l >= 4 &&
- original.at(currPos + 1) == QLatin1Char('&') &&
- original.at(currPos + 2) != QLatin1Char('&') &&
- original.at(currPos + 3) == QLatin1Char(')')) {
- /* remove mnemonics its format is "\s*(&X)" */
- int n = 0;
- while (finalDest > n && returnText.at(finalDest - n - 1).isSpace())
- ++n;
- finalDest -= n;
- currPos += 4;
- l -= 4;
+ } else if (text.size() >= 4 && mnemonicInParentheses(text.first(4))) {
+ // Advance over the matched mnemonic:
+ text = text.sliced(4);
+ // Also strip any leading space before it:
+ while (finalDest > 0 && returnText.at(finalDest - 1).isSpace())
+ --finalDest;
continue;
}
- returnText[finalDest] = original.at(currPos);
- ++currPos;
+ returnText[finalDest] = text.front();
+ text = text.sliced(1);
++finalDest;
- --l;
}
returnText.truncate(finalDest);
return returnText;
@@ -782,4 +866,11 @@ unsigned QPlatformThemePrivate::currentKeyPlatforms()
return result;
}
+QString QPlatformTheme::name() const
+{
+ return d_func()->name;
+}
+
QT_END_NAMESPACE
+
+#include "moc_qplatformtheme.cpp"
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 0b6c0254f0..c0193947b9 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMTHEME_H
#define QPLATFORMTHEME_H
@@ -50,6 +14,7 @@
//
#include <QtGui/qtguiglobal.h>
+#include <QtCore/QObject>
#include <QtCore/QScopedPointer>
#if QT_CONFIG(shortcut)
# include <QtGui/QKeySequence>
@@ -76,7 +41,9 @@ class QFileInfo;
class Q_GUI_EXPORT QPlatformTheme
{
+ Q_GADGET
Q_DECLARE_PRIVATE(QPlatformTheme)
+
public:
Q_DISABLE_COPY_MOVE(QPlatformTheme)
@@ -119,7 +86,19 @@ public:
IconFallbackSearchPaths,
MouseQuickSelectionThreshold,
InteractiveResizeAcrossScreens,
+ ShowDirectoriesFirst,
+ PreselectFirstFileInDirectory,
+ ButtonPressKeys,
+ SetFocusOnTouchRelease,
+ FlickStartDistance,
+ FlickMaximumVelocity,
+ FlickDeceleration,
+ MenuBarFocusOnAltPressRelease,
+ MouseCursorTheme,
+ MouseCursorSize,
+ UnderlineShortcut,
};
+ Q_ENUM(ThemeHint)
enum DialogType {
FileDialog,
@@ -127,6 +106,7 @@ public:
FontDialog,
MessageDialog
};
+ Q_ENUM(DialogType);
enum Palette {
SystemPalette,
@@ -149,6 +129,7 @@ public:
TextLineEditPalette,
NPalettes
};
+ Q_ENUM(Palette)
enum Font {
SystemFont,
@@ -180,6 +161,7 @@ public:
EditorFont,
NFonts
};
+ Q_ENUM(Font)
enum StandardPixmap { // Keep in sync with QStyle::StandardPixmap
TitleBarMenuButton,
@@ -253,9 +235,20 @@ public:
MediaVolume,
MediaVolumeMuted,
LineEditClearButton,
+ DialogYesToAllButton,
+ DialogNoToAllButton,
+ DialogSaveAllButton,
+ DialogAbortButton,
+ DialogRetryButton,
+ DialogIgnoreButton,
+ RestoreDefaultsButton,
+ TabCloseButton,
+ NStandardPixmap, // assertion value for sync with QStyle::StandardPixmap
+
// do not add any values below/greater than this
CustomBase = 0xf0000000
};
+ Q_ENUM(StandardPixmap)
enum KeyboardSchemes
{
@@ -266,6 +259,7 @@ public:
GnomeKeyboardScheme,
CdeKeyboardScheme
};
+ Q_ENUM(KeyboardSchemes)
enum UiEffect
{
@@ -278,6 +272,7 @@ public:
AnimateToolBoxUiEffect = 0x40,
HoverEffect = 0x80
};
+ Q_ENUM(UiEffect)
enum IconOption {
DontUseCustomDirectoryIcons = 0x01
@@ -299,6 +294,8 @@ public:
virtual QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const;
#endif
+ virtual Qt::ColorScheme colorScheme() const;
+
virtual const QPalette *palette(Palette type = SystemPalette) const;
virtual const QFont *font(Font type = SystemFont) const;
@@ -322,10 +319,14 @@ public:
static QVariant defaultThemeHint(ThemeHint hint);
static QString defaultStandardButtonText(int button);
static QString removeMnemonics(const QString &original);
+ QString name() const;
protected:
explicit QPlatformTheme(QPlatformThemePrivate *priv);
QScopedPointer<QPlatformThemePrivate> d_ptr;
+
+private:
+ friend class QPlatformThemeFactory;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformtheme_p.h b/src/gui/kernel/qplatformtheme_p.h
index 2c16fec141..e847ead3be 100644
--- a/src/gui/kernel/qplatformtheme_p.h
+++ b/src/gui/kernel/qplatformtheme_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMTHEME_P_H
#define QPLATFORMTHEME_P_H
@@ -77,6 +41,8 @@ public:
static unsigned currentKeyPlatforms();
QPalette *systemPalette;
+
+ QString name;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformthemefactory.cpp b/src/gui/kernel/qplatformthemefactory.cpp
index 447d385abe..beefa1c294 100644
--- a/src/gui/kernel/qplatformthemefactory.cpp
+++ b/src/gui/kernel/qplatformthemefactory.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qpa/qplatformthemefactory_p.h>
#include <qpa/qplatformthemeplugin.h>
@@ -44,33 +8,26 @@
#include "qmutex.h"
#include "qguiapplication.h"
+#include "qplatformtheme.h"
+#include "qplatformtheme_p.h"
#include "qdebug.h"
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QPlatformThemeFactoryInterface_iid, QLatin1String("/platformthemes"), Qt::CaseInsensitive))
+using namespace Qt::StringLiterals;
-#if QT_CONFIG(library)
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader,
- (QPlatformThemeFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive))
-#endif
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, ptLoader,
+ (QPlatformThemeFactoryInterface_iid, "/platformthemes"_L1, Qt::CaseInsensitive))
QPlatformTheme *QPlatformThemeFactory::create(const QString& key, const QString &platformPluginPath)
{
- QStringList paramList = key.split(QLatin1Char(':'));
+ QStringList paramList = key.split(u':');
const QString platform = paramList.takeFirst().toLower();
-#if QT_CONFIG(library)
- // Try loading the plugin from platformPluginPath first:
- if (!platformPluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(platformPluginPath);
- if (QPlatformTheme *ret = qLoadPlugin<QPlatformTheme, QPlatformThemePlugin>(directLoader(), platform, paramList))
- return ret;
- }
-#else
- Q_UNUSED(platformPluginPath);
-#endif
- return qLoadPlugin<QPlatformTheme, QPlatformThemePlugin>(loader(), platform, paramList);
+ ptLoader->setExtraSearchPath(platformPluginPath);
+ QPlatformTheme *theme = qLoadPlugin<QPlatformTheme, QPlatformThemePlugin>(ptLoader(), platform, paramList);
+ if (theme)
+ theme->d_func()->name = key;
+ return theme;
}
/*!
@@ -81,26 +38,8 @@ QPlatformTheme *QPlatformThemeFactory::create(const QString& key, const QString
*/
QStringList QPlatformThemeFactory::keys(const QString &platformPluginPath)
{
- QStringList list;
-
-#if QT_CONFIG(library)
- if (!platformPluginPath.isEmpty()) {
- QCoreApplication::addLibraryPath(platformPluginPath);
- list += directLoader()->keyMap().values();
- if (!list.isEmpty()) {
- const QString postFix = QLatin1String(" (from ")
- + QDir::toNativeSeparators(platformPluginPath)
- + QLatin1Char(')');
- const QStringList::iterator end = list.end();
- for (QStringList::iterator it = list.begin(); it != end; ++it)
- (*it).append(postFix);
- }
- }
-#else
- Q_UNUSED(platformPluginPath);
-#endif
- list += loader()->keyMap().values();
- return list;
+ ptLoader->setExtraSearchPath(platformPluginPath);
+ return ptLoader->keyMap().values();
}
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformthemefactory_p.h b/src/gui/kernel/qplatformthemefactory_p.h
index c312eadf27..c466dcd461 100644
--- a/src/gui/kernel/qplatformthemefactory_p.h
+++ b/src/gui/kernel/qplatformthemefactory_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMTHEMEFACTORY_H
#define QPLATFORMTHEMEFACTORY_H
diff --git a/src/gui/kernel/qplatformthemeplugin.cpp b/src/gui/kernel/qplatformthemeplugin.cpp
index c09476bee5..8b22680c05 100644
--- a/src/gui/kernel/qplatformthemeplugin.cpp
+++ b/src/gui/kernel/qplatformthemeplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformthemeplugin.h"
@@ -60,3 +24,5 @@ QPlatformThemePlugin::~QPlatformThemePlugin()
}
QT_END_NAMESPACE
+
+#include "moc_qplatformthemeplugin.cpp"
diff --git a/src/gui/kernel/qplatformthemeplugin.h b/src/gui/kernel/qplatformthemeplugin.h
index 0f88806b0b..a983f4c5b7 100644
--- a/src/gui/kernel/qplatformthemeplugin.h
+++ b/src/gui/kernel/qplatformthemeplugin.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMTHEMEPLUGIN_H
#define QPLATFORMTHEMEPLUGIN_H
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 0bee2968f7..5c0ae2ee2a 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformwindow.h"
#include "qplatformwindow_p.h"
@@ -229,7 +193,7 @@ bool QPlatformWindow::isActive() const
*/
bool QPlatformWindow::isAncestorOf(const QPlatformWindow *child) const
{
- for (const QPlatformWindow *parent = child->parent(); parent; parent = child->parent()) {
+ for (const QPlatformWindow *parent = child->parent(); parent; parent = parent->parent()) {
if (parent == this)
return true;
}
@@ -406,18 +370,18 @@ void QPlatformWindow::setMask(const QRegion &region)
Reimplement to let Qt be able to request activation/focus for a window
Some window systems will probably not have callbacks for this functionality,
- and then calling QWindowSystemInterface::handleWindowActivated(QWindow *w)
+ and then calling QWindowSystemInterface::handleFocusWindowChanged(QWindow *w)
would be sufficient.
If the window system has some event handling/callbacks then call
- QWindowSystemInterface::handleWindowActivated(QWindow *w) when the window system
+ QWindowSystemInterface::handleFocusWindowChanged(QWindow *w) when the window system
gives the notification.
- Default implementation calls QWindowSystem::handleWindowActivated(QWindow *w)
+ Default implementation calls QWindowSystem::handleFocusWindowChanged(QWindow *w)
*/
void QPlatformWindow::requestActivateWindow()
{
- QWindowSystemInterface::handleWindowActivated(window());
+ QWindowSystemInterface::handleFocusWindowChanged(window());
}
/*!
@@ -763,20 +727,29 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeo
should be delivered using QPlatformWindow::deliverUpdateRequest()
to not get out of sync with the internal state of QWindow.
- The default implementation posts an UpdateRequest event to the
- window after 5 ms. The additional time is there to give the event
- loop a bit of idle time to gather system events.
+ The default implementation posts an UpdateRequest event to the window after
+ an interval that is at most 5 ms. If the window's associated screen reports
+ a \l{QPlatformScreen::refreshRate()}{refresh rate} higher than 60 Hz, the
+ interval is scaled down to a valid smaller than 5. The additional time is
+ there to give the event loop a bit of idle time to gather system events.
*/
void QPlatformWindow::requestUpdate()
{
Q_D(QPlatformWindow);
- static int updateInterval = []() {
- bool ok = false;
- int customUpdateInterval = qEnvironmentVariableIntValue("QT_QPA_UPDATE_IDLE_TIME", &ok);
- return ok ? customUpdateInterval : 5;
- }();
+ static bool customUpdateIntervalValid = false;
+ static int customUpdateInterval = qEnvironmentVariableIntValue("QT_QPA_UPDATE_IDLE_TIME",
+ &customUpdateIntervalValid);
+ int updateInterval = customUpdateInterval;
+ if (!customUpdateIntervalValid) {
+ updateInterval = 5;
+ if (QPlatformScreen *currentScreen = screen()) {
+ const qreal refreshRate = currentScreen->refreshRate();
+ if (refreshRate > 60.0)
+ updateInterval /= refreshRate / 60.0;
+ }
+ }
Q_ASSERT(!d->updateTimer.isActive());
d->updateTimer.start(updateInterval, Qt::PreciseTimer, window());
@@ -805,6 +778,15 @@ void QPlatformWindow::deliverUpdateRequest()
QWindow *w = window();
QWindowPrivate *wp = qt_window_private(w);
+
+ // We expect that the platform plugins send DevicePixelRatioChange events.
+ // As a fail-safe make a final check here to make sure the cached DPR value is
+ // always up to date before delivering the update request.
+ if (wp->updateDevicePixelRatio()) {
+ qWarning() << "The cached device pixel ratio value was stale on window update. "
+ << "Please file a QTBUG which explains how to reproduce.";
+ }
+
wp->updateRequestPending = false;
QEvent request(QEvent::UpdateRequest);
QCoreApplication::sendEvent(w, &request);
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index cd621b7636..b6e96a457e 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMWINDOW_H
#define QPLATFORMWINDOW_H
@@ -60,6 +24,7 @@
QT_BEGIN_NAMESPACE
+#define QWINDOWSIZE_MAX ((1<<24)-1)
class QPlatformScreen;
class QPlatformWindowPrivate;
diff --git a/src/gui/kernel/qplatformwindow_p.h b/src/gui/kernel/qplatformwindow_p.h
index e35f527921..2bbdfd5bf9 100644
--- a/src/gui/kernel/qplatformwindow_p.h
+++ b/src/gui/kernel/qplatformwindow_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMWINDOW_P_H
#define QPLATFORMWINDOW_P_H
@@ -55,6 +19,14 @@
#include <QtCore/qbasictimer.h>
#include <QtCore/qrect.h>
#include <QtCore/qnativeinterface.h>
+#include <QtGui/qwindow.h>
+
+#if QT_CONFIG(wayland)
+#include <any>
+#include <QtCore/qobject.h>
+
+struct wl_surface;
+#endif
QT_BEGIN_NAMESPACE
@@ -71,7 +43,16 @@ public:
namespace QNativeInterface::Private {
-#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WASM) || defined(Q_QDOC)
+struct Q_GUI_EXPORT QWasmWindow
+{
+ QT_DECLARE_NATIVE_INTERFACE(QWasmWindow, 1, QWindow)
+ virtual emscripten::val document() const = 0;
+ virtual emscripten::val clientArea() const = 0;
+};
+#endif
+
+#if defined(Q_OS_MACOS) || defined(Q_QDOC)
struct Q_GUI_EXPORT QCocoaWindow
{
QT_DECLARE_NATIVE_INTERFACE(QCocoaWindow, 1, QWindow)
@@ -80,7 +61,7 @@ struct Q_GUI_EXPORT QCocoaWindow
};
#endif
-#if QT_CONFIG(xcb) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(xcb) || defined(Q_QDOC)
struct Q_GUI_EXPORT QXcbWindow
{
QT_DECLARE_NATIVE_INTERFACE(QXcbWindow, 1, QWindow)
@@ -112,7 +93,7 @@ struct Q_GUI_EXPORT QXcbWindow
};
#endif // xcb
-#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
struct Q_GUI_EXPORT QWindowsWindow
{
QT_DECLARE_NATIVE_INTERFACE(QWindowsWindow, 1, QWindow)
@@ -125,6 +106,35 @@ struct Q_GUI_EXPORT QWindowsWindow
};
#endif // Q_OS_WIN
+#if QT_CONFIG(wayland)
+struct Q_GUI_EXPORT QWaylandWindow : public QObject
+{
+ Q_OBJECT
+public:
+ QT_DECLARE_NATIVE_INTERFACE(QWaylandWindow, 1, QWindow)
+
+ virtual wl_surface *surface() const = 0;
+ virtual void setCustomMargins(const QMargins &margins) = 0;
+ virtual void requestXdgActivationToken(uint serial) = 0;
+ template<typename T>
+ T *surfaceRole() const
+ {
+ std::any anyRole = _surfaceRole();
+ auto role = std::any_cast<T *>(&anyRole);
+ return role ? *role : nullptr;
+ }
+Q_SIGNALS:
+ void surfaceCreated();
+ void surfaceDestroyed();
+ void surfaceRoleCreated();
+ void surfaceRoleDestroyed();
+ void xdgActivationTokenCreated(const QString &token);
+
+protected:
+ virtual std::any _surfaceRole() const = 0;
+};
+#endif
+
} // QNativeInterface::Private
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qpointingdevice.cpp b/src/gui/kernel/qpointingdevice.cpp
index 2a09ee3ca9..c4c1e5fd5c 100644
--- a/src/gui/kernel/qpointingdevice.cpp
+++ b/src/gui/kernel/qpointingdevice.cpp
@@ -1,45 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpointingdevice.h"
#include "qpointingdevice_p.h"
#include "qwindowsysteminterface_p.h"
+#include "qeventpoint_p.h"
+
#include <QList>
#include <QLoggingCategory>
#include <QMutex>
@@ -49,6 +15,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcPointerGrab, "qt.pointer.grab");
/*!
@@ -143,11 +111,53 @@ Q_LOGGING_CATEGORY(lcPointerGrab, "qt.pointer.grab");
Any of the above (used as a default filter value).
*/
+/*! \enum QPointingDevice::GrabTransition
+
+ This enum represents a transition of exclusive or passive grab
+ from one object (possibly \c nullptr) to another (possibly \c nullptr).
+ It is emitted as an argument of the QPointingDevice::grabChanged() signal.
+
+ Valid values are:
+
+ \value GrabExclusive
+ Emitted after QPointerEvent::setExclusiveGrabber().
+ \value UngrabExclusive
+ Emitted after QPointerEvent::setExclusiveGrabber() when the grabber is
+ set to \c nullptr, to notify that the grab has terminated normally.
+ \value CancelGrabExclusive
+ Emitted after QPointerEvent::setExclusiveGrabber() when the grabber is set
+ to a different object, to notify that the old grabber's grab is "stolen".
+ \value GrabPassive
+ Emitted after QPointerEvent::addPassiveGrabber().
+ \value UngrabPassive
+ Emitted when a passive grab is terminated normally,
+ for example after QPointerEvent::removePassiveGrabber().
+ \value CancelGrabPassive
+ Emitted when a passive grab is terminated abnormally (a gesture is canceled).
+ \value OverrideGrabPassive
+ This value is not currently used.
+*/
+
+/*! \fn void QPointingDevice::grabChanged(QObject *grabber, QPointingDevice::GrabTransition transition, const QPointerEvent *event, const QEventPoint &point) const
+
+ This signal is emitted when the \a grabber object gains or loses an
+ exclusive or passive grab of \a point during delivery of \a event.
+ The \a transition tells what happened, from the perspective of the
+ \c grabber object.
+
+ \note A grab transition from one object to another results in two signals,
+ to notify that one object has lost its grab, and to notify that there is
+ another grabber. In other cases, when transitioning to or from a non-grabbing
+ state, only one signal is emitted: the \a grabber argument is never \c nullptr.
+
+ \sa QPointerEvent::setExclusiveGrabber(), QPointerEvent::addPassiveGrabber(), QPointerEvent::removePassiveGrabber()
+*/
+
/*!
Creates a new invalid pointing device instance as a child of \a parent.
*/
QPointingDevice::QPointingDevice(QObject *parent)
- : QInputDevice(*(new QPointingDevicePrivate(QLatin1String("unknown"), -1,
+ : QInputDevice(*(new QPointingDevicePrivate("unknown"_L1, -1,
DeviceType::Unknown, PointerType::Unknown,
Capability::None, 0, 0)), parent)
{
@@ -177,9 +187,10 @@ QPointingDevice::QPointingDevice(QPointingDevicePrivate &d, QObject *parent)
{
}
+#if QT_DEPRECATED_SINCE(6, 0)
/*!
\internal
- \deprecated Please use the constructor rather than setters.
+ \deprecated [6.0] Please use the constructor rather than setters.
Sets the device type \a devType and infers the pointer type.
*/
@@ -210,7 +221,7 @@ void QPointingDevice::setType(DeviceType devType)
/*!
\internal
- \deprecated Please use the constructor rather than setters.
+ \deprecated [6.0] Please use the constructor rather than setters.
*/
void QPointingDevice::setCapabilities(QInputDevice::Capabilities caps)
{
@@ -220,13 +231,14 @@ void QPointingDevice::setCapabilities(QInputDevice::Capabilities caps)
/*!
\internal
- \deprecated Please use the constructor rather than setters.
+ \deprecated [6.0] Please use the constructor rather than setters.
*/
void QPointingDevice::setMaximumTouchPoints(int c)
{
Q_D(QPointingDevice);
d->maximumTouchPoints = c;
}
+#endif // QT_DEPRECATED_SINCE(6, 0)
/*!
Returns the pointer type.
@@ -284,7 +296,7 @@ const QPointingDevice *QPointingDevice::primaryPointingDevice(const QString& sea
const QPointingDevice *mouse = nullptr;
const QPointingDevice *touchpad = nullptr;
for (const QInputDevice *dev : v) {
- if (dev->seatName() != seatName)
+ if (!seatName.isNull() && dev->seatName() != seatName)
continue;
if (dev->type() == QInputDevice::DeviceType::Mouse) {
if (!mouse)
@@ -301,19 +313,22 @@ const QPointingDevice *QPointingDevice::primaryPointingDevice(const QString& sea
qCDebug(lcQpaInputDevices) << "no mouse-like devices registered for seat" << seatName
<< "The platform plugin should have provided one via "
"QWindowSystemInterface::registerInputDevice(). Creating a default mouse for now.";
- mouse = new QPointingDevice(QLatin1String("core pointer"), 1, DeviceType::Mouse,
+ mouse = new QPointingDevice("core pointer"_L1, 1, DeviceType::Mouse,
PointerType::Generic, Capability::Position, 1, 3, seatName,
QPointingDeviceUniqueId(), QCoreApplication::instance());
QInputDevicePrivate::registerDevice(mouse);
return mouse;
}
- if (v.length() > 1)
+ if (v.size() > 1)
qCDebug(lcQpaInputDevices) << "core pointer ambiguous for seat" << seatName;
if (mouse)
return mouse;
return touchpad;
}
+QPointingDevicePrivate::~QPointingDevicePrivate()
+ = default;
+
/*!
\internal
Finds the device instance belonging to the drawing or eraser end of a particular stylus,
@@ -422,13 +437,12 @@ QPointingDevicePrivate::EventPointData *QPointingDevicePrivate::queryPointById(i
*/
QPointingDevicePrivate::EventPointData *QPointingDevicePrivate::pointById(int id) const
{
- auto it = activePoints.find(id);
- if (it == activePoints.end()) {
+ const auto [it, inserted] = activePoints.try_emplace(id);
+ if (inserted) {
Q_Q(const QPointingDevice);
- QPointingDevicePrivate::EventPointData epd;
- QMutableEventPoint::from(epd.eventPoint).setId(id);
- QMutableEventPoint::from(epd.eventPoint).setDevice(q);
- return &activePoints.insert(id, epd).first.value();
+ auto &epd = it.value();
+ QMutableEventPoint::setId(epd.eventPoint, id);
+ QMutableEventPoint::setDevice(epd.eventPoint, q);
}
return &it.value();
}
@@ -451,7 +465,7 @@ void QPointingDevicePrivate::removePointById(int id)
QObject *QPointingDevicePrivate::firstActiveTarget() const
{
for (auto &pt : activePoints.values()) {
- if (auto target = QMutableEventPoint::constFrom(pt.eventPoint).target())
+ if (auto target = QMutableEventPoint::target(pt.eventPoint))
return target;
}
return nullptr;
@@ -466,7 +480,7 @@ QObject *QPointingDevicePrivate::firstActiveTarget() const
QWindow *QPointingDevicePrivate::firstActiveWindow() const
{
for (auto &pt : activePoints.values()) {
- if (auto window = QMutableEventPoint::constFrom(pt.eventPoint).window())
+ if (auto window = QMutableEventPoint::window(pt.eventPoint))
return window;
}
return nullptr;
@@ -493,6 +507,7 @@ void QPointingDevicePrivate::setExclusiveGrabber(const QPointerEvent *event, con
qWarning() << "point is not in activePoints" << point;
return;
}
+ Q_ASSERT(persistentPoint->eventPoint.id() == point.id());
if (persistentPoint->exclusiveGrabber == exclusiveGrabber)
return;
auto oldGrabber = persistentPoint->exclusiveGrabber;
@@ -505,7 +520,7 @@ void QPointingDevicePrivate::setExclusiveGrabber(const QPointerEvent *event, con
<< "@" << point.scenePosition()
<< ": grab" << oldGrabber << "->" << exclusiveGrabber;
}
- QMutableEventPoint::from(persistentPoint->eventPoint).setGlobalGrabPosition(point.globalPosition());
+ QMutableEventPoint::setGlobalGrabPosition(persistentPoint->eventPoint, point.globalPosition());
if (exclusiveGrabber)
emit q->grabChanged(exclusiveGrabber, QPointingDevice::GrabExclusive, event, point);
else
@@ -549,7 +564,7 @@ bool QPointingDevicePrivate::addPassiveGrabber(const QPointerEvent *event, const
bool QPointingDevicePrivate::setPassiveGrabberContext(QPointingDevicePrivate::EventPointData *epd, QObject *grabber, QObject *context)
{
- int i = epd->passiveGrabbers.indexOf(grabber);
+ qsizetype i = epd->passiveGrabbers.indexOf(grabber);
if (i < 0)
return false;
if (epd->passiveGrabbersContext.size() <= i)
@@ -566,7 +581,7 @@ bool QPointingDevicePrivate::removePassiveGrabber(const QPointerEvent *event, co
qWarning() << "point is not in activePoints" << point;
return false;
}
- int i = persistentPoint->passiveGrabbers.indexOf(grabber);
+ qsizetype i = persistentPoint->passiveGrabbers.indexOf(grabber);
if (i >= 0) {
if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
qCDebug(lcPointerGrab) << name << "point" << point.id() << point.state()
@@ -629,7 +644,7 @@ void QPointingDevicePrivate::removeGrabber(QObject *grabber, bool cancel)
cancel ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive,
nullptr, epd.eventPoint);
}
- int pi = epd.passiveGrabbers.indexOf(grabber);
+ qsizetype pi = epd.passiveGrabbers.indexOf(grabber);
if (pi >= 0) {
qCDebug(lcPointerGrab) << name << "point" << epd.eventPoint.id() << epd.eventPoint.state()
<< ": removing passive grabber" << grabber;
@@ -665,9 +680,9 @@ const QPointingDevice *QPointingDevicePrivate::tabletDevice(QInputDevice::Device
<< deviceType << pointerType << Qt::hex << uniqueId.numericId()
<< "The platform plugin should have provided one via "
"QWindowSystemInterface::registerInputDevice(). Creating a default one for now.";
- dev = new QPointingDevice(QLatin1String("fake tablet"), 2, deviceType, pointerType,
- QInputDevice::Capability::Position | QInputDevice::Capability::Pressure,
- 1, 1, QString(), uniqueId, QCoreApplication::instance());
+ dev = new QPointingDevice("fake tablet"_L1, 2, deviceType, pointerType,
+ QInputDevice::Capability::Position | QInputDevice::Capability::Pressure,
+ 1, 1, QString(), uniqueId, QCoreApplication::instance());
QInputDevicePrivate::registerDevice(dev);
}
return dev;
@@ -693,7 +708,7 @@ QDebug operator<<(QDebug debug, const QPointingDevice *device)
if (device) {
debug << '"' << device->name() << "\" ";
QtDebugUtils::formatQEnum(debug, device->type());
- debug << " id=" << Qt::hex << device->systemId() << Qt::dec;
+ debug << " id=" << device->systemId();
if (!device->seatName().isEmpty())
debug << " seat=" << device->seatName();
if (device->pointerType() != QPointingDevice::PointerType::Generic) {
@@ -804,3 +819,5 @@ size_t qHash(QPointingDeviceUniqueId key, size_t seed) noexcept
}
QT_END_NAMESPACE
+
+#include "moc_qpointingdevice.cpp"
diff --git a/src/gui/kernel/qpointingdevice.h b/src/gui/kernel/qpointingdevice.h
index 094780765a..b8e6460af7 100644
--- a/src/gui/kernel/qpointingdevice.h
+++ b/src/gui/kernel/qpointingdevice.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPOINTINGDEVICE_H
#define QPOINTINGDEVICE_H
@@ -143,7 +107,13 @@ public:
bool operator==(const QPointingDevice &other) const;
Q_SIGNALS:
- void grabChanged(QObject *grabber, GrabTransition transition, const QPointerEvent *event, const QEventPoint &point) const;
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ void grabChanged(QObject *grabber, GrabTransition transition,
+ const QPointerEvent *event, const QEventPoint &point) const;
+#else
+ void grabChanged(QObject *grabber, QPointingDevice::GrabTransition transition,
+ const QPointerEvent *event, const QEventPoint &point);
+#endif
protected:
QPointingDevice(QPointingDevicePrivate &d, QObject *parent);
diff --git a/src/gui/kernel/qpointingdevice_p.h b/src/gui/kernel/qpointingdevice_p.h
index 263bc91864..b2f0574e9b 100644
--- a/src/gui/kernel/qpointingdevice_p.h
+++ b/src/gui/kernel/qpointingdevice_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPOINTINGDEVICE_P_H
#define QPOINTINGDEVICE_P_H
@@ -56,6 +20,8 @@
#include <QtGui/qpointingdevice.h>
#include <QtGui/private/qtguiglobal_p.h>
#include <QtGui/private/qinputdevice_p.h>
+
+#include <QtCore/qpointer.h>
#include <QtCore/private/qflatmap_p.h>
QT_BEGIN_NAMESPACE
@@ -79,6 +45,7 @@ public:
pointingDeviceType = true;
activePoints.reserve(maxPoints);
}
+ ~QPointingDevicePrivate() override;
void sendTouchCancelEvent(QTouchEvent *cancelEvent);
@@ -107,7 +74,7 @@ public:
void clearPassiveGrabbers(const QPointerEvent *event, const QEventPoint &point);
void removeGrabber(QObject *grabber, bool cancel = false);
- using EventPointMap = QFlatMap<int, EventPointData>;
+ using EventPointMap = QVarLengthFlatMap<int, EventPointData, 20>;
mutable EventPointMap activePoints;
QPointingDeviceUniqueId uniqueId;
diff --git a/src/gui/kernel/qrasterwindow.cpp b/src/gui/kernel/qrasterwindow.cpp
index 70d87347c3..f292344ca1 100644
--- a/src/gui/kernel/qrasterwindow.cpp
+++ b/src/gui/kernel/qrasterwindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qrasterwindow.h"
@@ -70,14 +34,20 @@ class QRasterWindowPrivate : public QPaintDeviceWindowPrivate
{
Q_DECLARE_PUBLIC(QRasterWindow)
public:
+ void handleResizeEvent() override
+ {
+ Q_Q(QRasterWindow);
+ if (backingstore->size() != q->size())
+ markWindowAsDirty();
+ }
+
void beginPaint(const QRegion &region) override
{
Q_Q(QRasterWindow);
const QSize size = q->size();
- if (backingstore->size() != size) {
+ if (backingstore->size() != size)
backingstore->resize(size);
- markWindowAsDirty();
- }
+
backingstore->beginPaint(region);
}
@@ -138,4 +108,10 @@ QPaintDevice *QRasterWindow::redirected(QPoint *) const
return d->backingstore->paintDevice();
}
+void QRasterWindow::resizeEvent(QResizeEvent *)
+{
+}
+
QT_END_NAMESPACE
+
+#include "moc_qrasterwindow.cpp"
diff --git a/src/gui/kernel/qrasterwindow.h b/src/gui/kernel/qrasterwindow.h
index 9fe01c076b..986bf6b511 100644
--- a/src/gui/kernel/qrasterwindow.h
+++ b/src/gui/kernel/qrasterwindow.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRASTERWINDOW_H
#define QRASTERWINDOW_H
@@ -59,6 +23,7 @@ public:
protected:
int metric(PaintDeviceMetric metric) const override;
QPaintDevice *redirected(QPoint *) const override;
+ void resizeEvent(QResizeEvent *event) override;
private:
Q_DISABLE_COPY(QRasterWindow)
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index e6f408875e..83641e7676 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qscreen.h"
#include "qscreen_p.h"
@@ -73,100 +37,42 @@ QT_BEGIN_NAMESPACE
\inmodule QtGui
*/
-QScreen::QScreen(QPlatformScreen *screen)
+QScreen::QScreen(QPlatformScreen *platformScreen)
: QObject(*new QScreenPrivate(), nullptr)
{
Q_D(QScreen);
- d->setPlatformScreen(screen);
-}
-
-void QScreenPrivate::updateGeometriesWithSignals()
-{
- const QRect oldGeometry = geometry;
- const QRect oldAvailableGeometry = availableGeometry;
- updateHighDpi();
- emitGeometryChangeSignals(oldGeometry != geometry, oldAvailableGeometry != availableGeometry);
-}
-
-void QScreenPrivate::emitGeometryChangeSignals(bool geometryChanged, bool availableGeometryChanged)
-{
- Q_Q(QScreen);
- if (geometryChanged)
- emit q->geometryChanged(geometry);
- if (availableGeometryChanged)
- emit q->availableGeometryChanged(availableGeometry);
+ d->platformScreen = platformScreen;
+ platformScreen->d_func()->screen = this;
- if (geometryChanged || availableGeometryChanged) {
- const auto siblings = q->virtualSiblings();
- for (QScreen* sibling : siblings)
- emit sibling->virtualGeometryChanged(sibling->virtualGeometry());
- }
+ d->orientation = platformScreen->orientation();
+ d->logicalDpi = QPlatformScreen::overrideDpi(platformScreen->logicalDpi());
+ d->refreshRate = platformScreen->refreshRate();
+ // safeguard ourselves against buggy platform behavior...
+ if (d->refreshRate < 1.0)
+ d->refreshRate = 60.0;
- if (geometryChanged)
- emit q->physicalDotsPerInchChanged(q->physicalDotsPerInch());
+ d->updateGeometry();
+ d->updatePrimaryOrientation(); // derived from the geometry
}
-void QScreenPrivate::setPlatformScreen(QPlatformScreen *screen)
+void QScreenPrivate::updateGeometry()
{
- Q_Q(QScreen);
- platformScreen = screen;
- platformScreen->d_func()->screen = q;
- orientation = platformScreen->orientation();
-
- logicalDpi = QPlatformScreen::overrideDpi(platformScreen->logicalDpi());
-
- refreshRate = platformScreen->refreshRate();
- // safeguard ourselves against buggy platform behavior...
- if (refreshRate < 1.0)
- refreshRate = 60.0;
-
- updateHighDpi();
- updatePrimaryOrientation(); // derived from the geometry
+ qreal scaleFactor = QHighDpiScaling::factor(platformScreen);
+ QRect nativeGeometry = platformScreen->geometry();
+ geometry = QRect(nativeGeometry.topLeft(), QHighDpi::fromNative(nativeGeometry.size(), scaleFactor));
+ availableGeometry = QHighDpi::fromNative(platformScreen->availableGeometry(), scaleFactor, geometry.topLeft());
}
-
/*!
Destroys the screen.
+
+ \internal
*/
QScreen::~QScreen()
{
- // Remove screen
- const bool wasPrimary = QGuiApplication::primaryScreen() == this;
- QGuiApplicationPrivate::screen_list.removeOne(this);
- QGuiApplicationPrivate::resetCachedDevicePixelRatio();
-
- if (!qGuiApp)
- return;
-
- QScreen *newPrimaryScreen = QGuiApplication::primaryScreen();
- if (wasPrimary && newPrimaryScreen)
- emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
-
- // Allow clients to manage windows that are affected by the screen going
- // away, before we fall back to moving them to the primary screen.
- emit qApp->screenRemoved(this);
-
- if (QGuiApplication::closingDown())
- return;
-
- bool movingFromVirtualSibling = newPrimaryScreen
- && newPrimaryScreen->handle()->virtualSiblings().contains(handle());
-
- // Move any leftover windows to the primary screen
- const auto allWindows = QGuiApplication::allWindows();
- for (QWindow *window : allWindows) {
- if (!window->isTopLevel() || window->screen() != this)
- continue;
-
- const bool wasVisible = window->isVisible();
- window->setScreen(newPrimaryScreen);
-
- // Re-show window if moved from a virtual sibling screen. Otherwise
- // leave it up to the application developer to show the window.
- if (movingFromVirtualSibling)
- window->setVisible(wasVisible);
- }
+ Q_ASSERT_X(!QGuiApplicationPrivate::screen_list.contains(this), "QScreen",
+ "QScreens should be removed via QWindowSystemInterface::handleScreenRemoved()");
}
/*!
@@ -186,6 +92,10 @@ QPlatformScreen *QScreen::handle() const
For example, on X11 these correspond to the XRandr screen names,
typically "VGA1", "HDMI1", etc.
+
+ \note The user presentable string is not guaranteed to match the
+ result of any native APIs, and should not be used to uniquely identify
+ a screen.
*/
QString QScreen::name() const
{
@@ -449,9 +359,12 @@ QList<QScreen *> QScreen::virtualSiblings() const
Q_D(const QScreen);
const QList<QPlatformScreen *> platformScreens = d->platformScreen->virtualSiblings();
QList<QScreen *> screens;
- screens.reserve(platformScreens.count());
- for (QPlatformScreen *platformScreen : platformScreens)
- screens << platformScreen->screen();
+ screens.reserve(platformScreens.size());
+ for (QPlatformScreen *platformScreen : platformScreens) {
+ // Only consider platform screens that have been added
+ if (auto *knownScreen = platformScreen->screen())
+ screens << knownScreen;
+ }
return screens;
}
@@ -547,6 +460,11 @@ Qt::ScreenOrientation QScreen::orientation() const
/*!
\property QScreen::refreshRate
\brief the approximate vertical refresh rate of the screen in Hz
+
+ \warning Avoid using the screen's refresh rate to drive animations via a
+ timer such as QChronoTimer. Instead use QWindow::requestUpdate().
+
+ \sa QWindow::requestUpdate()
*/
qreal QScreen::refreshRate() const
{
@@ -785,8 +703,23 @@ QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height)
result.setDevicePixelRatio(result.devicePixelRatio() * factor);
return result;
}
+
+/*!
+ \fn template <typename QNativeInterface> QNativeInterface *QScreen::nativeInterface() const
+
+ Returns a native interface of the given type for the screen.
+
+ This function provides access to platform specific functionality
+ of QScreen, as defined in the QNativeInterface namespace:
+
+ \annotatedlist native-interfaces-qscreen
+
+ If the requested interface is not available a \nullptr is returned.
+ */
+
void *QScreen::resolveInterface(const char *name, int revision) const
{
+ using namespace QNativeInterface;
using namespace QNativeInterface::Private;
auto *platformScreen = handle();
@@ -806,17 +739,22 @@ void *QScreen::resolveInterface(const char *name, int revision) const
QT_NATIVE_INTERFACE_RETURN_IF(QWebOSScreen, platformScreen);
#endif
- return nullptr;
-}
+#if defined(Q_OS_WIN32)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWindowsScreen, platformScreen);
+#endif
-#ifndef QT_NO_DEBUG_STREAM
+#if defined(Q_OS_ANDROID)
+ QT_NATIVE_INTERFACE_RETURN_IF(QAndroidScreen, platformScreen);
+#endif
-static inline void formatRect(QDebug &debug, const QRect r)
-{
- debug << r.width() << 'x' << r.height()
- << Qt::forcesign << r.x() << r.y() << Qt::noforcesign;
+#if QT_CONFIG(wayland)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWaylandScreen, platformScreen);
+#endif
+
+ return nullptr;
}
+#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen)
{
const QDebugStateSaver saver(debug);
@@ -827,10 +765,8 @@ Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen)
if (debug.verbosity() > 2) {
if (screen == QGuiApplication::primaryScreen())
debug << ", primary";
- debug << ", geometry=";
- formatRect(debug, screen->geometry());
- debug << ", available=";
- formatRect(debug, screen->availableGeometry());
+ debug << ", geometry=" << screen->geometry();
+ debug << ", available=" << screen->availableGeometry();
debug << ", logical DPI=" << screen->logicalDotsPerInchX()
<< ',' << screen->logicalDotsPerInchY()
<< ", physical DPI=" << screen->physicalDotsPerInchX()
@@ -846,4 +782,60 @@ Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QScreen *screen)
}
#endif // !QT_NO_DEBUG_STREAM
+QScreenPrivate::UpdateEmitter::UpdateEmitter(QScreen *screen)
+{
+ initialState.platformScreen = screen->handle();
+
+ // Use public APIs to read out current state, rather
+ // than accessing the QScreenPrivate members, so that
+ // we detect any changes to the high-DPI scale factors
+ // that may be applied in the getters.
+
+ initialState.logicalDpi = QDpi{
+ screen->logicalDotsPerInchX(),
+ screen->logicalDotsPerInchY()
+ };
+ initialState.geometry = screen->geometry();
+ initialState.availableGeometry = screen->availableGeometry();
+ initialState.primaryOrientation = screen->primaryOrientation();
+}
+
+QScreenPrivate::UpdateEmitter::~UpdateEmitter()
+{
+ QScreen *screen = initialState.platformScreen->screen();
+
+ const auto logicalDotsPerInch = QDpi{
+ screen->logicalDotsPerInchX(),
+ screen->logicalDotsPerInchY()
+ };
+ if (logicalDotsPerInch != initialState.logicalDpi)
+ emit screen->logicalDotsPerInchChanged(screen->logicalDotsPerInch());
+
+ const auto geometry = screen->geometry();
+ const auto geometryChanged = geometry != initialState.geometry;
+ if (geometryChanged)
+ emit screen->geometryChanged(geometry);
+
+ const auto availableGeometry = screen->availableGeometry();
+ const auto availableGeometryChanged = availableGeometry != initialState.availableGeometry;
+ if (availableGeometryChanged)
+ emit screen->availableGeometryChanged(availableGeometry);
+
+ if (geometryChanged || availableGeometryChanged) {
+ const auto siblings = screen->virtualSiblings();
+ for (QScreen* sibling : siblings)
+ emit sibling->virtualGeometryChanged(sibling->virtualGeometry());
+ }
+
+ if (geometryChanged) {
+ emit screen->physicalDotsPerInchChanged(screen->physicalDotsPerInch());
+
+ const auto primaryOrientation = screen->primaryOrientation();
+ if (primaryOrientation != initialState.primaryOrientation)
+ emit screen->primaryOrientationChanged(primaryOrientation);
+ }
+}
+
QT_END_NAMESPACE
+
+#include "moc_qscreen.cpp"
diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h
index 8c2f0cf10f..9442e7525b 100644
--- a/src/gui/kernel/qscreen.h
+++ b/src/gui/kernel/qscreen.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSCREEN_H
#define QSCREEN_H
@@ -183,5 +147,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug, const QScreen *);
QT_END_NAMESPACE
+#include <QtGui/qscreen_platform.h>
+
#endif // QSCREEN_H
diff --git a/src/gui/kernel/qscreen_p.h b/src/gui/kernel/qscreen_p.h
index 7543202c2f..964bc1cc58 100644
--- a/src/gui/kernel/qscreen_p.h
+++ b/src/gui/kernel/qscreen_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSCREEN_P_H
#define QSCREEN_P_H
@@ -60,21 +24,8 @@
QT_BEGIN_NAMESPACE
-class QScreenPrivate : public QObjectPrivate
+struct QScreenData
{
- Q_DECLARE_PUBLIC(QScreen)
-public:
- void setPlatformScreen(QPlatformScreen *screen);
- void updateHighDpi()
- {
- geometry = platformScreen->deviceIndependentGeometry();
- availableGeometry = QHighDpi::fromNative(platformScreen->availableGeometry(), QHighDpiScaling::factor(platformScreen), geometry.topLeft());
- }
-
- void updatePrimaryOrientation();
- void updateGeometriesWithSignals();
- void emitGeometryChangeSignals(bool geometryChanged, bool availableGeometryChanged);
-
QPlatformScreen *platformScreen = nullptr;
Qt::ScreenOrientation orientation = Qt::PrimaryOrientation;
@@ -85,6 +36,25 @@ public:
qreal refreshRate = 60;
};
+class QScreenPrivate : public QObjectPrivate, public QScreenData
+{
+ Q_DECLARE_PUBLIC(QScreen)
+public:
+ void updateGeometry();
+ void updatePrimaryOrientation();
+
+ class UpdateEmitter
+ {
+ public:
+ explicit UpdateEmitter(QScreen *screen);
+ ~UpdateEmitter();
+ UpdateEmitter(UpdateEmitter&&) noexcept = default;
+ private:
+ Q_DISABLE_COPY(UpdateEmitter)
+ QScreenData initialState;
+ };
+};
+
QT_END_NAMESPACE
#endif // QSCREEN_P_H
diff --git a/src/gui/kernel/qscreen_platform.h b/src/gui/kernel/qscreen_platform.h
new file mode 100644
index 0000000000..6f40e9273f
--- /dev/null
+++ b/src/gui/kernel/qscreen_platform.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSCREEN_PLATFORM_H
+#define QSCREEN_PLATFORM_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the native interface APIs. Usage of
+// this API may make your code source and binary incompatible
+// with future versions of Qt.
+//
+
+#include <QtGui/qtguiglobal.h>
+
+#include <QtCore/qnativeinterface.h>
+#include <QtGui/qguiapplication.h>
+
+#if defined(Q_OS_WIN32)
+#include <QtGui/qwindowdefs_win.h>
+#endif
+
+#if QT_CONFIG(wayland)
+struct wl_output;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QNativeInterface {
+
+#if defined(Q_OS_WIN32) || defined(Q_QDOC)
+struct Q_GUI_EXPORT QWindowsScreen
+{
+ QT_DECLARE_NATIVE_INTERFACE(QWindowsScreen, 1, QScreen)
+ virtual HMONITOR handle() const = 0;
+};
+#endif
+
+#if QT_CONFIG(wayland) || defined(Q_QDOC)
+struct Q_GUI_EXPORT QWaylandScreen
+{
+ QT_DECLARE_NATIVE_INTERFACE(QWaylandScreen, 1, QScreen)
+ virtual wl_output *output() const = 0;
+};
+#endif
+
+#if defined(Q_OS_ANDROID) || defined(Q_QDOC)
+struct Q_GUI_EXPORT QAndroidScreen
+{
+ QT_DECLARE_NATIVE_INTERFACE(QAndroidScreen, 1, QScreen)
+ virtual int displayId() const = 0;
+};
+#endif
+
+} // namespace QNativeInterface
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/kernel/qsessionmanager.cpp b/src/gui/kernel/qsessionmanager.cpp
index 026e855874..0a1ff95656 100644
--- a/src/gui/kernel/qsessionmanager.cpp
+++ b/src/gui/kernel/qsessionmanager.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qsessionmanager.h>
#include <qguiapplication.h>
@@ -317,10 +281,6 @@ void QSessionManager::setRestartCommand(const QStringList &command)
/*!
Returns the currently set restart command.
- To iterate over the list, you can use the \l foreach pseudo-keyword:
-
- \snippet code/src_gui_kernel_qguiapplication.cpp 3
-
\sa setRestartCommand(), restartHint()
*/
QStringList QSessionManager::restartCommand() const
@@ -343,10 +303,6 @@ void QSessionManager::setDiscardCommand(const QStringList &command)
/*!
Returns the currently set discard command.
- To iterate over the list, you can use the \l foreach pseudo-keyword:
-
- \snippet code/src_gui_kernel_qguiapplication.cpp 4
-
\sa setDiscardCommand(), restartCommand(), setRestartCommand()
*/
QStringList QSessionManager::discardCommand() const
@@ -420,4 +376,6 @@ void QSessionManager::requestPhase2()
QT_END_NAMESPACE
+#include "moc_qsessionmanager.cpp"
+
#endif // QT_NO_SESSIONMANAGER
diff --git a/src/gui/kernel/qsessionmanager.h b/src/gui/kernel/qsessionmanager.h
index 21100b25d9..6015a0b378 100644
--- a/src/gui/kernel/qsessionmanager.h
+++ b/src/gui/kernel/qsessionmanager.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSESSIONMANAGER_H
#define QSESSIONMANAGER_H
diff --git a/src/gui/kernel/qsessionmanager_p.h b/src/gui/kernel/qsessionmanager_p.h
index d07d9b5eb8..c98f7a5a1d 100644
--- a/src/gui/kernel/qsessionmanager_p.h
+++ b/src/gui/kernel/qsessionmanager_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSESSIONMANAGER_P_H
#define QSESSIONMANAGER_P_H
@@ -63,7 +27,7 @@ QT_BEGIN_NAMESPACE
class QPlatformSessionManager;
-class QSessionManagerPrivate : public QObjectPrivate
+class Q_GUI_EXPORT QSessionManagerPrivate : public QObjectPrivate
{
public:
QSessionManagerPrivate(const QString &id,
diff --git a/src/gui/kernel/qshapedpixmapdndwindow.cpp b/src/gui/kernel/qshapedpixmapdndwindow.cpp
index e58d37693a..546a1a4937 100644
--- a/src/gui/kernel/qshapedpixmapdndwindow.cpp
+++ b/src/gui/kernel/qshapedpixmapdndwindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qshapedpixmapdndwindow_p.h"
@@ -56,7 +20,7 @@ QShapedPixmapWindow::QShapedPixmapWindow(QScreen *screen)
QSurfaceFormat format;
format.setAlphaBufferSize(8);
setFormat(format);
- setFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint
+ setFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint
| Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus);
}
@@ -104,11 +68,11 @@ void QShapedPixmapWindow::updateGeometry(const QPoint &pos)
{
QSize size(1, 1);
if (!m_pixmap.isNull()) {
- size = qFuzzyCompare(m_pixmap.devicePixelRatio(), qreal(1.0))
- ? m_pixmap.size()
- : (QSizeF(m_pixmap.size()) / m_pixmap.devicePixelRatio()).toSize();
+ size = m_pixmap.deviceIndependentSize().toSize();
}
setGeometry(QRect(pos - m_hotSpot, size));
}
QT_END_NAMESPACE
+
+#include "moc_qshapedpixmapdndwindow_p.cpp"
diff --git a/src/gui/kernel/qshapedpixmapdndwindow_p.h b/src/gui/kernel/qshapedpixmapdndwindow_p.h
index 5089be7284..a2ce26a60e 100644
--- a/src/gui/kernel/qshapedpixmapdndwindow_p.h
+++ b/src/gui/kernel/qshapedpixmapdndwindow_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSHAPEDPIXMAPDNDWINDOW_H
#define QSHAPEDPIXMAPDNDWINDOW_H
diff --git a/src/gui/kernel/qshortcut.cpp b/src/gui/kernel/qshortcut.cpp
index 524062ef30..3f6822cb03 100644
--- a/src/gui/kernel/qshortcut.cpp
+++ b/src/gui/kernel/qshortcut.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qshortcut.h"
#include "qshortcut_p.h"
@@ -132,7 +96,7 @@ QT_BEGIN_NAMESPACE
\sa activated()
*/
-static bool simpleContextMatcher(QObject *object, Qt::ShortcutContext context)
+bool QShortcutPrivate::simpleContextMatcher(QObject *object, Qt::ShortcutContext context)
{
auto guiShortcut = qobject_cast<QShortcut *>(object);
if (QGuiApplication::applicationState() != Qt::ApplicationActive || guiShortcut == nullptr)
@@ -163,14 +127,14 @@ void QShortcutPrivate::redoGrab(QShortcutMap &map)
return;
}
- for (int id : qAsConst(sc_ids))
+ for (int id : std::as_const(sc_ids))
map.removeShortcut(id, q);
sc_ids.clear();
if (sc_sequences.isEmpty())
return;
- sc_ids.reserve(sc_sequences.count());
- for (const auto &keySequence : qAsConst(sc_sequences)) {
+ sc_ids.reserve(sc_sequences.size());
+ for (const auto &keySequence : std::as_const(sc_sequences)) {
if (keySequence.isEmpty())
continue;
int id = map.addShortcut(q, keySequence, sc_context, contextMatcher());
@@ -373,7 +337,7 @@ QShortcut::~QShortcut()
{
Q_D(QShortcut);
if (qApp) {
- for (int id : qAsConst(d->sc_ids))
+ for (int id : std::as_const(d->sc_ids))
QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this);
}
}
@@ -572,6 +536,8 @@ QString QShortcut::whatsThis() const
/*!
Returns the primary key binding's ID.
+ \deprecated
+
\sa QShortcutEvent::shortcutId()
*/
int QShortcut::id() const
diff --git a/src/gui/kernel/qshortcut.h b/src/gui/kernel/qshortcut.h
index d3db30fd4d..00b9168bea 100644
--- a/src/gui/kernel/qshortcut.h
+++ b/src/gui/kernel/qshortcut.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSHORTCUT_H
#define QSHORTCUT_H
@@ -68,7 +32,7 @@ public:
const char *member = nullptr, const char *ambiguousMember = nullptr,
Qt::ShortcutContext context = Qt::WindowShortcut);
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
template<typename Functor>
QShortcut(const QKeySequence &key, QObject *parent,
Functor functor,
@@ -206,17 +170,18 @@ public:
bool autoRepeat() const;
#if QT_DEPRECATED_SINCE(6,0)
- Q_DECL_DEPRECATED int id() const;
+ QT_DEPRECATED_VERSION_6_0 int id() const;
#endif
void setWhatsThis(const QString &text);
QString whatsThis() const;
#if QT_DEPRECATED_SINCE(6,0)
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
QWidget *parentWidget() const;
#else
template<typename T = QWidget*>
+ QT_DEPRECATED_VERSION_X_6_0("Use parent() and qobject_cast instead")
inline T parentWidget() const
{ return static_cast<T>(QObject::parent()); }
#endif
diff --git a/src/gui/kernel/qshortcut_p.h b/src/gui/kernel/qshortcut_p.h
index f62bab0297..8ff833d477 100644
--- a/src/gui/kernel/qshortcut_p.h
+++ b/src/gui/kernel/qshortcut_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSHORTCUT_P_H
#define QSHORTCUT_P_H
@@ -79,6 +43,8 @@ public:
virtual QShortcutMap::ContextMatcher contextMatcher() const;
virtual bool handleWhatsThis() { return false; }
+ static bool simpleContextMatcher(QObject *object, Qt::ShortcutContext context);
+
QList<QKeySequence> sc_sequences;
QString sc_whatsthis;
Qt::ShortcutContext sc_context = Qt::WindowShortcut;
diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp
index cf729d28c4..800e703ac2 100644
--- a/src/gui/kernel/qshortcutmap.cpp
+++ b/src/gui/kernel/qshortcutmap.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qshortcutmap_p.h"
#include "private/qobject_p.h"
@@ -65,23 +29,23 @@ Q_LOGGING_CATEGORY(lcShortcutMap, "qt.gui.shortcutmap")
struct QShortcutEntry
{
QShortcutEntry()
- : keyseq(0), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(nullptr), contextMatcher(nullptr)
+ : keySequence(0), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(nullptr), contextMatcher(nullptr)
{}
QShortcutEntry(const QKeySequence &k)
- : keyseq(k), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(nullptr), contextMatcher(nullptr)
+ : keySequence(k), context(Qt::WindowShortcut), enabled(false), autorepeat(1), id(0), owner(nullptr), contextMatcher(nullptr)
{}
QShortcutEntry(QObject *o, const QKeySequence &k, Qt::ShortcutContext c, int i, bool a, QShortcutMap::ContextMatcher m)
- : keyseq(k), context(c), enabled(true), autorepeat(a), id(i), owner(o), contextMatcher(m)
+ : keySequence(k), context(c), enabled(true), autorepeat(a), id(i), owner(o), contextMatcher(m)
{}
bool correctContext() const { return contextMatcher(owner, context); }
bool operator<(const QShortcutEntry &f) const
- { return keyseq < f.keyseq; }
+ { return keySequence < f.keySequence; }
- QKeySequence keyseq;
+ QKeySequence keySequence;
Qt::ShortcutContext context;
bool enabled : 1;
bool autorepeat : 1;
@@ -124,7 +88,7 @@ public:
}
QShortcutMap *q_ptr; // Private's parent
- QList<QShortcutEntry> sequences; // All sequences!
+ QList<QShortcutEntry> shortcuts; // All shortcuts!
int currentId; // Global shortcut ID number
int ambigCount; // Index of last enabled ambiguous dispatch
@@ -156,18 +120,18 @@ QShortcutMap::~QShortcutMap()
Adds a shortcut to the global map.
Returns the id of the newly added shortcut.
*/
-int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &key, Qt::ShortcutContext context, ContextMatcher matcher)
+int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &keySequence, Qt::ShortcutContext context, ContextMatcher matcher)
{
Q_ASSERT_X(owner, "QShortcutMap::addShortcut", "All shortcuts need an owner");
- Q_ASSERT_X(!key.isEmpty(), "QShortcutMap::addShortcut", "Cannot add keyless shortcuts to map");
+ Q_ASSERT_X(!keySequence.isEmpty(), "QShortcutMap::addShortcut", "Cannot add keyless shortcuts to map");
Q_D(QShortcutMap);
- QShortcutEntry newEntry(owner, key, context, --(d->currentId), true, matcher);
- const auto it = std::upper_bound(d->sequences.begin(), d->sequences.end(), newEntry);
- d->sequences.insert(it, newEntry); // Insert sorted
+ QShortcutEntry newEntry(owner, keySequence, context, --(d->currentId), true, matcher);
+ const auto it = std::upper_bound(d->shortcuts.begin(), d->shortcuts.end(), newEntry);
+ d->shortcuts.insert(it, newEntry); // Insert sorted
qCDebug(lcShortcutMap).nospace()
<< "QShortcutMap::addShortcut(" << owner << ", "
- << key << ", " << context << ") added shortcut with ID " << d->currentId;
+ << keySequence << ", " << context << ") added shortcut with ID " << d->currentId;
return d->currentId;
}
@@ -180,36 +144,36 @@ int QShortcutMap::addShortcut(QObject *owner, const QKeySequence &key, Qt::Short
Returns the number of sequences removed from the map.
*/
-int QShortcutMap::removeShortcut(int id, QObject *owner, const QKeySequence &key)
+int QShortcutMap::removeShortcut(int id, QObject *owner, const QKeySequence &keySequence)
{
Q_D(QShortcutMap);
int itemsRemoved = 0;
bool allOwners = (owner == nullptr);
- bool allKeys = key.isEmpty();
+ bool allKeys = keySequence.isEmpty();
bool allIds = id == 0;
auto debug = qScopeGuard([&](){
qCDebug(lcShortcutMap).nospace()
<< "QShortcutMap::removeShortcut(" << id << ", " << owner << ", "
- << key << ") removed " << itemsRemoved << " shortcuts(s)";
+ << keySequence << ") removed " << itemsRemoved << " shortcuts(s)";
});
// Special case, remove everything
if (allOwners && allKeys && allIds) {
- itemsRemoved = d->sequences.size();
- d->sequences.clear();
+ itemsRemoved = d->shortcuts.size();
+ d->shortcuts.clear();
return itemsRemoved;
}
- int i = d->sequences.size()-1;
+ int i = d->shortcuts.size()-1;
while (i>=0)
{
- const QShortcutEntry &entry = d->sequences.at(i);
+ const QShortcutEntry &entry = d->shortcuts.at(i);
int entryId = entry.id;
if ((allOwners || entry.owner == owner)
&& (allIds || entry.id == id)
- && (allKeys || entry.keyseq == key)) {
- d->sequences.removeAt(i);
+ && (allKeys || entry.keySequence == keySequence)) {
+ d->shortcuts.removeAt(i);
++itemsRemoved;
}
if (id == entryId)
@@ -227,22 +191,22 @@ int QShortcutMap::removeShortcut(int id, QObject *owner, const QKeySequence &key
are changed.
Returns the number of sequences which are matched in the map.
*/
-int QShortcutMap::setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &key)
+int QShortcutMap::setShortcutEnabled(bool enable, int id, QObject *owner, const QKeySequence &keySequence)
{
Q_D(QShortcutMap);
int itemsChanged = 0;
bool allOwners = (owner == nullptr);
- bool allKeys = key.isEmpty();
+ bool allKeys = keySequence.isEmpty();
bool allIds = id == 0;
- int i = d->sequences.size()-1;
+ int i = d->shortcuts.size()-1;
while (i>=0)
{
- QShortcutEntry entry = d->sequences.at(i);
+ QShortcutEntry entry = d->shortcuts.at(i);
if ((allOwners || entry.owner == owner)
&& (allIds || entry.id == id)
- && (allKeys || entry.keyseq == key)) {
- d->sequences[i].enabled = enable;
+ && (allKeys || entry.keySequence == keySequence)) {
+ d->shortcuts[i].enabled = enable;
++itemsChanged;
}
if (id == entry.id)
@@ -251,7 +215,7 @@ int QShortcutMap::setShortcutEnabled(bool enable, int id, QObject *owner, const
}
qCDebug(lcShortcutMap).nospace()
<< "QShortcutMap::setShortcutEnabled(" << enable << ", " << id << ", "
- << owner << ", " << key << ") = " << itemsChanged;
+ << owner << ", " << keySequence << ") = " << itemsChanged;
return itemsChanged;
}
@@ -263,22 +227,22 @@ int QShortcutMap::setShortcutEnabled(bool enable, int id, QObject *owner, const
are changed.
Returns the number of sequences which are matched in the map.
*/
-int QShortcutMap::setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &key)
+int QShortcutMap::setShortcutAutoRepeat(bool on, int id, QObject *owner, const QKeySequence &keySequence)
{
Q_D(QShortcutMap);
int itemsChanged = 0;
bool allOwners = (owner == nullptr);
- bool allKeys = key.isEmpty();
+ bool allKeys = keySequence.isEmpty();
bool allIds = id == 0;
- int i = d->sequences.size()-1;
+ int i = d->shortcuts.size()-1;
while (i>=0)
{
- QShortcutEntry entry = d->sequences.at(i);
+ QShortcutEntry entry = d->shortcuts.at(i);
if ((allOwners || entry.owner == owner)
&& (allIds || entry.id == id)
- && (allKeys || entry.keyseq == key)) {
- d->sequences[i].autorepeat = on;
+ && (allKeys || entry.keySequence == keySequence)) {
+ d->shortcuts[i].autorepeat = on;
++itemsChanged;
}
if (id == entry.id)
@@ -287,7 +251,7 @@ int QShortcutMap::setShortcutAutoRepeat(bool on, int id, QObject *owner, const Q
}
qCDebug(lcShortcutMap).nospace()
<< "QShortcutMap::setShortcutAutoRepeat(" << on << ", " << id << ", "
- << owner << ", " << key << ") = " << itemsChanged;
+ << owner << ", " << keySequence << ") = " << itemsChanged;
return itemsChanged;
}
@@ -341,7 +305,7 @@ bool QShortcutMap::tryShortcut(QKeyEvent *e)
case QKeySequence::ExactMatch: {
// Save number of identical matches before dispatching
// to keep QShortcutMap and tryShortcut reentrant.
- const int identicalMatches = d->identicals.count();
+ const int identicalMatches = d->identicals.size();
resetState();
dispatchEvent(e);
// If there are no identicals we've only found disabled shortcuts, and
@@ -349,8 +313,7 @@ bool QShortcutMap::tryShortcut(QKeyEvent *e)
return identicalMatches > 0;
}
}
- Q_UNREACHABLE();
- return false;
+ Q_UNREACHABLE_RETURN(false);
}
/*! \internal
@@ -396,17 +359,18 @@ QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e)
/*! \internal
- Determines if an enabled shortcut has a matcing key sequence.
+ Determines if an enabled shortcut has a matching key sequence.
*/
bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const
{
Q_D(const QShortcutMap);
QShortcutEntry entry(seq); // needed for searching
- const auto itEnd = d->sequences.cend();
- auto it = std::lower_bound(d->sequences.cbegin(), itEnd, entry);
+ const auto itEnd = d->shortcuts.cend();
+ auto it = std::lower_bound(d->shortcuts.cbegin(), itEnd, entry);
for (;it != itEnd; ++it) {
- if (matches(entry.keyseq, (*it).keyseq) == QKeySequence::ExactMatch && (*it).correctContext() && (*it).enabled) {
+ if (entry.keySequence.matches(it->keySequence) == QKeySequence::ExactMatch
+ && (*it).correctContext() && (*it).enabled) {
return true;
}
}
@@ -425,15 +389,15 @@ bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const
QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifiers)
{
Q_D(QShortcutMap);
- if (!d->sequences.count())
+ if (!d->shortcuts.size())
return QKeySequence::NoMatch;
createNewSequences(e, d->newEntries, ignoredModifiers);
- qCDebug(lcShortcutMap) << "Possible shortcut key sequences:" << d->newEntries;
+ qCDebug(lcShortcutMap) << "Possible input sequences:" << d->newEntries;
// Should never happen
if (d->newEntries == d->currentSequences) {
- Q_ASSERT_X(e->key() != Qt::Key_unknown || e->text().length(),
+ Q_ASSERT_X(e->key() != Qt::Key_unknown || e->text().size(),
"QShortcutMap::find", "New sequence to find identical to previous");
return QKeySequence::NoMatch;
}
@@ -444,26 +408,33 @@ QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifier
bool partialFound = false;
bool identicalDisabledFound = false;
QList<QKeySequence> okEntries;
- int result = QKeySequence::NoMatch;
- for (int i = d->newEntries.count()-1; i >= 0 ; --i) {
+ QKeySequence::SequenceMatch result = QKeySequence::NoMatch;
+ for (int i = d->newEntries.size()-1; i >= 0 ; --i) {
QShortcutEntry entry(d->newEntries.at(i)); // needed for searching
- const auto itEnd = d->sequences.constEnd();
- auto it = std::lower_bound(d->sequences.constBegin(), itEnd, entry);
+ qCDebug(lcShortcutMap) << "Looking for shortcuts matching" << entry.keySequence;
+
+ QKeySequence::SequenceMatch bestMatchForEntry = QKeySequence::NoMatch;
- int oneKSResult = QKeySequence::NoMatch;
- int tempRes = QKeySequence::NoMatch;
- do {
- if (it == itEnd)
+ const auto itEnd = d->shortcuts.constEnd();
+ auto it = std::lower_bound(d->shortcuts.constBegin(), itEnd, entry);
+ for (; it != itEnd; ++it) {
+ QKeySequence::SequenceMatch match = entry.keySequence.matches(it->keySequence);
+ qCDebug(lcShortcutMap) << " -" << match << "for shortcut" << it->keySequence;
+
+ // If we got a valid match, there might still be more keys to check against,
+ // but if we get no match, we know that there are no more possible matches.
+ if (match == QKeySequence::NoMatch)
break;
- tempRes = matches(entry.keyseq, (*it).keyseq);
- oneKSResult = qMax(oneKSResult, tempRes);
- if (tempRes != QKeySequence::NoMatch && (*it).correctContext()) {
- if (tempRes == QKeySequence::ExactMatch) {
+
+ bestMatchForEntry = qMax(bestMatchForEntry, match);
+
+ if ((*it).correctContext()) {
+ if (match == QKeySequence::ExactMatch) {
if ((*it).enabled)
d->identicals.append(&*it);
else
identicalDisabledFound = true;
- } else if (tempRes == QKeySequence::PartialMatch) {
+ } else if (match == QKeySequence::PartialMatch) {
// We don't need partials, if we have identicals
if (d->identicals.size())
break;
@@ -471,20 +442,18 @@ QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifier
// key events when all partials are disabled!
partialFound |= (*it).enabled;
}
+ } else {
+ qCDebug(lcShortcutMap) << " - But context was not correct";
}
- ++it;
- // If we got a valid match on this run, there might still be more keys to check against,
- // so we'll loop once more. If we get NoMatch, there's guaranteed no more possible
- // matches in the shortcutmap.
- } while (tempRes != QKeySequence::NoMatch);
+ }
// If the type of match improves (ergo, NoMatch->Partial, or Partial->Exact), clear the
// previous list. If this match is equal or better than the last match, append to the list
- if (oneKSResult > result) {
+ if (bestMatchForEntry > result) {
okEntries.clear();
qCDebug(lcShortcutMap) << "Found better match (" << d->newEntries << "), clearing key sequence list";
}
- if (oneKSResult && oneKSResult >= result) {
+ if (bestMatchForEntry && bestMatchForEntry >= result) {
okEntries << d->newEntries.at(i);
qCDebug(lcShortcutMap) << "Added ok key sequence" << d->newEntries;
}
@@ -503,7 +472,7 @@ QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifier
if (result != QKeySequence::NoMatch)
d->currentSequences = okEntries;
qCDebug(lcShortcutMap) << "Returning shortcut match == " << result;
- return QKeySequence::SequenceMatch(result);
+ return result;
}
/*! \internal
@@ -524,14 +493,14 @@ void QShortcutMap::clearSequence(QList<QKeySequence> &ksl)
void QShortcutMap::createNewSequences(QKeyEvent *e, QList<QKeySequence> &ksl, int ignoredModifiers)
{
Q_D(QShortcutMap);
- QList<int> possibleKeys = QKeyMapper::possibleKeys(e);
+ QList<QKeyCombination> possibleKeys = QKeyMapper::possibleKeys(e);
qCDebug(lcShortcutMap) << "Creating new sequences for" << e
<< "with ignoredModifiers=" << Qt::KeyboardModifiers(ignoredModifiers);
- int pkTotal = possibleKeys.count();
+ int pkTotal = possibleKeys.size();
if (!pkTotal)
return;
- int ssActual = d->currentSequences.count();
+ int ssActual = d->currentSequences.size();
int ssTotal = qMax(1, ssActual);
// Resize to possible permutations of the current sequence(s).
ksl.resize(pkTotal * ssTotal);
@@ -553,46 +522,13 @@ void QShortcutMap::createNewSequences(QKeyEvent *e, QList<QKeySequence> &ksl, in
curKsl.setKey(QKeyCombination::fromCombined(0), 2);
curKsl.setKey(QKeyCombination::fromCombined(0), 3);
}
- curKsl.setKey(QKeyCombination::fromCombined(possibleKeys.at(pkNum) & ~ignoredModifiers), index);
+ const int key = possibleKeys.at(pkNum).toCombined();
+ curKsl.setKey(QKeyCombination::fromCombined(key & ~ignoredModifiers), index);
}
}
}
/*! \internal
- Basically the same function as QKeySequence::matches(const QKeySequence &seq) const
- only that is specially handles Key_hyphen as Key_Minus, as people mix these up all the time and
- they conceptually the same.
-*/
-QKeySequence::SequenceMatch QShortcutMap::matches(const QKeySequence &seq1,
- const QKeySequence &seq2) const
-{
- uint userN = seq1.count(),
- seqN = seq2.count();
-
- if (userN > seqN)
- return QKeySequence::NoMatch;
-
- // If equal in length, we have a potential ExactMatch sequence,
- // else we already know it can only be partial.
- QKeySequence::SequenceMatch match = (userN == seqN
- ? QKeySequence::ExactMatch
- : QKeySequence::PartialMatch);
-
- for (uint i = 0; i < userN; ++i) {
- int userKey = seq1[i].toCombined(),
- sequenceKey = seq2[i].toCombined();
- if ((userKey & Qt::Key_unknown) == Qt::Key_hyphen)
- userKey = (userKey & Qt::KeyboardModifierMask) | Qt::Key_Minus;
- if ((sequenceKey & Qt::Key_unknown) == Qt::Key_hyphen)
- sequenceKey = (sequenceKey & Qt::KeyboardModifierMask) | Qt::Key_Minus;
- if (userKey != sequenceKey)
- return QKeySequence::NoMatch;
- }
- return match;
-}
-
-
-/*! \internal
Converts keyboard button states into modifier states
*/
int QShortcutMap::translateModifiers(Qt::KeyboardModifiers modifiers)
@@ -627,7 +563,7 @@ void QShortcutMap::dispatchEvent(QKeyEvent *e)
if (!d->identicals.size())
return;
- const QKeySequence &curKey = d->identicals.at(0)->keyseq;
+ const QKeySequence &curKey = d->identicals.at(0)->keySequence;
if (d->prevSequence != curKey) {
d->ambigCount = 0;
d->prevSequence = curKey;
@@ -657,16 +593,16 @@ void QShortcutMap::dispatchEvent(QKeyEvent *e)
if (lcShortcutMap().isDebugEnabled()) {
if (ambiguousShortcuts.size() > 1) {
qCDebug(lcShortcutMap) << "The following shortcuts are about to be activated ambiguously:";
- for (const QShortcutEntry *entry : qAsConst(ambiguousShortcuts))
- qCDebug(lcShortcutMap).nospace() << "- " << entry->keyseq << " (belonging to " << entry->owner << ")";
+ for (const QShortcutEntry *entry : std::as_const(ambiguousShortcuts))
+ qCDebug(lcShortcutMap).nospace() << "- " << entry->keySequence << " (belonging to " << entry->owner << ")";
}
qCDebug(lcShortcutMap).nospace()
<< "QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\""
- << next->keyseq.toString() << "\", " << next->id << ", "
+ << next->keySequence.toString() << "\", " << next->id << ", "
<< static_cast<bool>(enabledShortcuts>1) << ") to object(" << next->owner << ')';
}
- QShortcutEvent se(next->keyseq, next->id, enabledShortcuts>1);
+ QShortcutEvent se(next->keySequence, next->id, enabledShortcuts > 1);
QCoreApplication::sendEvent(const_cast<QObject *>(next->owner), &se);
}
@@ -674,7 +610,7 @@ QList<QKeySequence> QShortcutMap::keySequences(bool getAll) const
{
Q_D(const QShortcutMap);
QList<QKeySequence> keys;
- for (auto sequence : d->sequences) {
+ for (auto sequence : d->shortcuts) {
bool addSequence = false;
if (sequence.enabled) {
if (getAll || sequence.context == Qt::ApplicationShortcut ||
@@ -703,7 +639,7 @@ QList<QKeySequence> QShortcutMap::keySequences(bool getAll) const
}
}
if (addSequence)
- keys << sequence.keyseq;
+ keys << sequence.keySequence;
}
}
return keys;
@@ -718,8 +654,8 @@ QList<QKeySequence> QShortcutMap::keySequences(bool getAll) const
void QShortcutMap::dumpMap() const
{
Q_D(const QShortcutMap);
- for (int i = 0; i < d->sequences.size(); ++i)
- qDebug().nospace() << &(d->sequences.at(i));
+ for (int i = 0; i < d->shortcuts.size(); ++i)
+ qDebug().nospace() << &(d->shortcuts.at(i));
}
#endif
diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h
index 287549ea3a..26d2b5301c 100644
--- a/src/gui/kernel/qshortcutmap_p.h
+++ b/src/gui/kernel/qshortcutmap_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSHORTCUTMAP_P_H
#define QSHORTCUTMAP_P_H
@@ -98,7 +62,6 @@ private:
void dispatchEvent(QKeyEvent *e);
QKeySequence::SequenceMatch find(QKeyEvent *e, int ignoredModifiers = 0);
- QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const;
QList<const QShortcutEntry *> matches() const;
void createNewSequences(QKeyEvent *e, QList<QKeySequence> &ksl, int ignoredModifiers);
void clearSequence(QList<QKeySequence> &ksl);
diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp
index a02efd5a7a..a90e8dd33c 100644
--- a/src/gui/kernel/qsimpledrag.cpp
+++ b/src/gui/kernel/qsimpledrag.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsimpledrag_p.h"
@@ -70,9 +34,10 @@ Q_LOGGING_CATEGORY(lcDnd, "qt.gui.dnd")
static QWindow* topLevelAt(const QPoint &pos)
{
- QWindowList list = QGuiApplication::topLevelWindows();
- for (int i = list.count()-1; i >= 0; --i) {
- QWindow *w = list.at(i);
+ const QWindowList list = QGuiApplication::topLevelWindows();
+ const auto crend = list.crend();
+ for (auto it = list.crbegin(); it != crend; ++it) {
+ QWindow *w = *it;
if (w->isVisible() && w->handle() && w->geometry().contains(pos) && !qobject_cast<QShapedPixmapWindow*>(w))
return w;
}
@@ -160,6 +125,7 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
}
case QEvent::MouseButtonRelease:
{
+ QPointer<QObject> objGuard(o);
disableEventFilter();
if (canDrop()) {
QPoint nativePosition = getNativeMousePos(e, m_drag_icon_window);
@@ -169,6 +135,8 @@ bool QBasicDrag::eventFilter(QObject *o, QEvent *e)
cancel();
}
exitDndEventLoop();
+ if (!objGuard)
+ return true;
// If a QShapedPixmapWindow (drag feedback) is being dragged along, the
// mouse event's localPos() will be relative to that, which is useless.
@@ -342,7 +310,7 @@ static inline QPoint fromNativeGlobalPixels(const QPoint &point)
#ifndef QT_NO_HIGHDPISCALING
QPoint res = point;
if (QHighDpiScaling::isActive()) {
- for (const QScreen *s : qAsConst(QGuiApplicationPrivate::screen_list)) {
+ for (const QScreen *s : std::as_const(QGuiApplicationPrivate::screen_list)) {
if (s->handle()->geometry().contains(point)) {
res = QHighDpi::fromNativePixels(point, s);
break;
diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h
index 4409deb1da..32ba1cef6f 100644
--- a/src/gui/kernel/qsimpledrag_p.h
+++ b/src/gui/kernel/qsimpledrag_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSIMPLEDRAG_P_H
#define QSIMPLEDRAG_P_H
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 7b3c70c51b..5029701f24 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -1,43 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qstylehints.h>
+#include "qstylehints_p.h"
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformtheme.h>
#include <private/qguiapplication_p.h>
@@ -79,25 +44,6 @@ static inline QVariant themeableHint(QPlatformTheme::ThemeHint th)
return QPlatformTheme::defaultThemeHint(th);
}
-class QStyleHintsPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QStyleHints)
-public:
- int m_mouseDoubleClickInterval = -1;
- int m_mousePressAndHoldInterval = -1;
- int m_startDragDistance = -1;
- int m_startDragTime = -1;
- int m_keyboardInputInterval = -1;
- int m_cursorFlashTime = -1;
- int m_tabFocusBehavior = -1;
- int m_uiEffects = -1;
- int m_showShortcutsInContextMenus = -1;
- int m_wheelScrollLines = -1;
- int m_mouseQuickSelectionThreshold = -1;
- int m_mouseDoubleClickDistance = -1;
- int m_touchDoubleTapDistance = -1;
-};
-
/*!
\class QStyleHints
\since 5.0
@@ -107,11 +53,10 @@ public:
An object of this class, obtained from QGuiApplication, provides access to certain global
user interface parameters of the current platform.
- Access is read only; typically the platform itself provides the user a way to tune these
- parameters.
-
- Access to these parameters are useful when implementing custom user interface components, in that
- they allow the components to exhibit the same behaviour and feel as other components.
+ Access to most settings is read only. The platform itself usually provides the user with
+ ways to tune these parameters. Authors of custom user interface components should read
+ relevant settings to allow the components to exhibit the same behavior and feel as other
+ components.
\sa QGuiApplication::styleHints()
*/
@@ -159,7 +104,7 @@ int QStyleHints::mouseDoubleClickDistance() const
Q_D(const QStyleHints);
return d->m_mouseDoubleClickDistance >= 0 ?
d->m_mouseDoubleClickDistance :
- themeableHint(QPlatformTheme::MouseDoubleClickDistance).toInt();
+ themeableHint(QPlatformTheme::MouseDoubleClickDistance, QPlatformIntegration::MouseDoubleClickDistance).toInt();
}
/*!
@@ -177,6 +122,18 @@ int QStyleHints::touchDoubleTapDistance() const
}
/*!
+ \property QStyleHints::colorScheme
+ \brief the color scheme of the platform theme.
+ \sa Qt::ColorScheme
+ \since 6.5
+*/
+Qt::ColorScheme QStyleHints::colorScheme() const
+{
+ Q_D(const QStyleHints);
+ return d->colorScheme();
+}
+
+/*!
Sets the \a mousePressAndHoldInterval.
\internal
\sa mousePressAndHoldInterval()
@@ -322,15 +279,29 @@ int QStyleHints::keyboardInputInterval() const
themeableHint(QPlatformTheme::KeyboardInputInterval, QPlatformIntegration::KeyboardInputInterval).toInt();
}
+#if QT_DEPRECATED_SINCE(6, 5)
/*!
\property QStyleHints::keyboardAutoRepeatRate
\brief the rate, in events per second, in which additional repeated key
presses will automatically be generated if a key is being held down.
+ \deprecated [6.5] Use keyboardAutoRepeatRateF() instead
*/
int QStyleHints::keyboardAutoRepeatRate() const
{
return themeableHint(QPlatformTheme::KeyboardAutoRepeatRate, QPlatformIntegration::KeyboardAutoRepeatRate).toInt();
}
+#endif
+
+/*!
+ \property QStyleHints::keyboardAutoRepeatRateF
+ \since 6.5
+ \brief the rate, in events per second, in which additional repeated key
+ presses will automatically be generated if a key is being held down.
+*/
+qreal QStyleHints::keyboardAutoRepeatRateF() const
+{
+ return themeableHint(QPlatformTheme::KeyboardAutoRepeatRate, QPlatformIntegration::KeyboardAutoRepeatRate).toReal();
+}
/*!
Sets the \a cursorFlashTime.
@@ -406,6 +377,8 @@ bool QStyleHints::showIsMaximized() const
Since Qt 5.13, the setShowShortcutsInContextMenus() function can be used to
override the platform default.
+
+ \sa Qt::AA_DontShowShortcutsInContextMenus
*/
bool QStyleHints::showShortcutsInContextMenus() const
{
@@ -476,7 +449,7 @@ bool QStyleHints::useRtlExtensions() const
*/
bool QStyleHints::setFocusOnTouchRelease() const
{
- return hint(QPlatformIntegration::SetFocusOnTouchRelease).toBool();
+ return themeableHint(QPlatformTheme::SetFocusOnTouchRelease, QPlatformIntegration::SetFocusOnTouchRelease).toBool();
}
/*!
@@ -620,4 +593,31 @@ int QStyleHints::mouseQuickSelectionThreshold() const
return themeableHint(QPlatformTheme::MouseQuickSelectionThreshold, QPlatformIntegration::MouseQuickSelectionThreshold).toInt();
}
+/*!
+ \internal
+ QStyleHintsPrivate::updateColorScheme - set a new color scheme.
+
+ This function is called by the QPA plugin when the system theme changes. This in
+ turn might be the result of an explicit request of a color scheme via setColorScheme.
+
+ Set \a colorScheme as the new color scheme of the QStyleHints.
+ The colorSchemeChanged signal will be emitted if present and new color scheme differ.
+ */
+void QStyleHintsPrivate::updateColorScheme(Qt::ColorScheme colorScheme)
+{
+ if (m_colorScheme == colorScheme)
+ return;
+ m_colorScheme = colorScheme;
+ Q_Q(QStyleHints);
+ emit q->colorSchemeChanged(colorScheme);
+}
+
+QStyleHintsPrivate *QStyleHintsPrivate::get(QStyleHints *q)
+{
+ Q_ASSERT(q);
+ return q->d_func();
+}
+
QT_END_NAMESPACE
+
+#include "moc_qstylehints.cpp"
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index c2d5d87d31..969bec4b35 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTYLEHINTS_H
#define QSTYLEHINTS_H
@@ -55,7 +19,10 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_DECLARE_PRIVATE(QStyleHints)
Q_PROPERTY(int cursorFlashTime READ cursorFlashTime NOTIFY cursorFlashTimeChanged FINAL)
Q_PROPERTY(qreal fontSmoothingGamma READ fontSmoothingGamma STORED false CONSTANT FINAL)
+#if QT_DEPRECATED_SINCE(6, 5)
Q_PROPERTY(int keyboardAutoRepeatRate READ keyboardAutoRepeatRate STORED false CONSTANT FINAL)
+#endif
+ Q_PROPERTY(qreal keyboardAutoRepeatRateF READ keyboardAutoRepeatRateF STORED false CONSTANT FINAL)
Q_PROPERTY(int keyboardInputInterval READ keyboardInputInterval
NOTIFY keyboardInputIntervalChanged FINAL)
Q_PROPERTY(int mouseDoubleClickInterval READ mouseDoubleClickInterval
@@ -85,6 +52,7 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_PROPERTY(int mouseDoubleClickDistance READ mouseDoubleClickDistance STORED false CONSTANT
FINAL)
Q_PROPERTY(int touchDoubleTapDistance READ touchDoubleTapDistance STORED false CONSTANT FINAL)
+ Q_PROPERTY(Qt::ColorScheme colorScheme READ colorScheme NOTIFY colorSchemeChanged FINAL)
public:
void setMouseDoubleClickInterval(int mouseDoubleClickInterval);
@@ -100,7 +68,11 @@ public:
int startDragVelocity() const;
void setKeyboardInputInterval(int keyboardInputInterval);
int keyboardInputInterval() const;
+#if QT_DEPRECATED_SINCE(6, 5)
+ QT_DEPRECATED_VERSION_X_6_5("Use keyboardAutoRepeatRateF() instead")
int keyboardAutoRepeatRate() const;
+#endif
+ qreal keyboardAutoRepeatRateF() const;
void setCursorFlashTime(int cursorFlashTime);
int cursorFlashTime() const;
bool showIsFullScreen() const;
@@ -121,6 +93,7 @@ public:
void setWheelScrollLines(int scrollLines);
void setMouseQuickSelectionThreshold(int threshold);
int mouseQuickSelectionThreshold() const;
+ Qt::ColorScheme colorScheme() const;
Q_SIGNALS:
void cursorFlashTimeChanged(int cursorFlashTime);
@@ -134,6 +107,7 @@ Q_SIGNALS:
void showShortcutsInContextMenusChanged(bool);
void wheelScrollLinesChanged(int scrollLines);
void mouseQuickSelectionThresholdChanged(int threshold);
+ void colorSchemeChanged(Qt::ColorScheme colorScheme);
private:
friend class QGuiApplication;
diff --git a/src/gui/kernel/qstylehints_p.h b/src/gui/kernel/qstylehints_p.h
new file mode 100644
index 0000000000..2b3979512a
--- /dev/null
+++ b/src/gui/kernel/qstylehints_p.h
@@ -0,0 +1,54 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSTYLEHINTS_P_H
+#define QSTYLEHINTS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qpa/qplatformintegration.h>
+#include <QPalette>
+#include <private/qguiapplication_p.h>
+#include "qstylehints.h"
+
+QT_BEGIN_NAMESPACE
+
+class QStyleHintsPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QStyleHints)
+public:
+ int m_mouseDoubleClickInterval = -1;
+ int m_mousePressAndHoldInterval = -1;
+ int m_startDragDistance = -1;
+ int m_startDragTime = -1;
+ int m_keyboardInputInterval = -1;
+ int m_cursorFlashTime = -1;
+ int m_tabFocusBehavior = -1;
+ int m_uiEffects = -1;
+ int m_showShortcutsInContextMenus = -1;
+ int m_wheelScrollLines = -1;
+ int m_mouseQuickSelectionThreshold = -1;
+ int m_mouseDoubleClickDistance = -1;
+ int m_touchDoubleTapDistance = -1;
+
+ Qt::ColorScheme colorScheme() const { return m_colorScheme; }
+ void updateColorScheme(Qt::ColorScheme colorScheme);
+
+ static QStyleHintsPrivate *get(QStyleHints *q);
+
+private:
+ Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/kernel/qsurface.cpp b/src/gui/kernel/qsurface.cpp
index 5a293e4250..c00cf55a09 100644
--- a/src/gui/kernel/qsurface.cpp
+++ b/src/gui/kernel/qsurface.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsurface.h"
#include "qopenglcontext.h"
@@ -44,6 +8,7 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN_TAGGED(QSurface*, QSurface_ptr)
/*!
\class QSurface
@@ -65,13 +30,12 @@ QT_BEGIN_NAMESPACE
\value Offscreen The surface is an instance of QOffscreenSurface.
*/
-
/*!
\enum QSurface::SurfaceType
The SurfaceType enum describes what type of surface this is.
- \value RasterSurface The surface is is composed of pixels and can be rendered to using
+ \value RasterSurface The surface is composed of pixels and can be rendered to using
a software rasterizer like Qt's raster paint engine.
\value OpenGLSurface The surface is an OpenGL compatible surface and can be used
in conjunction with QOpenGLContext.
@@ -83,14 +47,13 @@ QT_BEGIN_NAMESPACE
\value VulkanSurface The surface is a Vulkan compatible surface and can be used
in conjunction with the Vulkan graphics API.
\value MetalSurface The surface is a Metal compatible surface and can be used
- in conjunction with Apple's Metal graphics API. This surface type is supported
- on macOS only.
+ in conjunction with Apple's Metal graphics API. This surface type is only supported
+ on \macos and iOS.
\value Direct3DSurface The surface is a Direct 3D 11 and 12 compatible
surface and can be used in conjunction with the DXGI and Direct3D APIs. This
- surface type is supported on Windows only.
+ surface type is only supported on Windows.
*/
-
/*!
\fn QSurfaceFormat QSurface::format() const
@@ -162,3 +125,5 @@ QSurface::SurfaceClass QSurface::surfaceClass() const
QT_END_NAMESPACE
+#include "moc_qsurface.cpp"
+
diff --git a/src/gui/kernel/qsurface.h b/src/gui/kernel/qsurface.h
index 4ba1d4b589..ef70beab21 100644
--- a/src/gui/kernel/qsurface.h
+++ b/src/gui/kernel/qsurface.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSURFACE_H
#define QSURFACE_H
@@ -96,6 +60,6 @@ protected:
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QSurface*)
+QT_DECL_METATYPE_EXTERN_TAGGED(QSurface*, QSurface_ptr, Q_GUI_EXPORT)
#endif //QSURFACE_H
diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp
index e62f87b167..74add6e973 100644
--- a/src/gui/kernel/qsurfaceformat.cpp
+++ b/src/gui/kernel/qsurfaceformat.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsurfaceformat.h"
@@ -753,8 +717,10 @@ void QSurfaceFormat::setColorSpace(const QColorSpace &colorSpace)
}
}
+#if QT_DEPRECATED_SINCE(6, 0)
/*!
\overload
+ \deprecated [6.0] Use setColorSpace(QColorSpace) instead.
Sets the colorspace to one of the predefined values.
@@ -773,6 +739,7 @@ void QSurfaceFormat::setColorSpace(ColorSpace colorSpace)
break;
}
}
+#endif // QT_DEPRECATED_SINCE(6, 0)
/*!
\return the color space.
@@ -798,7 +765,7 @@ Q_GLOBAL_STATIC(QSurfaceFormat, qt_default_surface_format)
question's own setFormat() function. However, it is often more convenient to
set the format for all windows once at the start of the application. It also
guarantees proper behavior in cases where shared contexts are required,
- because settings the format via this function guarantees that all contexts
+ because setting the format via this function guarantees that all contexts
and surfaces, even the ones created internally by Qt, will use the same
format.
@@ -900,3 +867,5 @@ QDebug operator<<(QDebug dbg, const QSurfaceFormat &f)
#endif
QT_END_NAMESPACE
+
+#include "moc_qsurfaceformat.cpp"
diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h
index dfe55a338d..07ee1cc07d 100644
--- a/src/gui/kernel/qsurfaceformat.h
+++ b/src/gui/kernel/qsurfaceformat.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSURFACEFORMAT_H
#define QSURFACEFORMAT_H
diff --git a/src/gui/kernel/qt_gui_pch.h b/src/gui/kernel/qt_gui_pch.h
index e7cccba027..fbde1cf9a2 100644
--- a/src/gui/kernel/qt_gui_pch.h
+++ b/src/gui/kernel/qt_gui_pch.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
* This is a precompiled header file for use in Xcode / Mac GCC /
diff --git a/src/gui/kernel/qtestsupport_gui.cpp b/src/gui/kernel/qtestsupport_gui.cpp
index ab48111fb5..869eddce49 100644
--- a/src/gui/kernel/qtestsupport_gui.cpp
+++ b/src/gui/kernel/qtestsupport_gui.cpp
@@ -1,43 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qguiapplication_p.h>
+#include <private/qeventpoint_p.h>
#include <qpa/qplatformintegration.h>
@@ -53,11 +18,18 @@ QT_BEGIN_NAMESPACE
/*!
\since 5.0
- Waits for \a timeout milliseconds or until the \a window is active.
+ Returns \c true, if \a window is active within \a timeout milliseconds. Otherwise returns \c false.
- Returns \c true if \c window is active within \a timeout milliseconds, otherwise returns \c false.
+ The method is useful in tests that call QWindow::show() and rely on the window actually being
+ active (i.e. being visible and having focus) before proceeding.
- \sa qWaitForWindowExposed(), QWindow::isActive()
+ \note The method will time out and return \c false if another window prevents \a window from
+ becoming active.
+
+ \note Since focus is an exclusive property, \a window may loose its focus to another window at
+ any time - even after the method has returned \c true.
+
+ \sa qWaitForWindowExposed(), qWaitForWindowFocused(), QWindow::isActive()
*/
Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout)
{
@@ -73,17 +45,37 @@ Q_GUI_EXPORT bool QTest::qWaitForWindowActive(QWindow *window, int timeout)
}
/*!
+ \since 6.7
+
+ Returns \c true, if \a window is the focus window within \a timeout. Otherwise returns \c false.
+
+ The method is useful in tests that call QWindow::show() and rely on the window
+ having focus (for receiving keyboard events e.g.) before proceeding.
+
+ \note The method will time out and return \c false if another window prevents \a window from
+ becoming focused.
+
+ \note Since focus is an exclusive property, \a window may loose its focus to another window at
+ any time - even after the method has returned \c true.
+
+ \sa qWaitForWindowExposed(), qWaitForWindowActive(), QGuiApplication::focusWindow()
+*/
+Q_GUI_EXPORT bool QTest::qWaitForWindowFocused(QWindow *window, QDeadlineTimer timeout)
+{
+ return QTest::qWaitFor([&]() { return qGuiApp->focusWindow() == window; }, timeout);
+}
+
+/*!
\since 5.0
- Waits for \a timeout milliseconds or until the \a window is exposed.
- Returns \c true if \c window is exposed within \a timeout milliseconds, otherwise returns \c false.
+ Returns \c true, if \a window is exposed within \a timeout milliseconds. Otherwise returns \c false.
- This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
- time after being asked to show itself on the screen.
+ The method is useful in tests that call QWindow::show() and rely on the window actually being
+ being visible before proceeding.
- Note that a window that is mapped to screen may still not be considered exposed if the window client
- area is completely covered by other windows, or if the window is otherwise not visible. This function
- will then time out when waiting for such a window.
+ \note A window mapped to screen may still not be considered exposed, if the window client area is
+ not visible, e.g. because it is completely covered by other windows.
+ In such cases, the method will time out and return \c false.
\sa qWaitForWindowActive(), QWindow::isExposed()
*/
@@ -97,47 +89,49 @@ namespace QTest {
QTouchEventSequence::~QTouchEventSequence()
{
if (commitWhenDestroyed)
- commit();
+ QTouchEventSequence::commit();
}
QTouchEventSequence& QTouchEventSequence::press(int touchId, const QPoint &pt, QWindow *window)
{
- auto &p = QMutableEventPoint::from(point(touchId));
- p.setGlobalPosition(mapToScreen(window, pt));
- p.setState(QEventPoint::State::Pressed);
+ auto &p = point(touchId);
+ QMutableEventPoint::setGlobalPosition(p, mapToScreen(window, pt));
+ QMutableEventPoint::setState(p, QEventPoint::State::Pressed);
return *this;
}
QTouchEventSequence& QTouchEventSequence::move(int touchId, const QPoint &pt, QWindow *window)
{
- auto &p = QMutableEventPoint::from(point(touchId));
- p.setGlobalPosition(mapToScreen(window, pt));
- p.setState(QEventPoint::State::Updated);
+ auto &p = point(touchId);
+ QMutableEventPoint::setGlobalPosition(p, mapToScreen(window, pt));
+ QMutableEventPoint::setState(p, QEventPoint::State::Updated);
return *this;
}
QTouchEventSequence& QTouchEventSequence::release(int touchId, const QPoint &pt, QWindow *window)
{
- auto &p = QMutableEventPoint::from(point(touchId));
- p.setGlobalPosition(mapToScreen(window, pt));
- p.setState(QEventPoint::State::Released);
+ auto &p = point(touchId);
+ QMutableEventPoint::setGlobalPosition(p, mapToScreen(window, pt));
+ QMutableEventPoint::setState(p, QEventPoint::State::Released);
return *this;
}
QTouchEventSequence& QTouchEventSequence::stationary(int touchId)
{
- auto &p = QMutableEventPoint::from(pointOrPreviousPoint(touchId));
- p.setState(QEventPoint::State::Stationary);
+ auto &p = pointOrPreviousPoint(touchId);
+ QMutableEventPoint::setState(p, QEventPoint::State::Stationary);
return *this;
}
-void QTouchEventSequence::commit(bool processEvents)
+bool QTouchEventSequence::commit(bool processEvents)
{
if (points.isEmpty())
- return;
- QThread::msleep(1);
+ return false;
+ QThread::sleep(std::chrono::milliseconds{1});
+ bool ret = false;
if (targetWindow)
- qt_handleTouchEvent(targetWindow, device, points.values());
+ ret = qt_handleTouchEventv2(targetWindow, device, points.values());
if (processEvents)
QCoreApplication::processEvents();
previousPoints = points;
points.clear();
+ return ret;
}
QTouchEventSequence::QTouchEventSequence(QWindow *window, QPointingDevice *aDevice, bool autoCommit)
diff --git a/src/gui/kernel/qtestsupport_gui.h b/src/gui/kernel/qtestsupport_gui.h
index ac4271db46..e5b2a88455 100644
--- a/src/gui/kernel/qtestsupport_gui.h
+++ b/src/gui/kernel/qtestsupport_gui.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTESTSUPPORT_GUI_H
#define QTESTSUPPORT_GUI_H
@@ -48,13 +12,18 @@ QT_BEGIN_NAMESPACE
class QWindow;
-Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, const QPointingDevice *device,
+Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *w, const QPointingDevice *device,
+ const QList<QEventPoint> &points,
+ Qt::KeyboardModifiers mods = Qt::NoModifier);
+
+Q_GUI_EXPORT bool qt_handleTouchEventv2(QWindow *w, const QPointingDevice *device,
const QList<QEventPoint> &points,
Qt::KeyboardModifiers mods = Qt::NoModifier);
namespace QTest {
[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowActive(QWindow *window, int timeout = 5000);
+[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowFocused(QWindow *widget, QDeadlineTimer timeout = std::chrono::seconds{5});
[[nodiscard]] Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, int timeout = 5000);
Q_GUI_EXPORT QPointingDevice * createTouchDevice(QInputDevice::DeviceType devType = QInputDevice::DeviceType::TouchScreen,
@@ -69,7 +38,7 @@ public:
QTouchEventSequence& release(int touchId, const QPoint &pt, QWindow *window = nullptr);
virtual QTouchEventSequence& stationary(int touchId);
- virtual void commit(bool processEvents = true);
+ virtual bool commit(bool processEvents = true);
protected:
QTouchEventSequence(QWindow *window, QPointingDevice *aDevice, bool autoCommit);
diff --git a/src/gui/kernel/qtguiglobal.h b/src/gui/kernel/qtguiglobal.h
index 2303d75466..cea6448755 100644
--- a/src/gui/kernel/qtguiglobal.h
+++ b/src/gui/kernel/qtguiglobal.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTGUIGLOBAL_H
#define QTGUIGLOBAL_H
diff --git a/src/gui/kernel/qtguiglobal_p.h b/src/gui/kernel/qtguiglobal_p.h
index d2c0b3c5d1..c9f341c172 100644
--- a/src/gui/kernel/qtguiglobal_p.h
+++ b/src/gui/kernel/qtguiglobal_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTGUIGLOBAL_P_H
#define QTGUIGLOBAL_P_H
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 7f6e5044cb..b40fd7e8e8 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindow.h"
@@ -54,7 +18,7 @@
#include "qwindow_p.h"
#include "qguiapplication_p.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
# include "qaccessible.h"
#endif
#include "qhighdpiscaling_p.h"
@@ -164,7 +128,7 @@ QWindow::QWindow(QScreen *targetScreen)
, QSurface(QSurface::Window)
{
Q_D(QWindow);
- d->init(targetScreen);
+ d->init(nullptr, targetScreen);
}
static QWindow *nonDesktopParent(QWindow *parent)
@@ -205,11 +169,11 @@ QWindow::QWindow(QWindow *parent)
\sa setParent()
*/
QWindow::QWindow(QWindowPrivate &dd, QWindow *parent)
- : QObject(dd, nonDesktopParent(parent))
+ : QObject(dd, nullptr)
, QSurface(QSurface::Window)
{
Q_D(QWindow);
- d->init();
+ d->init(nonDesktopParent(parent));
}
/*!
@@ -219,35 +183,74 @@ QWindow::~QWindow()
{
Q_D(QWindow);
d->destroy();
+ // Decouple from parent before window goes under
+ setParent(nullptr);
QGuiApplicationPrivate::window_list.removeAll(this);
if (!QGuiApplicationPrivate::is_app_closing)
QGuiApplicationPrivate::instance()->modalWindowList.removeOne(this);
- // focus_window is normally cleared in destroy(), but the window may in
- // some cases end up becoming the focus window again. Clear it again
- // here as a workaround. See QTBUG-75326.
+ // thse are normally cleared in destroy(), but the window may in
+ // some cases end up becoming the focus window again, or receive an enter
+ // event. Clear it again here as a workaround. See QTBUG-75326.
if (QGuiApplicationPrivate::focus_window == this)
QGuiApplicationPrivate::focus_window = nullptr;
+ if (QGuiApplicationPrivate::currentMouseWindow == this)
+ QGuiApplicationPrivate::currentMouseWindow = nullptr;
+ if (QGuiApplicationPrivate::currentMousePressWindow == this)
+ QGuiApplicationPrivate::currentMousePressWindow = nullptr;
+
+ d->isWindow = false;
}
-void QWindowPrivate::init(QScreen *targetScreen)
+QWindowPrivate::QWindowPrivate()
+ = default;
+
+QWindowPrivate::~QWindowPrivate()
+ = default;
+
+void QWindowPrivate::init(QWindow *parent, QScreen *targetScreen)
{
Q_Q(QWindow);
+ q->QObject::setParent(parent);
+
+ isWindow = true;
parentWindow = static_cast<QWindow *>(q->QObject::parent());
+ QScreen *connectScreen = targetScreen ? targetScreen : QGuiApplication::primaryScreen();
+
if (!parentWindow)
- connectToScreen(targetScreen ? targetScreen : QGuiApplication::primaryScreen());
+ connectToScreen(connectScreen);
// If your application aborts here, you are probably creating a QWindow
// before the screen list is populated.
if (Q_UNLIKELY(!parentWindow && !topLevelScreen)) {
qFatal("Cannot create window: no screens available");
- exit(1);
}
QGuiApplicationPrivate::window_list.prepend(q);
requestedFormat = QSurfaceFormat::defaultFormat();
+ devicePixelRatio = connectScreen->devicePixelRatio();
+
+ QObject::connect(q, &QWindow::screenChanged, q, [q, this](QScreen *){
+ // We may have changed scaling; trigger resize event if needed,
+ // except on Windows, where we send resize events during WM_DPICHANGED
+ // event handling. FIXME: unify DPI change handling across all platforms.
+#ifndef Q_OS_WIN
+ if (q->handle()) {
+ QWindowSystemInterfacePrivate::GeometryChangeEvent gce(q, QHighDpi::fromNativePixels(q->handle()->geometry(), q));
+ QGuiApplicationPrivate::processGeometryChangeEvent(&gce);
+ }
+#else
+ Q_UNUSED(q);
+#endif
+ updateDevicePixelRatio();
+ });
+
+ if (parentWindow) {
+ QChildWindowEvent childAddedEvent(QEvent::ChildWindowAdded, q);
+ QCoreApplication::sendEvent(parentWindow, &childAddedEvent);
+ }
}
/*!
@@ -328,7 +331,6 @@ void QWindow::setVisibility(Visibility v)
break;
default:
Q_ASSERT(false);
- break;
}
}
@@ -453,14 +455,14 @@ void QWindowPrivate::updateSiblingPosition(SiblingPosition position)
QObjectList &siblings = q->parent()->d_ptr->children;
- const int siblingCount = siblings.size() - 1;
+ const qsizetype siblingCount = siblings.size() - 1;
if (siblingCount == 0)
return;
- const int currentPosition = siblings.indexOf(q);
+ const qsizetype currentPosition = siblings.indexOf(q);
Q_ASSERT(currentPosition >= 0);
- const int targetPosition = position == PositionTop ? siblingCount : 0;
+ const qsizetype targetPosition = position == PositionTop ? siblingCount : 0;
if (currentPosition == targetPosition)
return;
@@ -468,7 +470,7 @@ void QWindowPrivate::updateSiblingPosition(SiblingPosition position)
siblings.move(currentPosition, targetPosition);
}
-inline bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const
+bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const
{
Q_Q(const QWindow);
const QScreen *oldScreen = q->screen();
@@ -476,7 +478,7 @@ inline bool QWindowPrivate::windowRecreationRequired(QScreen *newScreen) const
&& !(oldScreen && oldScreen->virtualSiblings().contains(newScreen));
}
-inline void QWindowPrivate::disconnectFromScreen()
+void QWindowPrivate::disconnectFromScreen()
{
if (topLevelScreen)
topLevelScreen = nullptr;
@@ -519,7 +521,9 @@ void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate)
}
}
-void QWindowPrivate::create(bool recursive, WId nativeHandle)
+static constexpr auto kForeignWindowId = "_q_foreignWinId";
+
+void QWindowPrivate::create(bool recursive)
{
Q_Q(QWindow);
if (platformWindow)
@@ -533,6 +537,13 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
if (q->parent())
q->parent()->create();
+ if (platformWindow) {
+ // Creating the parent window will end up creating any child window
+ // that was already visible, via setVisible. If this applies to us,
+ // we will already have a platform window at this point.
+ return;
+ }
+
// QPlatformWindow will poll geometry() during construction below. Set the
// screen here so that high-dpi scaling will use the correct scale factor.
if (q->isTopLevel()) {
@@ -540,6 +551,8 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
setTopLevelScreen(screen, false);
}
+ const WId nativeHandle = q->property(kForeignWindowId).value<WId>();
+
QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
platformWindow = nativeHandle ? platformIntegration->createForeignWindow(q, nativeHandle)
: platformIntegration->createPlatformWindow(q);
@@ -575,6 +588,8 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
QGuiApplication::sendEvent(q, &e);
+ updateDevicePixelRatio();
+
if (needsUpdate)
q->requestUpdate();
}
@@ -592,6 +607,37 @@ QRectF QWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const
return QRectF();
}
+void QWindowPrivate::setMinOrMaxSize(QSize *oldSizeMember, const QSize &size,
+ qxp::function_ref<void()> funcWidthChanged,
+ qxp::function_ref<void()> funcHeightChanged)
+{
+ Q_Q(QWindow);
+ Q_ASSERT(oldSizeMember);
+ const QSize adjustedSize =
+ size.expandedTo(QSize(0, 0)).boundedTo(QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
+ if (*oldSizeMember == adjustedSize)
+ return;
+ const bool widthChanged = adjustedSize.width() != oldSizeMember->width();
+ const bool heightChanged = adjustedSize.height() != oldSizeMember->height();
+ *oldSizeMember = adjustedSize;
+
+ if (platformWindow && q->isTopLevel())
+ platformWindow->propagateSizeHints();
+
+ if (widthChanged)
+ funcWidthChanged();
+ if (heightChanged)
+ funcHeightChanged();
+
+ // resize window if current size is outside of min and max limits
+ if (minimumSize.width() <= maximumSize.width()
+ || minimumSize.height() <= maximumSize.height()) {
+ const QSize currentSize = q->size();
+ const QSize boundedSize = currentSize.expandedTo(minimumSize).boundedTo(maximumSize);
+ q->resize(boundedSize);
+ }
+}
+
/*!
Sets the \a surfaceType of the window.
@@ -631,6 +677,13 @@ QWindow::SurfaceType QWindow::surfaceType() const
By default, the window is not visible, you must call setVisible(true), or
show() or similar to make it visible.
+ \note Hiding a window does not remove the window from the windowing system,
+ it only hides it. On windowing systems that give full screen applications a
+ dedicated desktop (such as macOS), hiding a full screen window will not remove
+ that desktop, but leave it blank. Another window from the same application
+ might be shown full screen, and will fill that desktop. Use QWindow::close to
+ completely remove a window from the windowing system.
+
\sa show()
*/
void QWindow::setVisible(bool visible)
@@ -654,7 +707,7 @@ bool QWindow::isVisible() const
into an actual native surface. However, the window remains hidden until setVisible() is called.
Note that it is not usually necessary to call this function directly, as it will be implicitly
- called by show(), setVisible(), and other functions that require access to the platform
+ called by show(), setVisible(), winId(), and other functions that require access to the platform
resources.
Call destroy() to free the platform resources if necessary.
@@ -670,6 +723,9 @@ void QWindow::create()
/*!
Returns the window's platform id.
+ \note This function will cause the platform window to be created if it is not already.
+ Returns 0, if the platform window creation failed.
+
For platforms where this id might be useful, the value returned
will uniquely represent the window inside the corresponding screen.
@@ -682,6 +738,9 @@ WId QWindow::winId() const
if (!d->platformWindow)
const_cast<QWindow *>(this)->create();
+ if (!d->platformWindow)
+ return 0;
+
return d->platformWindow->winId();
}
@@ -725,6 +784,10 @@ void QWindow::setParent(QWindow *parent)
return;
}
+ QEvent parentAboutToChangeEvent(QEvent::ParentWindowAboutToChange);
+ QCoreApplication::sendEvent(this, &parentAboutToChangeEvent);
+
+ const auto previousParent = d->parentWindow;
QObject::setParent(parent);
d->parentWindow = parent;
@@ -747,6 +810,19 @@ void QWindow::setParent(QWindow *parent)
}
QGuiApplicationPrivate::updateBlockedStatus(this);
+
+ if (previousParent) {
+ QChildWindowEvent childRemovedEvent(QEvent::ChildWindowRemoved, this);
+ QCoreApplication::sendEvent(previousParent, &childRemovedEvent);
+ }
+
+ if (parent) {
+ QChildWindowEvent childAddedEvent(QEvent::ChildWindowAdded, this);
+ QCoreApplication::sendEvent(parent, &childAddedEvent);
+ }
+
+ QEvent parentChangedEvent(QEvent::ParentWindowChange);
+ QCoreApplication::sendEvent(this, &parentChangedEvent);
}
/*!
@@ -1230,12 +1306,16 @@ bool QWindow::isExposed() const
*/
/*!
- Returns \c true if the window should appear active from a style perspective.
+ Returns \c true if the window is active.
This is the case for the window that has input focus as well as windows
that are in the same parent / transient parent chain as the focus window.
+ Typically active windows should appear active from a style perspective.
+
To get the window that currently has focus, use QGuiApplication::focusWindow().
+
+ \sa requestActivate()
*/
bool QWindow::isActive() const
{
@@ -1309,14 +1389,31 @@ Qt::ScreenOrientation QWindow::contentOrientation() const
qreal QWindow::devicePixelRatio() const
{
Q_D(const QWindow);
+ return d->devicePixelRatio;
+}
+
+/*
+ Updates the cached devicePixelRatio value by polling for a new value.
+ Sends QEvent::DevicePixelRatioChange to the window if the DPR has changed.
+ Returns true if the DPR was changed.
+*/
+bool QWindowPrivate::updateDevicePixelRatio()
+{
+ Q_Q(QWindow);
// If there is no platform window use the associated screen's devicePixelRatio,
// which typically is the primary screen and will be correct for single-display
// systems (a very common case).
- if (!d->platformWindow)
- return screen()->devicePixelRatio();
+ const qreal newDevicePixelRatio = platformWindow ?
+ platformWindow->devicePixelRatio() * QHighDpiScaling::factor(q) : q->screen()->devicePixelRatio();
- return d->platformWindow->devicePixelRatio() * QHighDpiScaling::factor(this);
+ if (newDevicePixelRatio == devicePixelRatio)
+ return false;
+
+ devicePixelRatio = newDevicePixelRatio;
+ QEvent dprChangeEvent(QEvent::DevicePixelRatioChange);
+ QGuiApplication::sendEvent(q, &dprChangeEvent);
+ return true;
}
Qt::WindowState QWindowPrivate::effectiveState(Qt::WindowStates state)
@@ -1371,8 +1468,13 @@ void QWindow::setWindowStates(Qt::WindowStates state)
if (d->platformWindow)
d->platformWindow->setWindowState(state);
+
+ auto originalEffectiveState = QWindowPrivate::effectiveState(d->windowState);
d->windowState = state;
- emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
+ auto newEffectiveState = QWindowPrivate::effectiveState(d->windowState);
+ if (newEffectiveState != originalEffectiveState)
+ emit windowStateChanged(newEffectiveState);
+
d->updateVisibility();
}
@@ -1547,17 +1649,9 @@ QSize QWindow::sizeIncrement() const
void QWindow::setMinimumSize(const QSize &size)
{
Q_D(QWindow);
- QSize adjustedSize = QSize(qBound(0, size.width(), QWINDOWSIZE_MAX), qBound(0, size.height(), QWINDOWSIZE_MAX));
- if (d->minimumSize == adjustedSize)
- return;
- QSize oldSize = d->minimumSize;
- d->minimumSize = adjustedSize;
- if (d->platformWindow && isTopLevel())
- d->platformWindow->propagateSizeHints();
- if (d->minimumSize.width() != oldSize.width())
- emit minimumWidthChanged(d->minimumSize.width());
- if (d->minimumSize.height() != oldSize.height())
- emit minimumHeightChanged(d->minimumSize.height());
+ d->setMinOrMaxSize(
+ &d->minimumSize, size, [this, d]() { emit minimumWidthChanged(d->minimumSize.width()); },
+ [this, d]() { emit minimumHeightChanged(d->minimumSize.height()); });
}
/*!
@@ -1590,20 +1684,18 @@ void QWindow::setY(int arg)
\property QWindow::width
\brief the width of the window's geometry
*/
-void QWindow::setWidth(int arg)
+void QWindow::setWidth(int w)
{
- if (width() != arg)
- resize(arg, height());
+ resize(w, height());
}
/*!
\property QWindow::height
\brief the height of the window's geometry
*/
-void QWindow::setHeight(int arg)
+void QWindow::setHeight(int h)
{
- if (height() != arg)
- resize(width(), arg);
+ resize(width(), h);
}
/*!
@@ -1634,17 +1726,9 @@ void QWindow::setMinimumHeight(int h)
void QWindow::setMaximumSize(const QSize &size)
{
Q_D(QWindow);
- QSize adjustedSize = QSize(qBound(0, size.width(), QWINDOWSIZE_MAX), qBound(0, size.height(), QWINDOWSIZE_MAX));
- if (d->maximumSize == adjustedSize)
- return;
- QSize oldSize = d->maximumSize;
- d->maximumSize = adjustedSize;
- if (d->platformWindow && isTopLevel())
- d->platformWindow->propagateSizeHints();
- if (d->maximumSize.width() != oldSize.width())
- emit maximumWidthChanged(d->maximumSize.width());
- if (d->maximumSize.height() != oldSize.height())
- emit maximumHeightChanged(d->maximumSize.height());
+ d->setMinOrMaxSize(
+ &d->maximumSize, size, [this, d]() { emit maximumWidthChanged(d->maximumSize.width()); },
+ [this, d]() { emit maximumHeightChanged(d->maximumSize.height()); });
}
/*!
@@ -1740,13 +1824,7 @@ void QWindow::setGeometry(const QRect &rect)
QScreen *newScreen = d->screenForGeometry(rect);
if (newScreen && isTopLevel())
d->setTopLevelScreen(newScreen, true);
-
- QRect nativeRect;
- if (newScreen && isTopLevel())
- nativeRect = QHighDpi::toNativePixels(rect, newScreen);
- else
- nativeRect = QHighDpi::toNativeLocalPosition(rect, newScreen);
- d->platformWindow->setGeometry(nativeRect);
+ d->platformWindow->setGeometry(QHighDpi::toNativeWindowGeometry(rect, this));
} else {
d->geometry = rect;
@@ -1877,6 +1955,10 @@ void QWindow::setFramePosition(const QPoint &point)
For interactively moving windows, see startSystemMove(). For interactively
resizing windows, see startSystemResize().
+ \note Not all windowing systems support setting or querying top level window positions.
+ On such a system, programmatically moving windows may not have any effect, and artificial
+ values may be returned for the current positions, such as \c QPoint(0, 0).
+
\sa position(), startSystemMove()
*/
void QWindow::setPosition(const QPoint &pt)
@@ -1900,6 +1982,10 @@ void QWindow::setPosition(int posx, int posy)
\fn QPoint QWindow::position() const
\brief Returns the position of the window on the desktop excluding any window frame
+ \note Not all windowing systems support setting or querying top level window positions.
+ On such a system, programmatically moving windows may not have any effect, and artificial
+ values may be returned for the current positions, such as \c QPoint(0, 0).
+
\sa setPosition()
*/
@@ -1931,11 +2017,16 @@ void QWindow::resize(int w, int h)
void QWindow::resize(const QSize &newSize)
{
Q_D(QWindow);
+
+ const QSize oldSize = size();
+ if (newSize == oldSize)
+ return;
+
d->positionPolicy = QWindowPrivate::WindowFrameExclusive;
if (d->platformWindow) {
- d->platformWindow->setGeometry(QHighDpi::toNativePixels(QRect(position(), newSize), this));
+ d->platformWindow->setGeometry(
+ QHighDpi::toNativeWindowGeometry(QRect(position(), newSize), this));
} else {
- const QSize oldSize = d->geometry.size();
d->geometry.setSize(newSize);
if (newSize.width() != oldSize.width())
emit widthChanged(newSize.width());
@@ -1972,6 +2063,16 @@ void QWindowPrivate::destroy()
QObject *object = childrenWindows.at(i);
if (object->isWindowType()) {
QWindow *w = static_cast<QWindow*>(object);
+ auto *childPlatformWindow = w->handle();
+ if (!childPlatformWindow)
+ continue;
+
+ // Decouple the foreign window from this window,
+ // so that destroying our native handle doesn't
+ // bring down the foreign window as well.
+ if (childPlatformWindow->isForeignWindow())
+ childPlatformWindow->setParent(nullptr);
+
qt_window_private(w)->destroy();
}
}
@@ -1984,7 +2085,7 @@ void QWindowPrivate::destroy()
// Let subclasses act, typically by doing graphics resource cleaup, when
// the window, to which graphics resource may be tied, is going away.
//
- // NB! This is disfunctional when destroy() is invoked from the dtor since
+ // NB! This is dysfunctional when destroy() is invoked from the dtor since
// a reimplemented event() will not get called in the subclasses at that
// stage. However, the typical QWindow cleanup involves either close() or
// going through QWindowContainer, both of which will do an explicit, early
@@ -1996,9 +2097,7 @@ void QWindowPrivate::destroy()
// Unset platformWindow before deleting, so that the destructor of the
// platform window does not recurse back into the platform window via
// this window during destruction (e.g. as a result of platform events).
- QPlatformWindow *pw = platformWindow;
- platformWindow = nullptr;
- delete pw;
+ delete std::exchange(platformWindow, nullptr);
if (QGuiApplicationPrivate::focus_window == q)
QGuiApplicationPrivate::focus_window = q->parent();
@@ -2146,20 +2245,26 @@ QObject *QWindow::focusObject() const
/*!
Shows the window.
- This is equivalent to calling showFullScreen(), showMaximized(), or showNormal(),
+ For child windows, this is equivalent to calling showNormal().
+ Otherwise, it is equivalent to calling showFullScreen(), showMaximized(), or showNormal(),
depending on the platform's default behavior for the window type and flags.
\sa showFullScreen(), showMaximized(), showNormal(), hide(), QStyleHints::showIsFullScreen(), flags()
*/
void QWindow::show()
{
- Qt::WindowState defaultState = QGuiApplicationPrivate::platformIntegration()->defaultWindowState(d_func()->windowFlags);
- if (defaultState == Qt::WindowFullScreen)
- showFullScreen();
- else if (defaultState == Qt::WindowMaximized)
- showMaximized();
- else
+ if (parent()) {
showNormal();
+ } else {
+ const auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
+ Qt::WindowState defaultState = platformIntegration->defaultWindowState(d_func()->windowFlags);
+ if (defaultState == Qt::WindowFullScreen)
+ showFullScreen();
+ else if (defaultState == Qt::WindowMaximized)
+ showMaximized();
+ else
+ showNormal();
+ }
}
/*!
@@ -2208,6 +2313,9 @@ void QWindow::showMaximized()
Equivalent to calling setWindowStates(Qt::WindowFullScreen) and then
setVisible(true).
+ See the \l{QWidget::showFullScreen()} documentation for platform-specific
+ considerations and limitations.
+
\sa setWindowStates(), setVisible()
*/
void QWindow::showFullScreen()
@@ -2246,15 +2354,52 @@ void QWindow::showNormal()
bool QWindow::close()
{
Q_D(QWindow);
+ if (d->inClose)
+ return true;
// Do not close non top level windows
- if (parent())
+ if (!isTopLevel())
return false;
if (!d->platformWindow)
return true;
- return d->platformWindow->close();
+ // The window might be deleted during close,
+ // as a result of delivering the close event.
+ QPointer guard(this);
+ d->inClose = true;
+ bool success = d->platformWindow->close();
+ if (guard)
+ d->inClose = false;
+
+ return success;
+}
+
+bool QWindowPrivate::participatesInLastWindowClosed() const
+{
+ Q_Q(const QWindow);
+
+ if (!q->isTopLevel())
+ return false;
+
+ // Tool-tip widgets do not normally have Qt::WA_QuitOnClose,
+ // but since we do not have a similar flag for non-widget
+ // windows we need an explicit exclusion here as well.
+ if (q->type() == Qt::ToolTip)
+ return false;
+
+ // A window with a transient parent is not a primary window,
+ // it's a secondary window.
+ if (q->transientParent())
+ return false;
+
+ return true;
+}
+
+bool QWindowPrivate::treatAsVisible() const
+{
+ Q_Q(const QWindow);
+ return q->isVisible();
}
/*!
@@ -2407,7 +2552,7 @@ bool QWindow::event(QEvent *ev)
case QEvent::FocusIn: {
focusInEvent(static_cast<QFocusEvent *>(ev));
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::State state;
state.active = true;
QAccessibleStateChangeEvent event(this, state);
@@ -2417,7 +2562,7 @@ bool QWindow::event(QEvent *ev)
case QEvent::FocusOut: {
focusOutEvent(static_cast<QFocusEvent *>(ev));
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::State state;
state.active = true;
QAccessibleStateChangeEvent event(this, state);
@@ -2431,20 +2576,25 @@ bool QWindow::event(QEvent *ev)
break;
#endif
- case QEvent::Close:
+ case QEvent::Close: {
+
+ Q_D(QWindow);
+ const bool wasVisible = d->treatAsVisible();
+ const bool participatesInLastWindowClosed = d->participatesInLastWindowClosed();
+
+ // The window might be deleted in the close event handler
+ QPointer<QWindow> deletionGuard(this);
closeEvent(static_cast<QCloseEvent*>(ev));
+
if (ev->isAccepted()) {
- Q_D(QWindow);
- bool wasVisible = isVisible();
- destroy();
- if (wasVisible) {
- // FIXME: This check for visibility is a workaround for both QWidgetWindow
- // and QWindow having logic to emit lastWindowClosed, and possibly quit the
- // application. We should find a better way to handle this.
- d->maybeQuitOnLastWindowClosed();
- }
+ if (deletionGuard)
+ destroy();
+ if (wasVisible && participatesInLastWindowClosed)
+ QGuiApplicationPrivate::instance()->maybeLastWindowClosed();
}
+
break;
+ }
case QEvent::Expose:
exposeEvent(static_cast<QExposeEvent *>(ev));
@@ -2466,13 +2616,6 @@ bool QWindow::event(QEvent *ev)
setIcon(icon());
break;
- case QEvent::WindowStateChange: {
- Q_D(QWindow);
- emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
- d->updateVisibility();
- break;
- }
-
#if QT_CONFIG(tabletevent)
case QEvent::TabletPress:
case QEvent::TabletMove:
@@ -2514,11 +2657,15 @@ bool QWindow::event(QEvent *ev)
static const QEvent::Type contextMenuTrigger =
QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::ContextMenuOnMouseRelease).toBool() ?
QEvent::MouseButtonRelease : QEvent::MouseButtonPress;
- if (QMouseEvent *me = static_cast<QMouseEvent *>(ev);
+ auto asMouseEvent = [](QEvent *ev) {
+ const auto t = ev->type();
+ return t == QEvent::MouseButtonPress || t == QEvent::MouseButtonRelease
+ ? static_cast<QMouseEvent *>(ev) : nullptr ;
+ };
+ if (QMouseEvent *me = asMouseEvent(ev); me &&
ev->type() == contextMenuTrigger && me->button() == Qt::RightButton) {
- QSinglePointEvent *pev = static_cast<QSinglePointEvent*>(ev);
QContextMenuEvent e(QContextMenuEvent::Mouse, me->position().toPoint(),
- pev->globalPosition().toPoint(), pev->modifiers());
+ me->globalPosition().toPoint(), me->modifiers());
QGuiApplication::sendEvent(this, &e);
}
#endif
@@ -2528,11 +2675,13 @@ bool QWindow::event(QEvent *ev)
/*!
Schedules a QEvent::UpdateRequest event to be delivered to this window.
- The event is delivered in sync with the display vsync on platforms
- where this is possible. Otherwise, the event is delivered after a
- delay of 5 ms. The additional time is there to give the event loop
- a bit of idle time to gather system events, and can be overridden
- using the QT_QPA_UPDATE_IDLE_TIME environment variable.
+ The event is delivered in sync with the display vsync on platforms where
+ this is possible. Otherwise, the event is delivered after a delay of at
+ most 5 ms. If the window's associated screen reports a
+ \l{QScreen::refreshRate()}{refresh rate} higher than 60 Hz, the interval is
+ scaled down to a value smaller than 5. The additional time is there to give
+ the event loop a bit of idle time to gather system events, and can be
+ overridden using the QT_QPA_UPDATE_IDLE_TIME environment variable.
When driving animations, this function should be called once after drawing
has completed. Calling this function multiple times will result in a single
@@ -2708,7 +2857,7 @@ QPointF QWindow::mapToGlobal(const QPointF &pos) const
// QTBUG-43252, prefer platform implementation for foreign windows.
if (d->platformWindow
&& (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
- return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapToGlobalF(QHighDpi::toNativeLocalPosition(pos, this)), this);
+ return QHighDpi::fromNativeGlobalPosition(d->platformWindow->mapToGlobalF(QHighDpi::toNativeLocalPosition(pos, this)), this);
}
if (!QHighDpiScaling::isActive())
@@ -2721,7 +2870,12 @@ QPointF QWindow::mapToGlobal(const QPointF &pos) const
// Map the position (and the window's global position) to native coordinates, perform
// the addition, and then map back to device independent coordinates.
QPointF nativeLocalPos = QHighDpi::toNativeLocalPosition(pos, this);
- QPointF nativeWindowGlobalPos = QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
+ // Get the native window position directly from the platform window
+ // if available (it can be null if the window hasn't been shown yet),
+ // or fall back to scaling the QWindow position.
+ QPointF nativeWindowGlobalPos = d->platformWindow
+ ? d->platformWindow->mapToGlobal(QPoint(0,0)).toPointF()
+ : QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
QPointF nativeGlobalPos = nativeLocalPos + nativeWindowGlobalPos;
QPointF deviceIndependentGlobalPos = QHighDpi::fromNativeGlobalPosition(nativeGlobalPos, this);
return deviceIndependentGlobalPos;
@@ -2750,16 +2904,21 @@ QPointF QWindow::mapFromGlobal(const QPointF &pos) const
// QTBUG-43252, prefer platform implementation for foreign windows.
if (d->platformWindow
&& (d->platformWindow->isForeignWindow() || d->platformWindow->isEmbedded())) {
- return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobalF(QHighDpi::toNativeLocalPosition(pos, this)), this);
+ return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobalF(QHighDpi::toNativeGlobalPosition(pos, this)), this);
}
if (!QHighDpiScaling::isActive())
return pos - d->globalPosition();
// Calculate local position in the native coordinate system. (See comment for the
- // correspinding mapToGlobal() code above).
+ // corresponding mapToGlobal() code above).
QPointF nativeGlobalPos = QHighDpi::toNativeGlobalPosition(pos, this);
- QPointF nativeWindowGlobalPos = QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
+ // Get the native window position directly from the platform window
+ // if available (it can be null if the window hasn't been shown yet),
+ // or fall back to scaling the QWindow position.
+ QPointF nativeWindowGlobalPos = d->platformWindow
+ ? d->platformWindow->mapToGlobal(QPoint(0,0)).toPointF()
+ : QHighDpi::toNativeGlobalPosition(QPointF(d->globalPosition()), this);
QPointF nativeLocalPos = nativeGlobalPos - nativeWindowGlobalPos;
QPointF deviceIndependentLocalPos = QHighDpi::fromNativeLocalPosition(nativeLocalPos, this);
return deviceIndependentLocalPos;
@@ -2795,34 +2954,6 @@ Q_GUI_EXPORT QWindowPrivate *qt_window_private(QWindow *window)
return window->d_func();
}
-void QWindowPrivate::maybeQuitOnLastWindowClosed()
-{
- if (!QCoreApplication::instance())
- return;
-
- Q_Q(QWindow);
- if (!q->isTopLevel())
- return;
-
- QWindowList list = QGuiApplication::topLevelWindows();
- bool lastWindowClosed = true;
- for (int i = 0; i < list.size(); ++i) {
- QWindow *w = list.at(i);
- if (!w->isVisible() || w->transientParent() || w->type() == Qt::ToolTip)
- continue;
- lastWindowClosed = false;
- break;
- }
- if (lastWindowClosed) {
- QGuiApplicationPrivate::emitLastWindowClosed();
-
- if (QGuiApplication::quitOnLastWindowClosed()) {
- QCoreApplicationPrivate *applicationPrivate = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(QCoreApplication::instance()));
- applicationPrivate->maybeQuit();
- }
- }
-}
-
QWindow *QWindowPrivate::topLevelWindow(QWindow::AncestorMode mode) const
{
Q_Q(const QWindow);
@@ -2840,13 +2971,6 @@ QWindow *QWindowPrivate::topLevelWindow(QWindow::AncestorMode mode) const
return window;
}
-#if QT_CONFIG(opengl)
-QOpenGLContext *QWindowPrivate::shareContext() const
-{
- return qt_gl_global_share_context();
-};
-#endif
-
/*!
Creates a local representation of a window created by another process or by
using native libraries below Qt.
@@ -2876,7 +3000,11 @@ QWindow *QWindow::fromWinId(WId id)
}
QWindow *window = new QWindow;
- qt_window_private(window)->create(false, id);
+
+ // Persist the winId in a private property so that we
+ // can recreate the window after being destroyed.
+ window->setProperty(kForeignWindowId, id);
+ window->create();
if (!window->handle()) {
delete window;
@@ -2887,7 +3015,7 @@ QWindow *QWindow::fromWinId(WId id)
}
/*!
- Causes an alert to be shown for \a msec miliseconds. If \a msec is \c 0 (the
+ Causes an alert to be shown for \a msec milliseconds. If \a msec is \c 0 (the
default), then the alert is shown indefinitely until the window becomes
active again. This function has no effect on an active window.
@@ -3025,6 +3153,14 @@ void *QWindow::resolveInterface(const char *name, int revision) const
QT_NATIVE_INTERFACE_RETURN_IF(QCocoaWindow, platformWindow);
#endif
+#if QT_CONFIG(wayland)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWaylandWindow, platformWindow);
+#endif
+
+#if defined(Q_OS_WASM)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWasmWindow, platformWindow);
+#endif
+
return nullptr;
}
@@ -3067,7 +3203,7 @@ QDebug operator<<(QDebug debug, const QWindow *window)
}
#endif // !QT_NO_DEBUG_STREAM
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
/*!
Associates this window with the specified Vulkan \a instance.
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 102a324366..a5ec47708a 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOW_H
#define QWINDOW_H
@@ -91,7 +55,7 @@ class QWindowContainer;
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
#endif
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
class QVulkanInstance;
#endif
@@ -284,7 +248,7 @@ public:
static QWindow *fromWinId(WId id);
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
void setVulkanInstance(QVulkanInstance *instance);
QVulkanInstance *vulkanInstance() const;
#endif
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 5d9de82295..a9716847a1 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOW_P_H
#define QWINDOW_P_H
@@ -58,11 +22,13 @@
#include <QtCore/private/qobject_p.h>
#include <QtCore/qelapsedtimer.h>
-#include <QtGui/QIcon>
+#include <QtCore/qxpfunctional.h>
+#include <QtGui/qicon.h>
+#include <QtGui/qpalette.h>
-QT_BEGIN_NAMESPACE
+#include <QtCore/qpointer.h>
-#define QWINDOWSIZE_MAX ((1<<24)-1)
+QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QWindowPrivate : public QObjectPrivate
{
@@ -75,15 +41,11 @@ public:
WindowFrameExclusive
};
- QWindowPrivate()
- : QObjectPrivate()
- {
- isWindow = true;
- }
+ QWindowPrivate();
+ ~QWindowPrivate() override;
- void init(QScreen *targetScreen = nullptr);
+ void init(QWindow *parent, QScreen *targetScreen = nullptr);
- void maybeQuitOnLastWindowClosed();
#ifndef QT_NO_CURSOR
void setCursor(const QCursor *c = nullptr);
bool applyCursor();
@@ -93,11 +55,8 @@ public:
QWindow *topLevelWindow(QWindow::AncestorMode mode = QWindow::IncludeTransients) const;
-#if QT_CONFIG(opengl)
- virtual QOpenGLContext *shareContext() const;
-#endif
-
virtual QWindow *eventReceiver() { Q_Q(QWindow); return q; }
+ virtual QPalette windowPalette() const { return QPalette(); }
virtual void setVisible(bool visible);
void updateVisibility();
@@ -107,7 +66,7 @@ public:
void updateSiblingPosition(SiblingPosition);
bool windowRecreationRequired(QScreen *newScreen) const;
- void create(bool recursive, WId nativeHandle = 0);
+ void create(bool recursive);
void destroy();
void setTopLevelScreen(QScreen *newScreen, bool recreate);
void connectToScreen(QScreen *topLevelScreen);
@@ -119,12 +78,21 @@ public:
virtual void clearFocusObject();
virtual QRectF closestAcceptableGeometry(const QRectF &rect) const;
+ void setMinOrMaxSize(QSize *oldSizeMember, const QSize &size,
+ qxp::function_ref<void()> funcWidthChanged,
+ qxp::function_ref<void()> funcHeightChanged);
+
virtual void processSafeAreaMarginsChanged() {}
+ virtual bool participatesInLastWindowClosed() const;
+ virtual bool treatAsVisible() const;
+
bool isPopup() const { return (windowFlags & Qt::WindowType_Mask) == Qt::Popup; }
void setAutomaticPositionAndResizeEnabled(bool a)
{ positionAutomatic = resizeAutomatic = a; }
+ bool updateDevicePixelRatio();
+
static QWindowPrivate *get(QWindow *window) { return window->d_func(); }
static Qt::WindowState effectiveState(Qt::WindowStates);
@@ -136,11 +104,13 @@ public:
bool visible= false;
bool visibilityOnDestroy = false;
bool exposed = false;
+ bool inClose = false;
QSurfaceFormat requestedFormat;
QString windowTitle;
QString windowFilePath;
QIcon windowIcon;
QRect geometry;
+ qreal devicePixelRatio = 1.0;
Qt::WindowStates windowState = Qt::WindowNoState;
QWindow::Visibility visibility = QWindow::Hidden;
bool resizeEventPending = true;
@@ -175,7 +145,6 @@ public:
bool hasCursor = false;
#endif
- bool compositing = false;
QElapsedTimer lastComposeTime;
#if QT_CONFIG(vulkan)
diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h
index 1ac245900e..27d02d4d58 100644
--- a/src/gui/kernel/qwindowdefs.h
+++ b/src/gui/kernel/qwindowdefs.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWDEFS_H
#define QWINDOWDEFS_H
diff --git a/src/gui/kernel/qwindowdefs_win.h b/src/gui/kernel/qwindowdefs_win.h
index 40074d6cce..c2b968fe1f 100644
--- a/src/gui/kernel/qwindowdefs_win.h
+++ b/src/gui/kernel/qwindowdefs_win.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWDEFS_WIN_H
#define QWINDOWDEFS_WIN_H
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 355ebb87ec..1875594300 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -1,47 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsysteminterface.h"
#include <qpa/qplatformwindow.h>
#include "qwindowsysteminterface_p.h"
#include "private/qguiapplication_p.h"
#include "private/qevent_p.h"
+#include "private/qeventpoint_p.h"
#include "private/qpointingdevice_p.h"
+#include "private/qscreen_p.h"
#include <QAbstractEventDispatcher>
#include <qpa/qplatformintegration.h>
#include <qdebug.h>
@@ -56,14 +22,16 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcQpaInputDevices, "qt.qpa.input.devices")
-QElapsedTimer QWindowSystemInterfacePrivate::eventTime;
+Q_CONSTINIT QElapsedTimer QWindowSystemInterfacePrivate::eventTime;
bool QWindowSystemInterfacePrivate::synchronousWindowSystemEvents = false;
bool QWindowSystemInterfacePrivate::TabletEvent::platformSynthesizesMouse = true;
QWaitCondition QWindowSystemInterfacePrivate::eventsFlushed;
-QMutex QWindowSystemInterfacePrivate::flushEventMutex;
-QAtomicInt QWindowSystemInterfacePrivate::eventAccepted;
+Q_CONSTINIT QMutex QWindowSystemInterfacePrivate::flushEventMutex;
+Q_CONSTINIT QAtomicInt QWindowSystemInterfacePrivate::eventAccepted;
QWindowSystemEventHandler *QWindowSystemInterfacePrivate::eventHandler;
QWindowSystemInterfacePrivate::WindowSystemEventList QWindowSystemInterfacePrivate::windowSystemEventQueue;
@@ -72,20 +40,45 @@ extern QPointer<QWindow> qt_last_mouse_receiver;
// ------------------- QWindowSystemInterfacePrivate -------------------
+/*!
+ \internal
+
+ The QWindowSystemHelper creates synchronously delivered events on the stack, unless
+ the calling thread is not the Gui thread.
+
+ Asynchronously delivered events, and events created outside the Gui thread are
+ allocated on the heap.
+*/
+
+template<typename Delivery>
+struct QWindowSystemHelper
+{
+ template<typename EventType, typename ...Args>
+ static bool handleEvent(Args ...);
+};
+
/*
- Handles a window system event asynchronously by posting the event to Qt Gui.
+ Handles a window system event.
- This function posts the event on the window system event queue and wakes the
- Gui event dispatcher. Qt Gui will then handle the event asynchonously at a
- later point.
+ By default this function posts the event on the window system event queue and
+ wakes the Gui event dispatcher. Qt Gui will then handle the event asynchronously
+ at a later point. The return value is not used in asynchronous mode and will
+ always be true.
+
+ In synchronous mode Qt Gui will process the event immediately. The return value
+ indicates if Qt accepted the event. If the event is delivered from another thread
+ than the Qt main thread the window system event queue is flushed, which may deliver
+ other events as well.
+
+ \sa flushWindowSystemEvents(), setSynchronousWindowSystemEvents()
*/
template<>
-bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(WindowSystemEvent *ev)
+template<typename EventType, typename ...Args>
+bool QWindowSystemHelper<QWindowSystemInterface::DefaultDelivery>::handleEvent(Args ...args)
{
- windowSystemEventQueue.append(ev);
- if (QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher())
- dispatcher->wakeUp();
- return true;
+ return QWindowSystemInterfacePrivate::synchronousWindowSystemEvents
+ ? QWindowSystemHelper<QWindowSystemInterface::SynchronousDelivery>::handleEvent<EventType>(args...)
+ : QWindowSystemHelper<QWindowSystemInterface::AsynchronousDelivery>::handleEvent<EventType>(args...);
}
/*
@@ -99,50 +92,53 @@ bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterfa
well.
*/
template<>
-bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(WindowSystemEvent *ev)
+template<typename EventType, typename ...Args>
+bool QWindowSystemHelper<QWindowSystemInterface::SynchronousDelivery>::handleEvent(Args ...args)
{
- bool accepted = true;
if (QThread::currentThread() == QGuiApplication::instance()->thread()) {
- // Process the event immediately on the current thread and return the accepted state.
- QGuiApplicationPrivate::processWindowSystemEvent(ev);
- accepted = ev->eventAccepted;
- delete ev;
+ EventType event(args...);
+ // Process the event immediately on the Gui thread and return the accepted state
+ if (QWindowSystemInterfacePrivate::eventHandler) {
+ if (!QWindowSystemInterfacePrivate::eventHandler->sendEvent(&event))
+ return false;
+ } else {
+ QGuiApplicationPrivate::processWindowSystemEvent(&event);
+ }
+ return event.eventAccepted;
} else {
// Post the event on the Qt main thread queue and flush the queue.
// This will wake up the Gui thread which will process the event.
// Return the accepted state for the last event on the queue,
// which is the event posted by this function.
- handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(ev);
- accepted = QWindowSystemInterface::flushWindowSystemEvents();
+ QWindowSystemHelper<QWindowSystemInterface::AsynchronousDelivery>::handleEvent<EventType>(args...);
+ return QWindowSystemInterface::flushWindowSystemEvents();
}
- return accepted;
}
/*
- Handles a window system event.
-
- By default this function posts the event on the window system event queue and
- wakes the Gui event dispatcher. Qt Gui will then handle the event asynchonously
- at a later point. The return value is not used in asynchronous mode and will
- always be true.
-
- In synchronous mode Qt Gui will process the event immediately. The return value
- indicates if Qt accepted the event. If the event is delivered from another thread
- than the Qt main thread the window system event queue is flushed, which may deliver
- other events as well.
+ Handles a window system event asynchronously by posting the event to Qt Gui.
- \sa flushWindowSystemEvents(), setSynchronousWindowSystemEvents()
+ This function posts the event on the window system event queue and wakes the
+ Gui event dispatcher. Qt Gui will then handle the event asynchronously at a
+ later point.
*/
template<>
-bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterface::DefaultDelivery>(QWindowSystemInterfacePrivate::WindowSystemEvent *ev)
+template<typename EventType, typename ...Args>
+bool QWindowSystemHelper<QWindowSystemInterface::AsynchronousDelivery>::handleEvent(Args ...args)
{
- if (synchronousWindowSystemEvents)
- return handleWindowSystemEvent<QWindowSystemInterface::SynchronousDelivery>(ev);
- else
- return handleWindowSystemEvent<QWindowSystemInterface::AsynchronousDelivery>(ev);
+ QWindowSystemInterfacePrivate::windowSystemEventQueue.append(new EventType(args...));
+ if (QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::qt_qpa_core_dispatcher())
+ dispatcher->wakeUp();
+ return true;
+}
+
+template <typename EventType, typename Delivery = QWindowSystemInterface::DefaultDelivery, typename ...Args>
+static bool handleWindowSystemEvent(Args ...args)
+{
+ return QWindowSystemHelper<Delivery>::template handleEvent<EventType>(args...);
}
-int QWindowSystemInterfacePrivate::windowSystemEventsQueued()
+qsizetype QWindowSystemInterfacePrivate::windowSystemEventsQueued()
{
return windowSystemEventQueue.count();
}
@@ -221,16 +217,14 @@ bool QWindowSystemEventHandler::sendEvent(QWindowSystemInterfacePrivate::WindowS
QT_DEFINE_QPA_EVENT_HANDLER(void, handleEnterEvent, QWindow *window, const QPointF &local, const QPointF &global)
{
if (window) {
- QWindowSystemInterfacePrivate::EnterEvent *e
- = new QWindowSystemInterfacePrivate::EnterEvent(window, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window));
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::EnterEvent, Delivery>(window,
+ QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window));
}
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleLeaveEvent, QWindow *window)
{
- QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(window);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::LeaveEvent, Delivery>(window);
}
/*!
@@ -246,11 +240,9 @@ void QWindowSystemInterface::handleEnterLeaveEvent(QWindow *enter, QWindow *leav
handleEnterEvent(enter, local, global);
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *window, Qt::FocusReason r)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleFocusWindowChanged, QWindow *window, Qt::FocusReason r)
{
- QWindowSystemInterfacePrivate::ActivatedWindowEvent *e =
- new QWindowSystemInterfacePrivate::ActivatedWindowEvent(window, r);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::FocusWindowEvent, Delivery>(window, r);
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowStates newState, int oldState)
@@ -259,38 +251,35 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt:
if (oldState < Qt::WindowNoState)
oldState = window->windowStates();
- QWindowSystemInterfacePrivate::WindowStateChangedEvent *e =
- new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowStates(oldState));
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowStateChangedEvent, Delivery>(window, newState, Qt::WindowStates(oldState));
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowScreenChanged, QWindow *window, QScreen *screen)
{
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowScreenChangedEvent, Delivery>(window, screen);
+}
- QWindowSystemInterfacePrivate::WindowScreenChangedEvent *e =
- new QWindowSystemInterfacePrivate::WindowScreenChangedEvent(window, screen);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowDevicePixelRatioChanged, QWindow *window)
+{
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowDevicePixelRatioChangedEvent, Delivery>(window);
}
+
QT_DEFINE_QPA_EVENT_HANDLER(void, handleSafeAreaMarginsChanged, QWindow *window)
{
- QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent *e =
- new QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent(window);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::SafeAreaMarginsChangedEvent, Delivery>(window);
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleApplicationStateChanged, Qt::ApplicationState newState, bool forcePropagate)
{
Q_ASSERT(QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ApplicationState));
- QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *e =
- new QWindowSystemInterfacePrivate::ApplicationStateChangedEvent(newState, forcePropagate);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent, Delivery>(newState, forcePropagate);
}
QT_DEFINE_QPA_EVENT_HANDLER(bool, handleApplicationTermination)
{
- auto *e = new QWindowSystemInterfacePrivate::WindowSystemEvent(QWindowSystemInterfacePrivate::ApplicationTermination);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowSystemEvent, Delivery>(
+ QWindowSystemInterfacePrivate::ApplicationTermination);
}
QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry)
@@ -308,7 +297,6 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const Q
{
Q_ASSERT(window);
const auto newRectDi = QHighDpi::fromNativeWindowGeometry(newRect, window);
- auto e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, newRectDi);
if (window->handle()) {
// Persist the new geometry so that QWindow::geometry() can be queried in the resize event
window->handle()->QPlatformWindow::setGeometry(newRect);
@@ -316,7 +304,7 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const Q
// have its handle set up yet. Platforms that deliver events during window creation need
// to handle the persistence manually, e.g. by overriding geometry().
}
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::GeometryChangeEvent, Delivery>(window, newRectDi);
}
QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *window, const QRegion &region)
@@ -346,24 +334,21 @@ QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *window, const Q
*/
QT_DEFINE_QPA_EVENT_HANDLER(bool, handleExposeEvent, QWindow *window, const QRegion &region)
{
- QWindowSystemInterfacePrivate::ExposeEvent *e =
- new QWindowSystemInterfacePrivate::ExposeEvent(window, QHighDpi::fromNativeLocalExposedRegion(region, window));
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::ExposeEvent, Delivery>(window,
+ QHighDpi::fromNativeLocalExposedRegion(region, window));
}
QT_DEFINE_QPA_EVENT_HANDLER(bool, handlePaintEvent, QWindow *window, const QRegion &region)
{
- QWindowSystemInterfacePrivate::PaintEvent *e =
- new QWindowSystemInterfacePrivate::PaintEvent(window, QHighDpi::fromNativeLocalExposedRegion(region, window));
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::PaintEvent, Delivery>(window,
+ QHighDpi::fromNativeLocalExposedRegion(region, window));
}
QT_DEFINE_QPA_EVENT_HANDLER(bool, handleCloseEvent, QWindow *window)
{
Q_ASSERT(window);
- auto *event = new QWindowSystemInterfacePrivate::CloseEvent(window);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(event);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::CloseEvent, Delivery>(window);
}
/*!
@@ -404,65 +389,34 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleMouseEvent, QWindow *window, ulong times
Qt::MouseButton button, QEvent::Type type, Qt::KeyboardModifiers mods,
Qt::MouseEventSource source)
{
- Q_ASSERT_X(type != QEvent::MouseButtonDblClick && type != QEvent::NonClientAreaMouseButtonDblClick,
- "QWindowSystemInterface::handleMouseEvent",
- "QTBUG-71263: Native double clicks are not implemented.");
- auto localPos = QHighDpi::fromNativeLocalPosition(local, window);
- auto globalPos = QHighDpi::fromNativeGlobalPosition(global, window);
-
- QWindowSystemInterfacePrivate::MouseEvent *e =
- new QWindowSystemInterfacePrivate::MouseEvent(window, timestamp, localPos, globalPos,
- state, mods, button, type, source, false, device);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
-}
-
-bool QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window,
- const QPointF &local, const QPointF &global,
- Qt::MouseButtons state,
- Qt::MouseButton button, QEvent::Type type,
- Qt::KeyboardModifiers mods,
- Qt::MouseEventSource source)
-{
- const unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- return handleFrameStrutMouseEvent(window, time, local, global, state, button, type, mods, source);
-}
-bool QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, const QPointingDevice *device,
- const QPointF &local, const QPointF &global,
- Qt::MouseButtons state,
- Qt::MouseButton button, QEvent::Type type,
- Qt::KeyboardModifiers mods,
- Qt::MouseEventSource source)
-{
- const unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
- return handleFrameStrutMouseEvent(window, time, device, local, global, state, button, type, mods, source);
-}
+ bool isNonClientArea = {};
-bool QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, ulong timestamp,
- const QPointF &local, const QPointF &global,
- Qt::MouseButtons state,
- Qt::MouseButton button, QEvent::Type type,
- Qt::KeyboardModifiers mods,
- Qt::MouseEventSource source)
-{
- return handleFrameStrutMouseEvent(window, timestamp, QPointingDevice::primaryPointingDevice(),
- local, global, state, button, type, mods, source);
-}
+ switch (type) {
+ case QEvent::MouseButtonDblClick:
+ case QEvent::NonClientAreaMouseButtonDblClick:
+ Q_ASSERT_X(false, "QWindowSystemInterface::handleMouseEvent",
+ "QTBUG-71263: Native double clicks are not implemented.");
+ return false;
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ isNonClientArea = false;
+ break;
+ case QEvent::NonClientAreaMouseMove:
+ case QEvent::NonClientAreaMouseButtonPress:
+ case QEvent::NonClientAreaMouseButtonRelease:
+ isNonClientArea = true;
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
-bool QWindowSystemInterface::handleFrameStrutMouseEvent(QWindow *window, ulong timestamp, const QPointingDevice *device,
- const QPointF &local, const QPointF &global,
- Qt::MouseButtons state,
- Qt::MouseButton button, QEvent::Type type,
- Qt::KeyboardModifiers mods,
- Qt::MouseEventSource source)
-{
auto localPos = QHighDpi::fromNativeLocalPosition(local, window);
auto globalPos = QHighDpi::fromNativeGlobalPosition(global, window);
- QWindowSystemInterfacePrivate::MouseEvent *e =
- new QWindowSystemInterfacePrivate::MouseEvent(window, timestamp, localPos, globalPos,
- state, mods, button, type, source, true, device);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::MouseEvent, Delivery>(window,
+ timestamp, localPos, globalPos, state, mods, button, type, source, isNonClientArea, device);
}
bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestamp, int keyCode, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode,
@@ -479,13 +433,11 @@ bool QWindowSystemInterface::handleShortcutEvent(QWindow *window, ulong timestam
// key event, so that the target that accepted the shortcut override event can handle it. Note that we only
// do this if the shortcut map hasn't found a partial shortcut match yet. If it has, the shortcut can not be
// overridden.
- QWindowSystemInterfacePrivate::KeyEvent *shortcutOverrideEvent = new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp,
- QEvent::ShortcutOverride, keyCode, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorepeat, count);
-
- {
- if (QWindowSystemInterfacePrivate::handleWindowSystemEvent<SynchronousDelivery>(shortcutOverrideEvent))
- return false;
- }
+ bool overridden = handleWindowSystemEvent<QWindowSystemInterfacePrivate::KeyEvent, SynchronousDelivery>
+ (window,timestamp, QEvent::ShortcutOverride, keyCode, modifiers, nativeScanCode,
+ nativeVirtualKey, nativeModifiers, text, autorepeat, count);
+ if (overridden)
+ return false;
}
// The shortcut event is dispatched as a QShortcutEvent, not a QKeyEvent, but we use
@@ -517,25 +469,19 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, QEvent::Type
QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count)
{
-#if defined(Q_OS_MACOS)
- if (t == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window, timestamp, k, mods, 0, 0, 0, text, autorep, count))
- return true;
-#endif
-
- QWindowSystemInterfacePrivate::KeyEvent * e =
- new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp, t, k, mods, text, autorep, count);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::KeyEvent, Delivery>(window,
+ timestamp, t, k, mods, text, autorep, count);
}
bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text, bool autorep,
- ushort count, bool tryShortcutOverride)
+ ushort count)
{
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
return handleExtendedKeyEvent(window, time, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers,
- text, autorep, count, tryShortcutOverride);
+ text, autorep, count);
}
bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, ulong timestamp, QEvent::Type type, int key,
@@ -543,21 +489,10 @@ bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, ulong times
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text, bool autorep,
- ushort count, bool tryShortcutOverride)
+ ushort count)
{
-#if defined(Q_OS_MACOS)
- if (tryShortcutOverride && type == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window,
- timestamp, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count)) {
- return true;
- }
-#else
- Q_UNUSED(tryShortcutOverride);
-#endif
-
- QWindowSystemInterfacePrivate::KeyEvent * e =
- new QWindowSystemInterfacePrivate::KeyEvent(window, timestamp, type, key, modifiers,
- nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::KeyEvent>(window,
+ timestamp, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
}
bool QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source)
@@ -585,7 +520,6 @@ bool QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp,
// In addition high-resolution pixel-based deltas are also supported.
// Platforms that does not support these may pass a null point here.
// Angle deltas must always be sent in addition to pixel deltas.
- QWindowSystemInterfacePrivate::WheelEvent *e;
// Pass Qt::ScrollBegin and Qt::ScrollEnd through
// even if the wheel delta is null.
@@ -594,16 +528,16 @@ bool QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp,
// Simple case: vertical deltas only:
if (angleDelta.y() != 0 && angleDelta.x() == 0) {
- e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window),
- pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling, device);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::WheelEvent>(window,
+ timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window),
+ pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling, device);
}
// Simple case: horizontal deltas only:
if (angleDelta.y() == 0 && angleDelta.x() != 0) {
- e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window),
- pixelDelta, angleDelta, angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling, device);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::WheelEvent>(window,
+ timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window),
+ pixelDelta, angleDelta, angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling, device);
}
bool acceptVert;
@@ -611,15 +545,16 @@ bool QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp,
// Both horizontal and vertical deltas: Send two wheel events.
// The first event contains the Qt 5 pixel and angle delta as points,
// and in addition the Qt 4 compatibility vertical angle delta.
- e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window),
- pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling, device);
- acceptVert = QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ acceptVert = handleWindowSystemEvent<QWindowSystemInterfacePrivate::WheelEvent>(window,
+ timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window),
+ pixelDelta, angleDelta, angleDelta.y(), Qt::Vertical, mods, phase, source, invertedScrolling, device);
// The second event contains null pixel and angle points and the
// Qt 4 compatibility horizontal angle delta.
- e = new QWindowSystemInterfacePrivate::WheelEvent(window, timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window),
- QPoint(), QPoint(), angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling, device);
- acceptHorz = QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ acceptHorz = handleWindowSystemEvent<QWindowSystemInterfacePrivate::WheelEvent>(window,
+ timestamp, QHighDpi::fromNativeLocalPosition(local, window), QHighDpi::fromNativeGlobalPosition(global, window),
+ QPoint(), QPoint(), angleDelta.x(), Qt::Horizontal, mods, phase, source, invertedScrolling, device);
+
return acceptVert || acceptHorz;
}
@@ -679,19 +614,19 @@ QList<QEventPoint>
QList<QEventPoint> touchPoints;
QEventPoint::States states;
- touchPoints.reserve(points.count());
+ touchPoints.reserve(points.size());
QList<QWindowSystemInterface::TouchPoint>::const_iterator point = points.constBegin();
QList<QWindowSystemInterface::TouchPoint>::const_iterator end = points.constEnd();
while (point != end) {
QPointF globalPos = QHighDpi::fromNativePixels(point->area.center(), window);
- QMutableEventPoint p(point->id, point->state, globalPos, globalPos);
+ QEventPoint p(point->id, point->state, globalPos, globalPos);
states |= point->state;
if (point->uniqueId >= 0)
- p.setUniqueId(QPointingDeviceUniqueId::fromNumericId(point->uniqueId));
- p.setPressure(point->pressure);
- p.setRotation(point->rotation);
- p.setEllipseDiameters(QHighDpi::fromNativePixels(point->area.size(), window));
- p.setVelocity(QHighDpi::fromNativePixels(point->velocity, window));
+ QMutableEventPoint::setUniqueId(p, QPointingDeviceUniqueId::fromNumericId(point->uniqueId));
+ QMutableEventPoint::setPressure(p, point->pressure);
+ QMutableEventPoint::setRotation(p, point->rotation);
+ QMutableEventPoint::setEllipseDiameters(p, QHighDpi::fromNativePixels(point->area.size(), window));
+ QMutableEventPoint::setVelocity(p, QHighDpi::fromNativePixels(point->velocity, window));
// The local pos is not set: it will be calculated
// when the event gets processed by QGuiApplication.
@@ -746,9 +681,9 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchEvent, QWindow *window, ulong times
QEvent::Type type;
QList<QEventPoint> touchPoints =
QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, &type);
- QWindowSystemInterfacePrivate::TouchEvent *e =
- new QWindowSystemInterfacePrivate::TouchEvent(window, timestamp, type, device, touchPoints, mods);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TouchEvent, Delivery>(window,
+ timestamp, type, device, touchPoints, mods);
}
QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, const QPointingDevice *device,
@@ -761,10 +696,8 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, const
QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, ulong timestamp, const QPointingDevice *device,
Qt::KeyboardModifiers mods)
{
- QWindowSystemInterfacePrivate::TouchEvent *e =
- new QWindowSystemInterfacePrivate::TouchEvent(window, timestamp, QEvent::TouchCancel, device,
- QList<QEventPoint>(), mods);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TouchEvent, Delivery>(window,
+ timestamp, QEvent::TouchCancel, device, QList<QEventPoint>(), mods);
}
/*!
@@ -778,9 +711,9 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchCancelEvent, QWindow *window, ulong
The screen should be deleted by calling QWindowSystemInterface::handleScreenRemoved().
*/
-void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrimary)
+void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *platformScreen, bool isPrimary)
{
- QScreen *screen = new QScreen(ps);
+ QScreen *screen = new QScreen(platformScreen);
if (isPrimary)
QGuiApplicationPrivate::screen_list.prepend(screen);
@@ -789,6 +722,7 @@ void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrima
QGuiApplicationPrivate::resetCachedDevicePixelRatio();
QHighDpiScaling::updateHighDpiScaling();
+ screen->d_func()->updateGeometry();
emit qGuiApp->screenAdded(screen);
@@ -806,9 +740,45 @@ void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrima
*/
void QWindowSystemInterface::handleScreenRemoved(QPlatformScreen *platformScreen)
{
- // Important to keep this order since the QSceen doesn't own the platform screen.
- // The QScreen destructor will take care changing the primary screen, so no need here.
- delete platformScreen->screen();
+ QScreen *screen = platformScreen->screen();
+
+ // Remove screen
+ const bool wasPrimary = QGuiApplication::primaryScreen() == screen;
+ QGuiApplicationPrivate::screen_list.removeOne(screen);
+ QGuiApplicationPrivate::resetCachedDevicePixelRatio();
+
+ if (qGuiApp) {
+ QScreen *newPrimaryScreen = QGuiApplication::primaryScreen();
+ if (wasPrimary && newPrimaryScreen)
+ emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
+
+ // Allow clients to manage windows that are affected by the screen going
+ // away, before we fall back to moving them to the primary screen.
+ emit qApp->screenRemoved(screen);
+
+ if (!QGuiApplication::closingDown()) {
+ bool movingFromVirtualSibling = newPrimaryScreen
+ && newPrimaryScreen->handle()->virtualSiblings().contains(platformScreen);
+
+ // Move any leftover windows to the primary screen
+ const auto allWindows = QGuiApplication::allWindows();
+ for (QWindow *window : allWindows) {
+ if (!window->isTopLevel() || window->screen() != screen)
+ continue;
+
+ const bool wasVisible = window->isVisible();
+ window->setScreen(newPrimaryScreen);
+
+ // Re-show window if moved from a virtual sibling screen. Otherwise
+ // leave it up to the application developer to show the window.
+ if (movingFromVirtualSibling)
+ window->setVisible(wasVisible);
+ }
+ }
+ }
+
+ // Important to keep this order since the QSceen doesn't own the platform screen
+ delete screen;
delete platformScreen;
}
@@ -821,7 +791,7 @@ void QWindowSystemInterface::handleScreenRemoved(QPlatformScreen *platformScreen
void QWindowSystemInterface::handlePrimaryScreenChanged(QPlatformScreen *newPrimary)
{
QScreen *newPrimaryScreen = newPrimary->screen();
- int indexOfScreen = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen);
+ qsizetype indexOfScreen = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen);
Q_ASSERT(indexOfScreen >= 0);
if (indexOfScreen == 0)
return;
@@ -832,36 +802,36 @@ void QWindowSystemInterface::handlePrimaryScreenChanged(QPlatformScreen *newPrim
void QWindowSystemInterface::handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation orientation)
{
- QWindowSystemInterfacePrivate::ScreenOrientationEvent *e =
- new QWindowSystemInterfacePrivate::ScreenOrientationEvent(screen, orientation);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::ScreenOrientationEvent>(screen, orientation);
}
void QWindowSystemInterface::handleScreenGeometryChange(QScreen *screen, const QRect &geometry, const QRect &availableGeometry)
{
- QWindowSystemInterfacePrivate::ScreenGeometryEvent *e =
- new QWindowSystemInterfacePrivate::ScreenGeometryEvent(screen, QHighDpi::fromNativeScreenGeometry(geometry, screen), QHighDpi::fromNative(availableGeometry, screen, geometry.topLeft()));
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::ScreenGeometryEvent>(screen,
+ QHighDpi::fromNativeScreenGeometry(geometry, screen), QHighDpi::fromNative(availableGeometry,
+ screen, geometry.topLeft()));
}
void QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal dpiX, qreal dpiY)
{
+ // Keep QHighDpiScaling::m_active in sync with platform screen state, in
+ // order to make scaling calls made during DPI change use the new state.
+ // FIXME: Remove when QHighDpiScaling::m_active has been removed.
+ QHighDpiScaling::updateHighDpiScaling();
+
const QDpi effectiveDpi = QPlatformScreen::overrideDpi(QDpi{dpiX, dpiY});
- auto e = new QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent(screen, effectiveDpi.first, effectiveDpi.second);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent>(screen,
+ effectiveDpi.first, effectiveDpi.second);
}
void QWindowSystemInterface::handleScreenRefreshRateChange(QScreen *screen, qreal newRefreshRate)
{
- QWindowSystemInterfacePrivate::ScreenRefreshRateEvent *e =
- new QWindowSystemInterfacePrivate::ScreenRefreshRateEvent(screen, newRefreshRate);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::ScreenRefreshRateEvent>(screen, newRefreshRate);
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleThemeChange, QWindow *window)
{
- QWindowSystemInterfacePrivate::ThemeChangeEvent *e = new QWindowSystemInterfacePrivate::ThemeChangeEvent(window);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::ThemeChangeEvent, Delivery>(window);
}
#if QT_CONFIG(draganddrop)
@@ -924,13 +894,12 @@ bool QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp,
qreal tangentialPressure, qreal rotation, int z,
Qt::KeyboardModifiers modifiers)
{
- QWindowSystemInterfacePrivate::TabletEvent *e =
- new QWindowSystemInterfacePrivate::TabletEvent(window, timestamp,
- QHighDpi::fromNativeLocalPosition(local, window),
- QHighDpi::fromNativeGlobalPosition(global, window),
- device, buttons, pressure,
- xTilt, yTilt, tangentialPressure, rotation, z, modifiers);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletEvent>(window,
+ timestamp,
+ QHighDpi::fromNativeLocalPosition(local, window),
+ QHighDpi::fromNativeGlobalPosition(global, window),
+ device, buttons, pressure,
+ xTilt, yTilt, tangentialPressure, rotation, z, modifiers);
}
bool QWindowSystemInterface::handleTabletEvent(QWindow *window, const QPointingDevice *device,
@@ -982,15 +951,9 @@ bool QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(QWindow *windo
Q_UNUSED(rotation);
Q_UNUSED(z);
Q_UNUSED(modifiers);
- if (inProximity) {
- QWindowSystemInterfacePrivate::TabletEnterProximityEvent *e =
- new QWindowSystemInterfacePrivate::TabletEnterProximityEvent(timestamp, device);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
- } else {
- QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *e =
- new QWindowSystemInterfacePrivate::TabletLeaveProximityEvent(timestamp, device);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
- }
+ return inProximity
+ ? handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletEnterProximityEvent>(timestamp, device)
+ : handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletLeaveProximityEvent>(timestamp, device);
}
bool QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(QWindow *window, const QPointingDevice *device,
@@ -1011,9 +974,7 @@ bool QWindowSystemInterface::handleTabletEnterProximityEvent(ulong timestamp, in
const QPointingDevice *device = QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType(deviceType),
QPointingDevice::PointerType(pointerType),
QPointingDeviceUniqueId::fromNumericId(uid));
- QWindowSystemInterfacePrivate::TabletEnterProximityEvent *e =
- new QWindowSystemInterfacePrivate::TabletEnterProximityEvent(timestamp, device);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletEnterProximityEvent>(timestamp, device);
}
void QWindowSystemInterface::handleTabletEnterProximityEvent(int deviceType, int pointerType, qint64 uid)
@@ -1027,9 +988,7 @@ bool QWindowSystemInterface::handleTabletLeaveProximityEvent(ulong timestamp, in
const QPointingDevice *device = QPointingDevicePrivate::tabletDevice(QInputDevice::DeviceType(deviceType),
QPointingDevice::PointerType(pointerType),
QPointingDeviceUniqueId::fromNumericId(uid));
- QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *e =
- new QWindowSystemInterfacePrivate::TabletLeaveProximityEvent(timestamp, device);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::TabletLeaveProximityEvent>(timestamp, device);
}
void QWindowSystemInterface::handleTabletLeaveProximityEvent(int deviceType, int pointerType, qint64 uid)
@@ -1042,37 +1001,30 @@ void QWindowSystemInterface::handleTabletLeaveProximityEvent(int deviceType, int
bool QWindowSystemInterface::handleGestureEvent(QWindow *window, ulong timestamp, const QPointingDevice *device,
Qt::NativeGestureType type, const QPointF &local, const QPointF &global, int fingerCount)
{
- QWindowSystemInterfacePrivate::GestureEvent *e =
- new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, device, fingerCount, local, global);
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return handleGestureEventWithValueAndDelta(window, timestamp, device, type, {}, {}, local, global, fingerCount);
}
bool QWindowSystemInterface::handleGestureEventWithRealValue(QWindow *window, ulong timestamp, const QPointingDevice *device,
Qt::NativeGestureType type, qreal value, const QPointF &local, const QPointF &global, int fingerCount)
{
- QWindowSystemInterfacePrivate::GestureEvent *e =
- new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, device, fingerCount, local, global);
- e->realValue = value;
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ return handleGestureEventWithValueAndDelta(window, timestamp, device, type, value, {}, local, global, fingerCount);
}
bool QWindowSystemInterface::handleGestureEventWithValueAndDelta(QWindow *window, ulong timestamp, const QPointingDevice *device,
Qt::NativeGestureType type, qreal value, const QPointF &delta,
const QPointF &local, const QPointF &global, int fingerCount)
{
- QWindowSystemInterfacePrivate::GestureEvent *e =
- new QWindowSystemInterfacePrivate::GestureEvent(window, timestamp, type, device, fingerCount, local, global);
- e->realValue = value;
- e->delta = delta;
- return QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ auto localPos = QHighDpi::fromNativeLocalPosition(local, window);
+ auto globalPos = QHighDpi::fromNativeGlobalPosition(global, window);
+
+ return handleWindowSystemEvent<QWindowSystemInterfacePrivate::GestureEvent>(window,
+ timestamp, type, device, fingerCount, localPos, globalPos, value, delta);
}
#endif // QT_NO_GESTURES
void QWindowSystemInterface::handlePlatformPanelEvent(QWindow *w)
{
- QWindowSystemInterfacePrivate::PlatformPanelEvent *e =
- new QWindowSystemInterfacePrivate::PlatformPanelEvent(w);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::PlatformPanelEvent>(w);
}
#ifndef QT_NO_CONTEXTMENU
@@ -1080,19 +1032,16 @@ void QWindowSystemInterface::handleContextMenuEvent(QWindow *window, bool mouseT
const QPoint &pos, const QPoint &globalPos,
Qt::KeyboardModifiers modifiers)
{
- QWindowSystemInterfacePrivate::ContextMenuEvent *e =
- new QWindowSystemInterfacePrivate::ContextMenuEvent(window, mouseTriggered, pos,
- globalPos, modifiers);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::ContextMenuEvent>(window,
+ mouseTriggered, pos, globalPos, modifiers);
}
#endif
#if QT_CONFIG(whatsthis)
void QWindowSystemInterface::handleEnterWhatsThisEvent()
{
- QWindowSystemInterfacePrivate::WindowSystemEvent *e =
- new QWindowSystemInterfacePrivate::WindowSystemEvent(QWindowSystemInterfacePrivate::EnterWhatsThisMode);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::WindowSystemEvent>(
+ QWindowSystemInterfacePrivate::EnterWhatsThisMode);
}
#endif
@@ -1114,7 +1063,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo
*/
bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
{
- const int count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count();
+ const qsizetype count = QWindowSystemInterfacePrivate::windowSystemEventQueue.count();
if (!count)
return false;
if (!QGuiApplication::instance()) {
@@ -1128,8 +1077,7 @@ bool QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ProcessEventsFl
// Post a FlushEvents event which will trigger a call back to
// deferredFlushWindowSystemEvents from the Gui thread.
QMutexLocker locker(&QWindowSystemInterfacePrivate::flushEventMutex);
- QWindowSystemInterfacePrivate::FlushEventsEvent *e = new QWindowSystemInterfacePrivate::FlushEventsEvent(flags);
- QWindowSystemInterfacePrivate::handleWindowSystemEvent<AsynchronousDelivery>(e);
+ handleWindowSystemEvent<QWindowSystemInterfacePrivate::FlushEventsEvent, AsynchronousDelivery>(flags);
QWindowSystemInterfacePrivate::eventsFlushed.wait(&QWindowSystemInterfacePrivate::flushEventMutex);
} else {
sendWindowSystemEvents(flags);
@@ -1210,8 +1158,18 @@ Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *window, const QPointF &local, con
timestamp, nativeLocal, nativeGlobal, state, button, type, mods);
}
+/*
+ Used by QTest::simulateEvent() to synthesize key events during testing
+*/
Q_GUI_EXPORT void qt_handleKeyEvent(QWindow *window, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1)
{
+#if defined(Q_OS_MACOS)
+ // FIXME: Move into QTest::simulateEvent() and align with QGuiApplicationPrivate::processKeyEvent()
+ auto timestamp = QWindowSystemInterfacePrivate::eventTime.elapsed();
+ if (t == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window, timestamp, k, mods, 0, 0, 0, text, autorep, count))
+ return;
+#endif
+
QWindowSystemInterface::handleKeyEvent<QWindowSystemInterface::SynchronousDelivery>(window, t, k, mods, text, autorep, count);
}
@@ -1252,13 +1210,20 @@ Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int
#endif
}
+Q_GUI_EXPORT void qt_handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global,
+ QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods,
+ Qt::ScrollPhase phase)
+{
+ QWindowSystemInterface::handleWheelEvent(window, local, global, pixelDelta, angleDelta, mods, phase);
+}
+
namespace QTest
{
- Q_GUI_EXPORT QPointingDevice * createTouchDevice(QInputDevice::DeviceType devType = QInputDevice::DeviceType::TouchScreen,
- QInputDevice::Capabilities caps = QInputDevice::Capability::Position)
+ Q_GUI_EXPORT QPointingDevice * createTouchDevice(QInputDevice::DeviceType devType,
+ QInputDevice::Capabilities caps)
{
static qint64 nextId = 0x100000000;
- QPointingDevice *ret = new QPointingDevice(QLatin1String("test touch device"), nextId++,
+ QPointingDevice *ret = new QPointingDevice("test touch device"_L1, nextId++,
devType, QPointingDevice::PointerType::Finger,
caps, 8, 0);
QWindowSystemInterface::registerInputDevice(ret);
@@ -1266,13 +1231,19 @@ namespace QTest
}
}
-Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *window, const QPointingDevice *device,
+Q_GUI_EXPORT bool qt_handleTouchEventv2(QWindow *window, const QPointingDevice *device,
const QList<QEventPoint> &points,
- Qt::KeyboardModifiers mods = Qt::NoModifier)
+ Qt::KeyboardModifiers mods)
{
- QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(window, device,
+ return QWindowSystemInterface::handleTouchEvent<QWindowSystemInterface::SynchronousDelivery>(window, device,
QWindowSystemInterfacePrivate::toNativeTouchPoints(points, window), mods);
}
+Q_GUI_EXPORT void qt_handleTouchEvent(QWindow *window, const QPointingDevice *device,
+ const QList<QEventPoint> &points,
+ Qt::KeyboardModifiers mods)
+{
+ qt_handleTouchEventv2(window, device, points, mods);
+}
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index cb368d489a..4fc61a475d 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSYSTEMINTERFACE_H
#define QWINDOWSYSTEMINTERFACE_H
@@ -100,31 +64,6 @@ public:
Qt::KeyboardModifiers mods = Qt::NoModifier,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
- static bool handleFrameStrutMouseEvent(QWindow *window, const QPointF &local,
- const QPointF &global, Qt::MouseButtons state,
- Qt::MouseButton button, QEvent::Type type,
- Qt::KeyboardModifiers mods = Qt::NoModifier,
- Qt::MouseEventSource source =
- Qt::MouseEventNotSynthesized);
- static bool handleFrameStrutMouseEvent(QWindow *window, const QPointingDevice *device,
- const QPointF &local, const QPointF &global,
- Qt::MouseButtons state,
- Qt::MouseButton button, QEvent::Type type,
- Qt::KeyboardModifiers mods = Qt::NoModifier,
- Qt::MouseEventSource source =
- Qt::MouseEventNotSynthesized);
- static bool handleFrameStrutMouseEvent(QWindow *window, ulong timestamp, const QPointF &local,
- const QPointF &global, Qt::MouseButtons state,
- Qt::MouseButton button, QEvent::Type type,
- Qt::KeyboardModifiers mods = Qt::NoModifier,
- Qt::MouseEventSource source =
- Qt::MouseEventNotSynthesized);
- static bool handleFrameStrutMouseEvent(QWindow *window, ulong timestamp, const QPointingDevice *device,
- const QPointF &local, const QPointF &global, Qt::MouseButtons state,
- Qt::MouseButton button, QEvent::Type type,
- Qt::KeyboardModifiers mods = Qt::NoModifier,
- Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
-
static bool handleShortcutEvent(QWindow *window, ulong timestamp, int k, Qt::KeyboardModifiers mods, quint32 nativeScanCode,
quint32 nativeVirtualKey, quint32 nativeModifiers, const QString & text = QString(), bool autorep = false, ushort count = 1);
@@ -137,18 +76,18 @@ public:
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text = QString(), bool autorep = false,
- ushort count = 1, bool tryShortcutOverride = true);
+ ushort count = 1);
static bool handleExtendedKeyEvent(QWindow *window, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text = QString(), bool autorep = false,
- ushort count = 1, bool tryShortcutOverride = true);
+ ushort count = 1);
static bool handleExtendedKeyEvent(QWindow *window, ulong timestamp, const QInputDevice *device,
QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
quint32 nativeScanCode, quint32 nativeVirtualKey,
quint32 nativeModifiers,
const QString& text = QString(), bool autorep = false,
- ushort count = 1, bool tryShortcutOverride = true);
+ ushort count = 1);
static bool handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global,
QPoint pixelDelta, QPoint angleDelta,
Qt::KeyboardModifiers mods = Qt::NoModifier,
@@ -218,8 +157,9 @@ public:
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
static void handleLeaveEvent(QWindow *window);
static void handleEnterLeaveEvent(QWindow *enter, QWindow *leave, const QPointF &local = QPointF(), const QPointF& global = QPointF());
+
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleWindowActivated(QWindow *window, Qt::FocusReason r = Qt::OtherFocusReason);
+ static void handleFocusWindowChanged(QWindow *window, Qt::FocusReason r = Qt::OtherFocusReason);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
static void handleWindowStateChanged(QWindow *window, Qt::WindowStates newState, int oldState = -1);
@@ -227,6 +167,9 @@ public:
static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
+ static void handleWindowDevicePixelRatioChanged(QWindow *window);
+
+ template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
static void handleSafeAreaMarginsChanged(QWindow *window);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
@@ -257,7 +200,7 @@ public:
static void handleScreenRefreshRateChange(QScreen *screen, qreal newRefreshRate);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleThemeChange(QWindow *window);
+ static void handleThemeChange(QWindow *window = nullptr);
static void handleFileOpenEvent(const QString& fileName);
static void handleFileOpenEvent(const QUrl &url);
@@ -288,6 +231,8 @@ public:
Qt::MouseButtons buttons = {}, int xTilt = 0, int yTilt = 0,
qreal tangentialPressure = 0, qreal rotation = 0, int z = 0,
Qt::KeyboardModifiers modifiers = Qt::NoModifier);
+
+ // The following 4 functions are deprecated (QTBUG-114560)
static bool handleTabletEnterProximityEvent(ulong timestamp, int deviceType, int pointerType, qint64 uid);
static void handleTabletEnterProximityEvent(int deviceType, int pointerType, qint64 uid);
static bool handleTabletLeaveProximityEvent(ulong timestamp, int deviceType, int pointerType, qint64 uid);
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index 323fa92ce0..51ab58fc99 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSYSTEMINTERFACE_P_H
#define QWINDOWSYSTEMINTERFACE_P_H
@@ -76,7 +40,7 @@ public:
GeometryChange = 0x02,
Enter = UserInputEvent | 0x03,
Leave = UserInputEvent | 0x04,
- ActivatedWindow = 0x05,
+ FocusWindow = 0x05,
WindowStateChanged = 0x06,
Mouse = UserInputEvent | 0x07,
Wheel = UserInputEvent | 0x09,
@@ -104,7 +68,8 @@ public:
WindowScreenChanged = 0x21,
SafeAreaMarginsChanged = 0x22,
ApplicationTermination = 0x23,
- Paint = 0x24
+ Paint = 0x24,
+ WindowDevicePixelRatioChanged = 0x25,
};
class WindowSystemEvent {
@@ -160,12 +125,12 @@ public:
QPointer<QWindow> leave;
};
- class ActivatedWindowEvent : public WindowSystemEvent {
+ class FocusWindowEvent : public WindowSystemEvent {
public:
- explicit ActivatedWindowEvent(QWindow *activatedWindow, Qt::FocusReason r)
- : WindowSystemEvent(ActivatedWindow), activated(activatedWindow), reason(r)
+ explicit FocusWindowEvent(QWindow *focusedWindow, Qt::FocusReason r)
+ : WindowSystemEvent(FocusWindow), focused(focusedWindow), reason(r)
{ }
- QPointer<QWindow> activated;
+ QPointer<QWindow> focused;
Qt::FocusReason reason;
};
@@ -190,6 +155,15 @@ public:
QPointer<QScreen> screen;
};
+ class WindowDevicePixelRatioChangedEvent : public WindowSystemEvent {
+ public:
+ WindowDevicePixelRatioChangedEvent(QWindow *w)
+ : WindowSystemEvent(WindowDevicePixelRatioChanged), window(w)
+ { }
+
+ QPointer<QWindow> window;
+ };
+
class SafeAreaMarginsChangedEvent : public WindowSystemEvent {
public:
SafeAreaMarginsChangedEvent(QWindow *w)
@@ -452,9 +426,9 @@ public:
class GestureEvent : public PointerEvent {
public:
GestureEvent(QWindow *window, ulong time, Qt::NativeGestureType type, const QPointingDevice *dev,
- int fingerCount, QPointF pos, QPointF globalPos)
+ int fingerCount, QPointF pos, QPointF globalPos, qreal realValue, QPointF delta)
: PointerEvent(window, time, Gesture, Qt::NoModifier, dev), type(type), pos(pos), globalPos(globalPos),
- fingerCount(fingerCount), realValue(0), sequenceId(0), intValue(0) { }
+ delta(delta), fingerCount(fingerCount), realValue(realValue), sequenceId(0), intValue(0) { }
Qt::NativeGestureType type;
QPointF pos;
QPointF globalPos;
@@ -499,8 +473,8 @@ public:
}
void append(WindowSystemEvent *e)
{ const QMutexLocker locker(&mutex); impl.append(e); }
- int count() const
- { const QMutexLocker locker(&mutex); return impl.count(); }
+ qsizetype count() const
+ { const QMutexLocker locker(&mutex); return impl.size(); }
WindowSystemEvent *peekAtFirstOfType(EventType t) const
{
const QMutexLocker locker(&mutex);
@@ -526,14 +500,12 @@ public:
static WindowSystemEventList windowSystemEventQueue;
- static int windowSystemEventsQueued();
+ static qsizetype windowSystemEventsQueued();
static bool nonUserInputEventsQueued();
static WindowSystemEvent *getWindowSystemEvent();
static WindowSystemEvent *getNonUserInputWindowSystemEvent();
static WindowSystemEvent *peekWindowSystemEvent(EventType t);
static void removeWindowSystemEvent(WindowSystemEvent *event);
- template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static bool handleWindowSystemEvent(WindowSystemEvent *ev);
public:
static QElapsedTimer eventTime;
diff --git a/src/gui/math3d/qgenericmatrix.cpp b/src/gui/math3d/qgenericmatrix.cpp
index cf79ed9786..7ffb53a88b 100644
--- a/src/gui/math3d/qgenericmatrix.cpp
+++ b/src/gui/math3d/qgenericmatrix.cpp
@@ -1,46 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgenericmatrix.h"
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QMatrix2x2)
+QT_IMPL_METATYPE_EXTERN(QMatrix2x3)
+QT_IMPL_METATYPE_EXTERN(QMatrix2x4)
+QT_IMPL_METATYPE_EXTERN(QMatrix3x2)
+QT_IMPL_METATYPE_EXTERN(QMatrix3x3)
+QT_IMPL_METATYPE_EXTERN(QMatrix3x4)
+QT_IMPL_METATYPE_EXTERN(QMatrix4x2)
+QT_IMPL_METATYPE_EXTERN(QMatrix4x3)
+
/*!
\class QGenericMatrix
\brief The QGenericMatrix class is a template class that represents a NxM transformation matrix with N columns and M rows.
diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h
index 9d8869ff3a..1e20df5a6b 100644
--- a/src/gui/math3d/qgenericmatrix.h
+++ b/src/gui/math3d/qgenericmatrix.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGENERICMATRIX_H
#define QGENERICMATRIX_H
@@ -79,7 +43,6 @@ public:
const T *data() const { return *m; }
const T *constData() const { return *m; }
-#if !defined(Q_NO_TEMPLATE_FRIENDS)
template<int NN, int MM, typename TT>
friend QGenericMatrix<NN, MM, TT> operator+(const QGenericMatrix<NN, MM, TT>& m1, const QGenericMatrix<NN, MM, TT>& m2);
template<int NN, int MM, typename TT>
@@ -96,13 +59,10 @@ public:
friend QGenericMatrix<NN, MM, TT> operator/(const QGenericMatrix<NN, MM, TT>& matrix, TT divisor);
private:
-#endif
T m[N][M]; // Column-major order to match OpenGL.
-#if !defined(Q_NO_TEMPLATE_FRIENDS)
template <int NN, int MM, typename TT>
friend class QGenericMatrix;
-#endif
};
template <int N, int M, typename T>
class QTypeInfo<QGenericMatrix<N, M, T> >
@@ -385,13 +345,13 @@ QDataStream &operator>>(QDataStream &stream, QGenericMatrix<N, M, T> &matrix)
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QMatrix2x2)
-Q_DECLARE_METATYPE(QMatrix2x3)
-Q_DECLARE_METATYPE(QMatrix2x4)
-Q_DECLARE_METATYPE(QMatrix3x2)
-Q_DECLARE_METATYPE(QMatrix3x3)
-Q_DECLARE_METATYPE(QMatrix3x4)
-Q_DECLARE_METATYPE(QMatrix4x2)
-Q_DECLARE_METATYPE(QMatrix4x3)
+QT_DECL_METATYPE_EXTERN(QMatrix2x2, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QMatrix2x3, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QMatrix2x4, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QMatrix3x2, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QMatrix3x3, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QMatrix3x4, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QMatrix4x2, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QMatrix4x3, Q_GUI_EXPORT)
#endif
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index 752b4944d0..d04a502519 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmatrix4x4.h"
#include <QtCore/qmath.h>
@@ -136,7 +100,7 @@ QMatrix4x4::QMatrix4x4(const float *values)
*/
/*!
- \fn QGenericMatrix<N, M, float> QMatrix4x4::toGenericMatrix() const
+ \fn template <int N, int M> QGenericMatrix<N, M, float> QMatrix4x4::toGenericMatrix() const
Constructs a NxM generic matrix from the left-most N columns and
top-most M rows of this 4x4 matrix. If N or M is greater than 4,
@@ -633,7 +597,7 @@ QMatrix4x4& QMatrix4x4::operator/=(float divisor)
\fn QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
\relates QMatrix4x4
- \deprecated Convert the QVector3D to a QVector4D first, then multiply.
+ \deprecated [6.1] Convert the QVector3D to a QVector4D with 1.0 as the w coordinate, then multiply.
Returns the result of transforming \a vector according to \a matrix,
with the matrix applied post-vector. The vector is transformed as a point.
@@ -643,7 +607,7 @@ QMatrix4x4& QMatrix4x4::operator/=(float divisor)
\fn QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
\relates QMatrix4x4
- \deprecated Use QMatrix4x4::map() or QMatrix4x4::mapVector() instead.
+ \deprecated [6.1] Use QMatrix4x4::map() instead.
Returns the result of transforming \a vector according to \a matrix,
with the matrix applied pre-vector. The vector is transformed as a
@@ -696,7 +660,7 @@ QMatrix4x4& QMatrix4x4::operator/=(float divisor)
\fn QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
\relates QMatrix4x4
- \deprecated Use QMatrix4x4::map() instead.
+ \deprecated [6.1] Use QMatrix4x4::map() instead.
Returns the result of transforming \a point according to \a matrix,
with the matrix applied pre-point.
@@ -706,7 +670,7 @@ QMatrix4x4& QMatrix4x4::operator/=(float divisor)
\fn QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
\relates QMatrix4x4
- \deprecated Use QMatrix4x4::map() instead.
+ \deprecated [6.1] Use QMatrix4x4::map() instead.
Returns the result of transforming \a point according to \a matrix,
with the matrix applied pre-point.
@@ -1200,12 +1164,15 @@ void QMatrix4x4::rotate(float angle, float x, float y, float z)
/*!
\internal
*/
-void QMatrix4x4::projectedRotate(float angle, float x, float y, float z)
+void QMatrix4x4::projectedRotate(float angle, float x, float y, float z, float distanceToPlane)
{
// Used by QGraphicsRotation::applyTo() to perform a rotation
// and projection back to 2D in a single step.
+ if (qIsNull(distanceToPlane))
+ return rotate(angle, x, y, z);
if (angle == 0.0f)
return;
+
float c, s;
if (angle == 90.0f || angle == -270.0f) {
s = 1.0f;
@@ -1221,6 +1188,8 @@ void QMatrix4x4::projectedRotate(float angle, float x, float y, float z)
c = std::cos(a);
s = std::sin(a);
}
+
+ const qreal d = 1.0 / distanceToPlane;
if (x == 0.0f) {
if (y == 0.0f) {
if (z != 0.0f) {
@@ -1244,10 +1213,11 @@ void QMatrix4x4::projectedRotate(float angle, float x, float y, float z)
// Rotate around the Y axis.
if (y < 0)
s = -s;
- m[0][0] = m[0][0] * c + m[3][0] * s * inv_dist_to_plane;
- m[0][1] = m[0][1] * c + m[3][1] * s * inv_dist_to_plane;
- m[0][2] = m[0][2] * c + m[3][2] * s * inv_dist_to_plane;
- m[0][3] = m[0][3] * c + m[3][3] * s * inv_dist_to_plane;
+ s *= d;
+ m[0][0] = m[0][0] * c + m[3][0] * s;
+ m[0][1] = m[0][1] * c + m[3][1] * s;
+ m[0][2] = m[0][2] * c + m[3][2] * s;
+ m[0][3] = m[0][3] * c + m[3][3] * s;
flagBits = General;
return;
}
@@ -1255,10 +1225,11 @@ void QMatrix4x4::projectedRotate(float angle, float x, float y, float z)
// Rotate around the X axis.
if (x < 0)
s = -s;
- m[1][0] = m[1][0] * c - m[3][0] * s * inv_dist_to_plane;
- m[1][1] = m[1][1] * c - m[3][1] * s * inv_dist_to_plane;
- m[1][2] = m[1][2] * c - m[3][2] * s * inv_dist_to_plane;
- m[1][3] = m[1][3] * c - m[3][3] * s * inv_dist_to_plane;
+ s *= d;
+ m[1][0] = m[1][0] * c - m[3][0] * s;
+ m[1][1] = m[1][1] * c - m[3][1] * s;
+ m[1][2] = m[1][2] * c - m[3][2] * s;
+ m[1][3] = m[1][3] * c - m[3][3] * s;
flagBits = General;
return;
}
@@ -1285,14 +1256,24 @@ void QMatrix4x4::projectedRotate(float angle, float x, float y, float z)
rot.m[1][2] = 0.0f;
rot.m[2][2] = 1.0f;
rot.m[3][2] = 0.0f;
- rot.m[0][3] = (x * z * ic - y * s) * -inv_dist_to_plane;
- rot.m[1][3] = (y * z * ic + x * s) * -inv_dist_to_plane;
+ rot.m[0][3] = (x * z * ic - y * s) * -d;
+ rot.m[1][3] = (y * z * ic + x * s) * -d;
rot.m[2][3] = 0.0f;
rot.m[3][3] = 1.0f;
rot.flagBits = General;
*this *= rot;
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+/*!
+ \internal
+*/
+void QMatrix4x4::projectedRotate(float angle, float x, float y, float z)
+{
+ projectedRotate(angle, x, y, z, 1024.0);
+}
+#endif
+
/*!
\fn int QMatrix4x4::flags() const
\internal
@@ -1617,7 +1598,7 @@ void QMatrix4x4::viewport(float left, float bottom, float width, float height, f
\deprecated
Flips between right-handed and left-handed coordinate systems
- by multiplying the y and z co-ordinates by -1. This is normally
+ by multiplying the y and z coordinates by -1. This is normally
used to create a left-handed orthographic view without scaling
the viewport as ortho() does.
@@ -1662,7 +1643,7 @@ void QMatrix4x4::copyDataTo(float *values) const
The returned QTransform is formed by simply dropping the
third row and third column of the QMatrix4x4. This is suitable
- for implementing orthographic projections where the z co-ordinate
+ for implementing orthographic projections where the z coordinate
should be dropped rather than projected.
*/
QTransform QMatrix4x4::toTransform() const
@@ -1677,14 +1658,14 @@ QTransform QMatrix4x4::toTransform() const
corresponds to this matrix.
If \a distanceToPlane is non-zero, it indicates a projection
- factor to use to adjust for the z co-ordinate. The value of
+ factor to use to adjust for the z coordinate. The value of
1024 corresponds to the projection factor used
by QTransform::rotate() for the x and y axes.
If \a distanceToPlane is zero, then the returned QTransform
is formed by simply dropping the third row and third column
of the QMatrix4x4. This is suitable for implementing
- orthographic projections where the z co-ordinate should
+ orthographic projections where the z coordinate should
be dropped rather than projected.
*/
QTransform QMatrix4x4::toTransform(float distanceToPlane) const
@@ -1737,8 +1718,12 @@ QTransform QMatrix4x4::toTransform(float distanceToPlane) const
/*!
\fn QVector3D QMatrix4x4::map(const QVector3D& point) const
- Maps \a point by multiplying this matrix by \a point.
- The matrix is applied pre-point.
+ Maps \a point by multiplying this matrix by \a point extended to a 4D
+ vector by assuming 1.0 for the w coordinate. The matrix is applied
+ pre-point.
+
+ \note This function is not the same as mapVector(). For points, always use
+ map(). mapVector() is suitable for vectors (directions) only.
\sa mapRect(), mapVector()
*/
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
index 15c5cabbf2..f8e5bc4314 100644
--- a/src/gui/math3d/qmatrix4x4.h
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMATRIX4X4_H
#define QMATRIX4X4_H
@@ -190,7 +154,13 @@ public:
friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
#endif
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ void projectedRotate(float angle, float x, float y, float z, float distanceToPlane);
+ // ### Qt7: Remove
void projectedRotate(float angle, float x, float y, float z);
+#else
+ void projectedRotate(float angle, float x, float y, float z, float distanceToPlane = 1024.0);
+#endif
// When matrices are multiplied, the flag bits are or-ed together.
// Note that the ordering of the bit values matters. (ident < t < s < r2d < r < p)
@@ -434,7 +404,7 @@ inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& o)
const QMatrix4x4 other = o; // prevent aliasing when &o == this ### Qt 6: take o by value
flagBits |= other.flagBits;
- if (flagBits < Rotation2D) {
+ if (flagBits.toInt() < Rotation2D) {
m[3][0] += m[0][0] * other.m[3][0];
m[3][1] += m[1][1] * other.m[3][1];
m[3][2] += m[2][2] * other.m[3][2];
@@ -637,7 +607,7 @@ inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
{
QMatrix4x4::Flags flagBits = m1.flagBits | m2.flagBits;
- if (flagBits < QMatrix4x4::Rotation2D) {
+ if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
QMatrix4x4 m = m1;
m.m[3][0] += m.m[0][0] * m2.m[3][0];
m.m[3][1] += m.m[1][1] * m2.m[3][1];
@@ -726,7 +696,7 @@ inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
#if QT_DEPRECATED_SINCE(6, 1)
-QT_DEPRECATED_VERSION_X_6_1("Extend the QVector3D to a QVector4D before multiplying")
+QT_DEPRECATED_VERSION_X_6_1("Extend the QVector3D to a QVector4D with 1.0 as the w coordinate before multiplying")
inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
{
float x, y, z, w;
@@ -752,7 +722,7 @@ inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
return QVector3D(x / w, y / w, z / w);
}
-QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(vector) or matrix.mapVector(vector) instead")
+QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(vector) instead")
inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
{
return matrix.map(vector);
@@ -943,11 +913,11 @@ inline QPoint QMatrix4x4::map(const QPoint& point) const
yin = point.y();
if (flagBits == QMatrix4x4::Identity) {
return point;
- } else if (flagBits < QMatrix4x4::Rotation2D) {
+ } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
// Translation | Scale
return QPoint(qRound(xin * m[0][0] + m[3][0]),
qRound(yin * m[1][1] + m[3][1]));
- } else if (flagBits < QMatrix4x4::Perspective) {
+ } else if (flagBits.toInt() < QMatrix4x4::Perspective) {
return QPoint(qRound(xin * m[0][0] + yin * m[1][0] + m[3][0]),
qRound(xin * m[0][1] + yin * m[1][1] + m[3][1]));
} else {
@@ -975,11 +945,11 @@ inline QPointF QMatrix4x4::map(const QPointF& point) const
yin = point.y();
if (flagBits == QMatrix4x4::Identity) {
return point;
- } else if (flagBits < QMatrix4x4::Rotation2D) {
+ } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
// Translation | Scale
return QPointF(xin * qreal(m[0][0]) + qreal(m[3][0]),
yin * qreal(m[1][1]) + qreal(m[3][1]));
- } else if (flagBits < QMatrix4x4::Perspective) {
+ } else if (flagBits.toInt() < QMatrix4x4::Perspective) {
return QPointF(xin * qreal(m[0][0]) + yin * qreal(m[1][0]) +
qreal(m[3][0]),
xin * qreal(m[0][1]) + yin * qreal(m[1][1]) +
@@ -1009,12 +979,12 @@ inline QVector3D QMatrix4x4::map(const QVector3D& point) const
float x, y, z, w;
if (flagBits == QMatrix4x4::Identity) {
return point;
- } else if (flagBits < QMatrix4x4::Rotation2D) {
+ } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
// Translation | Scale
return QVector3D(point.x() * m[0][0] + m[3][0],
point.y() * m[1][1] + m[3][1],
point.z() * m[2][2] + m[3][2]);
- } else if (flagBits < QMatrix4x4::Rotation) {
+ } else if (flagBits.toInt() < QMatrix4x4::Rotation) {
// Translation | Scale | Rotation2D
return QVector3D(point.x() * m[0][0] + point.y() * m[1][0] + m[3][0],
point.x() * m[0][1] + point.y() * m[1][1] + m[3][1],
@@ -1045,10 +1015,10 @@ inline QVector3D QMatrix4x4::map(const QVector3D& point) const
inline QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const
{
- if (flagBits < Scale) {
+ if (flagBits.toInt() < Scale) {
// Translation
return vector;
- } else if (flagBits < Rotation2D) {
+ } else if (flagBits.toInt() < Rotation2D) {
// Translation | Scale
return QVector3D(vector.x() * m[0][0],
vector.y() * m[1][1],
diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp
index ba82aaa737..e7c5945208 100644
--- a/src/gui/math3d/qquaternion.cpp
+++ b/src/gui/math3d/qquaternion.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qquaternion.h"
#include <QtCore/qdatastream.h>
@@ -62,14 +26,14 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QQuaternion::QQuaternion()
+ \fn QQuaternion::QQuaternion() noexcept
Constructs an identity quaternion (1, 0, 0, 0), i.e. with the vector (0, 0, 0)
and scalar 1.
*/
/*!
- \fn QQuaternion::QQuaternion(Qt::Initialization)
+ \fn QQuaternion::QQuaternion(Qt::Initialization) noexcept
\since 5.5
\internal
@@ -77,7 +41,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QQuaternion::QQuaternion(float scalar, float xpos, float ypos, float zpos)
+ \fn QQuaternion::QQuaternion(float scalar, float xpos, float ypos, float zpos) noexcept
Constructs a quaternion with the vector (\a xpos, \a ypos, \a zpos)
and \a scalar.
@@ -86,7 +50,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_VECTOR3D
/*!
- \fn QQuaternion::QQuaternion(float scalar, const QVector3D& vector)
+ \fn QQuaternion::QQuaternion(float scalar, const QVector3D &vector) noexcept
Constructs a quaternion vector from the specified \a vector and
\a scalar.
@@ -95,7 +59,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QVector3D QQuaternion::vector() const
+ \fn QVector3D QQuaternion::vector() const noexcept
Returns the vector component of this quaternion.
@@ -103,7 +67,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QQuaternion::setVector(const QVector3D& vector)
+ \fn void QQuaternion::setVector(const QVector3D &vector) noexcept
Sets the vector component of this quaternion to \a vector.
@@ -113,7 +77,7 @@ QT_BEGIN_NAMESPACE
#endif
/*!
- \fn void QQuaternion::setVector(float x, float y, float z)
+ \fn void QQuaternion::setVector(float x, float y, float z) noexcept
Sets the vector component of this quaternion to (\a x, \a y, \a z).
@@ -123,13 +87,13 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_VECTOR4D
/*!
- \fn QQuaternion::QQuaternion(const QVector4D& vector)
+ \fn QQuaternion::QQuaternion(const QVector4D &vector) noexcept
Constructs a quaternion from the components of \a vector.
*/
/*!
- \fn QVector4D QQuaternion::toVector4D() const
+ \fn QVector4D QQuaternion::toVector4D() const noexcept
Returns this quaternion as a 4D vector.
*/
@@ -137,14 +101,14 @@ QT_BEGIN_NAMESPACE
#endif
/*!
- \fn bool QQuaternion::isNull() const
+ \fn bool QQuaternion::isNull() const noexcept
Returns \c true if the x, y, z, and scalar components of this
quaternion are set to 0.0; otherwise returns \c false.
*/
/*!
- \fn bool QQuaternion::isIdentity() const
+ \fn bool QQuaternion::isIdentity() const noexcept
Returns \c true if the x, y, and z components of this
quaternion are set to 0.0, and the scalar component is set
@@ -152,7 +116,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn float QQuaternion::x() const
+ \fn float QQuaternion::x() const noexcept
Returns the x coordinate of this quaternion's vector.
@@ -160,7 +124,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn float QQuaternion::y() const
+ \fn float QQuaternion::y() const noexcept
Returns the y coordinate of this quaternion's vector.
@@ -168,7 +132,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn float QQuaternion::z() const
+ \fn float QQuaternion::z() const noexcept
Returns the z coordinate of this quaternion's vector.
@@ -176,7 +140,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn float QQuaternion::scalar() const
+ \fn float QQuaternion::scalar() const noexcept
Returns the scalar component of this quaternion.
@@ -184,7 +148,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QQuaternion::setX(float x)
+ \fn void QQuaternion::setX(float x) noexcept
Sets the x coordinate of this quaternion's vector to the given
\a x coordinate.
@@ -193,7 +157,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QQuaternion::setY(float y)
+ \fn void QQuaternion::setY(float y) noexcept
Sets the y coordinate of this quaternion's vector to the given
\a y coordinate.
@@ -202,7 +166,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QQuaternion::setZ(float z)
+ \fn void QQuaternion::setZ(float z) noexcept
Sets the z coordinate of this quaternion's vector to the given
\a z coordinate.
@@ -211,7 +175,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QQuaternion::setScalar(float scalar)
+ \fn void QQuaternion::setScalar(float scalar) noexcept
Sets the scalar component of this quaternion to \a scalar.
@@ -219,7 +183,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn float QQuaternion::dotProduct(const QQuaternion &q1, const QQuaternion &q2)
+ \fn float QQuaternion::dotProduct(const QQuaternion &q1, const QQuaternion &q2) noexcept
\since 5.5
Returns the dot product of \a q1 and \a q2.
@@ -263,8 +227,6 @@ float QQuaternion::lengthSquared() const
QQuaternion QQuaternion::normalized() const
{
const float scale = length();
- if (qFuzzyCompare(scale, 1.0f))
- return *this;
if (qFuzzyIsNull(scale))
return QQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
return *this / scale;
@@ -279,7 +241,7 @@ QQuaternion QQuaternion::normalized() const
void QQuaternion::normalize()
{
const float len = length();
- if (qFuzzyCompare(len, 1.0f) || qFuzzyIsNull(len))
+ if (qFuzzyIsNull(len))
return;
xp /= len;
@@ -289,7 +251,7 @@ void QQuaternion::normalize()
}
/*!
- \fn QQuaternion QQuaternion::inverted() const
+ \fn QQuaternion QQuaternion::inverted() const noexcept
\since 5.5
Returns the inverse of this quaternion.
@@ -299,7 +261,7 @@ void QQuaternion::normalize()
*/
/*!
- \fn QQuaternion QQuaternion::conjugated() const
+ \fn QQuaternion QQuaternion::conjugated() const noexcept
\since 5.5
Returns the conjugate of this quaternion, which is
@@ -316,13 +278,13 @@ void QQuaternion::normalize()
\snippet code/src_gui_math3d_qquaternion.cpp 1
*/
-QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const
+QVector3D QQuaternion::rotatedVector(const QVector3D &vector) const
{
return (*this * QQuaternion(0, vector) * conjugated()).vector();
}
/*!
- \fn QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)
+ \fn QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion) noexcept
Adds the given \a quaternion to this quaternion and returns a reference to
this quaternion.
@@ -331,7 +293,7 @@ QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const
*/
/*!
- \fn QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion)
+ \fn QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion) noexcept
Subtracts the given \a quaternion from this quaternion and returns a
reference to this quaternion.
@@ -340,7 +302,7 @@ QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const
*/
/*!
- \fn QQuaternion &QQuaternion::operator*=(float factor)
+ \fn QQuaternion &QQuaternion::operator*=(float factor) noexcept
Multiplies this quaternion's components by the given \a factor, and
returns a reference to this quaternion.
@@ -349,7 +311,7 @@ QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const
*/
/*!
- \fn QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion)
+ \fn QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion) noexcept
Multiplies this quaternion by \a quaternion and returns a reference
to this quaternion.
@@ -367,7 +329,7 @@ QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const
#ifndef QT_NO_VECTOR3D
/*!
- \fn void QQuaternion::getAxisAndAngle(QVector3D *axis, float *angle) const
+ \fn void QQuaternion::getAxisAndAngle(QVector3D *axis, float *angle) const noexcept
\since 5.5
\overload
@@ -383,7 +345,7 @@ QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const
\sa getAxisAndAngle()
*/
-QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D& axis, float angle)
+QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D &axis, float angle)
{
// Algorithm from:
// http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56
@@ -424,7 +386,7 @@ void QQuaternion::getAxisAndAngle(float *x, float *y, float *z, float *angle) co
*y = yp / length;
*z = zp / length;
}
- *angle = qRadiansToDegrees(2.0f * std::acos(wp));
+ *angle = qRadiansToDegrees(2.0f * std::atan2(length, wp));
} else {
// angle is 0 (mod 2*pi), so any axis will fit
*x = *y = *z = *angle = 0.0f;
@@ -492,10 +454,14 @@ void QQuaternion::getEulerAngles(float *pitch, float *yaw, float *roll) const
Q_ASSERT(pitch && yaw && roll);
// Algorithm adapted from:
- // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q37
+ // https://ingmec.ual.es/~jlblanco/papers/jlblanco2010geometry3D_techrep.pdf
+ // "A tutorial on SE(3) transformation parameterizations and on-manifold optimization".
+ // We can only detect Gimbal lock when we normalize, which we can't do when
+ // length is nearly zero. Do so before multiplying coordinates, to avoid
+ // underflow.
const float len = length();
- const bool rescale = !qFuzzyCompare(len, 1.0f) && !qFuzzyIsNull(len);
+ const bool rescale = !qFuzzyIsNull(len);
const float xps = rescale ? xp / len : xp;
const float yps = rescale ? yp / len : yp;
const float zps = rescale ? zp / len : zp;
@@ -511,24 +477,23 @@ void QQuaternion::getEulerAngles(float *pitch, float *yaw, float *roll) const
const float zz = zps * zps;
const float zw = zps * wps;
+ // For the common case, we have a hidden division by cos(pitch) to calculate
+ // yaw and roll: atan2(a / cos(pitch), b / cos(pitch)) = atan2(a, b). This equation
+ // wouldn't work if cos(pitch) is close to zero (i.e. abs(sin(pitch)) =~ 1.0).
+ // This threshold is copied from qFuzzyIsNull() to avoid the hidden division by zero.
+ constexpr float epsilon = 0.00001f;
+
const float sinp = -2.0f * (yz - xw);
- if (std::abs(sinp) >= 1.0f)
- *pitch = std::copysign(M_PI_2, sinp);
- else
+ if (std::abs(sinp) < 1.0f - epsilon) {
*pitch = std::asin(sinp);
- if (*pitch < M_PI_2) {
- if (*pitch > -M_PI_2) {
- *yaw = std::atan2(2.0f * (xz + yw), 1.0f - 2.0f * (xx + yy));
- *roll = std::atan2(2.0f * (xy + zw), 1.0f - 2.0f * (xx + zz));
- } else {
- // not a unique solution
- *roll = 0.0f;
- *yaw = -std::atan2(-2.0f * (xy - zw), 1.0f - 2.0f * (yy + zz));
- }
+ *yaw = std::atan2(2.0f * (xz + yw), 1.0f - 2.0f * (xx + yy));
+ *roll = std::atan2(2.0f * (xy + zw), 1.0f - 2.0f * (xx + zz));
} else {
- // not a unique solution
+ // Gimbal lock case, which doesn't have a unique solution. We just use
+ // XY rotation.
+ *pitch = std::copysign(static_cast<float>(M_PI_2), sinp);
+ *yaw = 2.0f * std::atan2(yps, wps);
*roll = 0.0f;
- *yaw = std::atan2(-2.0f * (xy - zw), 1.0f - 2.0f * (yy + zz));
}
*pitch = qRadiansToDegrees(*pitch);
@@ -773,21 +738,21 @@ QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
#endif // QT_NO_VECTOR3D
/*!
- \fn bool QQuaternion::operator==(const QQuaternion &q1, const QQuaternion &q2)
+ \fn bool QQuaternion::operator==(const QQuaternion &q1, const QQuaternion &q2) noexcept
Returns \c true if \a q1 is equal to \a q2; otherwise returns \c false.
This operator uses an exact floating-point comparison.
*/
/*!
- \fn bool QQuaternion::operator!=(const QQuaternion &q1, const QQuaternion &q2)
+ \fn bool QQuaternion::operator!=(const QQuaternion &q1, const QQuaternion &q2) noexcept
Returns \c true if \a q1 is not equal to \a q2; otherwise returns \c false.
This operator uses an exact floating-point comparison.
*/
/*!
- \fn const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2)
+ \fn const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2) noexcept
\relates QQuaternion
Returns a QQuaternion object that is the sum of the given quaternions,
@@ -797,7 +762,7 @@ QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
*/
/*!
- \fn const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2)
+ \fn const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2) noexcept
\relates QQuaternion
Returns a QQuaternion object that is formed by subtracting
@@ -807,7 +772,7 @@ QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
*/
/*!
- \fn const QQuaternion operator*(float factor, const QQuaternion &quaternion)
+ \fn const QQuaternion operator*(float factor, const QQuaternion &quaternion) noexcept
\relates QQuaternion
Returns a copy of the given \a quaternion, multiplied by the
@@ -817,7 +782,7 @@ QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
*/
/*!
- \fn const QQuaternion operator*(const QQuaternion &quaternion, float factor)
+ \fn const QQuaternion operator*(const QQuaternion &quaternion, float factor) noexcept
\relates QQuaternion
Returns a copy of the given \a quaternion, multiplied by the
@@ -827,7 +792,7 @@ QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
*/
/*!
- \fn const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)
+ \fn const QQuaternion operator*(const QQuaternion &q1, const QQuaternion &q2) noexcept
\relates QQuaternion
Multiplies \a q1 and \a q2 using quaternion multiplication.
@@ -838,7 +803,7 @@ QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
*/
/*!
- \fn const QQuaternion operator-(const QQuaternion &quaternion)
+ \fn const QQuaternion operator-(const QQuaternion &quaternion) noexcept
\relates QQuaternion
\overload
@@ -861,7 +826,7 @@ QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
#ifndef QT_NO_VECTOR3D
/*!
- \fn QVector3D operator*(const QQuaternion &quaternion, const QVector3D &vec)
+ \fn QVector3D operator*(const QQuaternion &quaternion, const QVector3D &vec) noexcept
\since 5.5
\relates QQuaternion
@@ -871,7 +836,7 @@ QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
#endif
/*!
- \fn bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2)
+ \fn bool qFuzzyCompare(const QQuaternion &q1, const QQuaternion &q2) noexcept
\relates QQuaternion
Returns \c true if \a q1 and \a q2 are equal, allowing for a small
@@ -890,7 +855,7 @@ QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
\sa nlerp()
*/
QQuaternion QQuaternion::slerp
- (const QQuaternion& q1, const QQuaternion& q2, float t)
+ (const QQuaternion &q1, const QQuaternion &q2, float t)
{
// Handle the easy cases first.
if (t <= 0.0f)
@@ -939,7 +904,7 @@ QQuaternion QQuaternion::slerp
\sa slerp()
*/
QQuaternion QQuaternion::nlerp
- (const QQuaternion& q1, const QQuaternion& q2, float t)
+ (const QQuaternion &q1, const QQuaternion &q2, float t)
{
// Handle the easy cases first.
if (t <= 0.0f)
diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h
index 4d04ac6ad9..7cfbd9b818 100644
--- a/src/gui/math3d/qquaternion.h
+++ b/src/gui/math3d/qquaternion.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QQUATERNION_H
#define QQUATERNION_H
@@ -53,117 +17,123 @@ QT_BEGIN_NAMESPACE
class QMatrix4x4;
class QVariant;
-class Q_GUI_EXPORT QQuaternion
+class QT6_ONLY(Q_GUI_EXPORT) QQuaternion
{
public:
- QQuaternion();
- explicit QQuaternion(Qt::Initialization) {}
- QQuaternion(float scalar, float xpos, float ypos, float zpos);
+ constexpr QQuaternion() noexcept;
+ explicit QQuaternion(Qt::Initialization) noexcept {}
+ constexpr QQuaternion(float scalar, float xpos, float ypos, float zpos) noexcept;
#ifndef QT_NO_VECTOR3D
- QQuaternion(float scalar, const QVector3D& vector);
+ constexpr QQuaternion(float scalar, const QVector3D &vector) noexcept;
#endif
#ifndef QT_NO_VECTOR4D
- explicit QQuaternion(const QVector4D& vector);
+ constexpr explicit QQuaternion(const QVector4D &vector) noexcept;
#endif
- bool isNull() const;
- bool isIdentity() const;
+ constexpr bool isNull() const noexcept;
+ constexpr bool isIdentity() const noexcept;
#ifndef QT_NO_VECTOR3D
- QVector3D vector() const;
- void setVector(const QVector3D& vector);
+ constexpr QVector3D vector() const noexcept;
+ constexpr void setVector(const QVector3D &vector) noexcept;
#endif
- void setVector(float x, float y, float z);
+ constexpr void setVector(float x, float y, float z) noexcept;
- float x() const;
- float y() const;
- float z() const;
- float scalar() const;
+ constexpr float x() const noexcept;
+ constexpr float y() const noexcept;
+ constexpr float z() const noexcept;
+ constexpr float scalar() const noexcept;
- void setX(float x);
- void setY(float y);
- void setZ(float z);
- void setScalar(float scalar);
+ constexpr void setX(float x) noexcept;
+ constexpr void setY(float y) noexcept;
+ constexpr void setZ(float z) noexcept;
+ constexpr void setScalar(float scalar) noexcept;
- constexpr static inline float dotProduct(const QQuaternion &q1, const QQuaternion &q2);
+ constexpr static float dotProduct(const QQuaternion &q1, const QQuaternion &q2) noexcept;
- float length() const;
- float lengthSquared() const;
+ // ### Qt 7: make the next four constexpr
+ // (perhaps using std::hypot, constexpr in C++26, or constexpr qHypot)
+ QT7_ONLY(Q_GUI_EXPORT) float length() const;
+ QT7_ONLY(Q_GUI_EXPORT) float lengthSquared() const;
- [[nodiscard]] QQuaternion normalized() const;
- void normalize();
+ [[nodiscard]] QT7_ONLY(Q_GUI_EXPORT) QQuaternion normalized() const;
+ QT7_ONLY(Q_GUI_EXPORT) void normalize();
- inline QQuaternion inverted() const;
+ constexpr QQuaternion inverted() const noexcept;
- [[nodiscard]] QQuaternion conjugated() const;
+ [[nodiscard]] constexpr QQuaternion conjugated() const noexcept;
- QVector3D rotatedVector(const QVector3D& vector) const;
+ QT7_ONLY(Q_GUI_EXPORT) QVector3D rotatedVector(const QVector3D &vector) const;
- QQuaternion &operator+=(const QQuaternion &quaternion);
- QQuaternion &operator-=(const QQuaternion &quaternion);
- QQuaternion &operator*=(float factor);
- QQuaternion &operator*=(const QQuaternion &quaternion);
- QQuaternion &operator/=(float divisor);
+ constexpr QQuaternion &operator+=(const QQuaternion &quaternion) noexcept;
+ constexpr QQuaternion &operator-=(const QQuaternion &quaternion) noexcept;
+ constexpr QQuaternion &operator*=(float factor) noexcept;
+ constexpr QQuaternion &operator*=(const QQuaternion &quaternion) noexcept;
+ constexpr QQuaternion &operator/=(float divisor);
QT_WARNING_PUSH
QT_WARNING_DISABLE_FLOAT_COMPARE
- friend inline bool operator==(const QQuaternion &q1, const QQuaternion &q2) noexcept
+ friend constexpr bool operator==(const QQuaternion &q1, const QQuaternion &q2) noexcept
{
return q1.wp == q2.wp && q1.xp == q2.xp && q1.yp == q2.yp && q1.zp == q2.zp;
}
- friend inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2) noexcept
+ friend constexpr bool operator!=(const QQuaternion &q1, const QQuaternion &q2) noexcept
{
return !(q1 == q2);
}
QT_WARNING_POP
- friend inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2);
- friend inline const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2);
- friend inline const QQuaternion operator*(float factor, const QQuaternion &quaternion);
- friend inline const QQuaternion operator*(const QQuaternion &quaternion, float factor);
- friend inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2);
- friend inline const QQuaternion operator-(const QQuaternion &quaternion);
- friend inline const QQuaternion operator/(const QQuaternion &quaternion, float divisor);
+ friend constexpr QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2) noexcept;
+ friend constexpr QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2) noexcept;
+ friend constexpr QQuaternion operator*(float factor, const QQuaternion &quaternion) noexcept;
+ friend constexpr QQuaternion operator*(const QQuaternion &quaternion, float factor) noexcept;
+ friend constexpr QQuaternion operator*(const QQuaternion &q1, const QQuaternion &q2) noexcept;
+ friend constexpr QQuaternion operator-(const QQuaternion &quaternion) noexcept;
+ friend constexpr QQuaternion operator/(const QQuaternion &quaternion, float divisor);
- friend inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2);
+ friend constexpr bool qFuzzyCompare(const QQuaternion &q1, const QQuaternion &q2) noexcept;
#ifndef QT_NO_VECTOR4D
- QVector4D toVector4D() const;
+ constexpr QVector4D toVector4D() const noexcept;
#endif
- operator QVariant() const;
+ QT7_ONLY(Q_GUI_EXPORT) operator QVariant() const;
#ifndef QT_NO_VECTOR3D
inline void getAxisAndAngle(QVector3D *axis, float *angle) const;
- static QQuaternion fromAxisAndAngle(const QVector3D& axis, float angle);
+ QT7_ONLY(Q_GUI_EXPORT) static QQuaternion fromAxisAndAngle(const QVector3D &axis, float angle);
#endif
- void getAxisAndAngle(float *x, float *y, float *z, float *angle) const;
- static QQuaternion fromAxisAndAngle
- (float x, float y, float z, float angle);
+ QT7_ONLY(Q_GUI_EXPORT) void getAxisAndAngle(float *x, float *y, float *z, float *angle) const;
+ QT7_ONLY(Q_GUI_EXPORT) static QQuaternion fromAxisAndAngle(float x, float y, float z,
+ float angle);
#ifndef QT_NO_VECTOR3D
inline QVector3D toEulerAngles() const;
- static inline QQuaternion fromEulerAngles(const QVector3D &eulerAngles);
+ QT7_ONLY(Q_GUI_EXPORT) static inline QQuaternion fromEulerAngles(const QVector3D &eulerAngles);
#endif
- void getEulerAngles(float *pitch, float *yaw, float *roll) const;
- static QQuaternion fromEulerAngles(float pitch, float yaw, float roll);
+ QT7_ONLY(Q_GUI_EXPORT) void getEulerAngles(float *pitch, float *yaw, float *roll) const;
+ QT7_ONLY(Q_GUI_EXPORT) static QQuaternion fromEulerAngles(float pitch, float yaw, float roll);
- QMatrix3x3 toRotationMatrix() const;
- static QQuaternion fromRotationMatrix(const QMatrix3x3 &rot3x3);
+ QT7_ONLY(Q_GUI_EXPORT) QMatrix3x3 toRotationMatrix() const;
+ QT7_ONLY(Q_GUI_EXPORT) static QQuaternion fromRotationMatrix(const QMatrix3x3 &rot3x3);
#ifndef QT_NO_VECTOR3D
- void getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const;
- static QQuaternion fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis);
+ QT7_ONLY(Q_GUI_EXPORT) void getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const;
+ QT7_ONLY(Q_GUI_EXPORT) static QQuaternion fromAxes(const QVector3D &xAxis,
+ const QVector3D &yAxis,
+ const QVector3D &zAxis);
- static QQuaternion fromDirection(const QVector3D &direction, const QVector3D &up);
+ QT7_ONLY(Q_GUI_EXPORT) static QQuaternion fromDirection(const QVector3D &direction,
+ const QVector3D &up);
- static QQuaternion rotationTo(const QVector3D &from, const QVector3D &to);
+ QT7_ONLY(Q_GUI_EXPORT) static QQuaternion rotationTo(const QVector3D &from,
+ const QVector3D &to);
#endif
- static QQuaternion slerp
- (const QQuaternion& q1, const QQuaternion& q2, float t);
- static QQuaternion nlerp
- (const QQuaternion& q1, const QQuaternion& q2, float t);
+ QT7_ONLY(Q_GUI_EXPORT) static QQuaternion slerp(const QQuaternion &q1, const QQuaternion &q2,
+ float t);
+ QT7_ONLY(Q_GUI_EXPORT) static QQuaternion nlerp(const QQuaternion &q1, const QQuaternion &q2,
+ float t);
private:
float wp, xp, yp, zp;
@@ -171,40 +141,41 @@ private:
Q_DECLARE_TYPEINFO(QQuaternion, Q_PRIMITIVE_TYPE);
-inline QQuaternion::QQuaternion() : wp(1.0f), xp(0.0f), yp(0.0f), zp(0.0f) {}
+constexpr QQuaternion::QQuaternion() noexcept : wp(1.0f), xp(0.0f), yp(0.0f), zp(0.0f) {}
-inline QQuaternion::QQuaternion(float aScalar, float xpos, float ypos, float zpos) : wp(aScalar), xp(xpos), yp(ypos), zp(zpos) {}
+constexpr QQuaternion::QQuaternion(float aScalar, float xpos, float ypos, float zpos) noexcept
+ : wp(aScalar), xp(xpos), yp(ypos), zp(zpos) {}
QT_WARNING_PUSH
QT_WARNING_DISABLE_FLOAT_COMPARE
-inline bool QQuaternion::isNull() const
+constexpr bool QQuaternion::isNull() const noexcept
{
return wp == 0.0f && xp == 0.0f && yp == 0.0f && zp == 0.0f;
}
-inline bool QQuaternion::isIdentity() const
+constexpr bool QQuaternion::isIdentity() const noexcept
{
return wp == 1.0f && xp == 0.0f && yp == 0.0f && zp == 0.0f;
}
QT_WARNING_POP
-inline float QQuaternion::x() const { return xp; }
-inline float QQuaternion::y() const { return yp; }
-inline float QQuaternion::z() const { return zp; }
-inline float QQuaternion::scalar() const { return wp; }
+constexpr float QQuaternion::x() const noexcept { return xp; }
+constexpr float QQuaternion::y() const noexcept { return yp; }
+constexpr float QQuaternion::z() const noexcept { return zp; }
+constexpr float QQuaternion::scalar() const noexcept { return wp; }
-inline void QQuaternion::setX(float aX) { xp = aX; }
-inline void QQuaternion::setY(float aY) { yp = aY; }
-inline void QQuaternion::setZ(float aZ) { zp = aZ; }
-inline void QQuaternion::setScalar(float aScalar) { wp = aScalar; }
+constexpr void QQuaternion::setX(float aX) noexcept { xp = aX; }
+constexpr void QQuaternion::setY(float aY) noexcept { yp = aY; }
+constexpr void QQuaternion::setZ(float aZ) noexcept { zp = aZ; }
+constexpr void QQuaternion::setScalar(float aScalar) noexcept { wp = aScalar; }
-constexpr inline float QQuaternion::dotProduct(const QQuaternion &q1, const QQuaternion &q2)
+constexpr float QQuaternion::dotProduct(const QQuaternion &q1, const QQuaternion &q2) noexcept
{
return q1.wp * q2.wp + q1.xp * q2.xp + q1.yp * q2.yp + q1.zp * q2.zp;
}
-inline QQuaternion QQuaternion::inverted() const
+constexpr QQuaternion QQuaternion::inverted() const noexcept
{
// Need some extra precision if the length is very small.
double len = double(wp) * double(wp) +
@@ -217,12 +188,12 @@ inline QQuaternion QQuaternion::inverted() const
return QQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
}
-inline QQuaternion QQuaternion::conjugated() const
+constexpr QQuaternion QQuaternion::conjugated() const noexcept
{
return QQuaternion(wp, -xp, -yp, -zp);
}
-inline QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)
+constexpr QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion) noexcept
{
wp += quaternion.wp;
xp += quaternion.xp;
@@ -231,7 +202,7 @@ inline QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)
return *this;
}
-inline QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion)
+constexpr QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion) noexcept
{
wp -= quaternion.wp;
xp -= quaternion.xp;
@@ -240,7 +211,7 @@ inline QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion)
return *this;
}
-inline QQuaternion &QQuaternion::operator*=(float factor)
+constexpr QQuaternion &QQuaternion::operator*=(float factor) noexcept
{
wp *= factor;
xp *= factor;
@@ -249,7 +220,7 @@ inline QQuaternion &QQuaternion::operator*=(float factor)
return *this;
}
-inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)
+constexpr QQuaternion operator*(const QQuaternion &q1, const QQuaternion &q2) noexcept
{
float yy = (q1.wp - q1.yp) * (q2.wp + q2.zp);
float zz = (q1.wp + q1.yp) * (q2.wp - q2.zp);
@@ -265,13 +236,13 @@ inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)
return QQuaternion(w, x, y, z);
}
-inline QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion)
+constexpr QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion) noexcept
{
*this = *this * quaternion;
return *this;
}
-inline QQuaternion &QQuaternion::operator/=(float divisor)
+constexpr QQuaternion &QQuaternion::operator/=(float divisor)
{
wp /= divisor;
xp /= divisor;
@@ -280,37 +251,37 @@ inline QQuaternion &QQuaternion::operator/=(float divisor)
return *this;
}
-inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2)
+constexpr QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2) noexcept
{
return QQuaternion(q1.wp + q2.wp, q1.xp + q2.xp, q1.yp + q2.yp, q1.zp + q2.zp);
}
-inline const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2)
+constexpr QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2) noexcept
{
return QQuaternion(q1.wp - q2.wp, q1.xp - q2.xp, q1.yp - q2.yp, q1.zp - q2.zp);
}
-inline const QQuaternion operator*(float factor, const QQuaternion &quaternion)
+constexpr QQuaternion operator*(float factor, const QQuaternion &quaternion) noexcept
{
return QQuaternion(quaternion.wp * factor, quaternion.xp * factor, quaternion.yp * factor, quaternion.zp * factor);
}
-inline const QQuaternion operator*(const QQuaternion &quaternion, float factor)
+constexpr QQuaternion operator*(const QQuaternion &quaternion, float factor) noexcept
{
return QQuaternion(quaternion.wp * factor, quaternion.xp * factor, quaternion.yp * factor, quaternion.zp * factor);
}
-inline const QQuaternion operator-(const QQuaternion &quaternion)
+constexpr QQuaternion operator-(const QQuaternion &quaternion) noexcept
{
return QQuaternion(-quaternion.wp, -quaternion.xp, -quaternion.yp, -quaternion.zp);
}
-inline const QQuaternion operator/(const QQuaternion &quaternion, float divisor)
+constexpr QQuaternion operator/(const QQuaternion &quaternion, float divisor)
{
return QQuaternion(quaternion.wp / divisor, quaternion.xp / divisor, quaternion.yp / divisor, quaternion.zp / divisor);
}
-inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2)
+constexpr bool qFuzzyCompare(const QQuaternion &q1, const QQuaternion &q2) noexcept
{
return qFuzzyCompare(q1.wp, q2.wp) &&
qFuzzyCompare(q1.xp, q2.xp) &&
@@ -320,17 +291,17 @@ inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2)
#ifndef QT_NO_VECTOR3D
-inline QQuaternion::QQuaternion(float aScalar, const QVector3D& aVector)
+constexpr QQuaternion::QQuaternion(float aScalar, const QVector3D &aVector) noexcept
: wp(aScalar), xp(aVector.x()), yp(aVector.y()), zp(aVector.z()) {}
-inline void QQuaternion::setVector(const QVector3D& aVector)
+constexpr void QQuaternion::setVector(const QVector3D &aVector) noexcept
{
xp = aVector.x();
yp = aVector.y();
zp = aVector.z();
}
-inline QVector3D QQuaternion::vector() const
+constexpr QVector3D QQuaternion::vector() const noexcept
{
return QVector3D(xp, yp, zp);
}
@@ -361,7 +332,7 @@ inline QQuaternion QQuaternion::fromEulerAngles(const QVector3D &eulerAngles)
#endif
-inline void QQuaternion::setVector(float aX, float aY, float aZ)
+constexpr void QQuaternion::setVector(float aX, float aY, float aZ) noexcept
{
xp = aX;
yp = aY;
@@ -370,10 +341,10 @@ inline void QQuaternion::setVector(float aX, float aY, float aZ)
#ifndef QT_NO_VECTOR4D
-inline QQuaternion::QQuaternion(const QVector4D& aVector)
+constexpr QQuaternion::QQuaternion(const QVector4D &aVector) noexcept
: wp(aVector.w()), xp(aVector.x()), yp(aVector.y()), zp(aVector.z()) {}
-inline QVector4D QQuaternion::toVector4D() const
+constexpr QVector4D QQuaternion::toVector4D() const noexcept
{
return QVector4D(xp, yp, zp, wp);
}
diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h
index fc42579918..a9e55a8ef8 100644
--- a/src/gui/math3d/qvector2d.h
+++ b/src/gui/math3d/qvector2d.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qvectornd.h>
diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h
index fc42579918..a9e55a8ef8 100644
--- a/src/gui/math3d/qvector3d.h
+++ b/src/gui/math3d/qvector3d.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qvectornd.h>
diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h
index fc42579918..a9e55a8ef8 100644
--- a/src/gui/math3d/qvector4d.h
+++ b/src/gui/math3d/qvector4d.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qvectornd.h>
diff --git a/src/gui/math3d/qvectornd.cpp b/src/gui/math3d/qvectornd.cpp
index 123f2b46e8..dcd7bdbcf8 100644
--- a/src/gui/math3d/qvectornd.cpp
+++ b/src/gui/math3d/qvectornd.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qvectornd.h"
#include <QtCore/qdatastream.h>
@@ -215,7 +179,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn void QVector2D::normalize()
- Normalizes the currect vector in place. Nothing happens if this
+ Normalizes the current vector in place. Nothing happens if this
vector is a null vector or the length of the vector is very close to 1.
\sa length(), normalized()
@@ -692,7 +656,7 @@ QDataStream &operator>>(QDataStream &stream, QVector2D &vector)
/*!
\fn void QVector3D::normalize()
- Normalizes the currect vector in place. Nothing happens if this
+ Normalizes the current vector in place. Nothing happens if this
vector is a null vector or the length of the vector is very close to 1.
\sa length(), normalized()
@@ -1368,7 +1332,7 @@ QDataStream &operator>>(QDataStream &stream, QVector3D &vector)
/*!
\fn void QVector4D::normalize()
- Normalizes the currect vector in place. Nothing happens if this
+ Normalizes the current vector in place. Nothing happens if this
vector is a null vector or the length of the vector is very close to 1.
\sa length(), normalized()
diff --git a/src/gui/math3d/qvectornd.h b/src/gui/math3d/qvectornd.h
index dec98bd936..a8adf12801 100644
--- a/src/gui/math3d/qvectornd.h
+++ b/src/gui/math3d/qvectornd.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVECTORND_H
#define QVECTORND_H
@@ -46,8 +10,13 @@
#include <QtCore/qrect.h>
#include <QtCore/qmath.h>
+#include <QtCore/q20type_traits.h>
+#include <QtCore/q23utility.h>
+
QT_BEGIN_NAMESPACE
+// QT_ENABLE_P0846_SEMANTICS_FOR(get) // from qpoint.h
+
class QVector2D;
class QVector3D;
class QVector4D;
@@ -181,13 +150,10 @@ private:
template <std::size_t I,
typename V,
std::enable_if_t<(I < 2), bool> = true,
- std::enable_if_t<std::is_same_v<std::decay_t<V>, QVector2D>, bool> = true>
+ std::enable_if_t<std::is_same_v<q20::remove_cvref_t<V>, QVector2D>, bool> = true>
friend constexpr decltype(auto) get(V &&vec) noexcept
{
- if constexpr (I == 0)
- return (std::forward<V>(vec).v[0]);
- else if constexpr (I == 1)
- return (std::forward<V>(vec).v[1]);
+ return q23::forward_like<V>(vec.v[I]);
}
};
@@ -343,15 +309,10 @@ private:
template <std::size_t I,
typename V,
std::enable_if_t<(I < 3), bool> = true,
- std::enable_if_t<std::is_same_v<std::decay_t<V>, QVector3D>, bool> = true>
+ std::enable_if_t<std::is_same_v<q20::remove_cvref_t<V>, QVector3D>, bool> = true>
friend constexpr decltype(auto) get(V &&vec) noexcept
{
- if constexpr (I == 0)
- return (std::forward<V>(vec).v[0]);
- else if constexpr (I == 1)
- return (std::forward<V>(vec).v[1]);
- else if constexpr (I == 2)
- return (std::forward<V>(vec).v[2]);
+ return q23::forward_like<V>(vec.v[I]);
}
};
@@ -500,17 +461,10 @@ private:
template <std::size_t I,
typename V,
std::enable_if_t<(I < 4), bool> = true,
- std::enable_if_t<std::is_same_v<std::decay_t<V>, QVector4D>, bool> = true>
+ std::enable_if_t<std::is_same_v<q20::remove_cvref_t<V>, QVector4D>, bool> = true>
friend constexpr decltype(auto) get(V &&vec) noexcept
{
- if constexpr (I == 0)
- return (std::forward<V>(vec).v[0]);
- else if constexpr (I == 1)
- return (std::forward<V>(vec).v[1]);
- else if constexpr (I == 2)
- return (std::forward<V>(vec).v[2]);
- else if constexpr (I == 3)
- return (std::forward<V>(vec).v[3]);
+ return q23::forward_like<V>(vec.v[I]);
}
};
diff --git a/src/gui/opengl/platform/egl/qeglconvenience.cpp b/src/gui/opengl/platform/egl/qeglconvenience.cpp
index 6076498b3e..4af50d72f2 100644
--- a/src/gui/opengl/platform/egl/qeglconvenience.cpp
+++ b/src/gui/opengl/platform/egl/qeglconvenience.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qbytearray.h>
@@ -124,13 +88,12 @@ QList<EGLint> q_createConfigAttributesFromFormat(const QSurfaceFormat &format)
bool q_reduceConfigAttributes(QList<EGLint> *configAttributes)
{
- int i = -1;
// Reduce the complexity of a configuration request to ask for less
// because the previous request did not result in success. Returns
// true if the complexity was reduced, or false if no further
// reductions in complexity are possible.
- i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR);
+ qsizetype i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR);
if (i >= 0) {
configAttributes->remove(i,2);
}
@@ -252,14 +215,17 @@ EGLConfig QEglConfigChooser::chooseConfig()
configureAttributes.append(EGL_OPENVG_BIT);
break;
#ifdef EGL_VERSION_1_4
- case QSurfaceFormat::DefaultRenderableType:
+ case QSurfaceFormat::DefaultRenderableType: {
#ifndef QT_NO_OPENGL
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL)
+ // NVIDIA EGL only provides desktop GL for development purposes, and recommends against using it.
+ const char *vendor = eglQueryString(display(), EGL_VENDOR);
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL && (!vendor || !strstr(vendor, "NVIDIA")))
configureAttributes.append(EGL_OPENGL_BIT);
else
#endif // QT_NO_OPENGL
needsES2Plus = true;
break;
+ }
case QSurfaceFormat::OpenGL:
configureAttributes.append(EGL_OPENGL_BIT);
break;
@@ -291,7 +257,7 @@ EGLConfig QEglConfigChooser::chooseConfig()
// Fetch all of the matching configurations and find the
// first that matches the pixel format we wanted.
- int i = configureAttributes.indexOf(EGL_RED_SIZE);
+ qsizetype i = configureAttributes.indexOf(EGL_RED_SIZE);
m_confAttrRed = configureAttributes.at(i+1);
i = configureAttributes.indexOf(EGL_GREEN_SIZE);
m_confAttrGreen = configureAttributes.at(i+1);
@@ -301,7 +267,8 @@ EGLConfig QEglConfigChooser::chooseConfig()
m_confAttrAlpha = i == -1 ? 0 : configureAttributes.at(i+1);
QList<EGLConfig> configs(matching);
- eglChooseConfig(display(), configureAttributes.constData(), configs.data(), configs.size(), &matching);
+ eglChooseConfig(display(), configureAttributes.constData(), configs.data(),
+ EGLint(configs.size()), &matching);
if (!cfg && matching > 0)
cfg = configs.first();
@@ -389,6 +356,7 @@ QSurfaceFormat q_glFormatFromConfig(EGLDisplay display, const EGLConfig config,
else if (referenceFormat.renderableType() == QSurfaceFormat::DefaultRenderableType
#ifndef QT_NO_OPENGL
&& QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL
+ && !strstr(eglQueryString(display, EGL_VENDOR), "NVIDIA")
#endif
&& (renderableType & EGL_OPENGL_BIT))
format.setRenderableType(QSurfaceFormat::OpenGL);
diff --git a/src/gui/opengl/platform/egl/qeglconvenience_p.h b/src/gui/opengl/platform/egl/qeglconvenience_p.h
index 7675d1316a..d4a250c90f 100644
--- a/src/gui/opengl/platform/egl/qeglconvenience_p.h
+++ b/src/gui/opengl/platform/egl/qeglconvenience_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEGLCONVENIENCE_H
#define QEGLCONVENIENCE_H
diff --git a/src/gui/opengl/platform/egl/qeglpbuffer.cpp b/src/gui/opengl/platform/egl/qeglpbuffer.cpp
index 55e199a6ad..6a79d88f8c 100644
--- a/src/gui/opengl/platform/egl/qeglpbuffer.cpp
+++ b/src/gui/opengl/platform/egl/qeglpbuffer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qoffscreensurface.h>
#include "qeglpbuffer_p.h"
@@ -65,15 +29,6 @@ QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffs
m_hasSurfaceless = !flags.testFlag(QEGLPlatformContext::NoSurfaceless)
&& q_hasEglExtension(display, "EGL_KHR_surfaceless_context");
- // Disable surfaceless contexts on Mesa for now. As of 10.6.0 and Intel at least, some
- // operations (glReadPixels) are unable to work without a surface since they at some
- // point temporarily unbind the current FBO and then later blow up in some seemingly
- // safe operations, like setting the viewport, that apparently need access to the
- // read/draw surface in the Intel backend.
- const char *vendor = eglQueryString(display, EGL_VENDOR); // hard to check for GL_ strings here, so blacklist all Mesa
- if (vendor && strstr(vendor, "Mesa"))
- m_hasSurfaceless = false;
-
if (m_hasSurfaceless)
return;
diff --git a/src/gui/opengl/platform/egl/qeglpbuffer_p.h b/src/gui/opengl/platform/egl/qeglpbuffer_p.h
index 370c430f38..e6b6db1f38 100644
--- a/src/gui/opengl/platform/egl/qeglpbuffer_p.h
+++ b/src/gui/opengl/platform/egl/qeglpbuffer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEGLPBUFFER_H
#define QEGLPBUFFER_H
diff --git a/src/gui/opengl/platform/egl/qeglplatformcontext.cpp b/src/gui/opengl/platform/egl/qeglplatformcontext.cpp
index 5727b94aa2..0a6e83e875 100644
--- a/src/gui/opengl/platform/egl/qeglplatformcontext.cpp
+++ b/src/gui/opengl/platform/egl/qeglplatformcontext.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qeglplatformcontext_p.h"
#include "qeglconvenience_p.h"
@@ -44,7 +8,7 @@
#include <QtGui/qopenglcontext.h>
#include <QtCore/qdebug.h>
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#ifdef Q_OS_ANDROID
#include <QtCore/private/qjnihelpers_p.h>
#endif
#ifndef Q_OS_WIN
diff --git a/src/gui/opengl/platform/egl/qeglplatformcontext_p.h b/src/gui/opengl/platform/egl/qeglplatformcontext_p.h
index 5f399c6994..b1e9c4b4c2 100644
--- a/src/gui/opengl/platform/egl/qeglplatformcontext_p.h
+++ b/src/gui/opengl/platform/egl/qeglplatformcontext_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEGLPLATFORMCONTEXT_H
#define QEGLPLATFORMCONTEXT_H
@@ -105,9 +69,13 @@ public:
QSurfaceFormat format() const override;
bool isSharing() const override { return m_shareContext != EGL_NO_CONTEXT; }
- bool isValid() const override { return m_eglContext != EGL_NO_CONTEXT; }
+ bool isValid() const override { return m_eglContext != EGL_NO_CONTEXT && !m_markedInvalid; }
EGLContext nativeContext() const override { return eglContext(); }
+ EGLConfig config() const override { return eglConfig(); }
+ EGLDisplay display() const override { return eglDisplay(); }
+
+ virtual void invalidateContext() override { m_markedInvalid = true; }
EGLContext eglContext() const;
EGLDisplay eglDisplay() const;
@@ -136,6 +104,8 @@ private:
Flags m_flags;
bool m_ownsContext = false;
QList<EGLint> m_contextAttrs;
+
+ bool m_markedInvalid = false;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QEGLPlatformContext::Flags)
diff --git a/src/gui/opengl/platform/egl/qeglstreamconvenience.cpp b/src/gui/opengl/platform/egl/qeglstreamconvenience.cpp
index 228cdbb06b..869e763bb8 100644
--- a/src/gui/opengl/platform/egl/qeglstreamconvenience.cpp
+++ b/src/gui/opengl/platform/egl/qeglstreamconvenience.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qeglstreamconvenience_p.h"
#include <string.h>
diff --git a/src/gui/opengl/platform/egl/qeglstreamconvenience_p.h b/src/gui/opengl/platform/egl/qeglstreamconvenience_p.h
index 22e124b279..edf73fe981 100644
--- a/src/gui/opengl/platform/egl/qeglstreamconvenience_p.h
+++ b/src/gui/opengl/platform/egl/qeglstreamconvenience_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEGLSTREAMCONVENIENCE_H
#define QEGLSTREAMCONVENIENCE_H
@@ -149,6 +113,10 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay
#define EGL_PLATFORM_X11_KHR 0x31D5
#endif
+#ifndef EGL_PLATFORM_XCB_KHR
+#define EGL_PLATFORM_XCB_KHR 0x31DC
+#endif
+
#ifndef EGL_NV_stream_attrib
typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMATTRIBNVPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
diff --git a/src/gui/opengl/platform/egl/qt_egl_p.h b/src/gui/opengl/platform/egl/qt_egl_p.h
index c33cc8aa21..1f538e22af 100644
--- a/src/gui/opengl/platform/egl/qt_egl_p.h
+++ b/src/gui/opengl/platform/egl/qt_egl_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QT_EGL_P_H
#define QT_EGL_P_H
@@ -54,6 +18,7 @@
// q(data/text)stream.h must be included before any header file that defines Status
#include <QtCore/qdatastream.h>
#include <QtCore/qtextstream.h>
+#include <QtCore/private/qglobal_p.h>
#ifdef QT_EGL_NO_X11
# ifndef EGL_NO_X11
@@ -65,7 +30,11 @@
# if !defined(Q_OS_INTEGRITY)
# define WIN_INTERFACE_CUSTOM // NV
# endif // Q_OS_INTEGRITY
-#endif // QT_EGL_NO_X11
+#else // QT_EGL_NO_X11
+// If one has an eglplatform.h with https://github.com/KhronosGroup/EGL-Registry/pull/130
+// that needs USE_X11 to be defined.
+# define USE_X11
+#endif
#ifdef QT_EGL_WAYLAND
# define WAYLAND // NV
diff --git a/src/gui/opengl/platform/egl/qxlibeglintegration.cpp b/src/gui/opengl/platform/egl/qxlibeglintegration.cpp
deleted file mode 100644
index 59f7024c06..0000000000
--- a/src/gui/opengl/platform/egl/qxlibeglintegration.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtCore/qloggingcategory.h>
-#include "qxlibeglintegration_p.h"
-
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(lcXlibEglDebug, "qt.egl.xlib.debug")
-
-VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config)
-{
- VisualID visualId = 0;
- EGLint eglValue = 0;
-
- EGLint configRedSize = 0;
- eglGetConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &configRedSize);
-
- EGLint configGreenSize = 0;
- eglGetConfigAttrib(eglDisplay, config, EGL_GREEN_SIZE, &configGreenSize);
-
- EGLint configBlueSize = 0;
- eglGetConfigAttrib(eglDisplay, config, EGL_BLUE_SIZE, &configBlueSize);
-
- EGLint configAlphaSize = 0;
- eglGetConfigAttrib(eglDisplay, config, EGL_ALPHA_SIZE, &configAlphaSize);
-
- eglGetConfigAttrib(eglDisplay, config, EGL_CONFIG_ID, &eglValue);
- int configId = eglValue;
-
- // See if EGL provided a valid VisualID:
- eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &eglValue);
- visualId = (VisualID)eglValue;
- if (visualId) {
- // EGL has suggested a visual id, so get the rest of the visual info for that id:
- XVisualInfo visualInfoTemplate;
- memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
- visualInfoTemplate.visualid = visualId;
-
- XVisualInfo *chosenVisualInfo;
- int matchingCount = 0;
- chosenVisualInfo = XGetVisualInfo(display, VisualIDMask, &visualInfoTemplate, &matchingCount);
- if (chosenVisualInfo) {
- // Skip size checks if implementation supports non-matching visual
- // and config (QTBUG-9444).
- if (q_hasEglExtension(eglDisplay,"EGL_NV_post_convert_rounding")) {
- XFree(chosenVisualInfo);
- return visualId;
- }
- // Skip also for i.MX6 where 565 visuals are suggested for the default 444 configs and it works just fine.
- const char *vendor = eglQueryString(eglDisplay, EGL_VENDOR);
- if (vendor && strstr(vendor, "Vivante")) {
- XFree(chosenVisualInfo);
- return visualId;
- }
-
- int visualRedSize = qPopulationCount(chosenVisualInfo->red_mask);
- int visualGreenSize = qPopulationCount(chosenVisualInfo->green_mask);
- int visualBlueSize = qPopulationCount(chosenVisualInfo->blue_mask);
- int visualAlphaSize = chosenVisualInfo->depth - visualRedSize - visualBlueSize - visualGreenSize;
-
- const bool visualMatchesConfig = visualRedSize >= configRedSize
- && visualGreenSize >= configGreenSize
- && visualBlueSize >= configBlueSize
- && visualAlphaSize >= configAlphaSize;
-
- // In some cases EGL tends to suggest a 24-bit visual for 8888
- // configs. In such a case we have to fall back to XGetVisualInfo.
- if (!visualMatchesConfig) {
- visualId = 0;
- qCDebug(lcXlibEglDebug,
- "EGL suggested using X Visual ID %d (%d %d %d %d depth %d) for EGL config %d"
- "(%d %d %d %d), but this is incompatible",
- (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, visualAlphaSize, chosenVisualInfo->depth,
- configId, configRedSize, configGreenSize, configBlueSize, configAlphaSize);
- }
- } else {
- qCDebug(lcXlibEglDebug, "EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
- (int)visualId, configId);
- visualId = 0;
- }
- XFree(chosenVisualInfo);
- }
- else
- qCDebug(lcXlibEglDebug, "EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
-
- if (visualId) {
- qCDebug(lcXlibEglDebug, configAlphaSize > 0
- ? "Using ARGB Visual ID %d provided by EGL for config %d"
- : "Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId);
- return visualId;
- }
-
- // Finally, try to use XGetVisualInfo and only use the bit depths to match on:
- if (!visualId) {
- XVisualInfo visualInfoTemplate;
- memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
- XVisualInfo *matchingVisuals;
- int matchingCount = 0;
-
- visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
- matchingVisuals = XGetVisualInfo(display,
- VisualDepthMask,
- &visualInfoTemplate,
- &matchingCount);
- if (!matchingVisuals) {
- // Try again without taking the alpha channel into account:
- visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize;
- matchingVisuals = XGetVisualInfo(display,
- VisualDepthMask,
- &visualInfoTemplate,
- &matchingCount);
- }
-
- if (matchingVisuals) {
- visualId = matchingVisuals[0].visualid;
- XFree(matchingVisuals);
- }
- }
-
- if (visualId) {
- qCDebug(lcXlibEglDebug, "Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId);
- return visualId;
- }
-
- qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
- return (VisualID)0;
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/opengl/platform/egl/qxlibeglintegration_p.h b/src/gui/opengl/platform/egl/qxlibeglintegration_p.h
deleted file mode 100644
index 2c4e0b5080..0000000000
--- a/src/gui/opengl/platform/egl/qxlibeglintegration_p.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QXLIBEGLINTEGRATION_H
-#define QXLIBEGLINTEGRATION_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qeglconvenience_p.h>
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_GUI_EXPORT QXlibEglIntegration
-{
-public:
- static VisualID getCompatibleVisualId(Display *display, EGLDisplay eglDisplay, EGLConfig config);
-};
-
-QT_END_NAMESPACE
-
-#endif // QXLIBEGLINTEGRATION_H
diff --git a/src/gui/opengl/platform/unix/qglxconvenience.cpp b/src/gui/opengl/platform/unix/qglxconvenience.cpp
index fd6f1639a3..ce70818042 100644
--- a/src/gui/opengl/platform/unix/qglxconvenience.cpp
+++ b/src/gui/opengl/platform/unix/qglxconvenience.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// We have to include this before the X11 headers dragged in by
// qglxconvenience_p.h.
@@ -160,7 +124,7 @@ struct QXcbSoftwareOpenGLEnforcer {
}
if (forceSoftwareOpenGL)
- qputenv("LIBGL_ALWAYS_SOFTWARE", QByteArrayLiteral("1"));
+ qputenv("LIBGL_ALWAYS_SOFTWARE", "1");
}
~QXcbSoftwareOpenGLEnforcer() {
diff --git a/src/gui/opengl/platform/unix/qglxconvenience_p.h b/src/gui/opengl/platform/unix/qglxconvenience_p.h
index ecd8737f87..c755356c50 100644
--- a/src/gui/opengl/platform/unix/qglxconvenience_p.h
+++ b/src/gui/opengl/platform/unix/qglxconvenience_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGLXCONVENIENCE_H
#define QGLXCONVENIENCE_H
@@ -53,6 +17,7 @@
#include <QtCore/qlist.h>
#include <QtGui/qsurfaceformat.h>
+#include <QtCore/private/qglobal_p.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp
index 3066b83282..587975085a 100644
--- a/src/gui/opengl/qopengl.cpp
+++ b/src/gui/opengl/qopengl.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qopengl.h"
#include "qopengl_p.h"
@@ -56,6 +20,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#if defined(QT_OPENGL_3)
typedef const GLubyte * (QOPENGLF_APIENTRYP qt_glGetStringi)(GLenum, GLuint);
#endif
@@ -210,10 +176,10 @@ VersionTerm VersionTerm::fromJson(const QJsonValue &v)
if (!v.isObject())
return result;
const QJsonObject o = v.toObject();
- result.number = QVersionNumber::fromString(o.value(QLatin1String("value")).toString());
- const QString opS = o.value(QLatin1String("op")).toString();
+ result.number = QVersionNumber::fromString(o.value("value"_L1).toString());
+ const QString opS = o.value("op"_L1).toString();
for (size_t i = 0; i < sizeof(operators) / sizeof(operators[0]); ++i) {
- if (opS == QLatin1String(operators[i])) {
+ if (opS == QLatin1StringView(operators[i])) {
result.op = static_cast<Operator>(i);
break;
}
@@ -229,29 +195,13 @@ struct OsTypeTerm
static QString hostOs();
static QVersionNumber hostKernelVersion() { return QVersionNumber::fromString(QSysInfo::kernelVersion()); }
static QString hostOsRelease() {
- QString ver;
#ifdef Q_OS_WIN
- const auto osver = QOperatingSystemVersion::current();
-#define Q_WINVER(major, minor) (major << 8 | minor)
- switch (Q_WINVER(osver.majorVersion(), osver.minorVersion())) {
- case Q_WINVER(6, 1):
- ver = QStringLiteral("7");
- break;
- case Q_WINVER(6, 2):
- ver = QStringLiteral("8");
- break;
- case Q_WINVER(6, 3):
- ver = QStringLiteral("8.1");
- break;
- case Q_WINVER(10, 0):
- ver = QStringLiteral("10");
- break;
- default:
- break;
- }
-#undef Q_WINVER
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11)
+ return u"11"_s;
+ return u"10"_s;
+#else
+ return {};
#endif
- return ver;
}
bool isNull() const { return type.isEmpty(); }
@@ -282,9 +232,9 @@ OsTypeTerm OsTypeTerm::fromJson(const QJsonValue &v)
if (!v.isObject())
return result;
const QJsonObject o = v.toObject();
- result.type = o.value(QLatin1String("type")).toString();
- result.versionTerm = VersionTerm::fromJson(o.value(QLatin1String("version")));
- result.release = o.value(QLatin1String("release")).toArray();
+ result.type = o.value("type"_L1).toString();
+ result.versionTerm = VersionTerm::fromJson(o.value("version"_L1));
+ result.release = o.value("release"_L1).toArray();
return result;
}
@@ -308,8 +258,8 @@ QString OsTypeTerm::hostOs()
static QString msgSyntaxWarning(const QJsonObject &object, const QString &what)
{
QString result;
- QTextStream(&result) << "Id " << object.value(QLatin1String("id")).toInt()
- << " (\"" << object.value(QLatin1String("description")).toString()
+ QTextStream(&result) << "Id " << object.value("id"_L1).toInt()
+ << " (\"" << object.value("description"_L1).toString()
<< "\"): " << what;
return result;
}
@@ -323,11 +273,11 @@ static bool matches(const QJsonObject &object,
const QString &osRelease,
const QOpenGLConfig::Gpu &gpu)
{
- const OsTypeTerm os = OsTypeTerm::fromJson(object.value(QLatin1String("os")));
+ const OsTypeTerm os = OsTypeTerm::fromJson(object.value("os"_L1));
if (!os.isNull() && !os.matches(osName, kernelVersion, osRelease))
return false;
- const QJsonValue exceptionsV = object.value(QLatin1String("exceptions"));
+ const QJsonValue exceptionsV = object.value("exceptions"_L1);
if (exceptionsV.isArray()) {
const QJsonArray exceptionsA = exceptionsV.toArray();
for (JsonArrayConstIt it = exceptionsA.constBegin(), cend = exceptionsA.constEnd(); it != cend; ++it) {
@@ -336,20 +286,20 @@ static bool matches(const QJsonObject &object,
}
}
- const QJsonValue vendorV = object.value(QLatin1String("vendor_id"));
+ const QJsonValue vendorV = object.value("vendor_id"_L1);
if (vendorV.isString()) {
if (gpu.vendorId != vendorV.toString().toUInt(nullptr, /* base */ 0))
return false;
} else {
- if (object.contains(QLatin1String("gl_vendor"))) {
- const QByteArray glVendorV = object.value(QLatin1String("gl_vendor")).toString().toUtf8();
+ if (object.contains("gl_vendor"_L1)) {
+ const QByteArray glVendorV = object.value("gl_vendor"_L1).toString().toUtf8();
if (!gpu.glVendor.contains(glVendorV))
return false;
}
}
if (gpu.deviceId) {
- const QJsonValue deviceIdV = object.value(QLatin1String("device_id"));
+ const QJsonValue deviceIdV = object.value("device_id"_L1);
switch (deviceIdV.type()) {
case QJsonValue::Array:
if (!contains(deviceIdV.toArray(), gpu.deviceId))
@@ -360,12 +310,11 @@ static bool matches(const QJsonObject &object,
break;
default:
qWarning().noquote()
- << msgSyntaxWarning(object,
- QLatin1String("Device ID must be of type array."));
+ << msgSyntaxWarning(object, "Device ID must be of type array."_L1);
}
}
if (!gpu.driverVersion.isNull()) {
- const QJsonValue driverVersionV = object.value(QLatin1String("driver_version"));
+ const QJsonValue driverVersionV = object.value("driver_version"_L1);
switch (driverVersionV.type()) {
case QJsonValue::Object:
if (!VersionTerm::fromJson(driverVersionV).matches(gpu.driverVersion))
@@ -376,13 +325,12 @@ static bool matches(const QJsonObject &object,
break;
default:
qWarning().noquote()
- << msgSyntaxWarning(object,
- QLatin1String("Driver version must be of type object."));
+ << msgSyntaxWarning(object, "Driver version must be of type object."_L1);
}
}
if (!gpu.driverDescription.isEmpty()) {
- const QJsonValue driverDescriptionV = object.value(QLatin1String("driver_description"));
+ const QJsonValue driverDescriptionV = object.value("driver_description"_L1);
if (driverDescriptionV.isString()) {
if (!gpu.driverDescription.contains(driverDescriptionV.toString().toUtf8()))
return false;
@@ -402,9 +350,9 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
{
result->clear();
errorMessage->clear();
- const QJsonValue entriesV = doc.object().value(QLatin1String("entries"));
+ const QJsonValue entriesV = doc.object().value("entries"_L1);
if (!entriesV.isArray()) {
- *errorMessage = QLatin1String("No entries read.");
+ *errorMessage = "No entries read."_L1;
return false;
}
@@ -413,7 +361,7 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
if (eit->isObject()) {
const QJsonObject object = eit->toObject();
if (matches(object, osName, kernelVersion, osRelease, gpu)) {
- const QJsonValue featuresListV = object.value(QLatin1String("features"));
+ const QJsonValue featuresListV = object.value("features"_L1);
if (featuresListV.isArray()) {
const QJsonArray featuresListA = featuresListV.toArray();
for (JsonArrayConstIt fit = featuresListA.constBegin(), fcend = featuresListA.constEnd(); fit != fcend; ++fit)
@@ -437,7 +385,8 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
QJsonParseError error;
const QJsonDocument document = QJsonDocument::fromJson(jsonAsciiData, &error);
if (document.isNull()) {
- const int lineNumber = 1 + jsonAsciiData.left(error.offset).count('\n');
+ const qsizetype lineNumber =
+ QByteArrayView(jsonAsciiData).left(error.offset).count('\n') + 1;
QTextStream str(errorMessage);
str << "Failed to parse data: \"" << error.errorString()
<< "\" at line " << lineNumber << " (offset: "
@@ -465,9 +414,9 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
}
const bool success = readGpuFeatures(gpu, osName, kernelVersion, osRelease, file.readAll(), result, errorMessage);
if (!success) {
- errorMessage->prepend(QLatin1String("Error reading \"")
+ errorMessage->prepend("Error reading \""_L1
+ QDir::toNativeSeparators(fileName)
- + QLatin1String("\": "));
+ + "\": "_L1);
}
return success;
}
diff --git a/src/gui/opengl/qopengl.h b/src/gui/opengl/qopengl.h
index 5c0885f4ec..e9a11080ce 100644
--- a/src/gui/opengl/qopengl.h
+++ b/src/gui/opengl/qopengl.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPENGL_H
#define QOPENGL_H
@@ -44,9 +8,19 @@
#ifndef QT_NO_OPENGL
-// Windows always needs this to ensure that APIENTRY gets defined
+// On Windows we need to ensure that APIENTRY and WINGDIAPI are defined before
+// we can include gl.h. But we do not want to include <windows.h> in this public
+// Qt header, as it pollutes the global namespace with macros.
#if defined(Q_OS_WIN)
-# include <QtCore/qt_windows.h>
+# ifndef APIENTRY
+# define APIENTRY __stdcall
+# define Q_UNDEF_APIENTRY
+# endif // APIENTRY
+# ifndef WINGDIAPI
+# define WINGDIAPI __declspec(dllimport)
+# define Q_UNDEF_WINGDIAPI
+# endif // WINGDIAPI
+# define QT_APIENTRY __stdcall
#endif
// Note: Apple is a "controlled platform" for OpenGL ABI so we
@@ -157,20 +131,18 @@ typedef char GLchar;
# endif
#endif
-QT_BEGIN_NAMESPACE
-
// When all else fails we provide sensible fallbacks - this is needed to
// allow compilation on OS X 10.6
#if !QT_CONFIG(opengles2)
// OS X 10.6 doesn't define these which are needed below
-// OS X 10.7 and later defien them in gl3.h
-#ifndef APIENTRY
-#define APIENTRY
+// OS X 10.7 and later define them in gl3.h
+#ifndef QT_APIENTRY
+#define QT_APIENTRY
#endif
-#ifndef APIENTRYP
-#define APIENTRYP APIENTRY *
+#ifndef QT_APIENTRYP
+#define QT_APIENTRYP QT_APIENTRY *
#endif
#ifndef GLAPI
#define GLAPI extern
@@ -269,15 +241,15 @@ struct _cl_event;
#endif
#ifndef GL_ARB_debug_output
-typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const GLvoid *userParam);
+typedef void (QT_APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const GLvoid *userParam);
#endif
#ifndef GL_AMD_debug_output
-typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+typedef void (QT_APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
#endif
#ifndef GL_KHR_debug
-typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const GLvoid *userParam);
+typedef void (QT_APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const GLvoid *userParam);
#endif
#ifndef GL_NV_vdpau_interop
@@ -287,14 +259,15 @@ typedef GLintptr GLvdpauSurfaceNV;
// End of block copied from glext.h
#endif
+QT_BEGIN_NAMESPACE
// Types that aren't defined in all system's gl.h files.
typedef ptrdiff_t qopengl_GLintptr;
typedef ptrdiff_t qopengl_GLsizeiptr;
-#if defined(APIENTRY) && !defined(QOPENGLF_APIENTRY)
-# define QOPENGLF_APIENTRY APIENTRY
+#if defined(QT_APIENTRY) && !defined(QOPENGLF_APIENTRY)
+# define QOPENGLF_APIENTRY QT_APIENTRY
#endif
# ifndef QOPENGLF_APIENTRYP
@@ -308,6 +281,15 @@ typedef ptrdiff_t qopengl_GLsizeiptr;
QT_END_NAMESPACE
+#ifdef Q_UNDEF_WINGDIAPI
+# undef WINGDIAPI
+# undef Q_UNDEF_WINGDIAPI
+#endif
+#ifdef Q_UNDEF_APIENTRY
+# undef APIENTRY
+# undef Q_UNDEF_APIENTRY
+#endif
+
#endif // QT_NO_OPENGL
#endif // QOPENGL_H
diff --git a/src/gui/opengl/qopengl_p.h b/src/gui/opengl/qopengl_p.h
index 07fd159ba8..a3b2be7b49 100644
--- a/src/gui/opengl/qopengl_p.h
+++ b/src/gui/opengl/qopengl_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPENGL_P_H
#define QOPENGL_P_H
diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h
index 0d58b5f301..a6c4a68c6c 100644
--- a/src/gui/opengl/qopenglextensions_p.h
+++ b/src/gui/opengl/qopenglextensions_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPENGL_EXTENSIONS_P_H
#define QOPENGL_EXTENSIONS_P_H
@@ -93,6 +57,11 @@ public:
Sized16Formats = 0x00800000,
TextureSwizzle = 0x01000000,
StandardDerivatives = 0x02000000,
+ ASTCTextureCompression = 0x04000000,
+ ETC2TextureCompression = 0x08000000,
+ HalfFloatVertex = 0x10000000,
+ MultiView = 0x20000000,
+ MultiViewExtended = 0x40000000
};
Q_DECLARE_FLAGS(OpenGLExtensions, OpenGLExtension)
@@ -101,9 +70,9 @@ public:
GLvoid *glMapBuffer(GLenum target, GLenum access);
void glGetBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, GLvoid *data);
- void glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments);
void flushShared();
+ void discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments);
QOpenGLExtensionsPrivate *d() const;
@@ -148,14 +117,6 @@ inline void QOpenGLExtensions::glGetBufferSubData(GLenum target, qopengl_GLintpt
Q_OPENGL_FUNCTIONS_DEBUG
}
-
-inline void QOpenGLExtensions::glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments)
-{
- Q_D(QOpenGLExtensions);
- Q_ASSERT(QOpenGLExtensions::isInitialized(d));
- d->DiscardFramebuffer(target,numAttachments, attachments);
- Q_OPENGL_FUNCTIONS_DEBUG
-}
QT_END_NAMESPACE
#endif // QOPENGL_EXTENSIONS_P_H
diff --git a/src/gui/opengl/qopenglextrafunctions.h b/src/gui/opengl/qopenglextrafunctions.h
index 4b02b1a60d..e2608e9946 100644
--- a/src/gui/opengl/qopenglextrafunctions.h
+++ b/src/gui/opengl/qopenglextrafunctions.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPENGLEXTRAFUNCTIONS_H
#define QOPENGLEXTRAFUNCTIONS_H
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index 19012dddd3..c9352fbc31 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qopenglfunctions.h"
#include "qopenglextrafunctions.h"
@@ -57,6 +21,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#define QT_OPENGL_COUNT_FUNCTIONS(ret, name, args) +1
#define QT_OPENGL_FUNCTION_NAMES(ret, name, args) \
"gl"#name"\0"
@@ -364,6 +330,8 @@ static int qt_gl_resolve_extensions()
extensions |= QOpenGLExtensions::ETC1TextureCompression;
if (extensionMatcher.match("GL_IMG_texture_compression_pvrtc"))
extensions |= QOpenGLExtensions::PVRTCTextureCompression;
+ if (extensionMatcher.match("GL_KHR_texture_compression_astc_ldr"))
+ extensions |= QOpenGLExtensions::ASTCTextureCompression;
if (extensionMatcher.match("GL_ARB_texture_mirrored_repeat"))
extensions |= QOpenGLExtensions::MirroredRepeat;
if (extensionMatcher.match("GL_EXT_stencil_two_side"))
@@ -378,6 +346,12 @@ static int qt_gl_resolve_extensions()
extensions |= QOpenGLExtensions::TextureSwizzle;
if (extensionMatcher.match("GL_OES_standard_derivatives"))
extensions |= QOpenGLExtensions::StandardDerivatives;
+ if (extensionMatcher.match("GL_ARB_half_float_vertex"))
+ extensions |= QOpenGLExtensions::HalfFloatVertex;
+ if (extensionMatcher.match("GL_OVR_multiview"))
+ extensions |= QOpenGLExtensions::MultiView;
+ if (extensionMatcher.match("GL_OVR_multiview2"))
+ extensions |= QOpenGLExtensions::MultiViewExtended;
if (ctx->isOpenGLES()) {
if (format.majorVersion() >= 2)
@@ -391,7 +365,10 @@ static int qt_gl_resolve_extensions()
| QOpenGLExtensions::FramebufferBlit
| QOpenGLExtensions::FramebufferMultisample
| QOpenGLExtensions::Sized8Formats
- | QOpenGLExtensions::StandardDerivatives;
+ | QOpenGLExtensions::DiscardFramebuffer
+ | QOpenGLExtensions::StandardDerivatives
+ | QOpenGLExtensions::ETC2TextureCompression
+ | QOpenGLExtensions::HalfFloatVertex;
#ifndef Q_OS_WASM
// WebGL 2.0 specification explicitly does not support texture swizzles
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.19
@@ -413,6 +390,8 @@ static int qt_gl_resolve_extensions()
extensions |= QOpenGLExtensions::FramebufferMultisample;
if (extensionMatcher.match("GL_OES_rgb8_rgba8"))
extensions |= QOpenGLExtensions::Sized8Formats;
+ if (extensionMatcher.match("GL_OES_compressed_ETC2_RGB8_texture"))
+ extensions |= QOpenGLExtensions::ETC2TextureCompression;
}
if (extensionMatcher.match("GL_OES_mapbuffer"))
@@ -422,13 +401,13 @@ static int qt_gl_resolve_extensions()
// We don't match GL_APPLE_texture_format_BGRA8888 here because it has different semantics.
if (extensionMatcher.match("GL_IMG_texture_format_BGRA8888") || extensionMatcher.match("GL_EXT_texture_format_BGRA8888"))
extensions |= QOpenGLExtensions::BGRATextureFormat;
-#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
+#ifdef Q_OS_ANDROID
QString *deviceName =
static_cast<QString *>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("AndroidDeviceName"));
static bool wrongfullyReportsBgra8888Support = deviceName != 0
- && (deviceName->compare(QLatin1String("samsung SM-T211"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QLatin1String("samsung SM-T210"), Qt::CaseInsensitive) == 0
- || deviceName->compare(QLatin1String("samsung SM-T215"), Qt::CaseInsensitive) == 0);
+ && (deviceName->compare("samsung SM-T211"_L1, Qt::CaseInsensitive) == 0
+ || deviceName->compare("samsung SM-T210"_L1, Qt::CaseInsensitive) == 0
+ || deviceName->compare("samsung SM-T215"_L1, Qt::CaseInsensitive) == 0);
if (wrongfullyReportsBgra8888Support)
extensions &= ~QOpenGLExtensions::BGRATextureFormat;
#endif
@@ -472,6 +451,9 @@ static int qt_gl_resolve_extensions()
if (format.version() >= qMakePair(3, 3))
extensions |= QOpenGLExtensions::TextureSwizzle;
+ if (format.version() >= qMakePair(4, 3) || extensionMatcher.match("GL_ARB_invalidate_subdata"))
+ extensions |= QOpenGLExtensions::DiscardFramebuffer;
+
if (extensionMatcher.match("GL_ARB_map_buffer_range"))
extensions |= QOpenGLExtensions::MapBufferRange;
@@ -481,6 +463,9 @@ static int qt_gl_resolve_extensions()
if (srgbCapableFramebuffers)
extensions |= QOpenGLExtensions::SRGBFrameBuffer;
}
+
+ if (extensionMatcher.match("GL_ARB_ES3_compatibility"))
+ extensions |= QOpenGLExtensions::ETC2TextureCompression;
}
return extensions;
@@ -5070,7 +5055,23 @@ QOpenGLExtensionsPrivate::QOpenGLExtensionsPrivate(QOpenGLContext *ctx)
MapBuffer = RESOLVE(MapBuffer);
GetBufferSubData = RESOLVE(GetBufferSubData);
DiscardFramebuffer = RESOLVE(DiscardFramebuffer);
- }
+}
+
+void QOpenGLExtensions::discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
+{
+ Q_D(QOpenGLExtensions);
+ Q_ASSERT(QOpenGLExtensions::isInitialized(d));
+ Q_ASSERT(d->f.InvalidateFramebuffer || d->DiscardFramebuffer);
+
+ // On GLES >= 3 we prefer glInvalidateFramebuffer, even if the
+ // discard extension is present
+ if (d->f.InvalidateFramebuffer)
+ d->f.InvalidateFramebuffer(target, numAttachments, attachments);
+ else
+ d->DiscardFramebuffer(target, numAttachments, attachments);
+
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
void QOpenGLExtensions::flushShared()
{
diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h
index c288df53b5..05435903fb 100644
--- a/src/gui/opengl/qopenglfunctions.h
+++ b/src/gui/opengl/qopenglfunctions.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPENGLFUNCTIONS_H
#define QOPENGLFUNCTIONS_H
@@ -227,7 +191,7 @@ struct QOpenGLFunctionsPrivate;
#undef glTexLevelParameteriv
-#if defined(Q_CLANG_QDOC)
+#if defined(Q_QDOC)
#undef GLbitfield
typedef unsigned int GLbitfield;
#undef GLchar
diff --git a/src/gui/opengl/qopenglprogrambinarycache.cpp b/src/gui/opengl/qopenglprogrambinarycache.cpp
index 631c3d151b..28b09b553a 100644
--- a/src/gui/opengl/qopenglprogrambinarycache.cpp
+++ b/src/gui/opengl/qopenglprogrambinarycache.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qopenglprogrambinarycache_p.h"
#include <QOpenGLContext>
@@ -54,6 +18,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcOpenGLProgramDiskCache, "qt.opengl.diskcache")
#ifndef GL_CONTEXT_LOST
@@ -117,22 +83,26 @@ static inline bool qt_ensureWritableDir(const QString &name)
QOpenGLProgramBinaryCache::QOpenGLProgramBinaryCache()
: m_cacheWritable(false)
{
- const QString subPath = QLatin1String("/qtshadercache-") + QSysInfo::buildAbi() + QLatin1Char('/');
+ const QString subPath = "/qtshadercache-"_L1 + QSysInfo::buildAbi() + u'/';
const QString sharedCachePath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
+ m_globalCacheDir = sharedCachePath + subPath;
+ m_localCacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + subPath;
+
if (!sharedCachePath.isEmpty()) {
- m_cacheDir = sharedCachePath + subPath;
- m_cacheWritable = qt_ensureWritableDir(m_cacheDir);
+ m_currentCacheDir = m_globalCacheDir;
+ m_cacheWritable = qt_ensureWritableDir(m_currentCacheDir);
}
if (!m_cacheWritable) {
- m_cacheDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + subPath;
- m_cacheWritable = qt_ensureWritableDir(m_cacheDir);
+ m_currentCacheDir = m_localCacheDir;
+ m_cacheWritable = qt_ensureWritableDir(m_currentCacheDir);
}
- qCDebug(lcOpenGLProgramDiskCache, "Cache location '%s' writable = %d", qPrintable(m_cacheDir), m_cacheWritable);
+
+ qCDebug(lcOpenGLProgramDiskCache, "Cache location '%s' writable = %d", qPrintable(m_currentCacheDir), m_cacheWritable);
}
QString QOpenGLProgramBinaryCache::cacheFileName(const QByteArray &cacheKey) const
{
- return m_cacheDir + QString::fromUtf8(cacheKey);
+ return m_currentCacheDir + QString::fromUtf8(cacheKey);
}
#define BASE_HEADER_SIZE (int(4 * sizeof(quint32)))
@@ -361,6 +331,25 @@ static inline void writeStr(uchar **p, const QByteArray &str)
*p += str.size();
}
+static inline bool writeFile(const QString &filename, const QByteArray &data)
+{
+#if QT_CONFIG(temporaryfile)
+ QSaveFile f(filename);
+ if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ f.write(data);
+ if (f.commit())
+ return true;
+ }
+#else
+ QFile f(filename);
+ if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ if (f.write(data) == data.length())
+ return true;
+ }
+#endif
+ return false;
+}
+
void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
{
if (!m_cacheWritable)
@@ -427,20 +416,20 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
writeUInt(&blobFormatPtr, blobFormat);
-#if QT_CONFIG(temporaryfile)
- QSaveFile f(cacheFileName(cacheKey));
- if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- f.write(blob);
- if (!f.commit())
-#else
- QFile f(cacheFileName(cacheKey));
- if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
- if (f.write(blob) < blob.length())
-#endif
- qCDebug(lcOpenGLProgramDiskCache, "Failed to write %s to shader cache", qPrintable(f.fileName()));
- } else {
- qCDebug(lcOpenGLProgramDiskCache, "Failed to create %s in shader cache", qPrintable(f.fileName()));
+ QString filename = cacheFileName(cacheKey);
+ bool ok = writeFile(filename, blob);
+ if (!ok && m_currentCacheDir == m_globalCacheDir) {
+ m_currentCacheDir = m_localCacheDir;
+ m_cacheWritable = qt_ensureWritableDir(m_currentCacheDir);
+ qCDebug(lcOpenGLProgramDiskCache, "Cache location changed to '%s' writable = %d",
+ qPrintable(m_currentCacheDir), m_cacheWritable);
+ if (m_cacheWritable) {
+ filename = cacheFileName(cacheKey);
+ ok = writeFile(filename, blob);
+ }
}
+ if (!ok)
+ qCDebug(lcOpenGLProgramDiskCache, "Failed to write %s to shader cache", qPrintable(filename));
}
#if QT_CONFIG(opengles2)
diff --git a/src/gui/opengl/qopenglprogrambinarycache_p.h b/src/gui/opengl/qopenglprogrambinarycache_p.h
index d8fdf1d8c5..c3850bdee3 100644
--- a/src/gui/opengl/qopenglprogrambinarycache_p.h
+++ b/src/gui/opengl/qopenglprogrambinarycache_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOPENGLPROGRAMBINARYCACHE_P_H
#define QOPENGLPROGRAMBINARYCACHE_P_H
@@ -56,7 +20,7 @@
#include <QtCore/qmutex.h>
#include <QtCore/QLoggingCategory>
#include <QtGui/private/qopenglcontext_p.h>
-#include <QtGui/private/qshader_p.h>
+#include <rhi/qshader.h>
QT_BEGIN_NAMESPACE
@@ -64,7 +28,7 @@ QT_BEGIN_NAMESPACE
// therefore stay independent from QOpenGLShader(Program). Must rely only on
// QOpenGLContext/Functions.
-Q_GUI_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcOpenGLProgramDiskCache)
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcOpenGLProgramDiskCache, Q_GUI_EXPORT)
class Q_GUI_EXPORT QOpenGLProgramBinaryCache
{
@@ -92,7 +56,9 @@ private:
bool verifyHeader(const QByteArray &buf) const;
bool setProgramBinary(uint programId, uint blobFormat, const void *p, uint blobSize);
- QString m_cacheDir;
+ QString m_globalCacheDir;
+ QString m_localCacheDir;
+ QString m_currentCacheDir;
bool m_cacheWritable;
struct MemCacheEntry {
MemCacheEntry(const void *p, int size, uint format)
diff --git a/src/gui/opengl/qt_attribution.json b/src/gui/opengl/qt_attribution.json
index d3ff10d803..44310980e2 100644
--- a/src/gui/opengl/qt_attribution.json
+++ b/src/gui/opengl/qt_attribution.json
@@ -5,7 +5,7 @@
"QDocModule": "qtgui",
"Description": "OpenGL header generated from the Khronos OpenGL / OpenGL ES XML API Registry.",
"QtUsage": "Used on Windows and Linux in the OpenGL related headers of Qt GUI.",
- "Path": "qopenglext.h",
+ "Files": "qopenglext.h",
"Homepage": "https://www.khronos.org/",
"Version": "Revision 27684",
@@ -20,7 +20,7 @@
"QDocModule": "qtgui",
"Description": "OpenGL ES 2 header generated from the Khronos OpenGL / OpenGL ES XML API Registry.",
"QtUsage": "Used on Windows and Linux in the OpenGL related headers of Qt GUI.",
- "Path": "qopengles2ext.h",
+ "Files": "qopengles2ext.h",
"Homepage": "https://www.khronos.org/",
"Version": "Revision 27673",
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index a2e5f7286e..2304ee2256 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qbackingstore.h>
#include <qwindow.h>
@@ -61,11 +25,32 @@ public:
{
}
+ // Returns the DPR for the backing store. This is the DPR for the QWindow,
+ // possibly rounded up to the nearest integer.
+ qreal backingStoreDevicePixelRatio() const
+ {
+ // Note: keep in sync with QWidget::metric()!
+ qreal windowDpr = window->devicePixelRatio();
+ return downscale ? std::ceil(windowDpr) : windowDpr;
+ }
+
+ // Returns the factor used for converting from device independent to native
+ // backing store sizes. Normally this is just the gui scale factor, however
+ // if the backing store rounds the DPR up to the nearest integer then we also
+ // need to account for the factor introduced by that rounding.
+ qreal deviceIndependentToNativeFactor() const
+ {
+ const qreal roundingFactor = backingStoreDevicePixelRatio() / window->devicePixelRatio();
+ const qreal guiFactor = QHighDpiScaling::factor(window);
+ return roundingFactor * guiFactor;
+ }
+
QWindow *window;
QPlatformBackingStore *platformBackingStore = nullptr;
QScopedPointer<QImage> highDpiBackingstore;
QRegion staticContents;
QSize size;
+ bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
};
/*!
@@ -130,12 +115,14 @@ QWindow* QBackingStore::window() const
void QBackingStore::beginPaint(const QRegion &region)
{
+ const qreal dpr = d_ptr->backingStoreDevicePixelRatio();
+
if (d_ptr->highDpiBackingstore &&
- d_ptr->highDpiBackingstore->devicePixelRatio() != d_ptr->window->devicePixelRatio())
+ d_ptr->highDpiBackingstore->devicePixelRatio() != dpr)
resize(size());
QPlatformBackingStore *platformBackingStore = handle();
- platformBackingStore->beginPaint(QHighDpi::toNativeLocalRegion(region, d_ptr->window));
+ platformBackingStore->beginPaint(QHighDpi::scale(region, d_ptr->deviceIndependentToNativeFactor()));
// When QtGui is applying a high-dpi scale factor the backing store
// creates a "large" backing store image. This image needs to be
@@ -154,8 +141,7 @@ void QBackingStore::beginPaint(const QRegion &region)
d_ptr->highDpiBackingstore.reset(
new QImage(source->bits(), source->width(), source->height(), source->bytesPerLine(), source->format()));
- qreal targetDevicePixelRatio = d_ptr->window->devicePixelRatio();
- d_ptr->highDpiBackingstore->setDevicePixelRatio(targetDevicePixelRatio);
+ d_ptr->highDpiBackingstore->setDevicePixelRatio(dpr);
}
}
}
@@ -192,17 +178,6 @@ void QBackingStore::endPaint()
handle()->endPaint();
}
-static bool isRasterSurface(QWindow *window)
-{
- switch (window->surfaceType()) {
- case QSurface::RasterSurface:
- case QSurface::RasterGLSurface:
- return true;
- default:
- return false;
- };
-}
-
/*!
Flushes the given \a region from the specified \a window onto the
screen.
@@ -229,17 +204,22 @@ void QBackingStore::flush(const QRegion &region, QWindow *window, const QPoint &
return;
}
- if (!isRasterSurface(window)) {
- qWarning() << "Attempted flush to non-raster surface" << window << "of type" << window->surfaceType()
- << (window->inherits("QWidgetWindow") ? "(consider using Qt::WA_PaintOnScreen to exclude "
- "from backingstore sync)" : "");
- return;
- }
-
Q_ASSERT(window == topLevelWindow || topLevelWindow->isAncestorOf(window, QWindow::ExcludeTransients));
- handle()->flush(window, QHighDpi::toNativeLocalRegion(region, window),
- QHighDpi::toNativeLocalPosition(offset, window));
+ const qreal toNativeFactor = d_ptr->deviceIndependentToNativeFactor();
+
+ QRegion nativeRegion = QHighDpi::scale(region, toNativeFactor);
+ QPoint nativeOffset;
+ if (!offset.isNull()) {
+ nativeOffset = QHighDpi::scale(offset, toNativeFactor);
+ // Under fractional DPR, rounding of region and offset may accumulate to an off-by-one
+ QPoint topLeft = region.boundingRect().topLeft() + offset;
+ QPoint nativeTopLeft = QHighDpi::scale(topLeft, toNativeFactor);
+ QPoint diff = nativeTopLeft - (nativeRegion.boundingRect().topLeft() + nativeOffset);
+ Q_ASSERT(qMax(qAbs(diff.x()), qAbs(diff.y())) <= 1);
+ nativeRegion.translate(diff);
+ }
+ handle()->flush(window, nativeRegion, nativeOffset);
}
/*!
@@ -250,7 +230,8 @@ void QBackingStore::flush(const QRegion &region, QWindow *window, const QPoint &
void QBackingStore::resize(const QSize &size)
{
d_ptr->size = size;
- handle()->resize(QHighDpi::toNativePixels(size, d_ptr->window), d_ptr->staticContents);
+ const qreal factor = d_ptr->deviceIndependentToNativeFactor();
+ handle()->resize(QHighDpi::scale(size, factor), QHighDpi::scale(d_ptr->staticContents, factor));
}
/*!
@@ -272,13 +253,13 @@ bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
// Disable scrolling for non-integer scroll deltas. For this case
// the existing rendered pixels can't be re-used, and we return
// false to signal that a repaint is needed.
- const qreal nativeDx = QHighDpi::toNativePixels(qreal(dx), d_ptr->window);
- const qreal nativeDy = QHighDpi::toNativePixels(qreal(dy), d_ptr->window);
+ const qreal toNativeFactor = d_ptr->deviceIndependentToNativeFactor();
+ const qreal nativeDx = QHighDpi::scale(qreal(dx), toNativeFactor);
+ const qreal nativeDy = QHighDpi::scale(qreal(dy), toNativeFactor);
if (qFloor(nativeDx) != nativeDx || qFloor(nativeDy) != nativeDy)
return false;
- return handle()->scroll(QHighDpi::toNativeLocalRegion(area, d_ptr->window),
- nativeDx, nativeDy);
+ return handle()->scroll(QHighDpi::scale(area, toNativeFactor), nativeDx, nativeDy);
}
/*!
@@ -286,6 +267,13 @@ bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
*/
void QBackingStore::setStaticContents(const QRegion &region)
{
+ [[maybe_unused]] static const bool didCheckPlatformSupport = []{
+ const auto *integration = QGuiApplicationPrivate::platformIntegration();
+ if (!integration->hasCapability(QPlatformIntegration::BackingStoreStaticContents))
+ qWarning("QBackingStore::setStaticContents(): Platform does not support static contents");
+ return true;
+ }();
+
d_ptr->staticContents = region;
}
@@ -309,32 +297,34 @@ bool QBackingStore::hasStaticContents() const
void Q_GUI_EXPORT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset)
{
// make sure we don't detach
- uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits());
+ uchar *mem = const_cast<uchar*>(img.constBits());
qsizetype lineskip = img.bytesPerLine();
int depth = img.depth() >> 3;
const QRect imageRect(0, 0, img.width(), img.height());
- const QRect r = rect & imageRect & imageRect.translated(-offset);
- const QPoint p = rect.topLeft() + offset;
-
- if (r.isEmpty())
+ const QRect sourceRect = rect.intersected(imageRect).intersected(imageRect.translated(-offset));
+ if (sourceRect.isEmpty())
return;
+ const QRect destRect = sourceRect.translated(offset);
+ Q_ASSERT_X(imageRect.contains(destRect), "qt_scrollRectInImage",
+ "The sourceRect should already account for clipping, both pre and post scroll");
+
const uchar *src;
uchar *dest;
- if (r.top() < p.y()) {
- src = mem + r.bottom() * lineskip + r.left() * depth;
- dest = mem + (p.y() + r.height() - 1) * lineskip + p.x() * depth;
+ if (sourceRect.top() < destRect.top()) {
+ src = mem + sourceRect.bottom() * lineskip + sourceRect.left() * depth;
+ dest = mem + (destRect.top() + sourceRect.height() - 1) * lineskip + destRect.left() * depth;
lineskip = -lineskip;
} else {
- src = mem + r.top() * lineskip + r.left() * depth;
- dest = mem + p.y() * lineskip + p.x() * depth;
+ src = mem + sourceRect.top() * lineskip + sourceRect.left() * depth;
+ dest = mem + destRect.top() * lineskip + destRect.left() * depth;
}
- const int w = r.width();
- int h = r.height();
+ const int w = sourceRect.width();
+ int h = sourceRect.height();
const int bytes = w * depth;
// overlapping segments?
diff --git a/src/gui/painting/qbackingstore.h b/src/gui/painting/qbackingstore.h
index ed37e11a5b..3673d66a0f 100644
--- a/src/gui/painting/qbackingstore.h
+++ b/src/gui/painting/qbackingstore.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBACKINGSTORE_H
#define QBACKINGSTORE_H
diff --git a/src/gui/painting/qbackingstoredefaultcompositor.cpp b/src/gui/painting/qbackingstoredefaultcompositor.cpp
new file mode 100644
index 0000000000..c1452ca768
--- /dev/null
+++ b/src/gui/painting/qbackingstoredefaultcompositor.cpp
@@ -0,0 +1,676 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qbackingstoredefaultcompositor_p.h"
+#include <QtGui/private/qwindow_p.h>
+#include <qpa/qplatformgraphicsbuffer.h>
+#include <QtCore/qfile.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+QBackingStoreDefaultCompositor::~QBackingStoreDefaultCompositor()
+{
+ reset();
+}
+
+void QBackingStoreDefaultCompositor::reset()
+{
+ m_rhi = nullptr;
+ m_psNoBlend.reset();
+ m_psBlend.reset();
+ m_psPremulBlend.reset();
+ m_samplerNearest.reset();
+ m_samplerLinear.reset();
+ m_vbuf.reset();
+ m_texture.reset();
+ m_widgetQuadData.reset();
+ for (PerQuadData &d : m_textureQuadData)
+ d.reset();
+}
+
+QRhiTexture *QBackingStoreDefaultCompositor::toTexture(const QPlatformBackingStore *backingStore,
+ QRhi *rhi,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ const QRegion &dirtyRegion,
+ QPlatformBackingStore::TextureFlags *flags) const
+{
+ return toTexture(backingStore->toImage(), rhi, resourceUpdates, dirtyRegion, flags);
+}
+
+QRhiTexture *QBackingStoreDefaultCompositor::toTexture(const QImage &sourceImage,
+ QRhi *rhi,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ const QRegion &dirtyRegion,
+ QPlatformBackingStore::TextureFlags *flags) const
+{
+ Q_ASSERT(rhi);
+ Q_ASSERT(resourceUpdates);
+ Q_ASSERT(flags);
+
+ if (!m_rhi) {
+ m_rhi = rhi;
+ } else if (m_rhi != rhi) {
+ qWarning("QBackingStoreDefaultCompositor: the QRhi has changed unexpectedly, this should not happen");
+ return nullptr;
+ }
+
+ QImage image = sourceImage;
+
+ bool needsConversion = false;
+ *flags = {};
+
+ switch (image.format()) {
+ case QImage::Format_ARGB32_Premultiplied:
+ *flags |= QPlatformBackingStore::TexturePremultiplied;
+ Q_FALLTHROUGH();
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ *flags |= QPlatformBackingStore::TextureSwizzle;
+ break;
+ case QImage::Format_RGBA8888_Premultiplied:
+ *flags |= QPlatformBackingStore::TexturePremultiplied;
+ Q_FALLTHROUGH();
+ case QImage::Format_RGBX8888:
+ case QImage::Format_RGBA8888:
+ break;
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ // no fast path atm
+ needsConversion = true;
+ break;
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
+ // no fast path atm
+ needsConversion = true;
+ break;
+ default:
+ needsConversion = true;
+ break;
+ }
+
+ if (image.size().isEmpty())
+ return nullptr;
+
+ const bool resized = !m_texture || m_texture->pixelSize() != image.size();
+ if (dirtyRegion.isEmpty() && !resized)
+ return m_texture.get();
+
+ if (needsConversion)
+ image = image.convertToFormat(QImage::Format_RGBA8888);
+ else
+ image.detach(); // if it was just wrapping data, that's no good, we need ownership, so detach
+
+ if (resized) {
+ if (!m_texture)
+ m_texture.reset(rhi->newTexture(QRhiTexture::RGBA8, image.size()));
+ else
+ m_texture->setPixelSize(image.size());
+ m_texture->create();
+ resourceUpdates->uploadTexture(m_texture.get(), image);
+ } else {
+ QRect imageRect = image.rect();
+ QRect rect = dirtyRegion.boundingRect() & imageRect;
+ QRhiTextureSubresourceUploadDescription subresDesc(image);
+ subresDesc.setSourceTopLeft(rect.topLeft());
+ subresDesc.setSourceSize(rect.size());
+ subresDesc.setDestinationTopLeft(rect.topLeft());
+ QRhiTextureUploadDescription uploadDesc(QRhiTextureUploadEntry(0, 0, subresDesc));
+ resourceUpdates->uploadTexture(m_texture.get(), uploadDesc);
+ }
+
+ return m_texture.get();
+}
+
+static inline QRect scaledRect(const QRect &rect, qreal factor)
+{
+ return QRect(rect.topLeft() * factor, rect.size() * factor);
+}
+
+static inline QPoint scaledOffset(const QPoint &pt, qreal factor)
+{
+ return pt * factor;
+}
+
+static QRegion scaledRegion(const QRegion &region, qreal factor, const QPoint &offset)
+{
+ if (offset.isNull() && factor <= 1)
+ return region;
+
+ QVarLengthArray<QRect, 4> rects;
+ rects.reserve(region.rectCount());
+ for (const QRect &rect : region)
+ rects.append(scaledRect(rect.translated(offset), factor));
+
+ QRegion deviceRegion;
+ deviceRegion.setRects(rects.constData(), rects.size());
+ return deviceRegion;
+}
+
+static QMatrix4x4 targetTransform(const QRectF &target, const QRect &viewport, bool invertY)
+{
+ qreal x_scale = target.width() / viewport.width();
+ qreal y_scale = target.height() / viewport.height();
+
+ const QPointF relative_to_viewport = target.topLeft() - viewport.topLeft();
+ qreal x_translate = x_scale - 1 + ((relative_to_viewport.x() / viewport.width()) * 2);
+ qreal y_translate;
+ if (invertY)
+ y_translate = y_scale - 1 + ((relative_to_viewport.y() / viewport.height()) * 2);
+ else
+ y_translate = -y_scale + 1 - ((relative_to_viewport.y() / viewport.height()) * 2);
+
+ QMatrix4x4 matrix;
+ matrix(0,3) = x_translate;
+ matrix(1,3) = y_translate;
+
+ matrix(0,0) = x_scale;
+ matrix(1,1) = (invertY ? -1.0 : 1.0) * y_scale;
+
+ return matrix;
+}
+
+enum class SourceTransformOrigin {
+ BottomLeft,
+ TopLeft
+};
+
+static QMatrix3x3 sourceTransform(const QRectF &subTexture,
+ const QSize &textureSize,
+ SourceTransformOrigin origin)
+{
+ qreal x_scale = subTexture.width() / textureSize.width();
+ qreal y_scale = subTexture.height() / textureSize.height();
+
+ const QPointF topLeft = subTexture.topLeft();
+ qreal x_translate = topLeft.x() / textureSize.width();
+ qreal y_translate = topLeft.y() / textureSize.height();
+
+ if (origin == SourceTransformOrigin::TopLeft) {
+ y_scale = -y_scale;
+ y_translate = 1 - y_translate;
+ }
+
+ QMatrix3x3 matrix;
+ matrix(0,2) = x_translate;
+ matrix(1,2) = y_translate;
+
+ matrix(0,0) = x_scale;
+ matrix(1,1) = y_scale;
+
+ return matrix;
+}
+
+static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
+{
+ return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1,
+ topLeftRect.width(), topLeftRect.height());
+}
+
+static bool prepareDrawForRenderToTextureWidget(const QPlatformTextureList *textures,
+ int idx,
+ QWindow *window,
+ const QRect &deviceWindowRect,
+ const QPoint &offset,
+ bool invertTargetY,
+ bool invertSource,
+ QMatrix4x4 *target,
+ QMatrix3x3 *source)
+{
+ const QRect clipRect = textures->clipRect(idx);
+ if (clipRect.isEmpty())
+ return false;
+
+ QRect rectInWindow = textures->geometry(idx);
+ // relative to the TLW, not necessarily our window (if the flush is for a native child widget), have to adjust
+ rectInWindow.translate(-offset);
+
+ const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());
+ const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());
+
+ *target = targetTransform(scaledRect(clippedRectInWindow, window->devicePixelRatio()),
+ deviceWindowRect,
+ invertTargetY);
+
+ *source = sourceTransform(scaledRect(srcRect, window->devicePixelRatio()),
+ scaledRect(rectInWindow, window->devicePixelRatio()).size(),
+ invertSource ? SourceTransformOrigin::TopLeft : SourceTransformOrigin::BottomLeft);
+
+ return true;
+}
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ qWarning("QBackingStoreDefaultCompositor: Could not find built-in shader %s "
+ "(is something wrong with QtGui library resources?)",
+ qPrintable(name));
+ return QShader();
+}
+
+static void updateMatrix3x3(QRhiResourceUpdateBatch *resourceUpdates, QRhiBuffer *ubuf, const QMatrix3x3 &m)
+{
+ // mat3 is still 4 floats per column in the uniform buffer (but there is no
+ // 4th column), so 48 bytes altogether, not 36 or 64.
+
+ float f[12];
+ const float *src = static_cast<const float *>(m.constData());
+ float *dst = f;
+ memcpy(dst, src, 3 * sizeof(float));
+ memcpy(dst + 4, src + 3, 3 * sizeof(float));
+ memcpy(dst + 8, src + 6, 3 * sizeof(float));
+
+ resourceUpdates->updateDynamicBuffer(ubuf, 64, 48, f);
+}
+
+enum class PipelineBlend {
+ None,
+ Alpha,
+ PremulAlpha
+};
+
+static QRhiGraphicsPipeline *createGraphicsPipeline(QRhi *rhi,
+ QRhiShaderResourceBindings *srb,
+ QRhiRenderPassDescriptor *rpDesc,
+ PipelineBlend blend)
+{
+ QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
+
+ switch (blend) {
+ case PipelineBlend::Alpha:
+ {
+ QRhiGraphicsPipeline::TargetBlend blend;
+ blend.enable = true;
+ blend.srcColor = QRhiGraphicsPipeline::SrcAlpha;
+ blend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
+ blend.srcAlpha = QRhiGraphicsPipeline::One;
+ blend.dstAlpha = QRhiGraphicsPipeline::One;
+ ps->setTargetBlends({ blend });
+ }
+ break;
+ case PipelineBlend::PremulAlpha:
+ {
+ QRhiGraphicsPipeline::TargetBlend blend;
+ blend.enable = true;
+ blend.srcColor = QRhiGraphicsPipeline::One;
+ blend.dstColor = QRhiGraphicsPipeline::OneMinusSrcAlpha;
+ blend.srcAlpha = QRhiGraphicsPipeline::One;
+ blend.dstAlpha = QRhiGraphicsPipeline::One;
+ ps->setTargetBlends({ blend });
+ }
+ break;
+ default:
+ break;
+ }
+
+ ps->setShaderStages({
+ { QRhiShaderStage::Vertex, getShader(":/qt-project.org/gui/painting/shaders/backingstorecompose.vert.qsb"_L1) },
+ { QRhiShaderStage::Fragment, getShader(":/qt-project.org/gui/painting/shaders/backingstorecompose.frag.qsb"_L1) }
+ });
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({ { 5 * sizeof(float) } });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, quint32(3 * sizeof(float)) }
+ });
+ ps->setVertexInputLayout(inputLayout);
+ ps->setShaderResourceBindings(srb);
+ ps->setRenderPassDescriptor(rpDesc);
+
+ if (!ps->create()) {
+ qWarning("QBackingStoreDefaultCompositor: Failed to build graphics pipeline");
+ delete ps;
+ return nullptr;
+ }
+ return ps;
+}
+
+static const int UBUF_SIZE = 120;
+
+QBackingStoreDefaultCompositor::PerQuadData QBackingStoreDefaultCompositor::createPerQuadData(QRhiTexture *texture, QRhiTexture *textureExtra)
+{
+ PerQuadData d;
+
+ d.ubuf = m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, UBUF_SIZE);
+ if (!d.ubuf->create())
+ qWarning("QBackingStoreDefaultCompositor: Failed to create uniform buffer");
+
+ d.srb = m_rhi->newShaderResourceBindings();
+ d.srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf, 0, UBUF_SIZE),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, m_samplerNearest.get())
+ });
+ if (!d.srb->create())
+ qWarning("QBackingStoreDefaultCompositor: Failed to create srb");
+ d.lastUsedTexture = texture;
+
+ if (textureExtra) {
+ d.srbExtra = m_rhi->newShaderResourceBindings();
+ d.srbExtra->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf, 0, UBUF_SIZE),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, textureExtra, m_samplerNearest.get())
+ });
+ if (!d.srbExtra->create())
+ qWarning("QBackingStoreDefaultCompositor: Failed to create srb");
+ }
+
+ d.lastUsedTextureExtra = textureExtra;
+
+ return d;
+}
+
+void QBackingStoreDefaultCompositor::updatePerQuadData(PerQuadData *d, QRhiTexture *texture, QRhiTexture *textureExtra,
+ UpdateQuadDataOptions options)
+{
+ // This whole check-if-texture-ptr-is-different is needed because there is
+ // nothing saying a QPlatformTextureList cannot return a different
+ // QRhiTexture* from the same index in a subsequent flush.
+
+ const QRhiSampler::Filter filter = options.testFlag(NeedsLinearFiltering) ? QRhiSampler::Linear : QRhiSampler::Nearest;
+ if ((d->lastUsedTexture == texture && d->lastUsedFilter == filter) || !d->srb)
+ return;
+
+ QRhiSampler *sampler = filter == QRhiSampler::Linear ? m_samplerLinear.get() : m_samplerNearest.get();
+ d->srb->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d->ubuf, 0, UBUF_SIZE),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
+ });
+
+ d->srb->updateResources(QRhiShaderResourceBindings::BindingsAreSorted);
+ d->lastUsedTexture = texture;
+ d->lastUsedFilter = filter;
+
+ if (textureExtra) {
+ d->srbExtra->setBindings({
+ QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d->ubuf, 0, UBUF_SIZE),
+ QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, textureExtra, sampler)
+ });
+
+ d->srbExtra->updateResources(QRhiShaderResourceBindings::BindingsAreSorted);
+ d->lastUsedTextureExtra = textureExtra;
+ }
+}
+
+void QBackingStoreDefaultCompositor::updateUniforms(PerQuadData *d, QRhiResourceUpdateBatch *resourceUpdates,
+ const QMatrix4x4 &target, const QMatrix3x3 &source,
+ UpdateUniformOptions options)
+{
+ resourceUpdates->updateDynamicBuffer(d->ubuf, 0, 64, target.constData());
+ updateMatrix3x3(resourceUpdates, d->ubuf, source);
+ float opacity = 1.0f;
+ resourceUpdates->updateDynamicBuffer(d->ubuf, 112, 4, &opacity);
+ qint32 textureSwizzle = options;
+ resourceUpdates->updateDynamicBuffer(d->ubuf, 116, 4, &textureSwizzle);
+}
+
+void QBackingStoreDefaultCompositor::ensureResources(QRhiResourceUpdateBatch *resourceUpdates, QRhiRenderPassDescriptor *rpDesc)
+{
+ static const float vertexData[] = {
+ -1, -1, 0, 0, 0,
+ -1, 1, 0, 0, 1,
+ 1, -1, 0, 1, 0,
+ -1, 1, 0, 0, 1,
+ 1, -1, 0, 1, 0,
+ 1, 1, 0, 1, 1
+ };
+
+ if (!m_vbuf) {
+ m_vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)));
+ if (m_vbuf->create())
+ resourceUpdates->uploadStaticBuffer(m_vbuf.get(), vertexData);
+ else
+ qWarning("QBackingStoreDefaultCompositor: Failed to create vertex buffer");
+ }
+
+ if (!m_samplerNearest) {
+ m_samplerNearest.reset(m_rhi->newSampler(QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge));
+ if (!m_samplerNearest->create())
+ qWarning("QBackingStoreDefaultCompositor: Failed to create sampler (Nearest filtering)");
+ }
+
+ if (!m_samplerLinear) {
+ m_samplerLinear.reset(m_rhi->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
+ QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge));
+ if (!m_samplerLinear->create())
+ qWarning("QBackingStoreDefaultCompositor: Failed to create sampler (Linear filtering)");
+ }
+
+ if (!m_widgetQuadData.isValid())
+ m_widgetQuadData = createPerQuadData(m_texture.get());
+
+ QRhiShaderResourceBindings *srb = m_widgetQuadData.srb; // just for the layout
+ if (!m_psNoBlend)
+ m_psNoBlend.reset(createGraphicsPipeline(m_rhi, srb, rpDesc, PipelineBlend::None));
+ if (!m_psBlend)
+ m_psBlend.reset(createGraphicsPipeline(m_rhi, srb, rpDesc, PipelineBlend::Alpha));
+ if (!m_psPremulBlend)
+ m_psPremulBlend.reset(createGraphicsPipeline(m_rhi, srb, rpDesc, PipelineBlend::PremulAlpha));
+}
+
+QPlatformBackingStore::FlushResult QBackingStoreDefaultCompositor::flush(QPlatformBackingStore *backingStore,
+ QRhi *rhi,
+ QRhiSwapChain *swapchain,
+ QWindow *window,
+ qreal sourceDevicePixelRatio,
+ const QRegion &region,
+ const QPoint &offset,
+ QPlatformTextureList *textures,
+ bool translucentBackground)
+{
+ if (!rhi)
+ return QPlatformBackingStore::FlushFailed;
+
+ Q_ASSERT(textures); // may be empty if there are no render-to-texture widgets at all, but null it cannot be
+
+ if (!m_rhi) {
+ m_rhi = rhi;
+ } else if (m_rhi != rhi) {
+ qWarning("QBackingStoreDefaultCompositor: the QRhi has changed unexpectedly, this should not happen");
+ return QPlatformBackingStore::FlushFailed;
+ }
+
+ if (!qt_window_private(window)->receivedExpose)
+ return QPlatformBackingStore::FlushSuccess;
+
+ qCDebug(lcQpaBackingStore) << "Composing and flushing" << region << "of" << window
+ << "at offset" << offset << "with" << textures->count() << "texture(s) in" << textures
+ << "via swapchain" << swapchain;
+
+ QWindowPrivate::get(window)->lastComposeTime.start();
+
+ if (swapchain->currentPixelSize() != swapchain->surfacePixelSize())
+ swapchain->createOrResize();
+
+ // Start recording a new frame.
+ QRhi::FrameOpResult frameResult = rhi->beginFrame(swapchain);
+ if (frameResult == QRhi::FrameOpSwapChainOutOfDate) {
+ if (!swapchain->createOrResize())
+ return QPlatformBackingStore::FlushFailed;
+ frameResult = rhi->beginFrame(swapchain);
+ }
+ if (frameResult == QRhi::FrameOpDeviceLost)
+ return QPlatformBackingStore::FlushFailedDueToLostDevice;
+ if (frameResult != QRhi::FrameOpSuccess)
+ return QPlatformBackingStore::FlushFailed;
+
+ // Prepare resource updates.
+ QRhiResourceUpdateBatch *resourceUpdates = rhi->nextResourceUpdateBatch();
+ QPlatformBackingStore::TextureFlags flags;
+
+ bool gotTextureFromGraphicsBuffer = false;
+ if (QPlatformGraphicsBuffer *graphicsBuffer = backingStore->graphicsBuffer()) {
+ if (graphicsBuffer->lock(QPlatformGraphicsBuffer::SWReadAccess)) {
+ const QImage::Format format = QImage::toImageFormat(graphicsBuffer->format());
+ const QSize size = graphicsBuffer->size();
+ QImage wrapperImage(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), format);
+ toTexture(wrapperImage, rhi, resourceUpdates, scaledRegion(region, sourceDevicePixelRatio, offset), &flags);
+ gotTextureFromGraphicsBuffer = true;
+ graphicsBuffer->unlock();
+ if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft)
+ flags |= QPlatformBackingStore::TextureFlip;
+ }
+ }
+ if (!gotTextureFromGraphicsBuffer)
+ toTexture(backingStore, rhi, resourceUpdates, scaledRegion(region, sourceDevicePixelRatio, offset), &flags);
+
+ ensureResources(resourceUpdates, swapchain->renderPassDescriptor());
+
+ UpdateUniformOptions uniformOptions;
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ if (flags & QPlatformBackingStore::TextureSwizzle)
+ uniformOptions |= NeedsRedBlueSwap;
+#else
+ if (flags & QPlatformBackingStore::TextureSwizzle)
+ uniformOptions |= NeedsAlphaRotate;
+#endif
+ const bool premultiplied = (flags & QPlatformBackingStore::TexturePremultiplied) != 0;
+ SourceTransformOrigin origin = SourceTransformOrigin::TopLeft;
+ if (flags & QPlatformBackingStore::TextureFlip)
+ origin = SourceTransformOrigin::BottomLeft;
+
+ const qreal dpr = window->devicePixelRatio();
+ const QRect deviceWindowRect = scaledRect(QRect(QPoint(), window->size()), dpr);
+ const QRect sourceWindowRect = scaledRect(QRect(QPoint(), window->size()), sourceDevicePixelRatio);
+ // If sourceWindowRect is larger than deviceWindowRect, we are doing high
+ // DPI downscaling. In that case Linear filtering is a must, whereas for the
+ // 1:1 case Nearest must be used for Qt 5 visual compatibility.
+ const bool needsLinearSampler = sourceWindowRect.width() > deviceWindowRect.width()
+ && sourceWindowRect.height() > deviceWindowRect.height();
+
+ const bool invertTargetY = !rhi->isYUpInNDC();
+ const bool invertSource = !rhi->isYUpInFramebuffer();
+
+ if (m_texture) {
+ // The backingstore is for the entire tlw. In case of native children, offset tells the position
+ // relative to the tlw. The window rect is scaled by the source device pixel ratio to get
+ // the source rect.
+ const QPoint sourceWindowOffset = scaledOffset(offset, sourceDevicePixelRatio);
+ const QRect srcRect = toBottomLeftRect(sourceWindowRect.translated(sourceWindowOffset), m_texture->pixelSize().height());
+ const QMatrix3x3 source = sourceTransform(srcRect, m_texture->pixelSize(), origin);
+ QMatrix4x4 target; // identity
+ if (invertTargetY)
+ target.data()[5] = -1.0f;
+ updateUniforms(&m_widgetQuadData, resourceUpdates, target, source, uniformOptions);
+ if (needsLinearSampler)
+ updatePerQuadData(&m_widgetQuadData, m_texture.get(), nullptr, NeedsLinearFiltering);
+ }
+
+ const int textureWidgetCount = textures->count();
+ const int oldTextureQuadDataCount = m_textureQuadData.size();
+ if (oldTextureQuadDataCount != textureWidgetCount) {
+ for (int i = textureWidgetCount; i < oldTextureQuadDataCount; ++i)
+ m_textureQuadData[i].reset();
+ m_textureQuadData.resize(textureWidgetCount);
+ }
+
+ for (int i = 0; i < textureWidgetCount; ++i) {
+ const bool invertSourceForTextureWidget = textures->flags(i).testFlag(QPlatformTextureList::MirrorVertically)
+ ? !invertSource : invertSource;
+ QMatrix4x4 target;
+ QMatrix3x3 source;
+ if (!prepareDrawForRenderToTextureWidget(textures, i, window, deviceWindowRect,
+ offset, invertTargetY, invertSourceForTextureWidget,
+ &target, &source))
+ {
+ m_textureQuadData[i].reset();
+ continue;
+ }
+ QRhiTexture *t = textures->texture(i);
+ QRhiTexture *tExtra = textures->textureExtra(i);
+ if (t) {
+ if (!m_textureQuadData[i].isValid())
+ m_textureQuadData[i] = createPerQuadData(t, tExtra);
+ else
+ updatePerQuadData(&m_textureQuadData[i], t, tExtra);
+ updateUniforms(&m_textureQuadData[i], resourceUpdates, target, source);
+ if (needsLinearSampler)
+ updatePerQuadData(&m_textureQuadData[i], t, tExtra, NeedsLinearFiltering);
+ } else {
+ m_textureQuadData[i].reset();
+ }
+ }
+
+ // Record the render pass (with committing the resource updates).
+ QRhiCommandBuffer *cb = swapchain->currentFrameCommandBuffer();
+ const QSize outputSizeInPixels = swapchain->currentPixelSize();
+ QColor clearColor = translucentBackground ? Qt::transparent : Qt::black;
+
+ cb->resourceUpdate(resourceUpdates);
+
+ auto render = [&](std::optional<QRhiSwapChain::StereoTargetBuffer> buffer = std::nullopt) {
+ QRhiRenderTarget* target = nullptr;
+ if (buffer.has_value())
+ target = swapchain->currentFrameRenderTarget(buffer.value());
+ else
+ target = swapchain->currentFrameRenderTarget();
+
+ cb->beginPass(target, clearColor, { 1.0f, 0 });
+
+ cb->setGraphicsPipeline(m_psNoBlend.get());
+ cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
+ QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0);
+ cb->setVertexInput(0, 1, &vbufBinding);
+
+ // Textures for renderToTexture widgets.
+ for (int i = 0; i < textureWidgetCount; ++i) {
+ if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
+ if (m_textureQuadData[i].isValid()) {
+
+ QRhiShaderResourceBindings* srb = m_textureQuadData[i].srb;
+ if (buffer == QRhiSwapChain::RightBuffer && m_textureQuadData[i].srbExtra)
+ srb = m_textureQuadData[i].srbExtra;
+
+ cb->setShaderResources(srb);
+ cb->draw(6);
+ }
+ }
+ }
+
+ cb->setGraphicsPipeline(premultiplied ? m_psPremulBlend.get() : m_psBlend.get());
+
+ // Backingstore texture with the normal widgets.
+ if (m_texture) {
+ cb->setShaderResources(m_widgetQuadData.srb);
+ cb->draw(6);
+ }
+
+ // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
+ for (int i = 0; i < textureWidgetCount; ++i) {
+ const QPlatformTextureList::Flags flags = textures->flags(i);
+ if (flags.testFlag(QPlatformTextureList::StacksOnTop)) {
+ if (m_textureQuadData[i].isValid()) {
+ if (flags.testFlag(QPlatformTextureList::NeedsPremultipliedAlphaBlending))
+ cb->setGraphicsPipeline(m_psPremulBlend.get());
+ else
+ cb->setGraphicsPipeline(m_psBlend.get());
+
+ QRhiShaderResourceBindings* srb = m_textureQuadData[i].srb;
+ if (buffer == QRhiSwapChain::RightBuffer && m_textureQuadData[i].srbExtra)
+ srb = m_textureQuadData[i].srbExtra;
+
+ cb->setShaderResources(srb);
+ cb->draw(6);
+ }
+ }
+ }
+
+ cb->endPass();
+ };
+
+ if (swapchain->window()->format().stereo()) {
+ render(QRhiSwapChain::LeftBuffer);
+ render(QRhiSwapChain::RightBuffer);
+ } else
+ render();
+
+ rhi->endFrame(swapchain);
+
+ return QPlatformBackingStore::FlushSuccess;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qbackingstoredefaultcompositor_p.h b/src/gui/painting/qbackingstoredefaultcompositor_p.h
new file mode 100644
index 0000000000..c5a8ffd328
--- /dev/null
+++ b/src/gui/painting/qbackingstoredefaultcompositor_p.h
@@ -0,0 +1,110 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QBACKINGSTOREDEFAULTCOMPOSITOR_P_H
+#define QBACKINGSTOREDEFAULTCOMPOSITOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qpa/qplatformbackingstore.h>
+#include <rhi/qrhi.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBackingStoreDefaultCompositor
+{
+public:
+ ~QBackingStoreDefaultCompositor();
+
+ void reset();
+
+ QRhiTexture *toTexture(const QPlatformBackingStore *backingStore,
+ QRhi *rhi,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ const QRegion &dirtyRegion,
+ QPlatformBackingStore::TextureFlags *flags) const;
+
+ QPlatformBackingStore::FlushResult flush(QPlatformBackingStore *backingStore,
+ QRhi *rhi,
+ QRhiSwapChain *swapchain,
+ QWindow *window,
+ qreal sourceDevicePixelRatio,
+ const QRegion &region,
+ const QPoint &offset,
+ QPlatformTextureList *textures,
+ bool translucentBackground);
+
+private:
+ enum UpdateUniformOption {
+ NeedsRedBlueSwap = 1 << 0,
+ NeedsAlphaRotate = 1 << 1
+ };
+ Q_DECLARE_FLAGS(UpdateUniformOptions, UpdateUniformOption)
+ enum UpdateQuadDataOption {
+ NeedsLinearFiltering = 1 << 0
+ };
+ Q_DECLARE_FLAGS(UpdateQuadDataOptions, UpdateQuadDataOption)
+
+ void ensureResources(QRhiResourceUpdateBatch *resourceUpdates, QRhiRenderPassDescriptor *rpDesc);
+ QRhiTexture *toTexture(const QImage &image,
+ QRhi *rhi,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ const QRegion &dirtyRegion,
+ QPlatformBackingStore::TextureFlags *flags) const;
+
+ mutable QRhi *m_rhi = nullptr;
+ mutable std::unique_ptr<QRhiTexture> m_texture;
+
+ std::unique_ptr<QRhiBuffer> m_vbuf;
+ std::unique_ptr<QRhiSampler> m_samplerNearest;
+ std::unique_ptr<QRhiSampler> m_samplerLinear;
+ std::unique_ptr<QRhiGraphicsPipeline> m_psNoBlend;
+ std::unique_ptr<QRhiGraphicsPipeline> m_psBlend;
+ std::unique_ptr<QRhiGraphicsPipeline> m_psPremulBlend;
+
+ struct PerQuadData {
+ QRhiBuffer *ubuf = nullptr;
+ // All srbs are layout-compatible.
+ QRhiShaderResourceBindings *srb = nullptr;
+ QRhiShaderResourceBindings *srbExtra = nullptr; // may be null (used for stereo)
+ QRhiTexture *lastUsedTexture = nullptr;
+ QRhiTexture *lastUsedTextureExtra = nullptr; // may be null (used for stereo)
+ QRhiSampler::Filter lastUsedFilter = QRhiSampler::None;
+ bool isValid() const { return ubuf && srb; }
+ void reset() {
+ delete ubuf;
+ ubuf = nullptr;
+ delete srb;
+ srb = nullptr;
+ if (srbExtra) {
+ delete srbExtra;
+ srbExtra = nullptr;
+ }
+ lastUsedTexture = nullptr;
+ lastUsedTextureExtra = nullptr;
+ lastUsedFilter = QRhiSampler::None;
+ }
+ };
+ PerQuadData m_widgetQuadData;
+ QVarLengthArray<PerQuadData, 8> m_textureQuadData;
+
+ PerQuadData createPerQuadData(QRhiTexture *texture, QRhiTexture *textureExtra = nullptr);
+ void updatePerQuadData(PerQuadData *d, QRhiTexture *texture, QRhiTexture *textureExtra = nullptr,
+ UpdateQuadDataOptions options = {});
+ void updateUniforms(PerQuadData *d, QRhiResourceUpdateBatch *resourceUpdates,
+ const QMatrix4x4 &target, const QMatrix3x3 &source,
+ UpdateUniformOptions options = {});
+};
+
+QT_END_NAMESPACE
+
+#endif // QBACKINGSTOREDEFAULTCOMPOSITOR_P_H
diff --git a/src/gui/painting/qbackingstorerhisupport.cpp b/src/gui/painting/qbackingstorerhisupport.cpp
new file mode 100644
index 0000000000..fe5589dc2d
--- /dev/null
+++ b/src/gui/painting/qbackingstorerhisupport.cpp
@@ -0,0 +1,327 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qbackingstorerhisupport_p.h"
+#include <qpa/qplatformintegration.h>
+#include <private/qguiapplication_p.h>
+
+#if QT_CONFIG(opengl)
+#include <QtGui/qoffscreensurface.h>
+#include <QtGui/private/qopenglcontext_p.h>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QtGui/private/qvulkandefaultinstance_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcQpaBackingStore)
+
+QBackingStoreRhiSupport::~QBackingStoreRhiSupport()
+{
+ reset();
+}
+
+void QBackingStoreRhiSupport::SwapchainData::reset()
+{
+ delete swapchain;
+ delete renderPassDescriptor;
+ delete windowWatcher;
+ *this = {};
+}
+
+void QBackingStoreRhiSupport::reset()
+{
+ for (SwapchainData &d : m_swapchains)
+ d.reset();
+
+ m_swapchains.clear();
+
+ delete m_rhi;
+ m_rhi = nullptr;
+
+ delete m_openGLFallbackSurface;
+ m_openGLFallbackSurface = nullptr;
+}
+
+bool QBackingStoreRhiSupport::create()
+{
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RhiBasedRendering))
+ return false;
+
+ // note: m_window may be null (special case for fully offscreen rendering)
+
+ QRhi *rhi = nullptr;
+ QOffscreenSurface *surface = nullptr;
+ QRhi::Flags flags;
+
+ // These must be the same env.vars Qt Quick uses (as documented), in order
+ // to ensure symmetry in the behavior between a QQuickWindow and a
+ // (QRhi-based) widget top-level window.
+ if (qEnvironmentVariableIntValue("QSG_RHI_PREFER_SOFTWARE_RENDERER"))
+ flags |= QRhi::PreferSoftwareRenderer;
+ if (qEnvironmentVariableIntValue("QSG_RHI_PROFILE"))
+ flags |= QRhi::EnableDebugMarkers | QRhi::EnableTimestamps;
+
+ if (m_config.api() == QPlatformBackingStoreRhiConfig::Null) {
+ QRhiNullInitParams params;
+ rhi = QRhi::create(QRhi::Null, &params, flags);
+ }
+
+#if QT_CONFIG(opengl)
+ if (!rhi && m_config.api() == QPlatformBackingStoreRhiConfig::OpenGL) {
+ surface = QRhiGles2InitParams::newFallbackSurface(m_format);
+ QRhiGles2InitParams params;
+ params.fallbackSurface = surface;
+ params.window = m_window;
+ params.format = m_format;
+ params.shareContext = qt_gl_global_share_context();
+ rhi = QRhi::create(QRhi::OpenGLES2, &params, flags);
+ }
+#endif
+
+#ifdef Q_OS_WIN
+ if (!rhi) {
+ if (m_config.api() == QPlatformBackingStoreRhiConfig::D3D11) {
+ QRhiD3D11InitParams params;
+ params.enableDebugLayer = m_config.isDebugLayerEnabled();
+ rhi = QRhi::create(QRhi::D3D11, &params, flags);
+ if (!rhi && !flags.testFlag(QRhi::PreferSoftwareRenderer)) {
+ qCDebug(lcQpaBackingStore, "Failed to create a D3D11 device with default settings; "
+ "attempting to get a software rasterizer backed device instead");
+ flags |= QRhi::PreferSoftwareRenderer;
+ rhi = QRhi::create(QRhi::D3D11, &params, flags);
+ }
+ } else if (m_config.api() == QPlatformBackingStoreRhiConfig::D3D12) {
+ QRhiD3D12InitParams params;
+ params.enableDebugLayer = m_config.isDebugLayerEnabled();
+ rhi = QRhi::create(QRhi::D3D12, &params, flags);
+ if (!rhi && !flags.testFlag(QRhi::PreferSoftwareRenderer)) {
+ qCDebug(lcQpaBackingStore, "Failed to create a D3D12 device with default settings; "
+ "attempting to get a software rasterizer backed device instead");
+ flags |= QRhi::PreferSoftwareRenderer;
+ rhi = QRhi::create(QRhi::D3D12, &params, flags);
+ }
+ }
+ }
+#endif
+
+#if QT_CONFIG(metal)
+ if (!rhi && m_config.api() == QPlatformBackingStoreRhiConfig::Metal) {
+ QRhiMetalInitParams params;
+ // For parity with Qt Quick, fall back to OpenGL when there is no Metal (f.ex. in macOS virtual machines).
+ if (QRhi::probe(QRhi::Metal, &params)) {
+ rhi = QRhi::create(QRhi::Metal, &params, flags);
+ } else {
+ qCDebug(lcQpaBackingStore, "Metal does not seem to be supported. Falling back to OpenGL.");
+ rhi = QRhi::create(QRhi::OpenGLES2, &params, flags);
+ }
+ }
+#endif
+
+#if QT_CONFIG(vulkan)
+ if (!rhi && m_config.api() == QPlatformBackingStoreRhiConfig::Vulkan) {
+ if (m_config.isDebugLayerEnabled())
+ QVulkanDefaultInstance::setFlag(QVulkanDefaultInstance::EnableValidation);
+ QRhiVulkanInitParams params;
+ if (m_window) {
+ if (!m_window->vulkanInstance())
+ m_window->setVulkanInstance(QVulkanDefaultInstance::instance());
+ params.inst = m_window->vulkanInstance();
+ } else {
+ params.inst = QVulkanDefaultInstance::instance();
+ }
+ if (!params.inst) {
+ qWarning("No QVulkanInstance set for the top-level window, this is wrong.");
+ return false;
+ }
+ params.window = m_window;
+ rhi = QRhi::create(QRhi::Vulkan, &params, flags);
+ }
+#endif
+
+ if (!rhi) {
+ qWarning("Failed to create QRhi for QBackingStoreRhiSupport");
+ delete surface;
+ return false;
+ }
+
+ m_rhi = rhi;
+ m_openGLFallbackSurface = surface;
+ return true;
+}
+
+QRhiSwapChain *QBackingStoreRhiSupport::swapChainForWindow(QWindow *window)
+{
+ auto it = m_swapchains.constFind(window);
+ if (it != m_swapchains.constEnd())
+ return it.value().swapchain;
+
+ QRhiSwapChain *swapchain = nullptr;
+ QRhiRenderPassDescriptor *rp = nullptr;
+ if (window && m_rhi) {
+ QRhiSwapChain::Flags flags;
+ const QSurfaceFormat format = window->requestedFormat();
+ if (format.swapInterval() == 0)
+ flags |= QRhiSwapChain::NoVSync;
+ if (format.alphaBufferSize() > 0)
+ flags |= QRhiSwapChain::SurfaceHasNonPreMulAlpha;
+#if QT_CONFIG(vulkan)
+ if (m_config.api() == QPlatformBackingStoreRhiConfig::Vulkan && !window->vulkanInstance())
+ window->setVulkanInstance(QVulkanDefaultInstance::instance());
+#endif
+ qCDebug(lcQpaBackingStore) << "Creating swapchain for window" << window;
+ swapchain = m_rhi->newSwapChain();
+ swapchain->setWindow(window);
+ swapchain->setFlags(flags);
+ rp = swapchain->newCompatibleRenderPassDescriptor();
+ swapchain->setRenderPassDescriptor(rp);
+ if (!swapchain->createOrResize()) {
+ qWarning("Failed to create swapchain for window flushed with an RHI-enabled backingstore");
+ delete rp;
+ return nullptr;
+ }
+ }
+ if (swapchain) {
+ SwapchainData d;
+ d.swapchain = swapchain;
+ d.renderPassDescriptor = rp;
+ d.windowWatcher = new QBackingStoreRhiSupportWindowWatcher(this);
+ m_swapchains.insert(window, d);
+ window->installEventFilter(d.windowWatcher);
+ }
+ return swapchain;
+}
+
+bool QBackingStoreRhiSupportWindowWatcher::eventFilter(QObject *obj, QEvent *event)
+{
+ if (event->type() == QEvent::WindowAboutToChangeInternal
+ || (event->type() == QEvent::PlatformSurface
+ && static_cast<QPlatformSurfaceEvent *>(event)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed))
+ {
+ QWindow *window = qobject_cast<QWindow *>(obj);
+ auto it = m_rhiSupport->m_swapchains.find(window);
+ if (it != m_rhiSupport->m_swapchains.end()) {
+ qCDebug(lcQpaBackingStore) << event << "received for" << window << "- cleaning up swapchain";
+ auto data = *it;
+ m_rhiSupport->m_swapchains.erase(it);
+ data.reset(); // deletes 'this'
+ }
+ }
+ return false;
+}
+
+QSurface::SurfaceType QBackingStoreRhiSupport::surfaceTypeForConfig(const QPlatformBackingStoreRhiConfig &config)
+{
+ QSurface::SurfaceType type = QSurface::RasterSurface;
+ switch (config.api()) {
+ case QPlatformBackingStoreRhiConfig::D3D11:
+ case QPlatformBackingStoreRhiConfig::D3D12:
+ type = QSurface::Direct3DSurface;
+ break;
+ case QPlatformBackingStoreRhiConfig::Vulkan:
+ type = QSurface::VulkanSurface;
+ break;
+ case QPlatformBackingStoreRhiConfig::Metal:
+ type = QSurface::MetalSurface;
+ break;
+ case QPlatformBackingStoreRhiConfig::OpenGL:
+ type = QSurface::OpenGLSurface;
+ break;
+ default:
+ break;
+ }
+ return type;
+}
+
+QRhi::Implementation QBackingStoreRhiSupport::apiToRhiBackend(QPlatformBackingStoreRhiConfig::Api api)
+{
+ switch (api) {
+ case QPlatformBackingStoreRhiConfig::OpenGL:
+ return QRhi::OpenGLES2;
+ case QPlatformBackingStoreRhiConfig::Metal:
+ return QRhi::Metal;
+ case QPlatformBackingStoreRhiConfig::Vulkan:
+ return QRhi::Vulkan;
+ case QPlatformBackingStoreRhiConfig::D3D11:
+ return QRhi::D3D11;
+ case QPlatformBackingStoreRhiConfig::D3D12:
+ return QRhi::D3D12;
+ case QPlatformBackingStoreRhiConfig::Null:
+ return QRhi::Null;
+ default:
+ break;
+ }
+ return QRhi::Null;
+}
+
+bool QBackingStoreRhiSupport::checkForceRhi(QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType)
+{
+ static QPlatformBackingStoreRhiConfig config;
+ static bool checked = false;
+
+ if (!checked) {
+ checked = true;
+
+ const bool alwaysRhi = qEnvironmentVariableIntValue("QT_WIDGETS_RHI");
+ if (alwaysRhi)
+ config.setEnabled(true);
+
+ // if enabled, choose an api
+ if (config.isEnabled()) {
+#if defined(Q_OS_WIN)
+ config.setApi(QPlatformBackingStoreRhiConfig::D3D11);
+#elif QT_CONFIG(metal)
+ config.setApi(QPlatformBackingStoreRhiConfig::Metal);
+#elif QT_CONFIG(opengl)
+ config.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
+#elif QT_CONFIG(vulkan)
+ config.setApi(QPlatformBackingStoreRhiConfig::Vulkan);
+#else
+ qWarning("QT_WIDGETS_RHI is set but no backend is available; ignoring");
+ return false;
+#endif
+
+ // the env.var. will always override
+ if (qEnvironmentVariableIsSet("QT_WIDGETS_RHI_BACKEND")) {
+ const QString backend = qEnvironmentVariable("QT_WIDGETS_RHI_BACKEND");
+#ifdef Q_OS_WIN
+ if (backend == QStringLiteral("d3d11") || backend == QStringLiteral("d3d"))
+ config.setApi(QPlatformBackingStoreRhiConfig::D3D11);
+ if (backend == QStringLiteral("d3d12"))
+ config.setApi(QPlatformBackingStoreRhiConfig::D3D12);
+#endif
+#if QT_CONFIG(metal)
+ if (backend == QStringLiteral("metal"))
+ config.setApi(QPlatformBackingStoreRhiConfig::Metal);
+#endif
+#if QT_CONFIG(opengl)
+ if (backend == QStringLiteral("opengl") || backend == QStringLiteral("gl"))
+ config.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
+#endif
+#if QT_CONFIG(vulkan)
+ if (backend == QStringLiteral("vulkan"))
+ config.setApi(QPlatformBackingStoreRhiConfig::Vulkan);
+#endif
+ }
+
+ if (qEnvironmentVariableIntValue("QT_WIDGETS_RHI_DEBUG_LAYER"))
+ config.setDebugLayer(true);
+ }
+
+ qCDebug(lcQpaBackingStore) << "Check for forced use of QRhi resulted in enable"
+ << config.isEnabled() << "with api" << QRhi::backendName(apiToRhiBackend(config.api()));
+ }
+
+ if (config.isEnabled()) {
+ if (outConfig)
+ *outConfig = config;
+ if (outType)
+ *outType = surfaceTypeForConfig(config);
+ return true;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qbackingstorerhisupport_p.h b/src/gui/painting/qbackingstorerhisupport_p.h
new file mode 100644
index 0000000000..39ce36c680
--- /dev/null
+++ b/src/gui/painting/qbackingstorerhisupport_p.h
@@ -0,0 +1,77 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QBACKINGSTORERHISUPPORT_P_H
+#define QBACKINGSTORERHISUPPORT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qsurfaceformat.h>
+#include <QtGui/qoffscreensurface.h>
+#include <rhi/qrhi.h>
+#include <qpa/qplatformbackingstore.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QBackingStoreRhiSupport
+{
+public:
+ ~QBackingStoreRhiSupport();
+
+ void reset();
+
+ void setFormat(const QSurfaceFormat &format) { m_format = format; }
+ void setWindow(QWindow *window) { m_window = window; }
+ void setConfig(const QPlatformBackingStoreRhiConfig &config) { m_config = config; }
+
+ bool create();
+
+ QRhiSwapChain *swapChainForWindow(QWindow *window);
+
+ static QSurface::SurfaceType surfaceTypeForConfig(const QPlatformBackingStoreRhiConfig &config);
+
+ static bool checkForceRhi(QPlatformBackingStoreRhiConfig *outConfig, QSurface::SurfaceType *outType);
+
+ static QRhi::Implementation apiToRhiBackend(QPlatformBackingStoreRhiConfig::Api api);
+
+ QRhi *rhi() const { return m_rhi; }
+
+private:
+ QSurfaceFormat m_format;
+ QWindow *m_window = nullptr;
+ QPlatformBackingStoreRhiConfig m_config;
+ QRhi *m_rhi = nullptr;
+ QOffscreenSurface *m_openGLFallbackSurface = nullptr;
+ struct SwapchainData {
+ QRhiSwapChain *swapchain = nullptr;
+ QRhiRenderPassDescriptor *renderPassDescriptor = nullptr;
+ QObject *windowWatcher = nullptr;
+ void reset();
+ };
+ QHash<QWindow *, SwapchainData> m_swapchains;
+ friend class QBackingStoreRhiSupportWindowWatcher;
+};
+
+class QBackingStoreRhiSupportWindowWatcher : public QObject
+{
+public:
+ QBackingStoreRhiSupportWindowWatcher(QBackingStoreRhiSupport *rhiSupport) : m_rhiSupport(rhiSupport) { }
+ bool eventFilter(QObject *obj, QEvent *ev) override;
+private:
+ QBackingStoreRhiSupport *m_rhiSupport;
+};
+
+QT_END_NAMESPACE
+
+#endif // QBACKINGSTORERHISUPPORT_P_H
diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp
index b14843a703..5b2a962661 100644
--- a/src/gui/painting/qbezier.cpp
+++ b/src/gui/painting/qbezier.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbezier_p.h"
#include <qdebug.h>
diff --git a/src/gui/painting/qbezier_p.h b/src/gui/painting/qbezier_p.h
index bf712822a2..6c39dd55f9 100644
--- a/src/gui/painting/qbezier_p.h
+++ b/src/gui/painting/qbezier_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBEZIER_P_H
#define QBEZIER_P_H
@@ -54,7 +18,6 @@
#include <QtGui/private/qtguiglobal_p.h>
#include "QtCore/qline.h"
#include "QtCore/qlist.h"
-#include "QtCore/qpair.h"
#include "QtCore/qpoint.h"
#include "QtCore/qrect.h"
#include "QtGui/qtransform.h"
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index 519601a11d..fa9f89262c 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qmath.h>
#include "qblendfunctions_p.h"
@@ -188,7 +152,7 @@ void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl,
if (const_alpha == 256) {
int length = w << 1;
- while (h--) {
+ while (--h >= 0) {
memcpy(dst, src, length);
dst += dbpl;
src += sbpl;
@@ -198,7 +162,7 @@ void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl,
const quint16 *s = (const quint16 *) src;
quint8 a = (255 * const_alpha) >> 8;
quint8 ia = 255 - a;
- while (h--) {
+ while (--h >= 0) {
for (int x=0; x<w; ++x) {
d[x] = BYTE_MUL_RGB16(s[x], a) + BYTE_MUL_RGB16(d[x], ia);
}
diff --git a/src/gui/painting/qblendfunctions_p.h b/src/gui/painting/qblendfunctions_p.h
index 080da98ec4..2f5ed36c73 100644
--- a/src/gui/painting/qblendfunctions_p.h
+++ b/src/gui/painting/qblendfunctions_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBLENDFUNCTIONS_P_H
#define QBLENDFUNCTIONS_P_H
@@ -125,7 +89,7 @@ void qt_scale_image_16bit(uchar *destPixels, int dbpl,
if (xend < 0 || xend >= (int)(sbpl/sizeof(SRC)))
--w;
- while (h--) {
+ while (--h >= 0) {
const SRC *src = (const SRC *) (srcPixels + (srcy >> 16) * sbpl);
quint32 srcx = basex;
int x = 0;
@@ -216,7 +180,7 @@ template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl,
if (xend < 0 || xend >= (int)(sbpl/sizeof(quint32)))
--w;
- while (h--) {
+ while (--h >= 0) {
const uint *src = (const quint32 *) (srcPixels + (srcy >> 16) * sbpl);
quint32 srcx = basex;
int x = 0;
@@ -246,25 +210,32 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
int dudx, int dvdx, int dudy, int dvdy, int u0, int v0,
Blender blender)
{
- int fromY = qMax(qRound(topY), clip.top());
- int toY = qMin(qRound(bottomY), clip.top() + clip.height());
+ qint64 fromY = qMax(qRound(topY), clip.top());
+ qint64 toY = qMin(qRound(bottomY), clip.top() + clip.height());
if (fromY >= toY)
return;
qreal leftSlope = (bottomLeft.x - topLeft.x) / (bottomLeft.y - topLeft.y);
qreal rightSlope = (bottomRight.x - topRight.x) / (bottomRight.y - topRight.y);
- int dx_l = int(leftSlope * 0x10000);
- int dx_r = int(rightSlope * 0x10000);
- int x_l = int((topLeft.x + (qreal(0.5) + fromY - topLeft.y) * leftSlope + qreal(0.5)) * 0x10000);
- int x_r = int((topRight.x + (qreal(0.5) + fromY - topRight.y) * rightSlope + qreal(0.5)) * 0x10000);
-
- int fromX, toX, x1, x2, u, v, i, ii;
+ qint64 dx_l = qint64(leftSlope * 0x10000);
+ qint64 dx_r = qint64(rightSlope * 0x10000);
+ qint64 x_l = qint64((topLeft.x + (qreal(0.5) + fromY - topLeft.y) * leftSlope + qreal(0.5)) * 0x10000);
+ qint64 x_r = qint64((topRight.x + (qreal(0.5) + fromY - topRight.y) * rightSlope + qreal(0.5)) * 0x10000);
+
+ qint64 sourceRectTop = qint64(sourceRect.top());
+ qint64 sourceRectLeft = qint64(sourceRect.left());
+ qint64 sourceRectWidth = qint64(sourceRect.width());
+ qint64 sourceRectHeight = qint64(sourceRect.height());
+ qint64 clipLeft = qint64(clip.left());
+ qint64 clipWidth = qint64(clip.width());
+
+ qint64 fromX, toX, x1, x2, u, v, i, ii;
DestT *line;
- for (int y = fromY; y < toY; ++y) {
+ for (qint64 y = fromY; y < toY; ++y) {
line = reinterpret_cast<DestT *>(reinterpret_cast<uchar *>(destPixels) + y * dbpl);
- fromX = qMax(x_l >> 16, clip.left());
- toX = qMin(x_r >> 16, clip.left() + clip.width());
+ fromX = qMax(x_l >> 16, clipLeft);
+ toX = qMin(x_r >> 16, clipLeft + clipWidth);
if (fromX < toX) {
// Because of rounding, we can get source coordinates outside the source image.
// Clamp these coordinates to the source rect to avoid segmentation fault and
@@ -275,10 +246,10 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
u = x1 * dudx + y * dudy + u0;
v = x1 * dvdx + y * dvdy + v0;
for (; x1 < toX; ++x1) {
- int uu = u >> 16;
- int vv = v >> 16;
- if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
- && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
+ qint64 uu = u >> 16;
+ qint64 vv = v >> 16;
+ if (uu >= sourceRectLeft && uu < sourceRectLeft + sourceRectWidth
+ && vv >= sourceRectTop && vv < sourceRectTop + sourceRectHeight) {
break;
}
u += dudx;
@@ -290,10 +261,10 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
u = (x2 - 1) * dudx + y * dudy + u0;
v = (x2 - 1) * dvdx + y * dvdy + v0;
for (; x2 > x1; --x2) {
- int uu = u >> 16;
- int vv = v >> 16;
- if (uu >= sourceRect.left() && uu < sourceRect.left() + sourceRect.width()
- && vv >= sourceRect.top() && vv < sourceRect.top() + sourceRect.height()) {
+ qint64 uu = u >> 16;
+ qint64 vv = v >> 16;
+ if (uu >= sourceRectLeft && uu < sourceRectLeft + sourceRectWidth
+ && vv >= sourceRectTop && vv < sourceRectTop + sourceRectHeight) {
break;
}
u -= dudx;
@@ -308,8 +279,8 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
// Beginning of the scan line, with per-pixel checks.
i = x1 - fromX;
while (i) {
- int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
- int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
+ qint64 uu = qBound(sourceRectLeft, u >> 16, sourceRectLeft + sourceRectWidth - 1);
+ qint64 vv = qBound(sourceRectTop, v >> 16, sourceRectTop + sourceRectHeight - 1);
blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
u += dudx;
v += dvdx;
@@ -348,8 +319,8 @@ void qt_transform_image_rasterize(DestT *destPixels, int dbpl,
// End of the scan line, with per-pixel checks.
i = toX - x2;
while (i) {
- int uu = qBound(sourceRect.left(), u >> 16, sourceRect.left() + sourceRect.width() - 1);
- int vv = qBound(sourceRect.top(), v >> 16, sourceRect.top() + sourceRect.height() - 1);
+ qint64 uu = qBound(sourceRectLeft, u >> 16, sourceRectLeft + sourceRectWidth - 1);
+ qint64 vv = qBound(sourceRectTop, v >> 16, sourceRectTop + sourceRectHeight - 1);
blender.write(line, reinterpret_cast<const SrcT *>(reinterpret_cast<const uchar *>(srcPixels) + vv * sbpl)[uu]);
u += dudx;
v += dvdx;
diff --git a/src/gui/painting/qblittable.cpp b/src/gui/painting/qblittable.cpp
index 494104251f..75141537a9 100644
--- a/src/gui/painting/qblittable.cpp
+++ b/src/gui/painting/qblittable.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qblittable_p.h"
diff --git a/src/gui/painting/qblittable_p.h b/src/gui/painting/qblittable_p.h
index 24440c3c61..55c66e1535 100644
--- a/src/gui/painting/qblittable_p.h
+++ b/src/gui/painting/qblittable_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBLITTABLE_P_H
#define QBLITTABLE_P_H
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index 432d53a69b..b053896233 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbrush.h"
#include "qpixmap.h"
@@ -54,9 +18,12 @@
#include <QtCore/qnumeric.h>
#include <QtCore/qfile.h>
#include <QtCore/qmutex.h>
+#include <QtCore/private/qoffsetstringarray_p.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
// Avoid an ABI break due to the QScopedPointer->std::unique_ptr change
static_assert(sizeof(QBrush::DataPtr) == sizeof(QScopedPointer<QBrushData, QBrushDataPointerDeleter>));
@@ -114,7 +81,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapForBrush(int brushStyle, bool invert)
{
QPixmap pm;
- QString key = QLatin1String("$qt-brush$")
+ QString key = "$qt-brush$"_L1
% HexString<uint>(brushStyle)
% QLatin1Char(invert ? '1' : '0');
if (!QPixmapCache::find(key, &pm)) {
@@ -862,7 +829,7 @@ Q_GUI_EXPORT bool qt_isExtendedRadialGradient(const QBrush &brush)
bool QBrush::isOpaque() const
{
- bool opaqueColor = d->color.alpha() == 255;
+ bool opaqueColor = d->color.alphaF() >= 1.0f;
// Test awfully simple case first
if (d->style == Qt::SolidPattern)
@@ -876,7 +843,7 @@ bool QBrush::isOpaque() const
|| d->style == Qt::ConicalGradientPattern) {
QGradientStops stops = gradient()->stops();
for (int i=0; i<stops.size(); ++i)
- if (stops.at(i).second.alpha() != 255)
+ if (stops.at(i).second.alphaF() < 1.0f)
return false;
return true;
} else if (d->style == Qt::TexturePattern) {
@@ -985,7 +952,7 @@ bool QBrush::operator==(const QBrush &b) const
*/
QDebug operator<<(QDebug dbg, const QBrush &b)
{
- static const char BRUSH_STYLES[][24] = {
+ static constexpr auto BRUSH_STYLES = qOffsetStringArray(
"NoBrush",
"SolidPattern",
"Dense1Pattern",
@@ -1006,7 +973,7 @@ QDebug operator<<(QDebug dbg, const QBrush &b)
"ConicalGradientPattern",
"", "", "", "", "", "",
"TexturePattern" // 24
- };
+ );
QDebugStateSaver saver(dbg);
dbg.nospace() << "QBrush(" << b.color() << ',' << BRUSH_STYLES[b.style()] << ')';
@@ -1273,7 +1240,7 @@ QDataStream &operator>>(QDataStream &s, QBrush &b)
\snippet brush/brush.cpp 1
It is possible to repeat or reflect the gradient outside its area
- by specifiying the \l {QGradient::Spread}{spread method} using the
+ by specifying the \l {QGradient::Spread}{spread method} using the
setSpread() function. The default is to pad the outside area with
the color at the closest stop point. The currently set \l
{QGradient::Spread}{spread method} can be retrieved using the
@@ -2545,3 +2512,5 @@ void QConicalGradient::setAngle(qreal angle)
*/
QT_END_NAMESPACE
+
+#include "moc_qbrush.cpp"
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index b5bdd9fb24..ca8112ff31 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBRUSH_H
#define QBRUSH_H
@@ -83,7 +47,7 @@ public:
QBrush &operator=(const QBrush &brush);
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QBrush)
inline void swap(QBrush &other) noexcept
- { qSwap(d, other.d); }
+ { d.swap(other.d); }
operator QVariant() const;
diff --git a/src/gui/painting/qcmyk_p.h b/src/gui/painting/qcmyk_p.h
new file mode 100644
index 0000000000..d00a4b5a6e
--- /dev/null
+++ b/src/gui/painting/qcmyk_p.h
@@ -0,0 +1,88 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCMYK_P_H
+#define QCMYK_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCmyk32
+{
+private:
+ uint m_cmyk = 0;
+
+public:
+ QCmyk32() = default;
+
+ constexpr QCmyk32(int cyan, int magenta, int yellow, int black) :
+#if QT_BYTE_ORDER == Q_BIG_ENDIAN
+ m_cmyk(cyan << 24 | magenta << 16 | yellow << 8 | black)
+#else
+ m_cmyk(cyan | magenta << 8 | yellow << 16 | black << 24)
+#endif
+ {
+ }
+
+#if QT_BYTE_ORDER == Q_BIG_ENDIAN
+ constexpr int cyan() const noexcept { return (m_cmyk >> 24) & 0xff; }
+ constexpr int magenta() const noexcept { return (m_cmyk >> 16) & 0xff; }
+ constexpr int yellow() const noexcept { return (m_cmyk >> 8) & 0xff; }
+ constexpr int black() const noexcept { return (m_cmyk ) & 0xff; }
+#else
+ constexpr int cyan() const noexcept { return (m_cmyk ) & 0xff; }
+ constexpr int magenta() const noexcept { return (m_cmyk >> 8) & 0xff; }
+ constexpr int yellow() const noexcept { return (m_cmyk >> 16) & 0xff; }
+ constexpr int black() const noexcept { return (m_cmyk >> 24) & 0xff; }
+#endif
+
+ QColor toColor() const noexcept
+ {
+ return QColor::fromCmyk(cyan(), magenta(), yellow(), black());
+ }
+
+ constexpr uint toUint() const noexcept
+ {
+ return m_cmyk;
+ }
+
+ constexpr static QCmyk32 fromCmyk32(uint cmyk) noexcept
+ {
+ QCmyk32 result;
+ result.m_cmyk = cmyk;
+ return result;
+ }
+
+ static QCmyk32 fromRgba(QRgb rgba) noexcept
+ {
+ const QColor c = QColor(rgba).toCmyk();
+ return QCmyk32(c.cyan(), c.magenta(), c.yellow(), c.black());
+ }
+
+ static QCmyk32 fromColor(const QColor &color) noexcept
+ {
+ QColor c = color.toCmyk();
+ return QCmyk32(c.cyan(), c.magenta(), c.yellow(), c.black());
+ }
+};
+
+static_assert(sizeof(QCmyk32) == sizeof(int));
+static_assert(alignof(QCmyk32) == alignof(int));
+static_assert(std::is_standard_layout_v<QCmyk32>);
+
+QT_END_NAMESPACE
+
+#endif // QCMYK_P_H
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index bd7d9d4e4f..2af2e8cb6b 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcolor.h"
#include "qcolor_p.h"
@@ -48,6 +12,7 @@
#include "private/qtools_p.h"
#include <algorithm>
+#include <optional>
#include <stdio.h>
#include <limits.h>
@@ -80,10 +45,10 @@ static inline int hex2int(const char *s, int n)
return result;
}
-static bool get_hex_rgb(const char *name, size_t len, QRgba64 *rgb)
+static std::optional<QRgba64> get_hex_rgb(const char *name, size_t len)
{
if (name[0] != '#')
- return false;
+ return std::nullopt;
name++;
--len;
int a, r, g, b;
@@ -97,7 +62,7 @@ static bool get_hex_rgb(const char *name, size_t len, QRgba64 *rgb)
g = hex2int(name + 3, 3);
b = hex2int(name + 6, 3);
if (r == -1 || g == -1 || b == -1)
- return false;
+ return std::nullopt;
r = (r << 4) | (r >> 8);
g = (g << 4) | (g >> 8);
b = (b << 4) | (b >> 8);
@@ -117,32 +82,34 @@ static bool get_hex_rgb(const char *name, size_t len, QRgba64 *rgb)
} else {
r = g = b = -1;
}
- if ((uint)r > 65535 || (uint)g > 65535 || (uint)b > 65535 || (uint)a > 65535) {
- *rgb = 0;
- return false;
- }
- *rgb = qRgba64(r, g ,b, a);
- return true;
+ if (uint(r) > 65535 || uint(g) > 65535 || uint(b) > 65535 || uint(a) > 65535)
+ return std::nullopt;
+ return qRgba64(r, g ,b, a);
}
-bool qt_get_hex_rgb(const char *name, QRgb *rgb)
+std::optional<QRgb> qt_get_hex_rgb(const char *name)
{
- QRgba64 rgba64;
- if (!get_hex_rgb(name, qstrlen(name), &rgba64))
- return false;
- *rgb = rgba64.toArgb32();
- return true;
+ if (std::optional<QRgba64> rgba64 = get_hex_rgb(name, qstrlen(name)))
+ return rgba64->toArgb32();
+ return std::nullopt;
}
-static bool get_hex_rgb(const QChar *str, size_t len, QRgba64 *rgb)
+static std::optional<QRgba64> get_hex_rgb(const QChar *str, size_t len)
{
if (len > 13)
- return false;
+ return std::nullopt;
char tmp[16];
for (size_t i = 0; i < len; ++i)
tmp[i] = str[i].toLatin1();
tmp[len] = 0;
- return get_hex_rgb(tmp, len, rgb);
+ return get_hex_rgb(tmp, len);
+}
+
+static std::optional<QRgba64> get_hex_rgb(QAnyStringView name)
+{
+ return name.visit([] (auto name) {
+ return get_hex_rgb(name.data(), name.size());
+ });
}
#ifndef QT_NO_COLORNAMES
@@ -157,7 +124,7 @@ static bool get_hex_rgb(const QChar *str, size_t len, QRgba64 *rgb)
#define rgb(r,g,b) (0xff000000 | (r << 16) | (g << 8) | b)
// keep this is in sync with QColorConstants
-static const struct RGBData {
+static constexpr struct RGBData {
const char name[21];
uint value;
} rgbTbl[] = {
@@ -313,6 +280,16 @@ static const struct RGBData {
static const int rgbTblSize = sizeof(rgbTbl) / sizeof(RGBData);
+static_assert([] {
+ for (auto e : rgbTbl) {
+ for (auto it = e.name; *it ; ++it) {
+ if (uchar(*it) > 127)
+ return false;
+ }
+ }
+ return true;
+ }(), "the lookup code expects color names to be US-ASCII-only");
+
#undef rgb
inline bool operator<(const char *name, const RGBData &data)
@@ -320,43 +297,35 @@ inline bool operator<(const char *name, const RGBData &data)
inline bool operator<(const RGBData &data, const char *name)
{ return qstrcmp(data.name, name) < 0; }
-static bool get_named_rgb_no_space(const char *name_no_space, QRgb *rgb)
+static std::optional<QRgb> get_named_rgb_no_space(const char *name_no_space)
{
const RGBData *r = std::lower_bound(rgbTbl, rgbTbl + rgbTblSize, name_no_space);
- if ((r != rgbTbl + rgbTblSize) && !(name_no_space < *r)) {
- *rgb = r->value;
- return true;
- }
- return false;
+ if ((r != rgbTbl + rgbTblSize) && !(name_no_space < *r))
+ return r->value;
+ return std::nullopt;
}
-static bool get_named_rgb(const char *name, int len, QRgb* rgb)
-{
- if (len > 255)
- return false;
- char name_no_space[256];
- int pos = 0;
- for (int i = 0; i < len; i++) {
- if (name[i] != '\t' && name[i] != ' ')
- name_no_space[pos++] = QChar::toLower(name[i]);
- }
- name_no_space[pos] = 0;
-
- return get_named_rgb_no_space(name_no_space, rgb);
+namespace {
+// named colors are US-ASCII (enforced by static_assert above):
+static char to_char(char ch) noexcept { return ch; }
+static char to_char(QChar ch) noexcept { return ch.toLatin1(); }
}
-static bool get_named_rgb(const QChar *name, int len, QRgb *rgb)
+static std::optional<QRgb> get_named_rgb(QAnyStringView name)
{
- if (len > 255)
- return false;
+ if (name.size() > 255)
+ return std::nullopt;
char name_no_space[256];
int pos = 0;
- for (int i = 0; i < len; i++) {
- if (name[i] != QLatin1Char('\t') && name[i] != QLatin1Char(' '))
- name_no_space[pos++] = name[i].toLower().toLatin1();
- }
+ name.visit([&pos, &name_no_space] (auto name) {
+ for (auto c : name) {
+ if (c != u'\t' && c != u' ')
+ name_no_space[pos++] = QtMiscUtils::toAsciiLower(to_char(c));
+ }
+ });
name_no_space[pos] = 0;
- return get_named_rgb_no_space(name_no_space, rgb);
+
+ return get_named_rgb_no_space(name_no_space);
}
#endif // QT_NO_COLORNAMES
@@ -367,7 +336,7 @@ static QStringList get_colornames()
#ifndef QT_NO_COLORNAMES
lst.reserve(rgbTblSize);
for (int i = 0; i < rgbTblSize; i++)
- lst << QLatin1String(rgbTbl[i].name);
+ lst << QLatin1StringView(rgbTbl[i].name);
#endif
return lst;
}
@@ -411,7 +380,7 @@ static QStringList get_colornames()
A color can be set by passing an RGB string (such as "#112233"),
or an ARGB string (such as "#ff112233") or a color name (such as "blue"),
- to the setNamedColor() function.
+ to the fromString() function.
The color names are taken from the SVG 1.0 color names. The name()
function returns the name of the color in the format
"#RRGGBB". Colors can also be set using setRgb(), setHsv() and
@@ -786,7 +755,7 @@ QColor::QColor(QRgba64 rgba64) noexcept
Constructs a color with the given \a spec.
- This function is primarly present to avoid that QColor::Invalid
+ This function is primarily present to avoid that QColor::Invalid
becomes a valid color by accident.
*/
@@ -815,6 +784,7 @@ QColor::QColor(Spec spec) noexcept
}
}
+// ### Qt 7: remove those after deprecating them for the last Qt 6 LTS release
/*!
\fn QColor::QColor(const QString &name)
@@ -837,7 +807,7 @@ QColor::QColor(Spec spec) noexcept
*/
/*!
- \fn QColor::QColor(QLatin1String name)
+ \fn QColor::QColor(QLatin1StringView name)
Constructs a named color in the same way as setNamedColor() using
the given \a name.
@@ -858,23 +828,25 @@ QColor::QColor(Spec spec) noexcept
Returns the name of the color in the specified \a format.
- \sa setNamedColor(), NameFormat
+ \sa fromString(), NameFormat
*/
QString QColor::name(NameFormat format) const
{
switch (format) {
case HexRgb:
- return QLatin1Char('#') + QStringView{QString::number(rgba() | 0x1000000, 16)}.right(6);
+ return u'#' + QStringView{QString::number(rgba() | 0x1000000, 16)}.right(6);
case HexArgb:
// it's called rgba() but it does return AARRGGBB
- return QLatin1Char('#') + QStringView{QString::number(rgba() | Q_INT64_C(0x100000000), 16)}.right(8);
+ return u'#' + QStringView{QString::number(rgba() | Q_INT64_C(0x100000000), 16)}.right(8);
}
return QString();
}
-#if QT_STRINGVIEW_LEVEL < 2
+#if QT_DEPRECATED_SINCE(6, 6)
/*!
+ \deprecated [6.6] Use fromString() instead.
+
Sets the RGB value of this QColor to \a name, which may be in one
of these formats:
@@ -900,34 +872,36 @@ QString QColor::name(NameFormat format) const
void QColor::setNamedColor(const QString &name)
{
- setColorFromString(qToStringViewIgnoringNull(name));
+ *this = fromString(qToAnyStringViewIgnoringNull(name));
}
-#endif
/*!
\overload
\since 5.10
+ \deprecated [6.6] Use fromString() instead.
*/
void QColor::setNamedColor(QStringView name)
{
- setColorFromString(name);
+ *this = fromString(name);
}
/*!
\overload
\since 5.8
+ \deprecated [6.6] Use fromString() instead.
*/
-void QColor::setNamedColor(QLatin1String name)
+void QColor::setNamedColor(QLatin1StringView name)
{
- setColorFromString(name);
+ *this = fromString(name);
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
\since 4.7
+ \deprecated [6.6] Use isValidColorName() instead.
+
Returns \c true if the \a name is a valid color name and can
be used to construct a valid QColor object, otherwise returns
false.
@@ -938,58 +912,86 @@ void QColor::setNamedColor(QLatin1String name)
*/
bool QColor::isValidColor(const QString &name)
{
- return isValidColor(qToStringViewIgnoringNull(name));
+ return isValidColorName(qToAnyStringViewIgnoringNull(name));
}
-#endif
/*!
\overload
\since 5.10
+ \deprecated [6.6] Use isValidColorName() instead.
*/
bool QColor::isValidColor(QStringView name) noexcept
{
- return name.size() && QColor().setColorFromString(name);
+ return isValidColorName(name);
}
/*!
\overload
\since 5.8
+ \deprecated [6.6] Use isValidColorName() instead.
*/
-bool QColor::isValidColor(QLatin1String name) noexcept
+bool QColor::isValidColor(QLatin1StringView name) noexcept
{
- return name.size() && QColor().setColorFromString(name);
+ return isValidColorName(name);
}
+#endif // QT_DEPRECATED_SINCE(6, 6)
-template <typename String>
-bool QColor::setColorFromString(String name)
+/*!
+ \since 6.4
+
+ Returns \c true if the \a name is a valid color name and can
+ be used to construct a valid QColor object, otherwise returns
+ false.
+
+ It uses the same algorithm used in fromString().
+
+ \sa fromString()
+*/
+bool QColor::isValidColorName(QAnyStringView name) noexcept
{
- if (!name.size()) {
- invalidate();
- return true;
- }
+ return fromString(name).isValid();
+}
- if (name[0] == QLatin1Char('#')) {
- QRgba64 rgba;
- if (get_hex_rgb(name.data(), name.size(), &rgba)) {
- setRgba64(rgba);
- return true;
- } else {
- invalidate();
- return false;
- }
- }
+/*!
+ \since 6.4
+
+ Returns an RGB QColor parsed from \a name, which may be in one
+ of these formats:
+
+ \list
+ \li #RGB (each of R, G, and B is a single hex digit)
+ \li #RRGGBB
+ \li #AARRGGBB (Since 5.2)
+ \li #RRRGGGBBB
+ \li #RRRRGGGGBBBB
+ \li A name from the list of colors defined in the list of
+ \l{https://www.w3.org/TR/SVG11/types.html#ColorKeywords}{SVG color keyword names}
+ provided by the World Wide Web Consortium; for example, "steelblue" or "gainsboro".
+ These color names work on all platforms. Note that these color names are \e not the
+ same as defined by the Qt::GlobalColor enums, e.g. "green" and Qt::green does not
+ refer to the same color.
+ \li \c transparent - representing the absence of a color.
+ \endlist
+ Returns an invalid color if \a name cannot be parsed.
+
+ \sa isValidColorName()
+*/
+QColor QColor::fromString(QAnyStringView name) noexcept
+{
+ if (!name.size())
+ return {};
+
+ if (name.front() == u'#') {
+ if (std::optional<QRgba64> r = get_hex_rgb(name))
+ return QColor::fromRgba64(*r);
#ifndef QT_NO_COLORNAMES
- QRgb rgb;
- if (get_named_rgb(name.data(), name.size(), &rgb)) {
- setRgba(rgb);
- return true;
- } else
+ } else if (std::optional<QRgb> r = get_named_rgb(name)) {
+ return QColor::fromRgba(*r);
#endif
- {
- invalidate();
- return false;
}
+
+ return {};
}
/*!
@@ -1252,15 +1254,12 @@ void QColor::getRgbF(float *r, float *g, float *b, float *a) const
if (!r || !g || !b)
return;
- if (cspec == Invalid)
- return;
-
- if (cspec != Rgb && cspec != ExtendedRgb) {
+ if (cspec != Invalid && cspec != Rgb && cspec != ExtendedRgb) {
toRgb().getRgbF(r, g, b, a);
return;
}
- if (cspec == Rgb) {
+ if (cspec == Rgb || cspec == Invalid) {
*r = ct.argb.red / float(USHRT_MAX);
*g = ct.argb.green / float(USHRT_MAX);
*b = ct.argb.blue / float(USHRT_MAX);
@@ -1484,7 +1483,7 @@ void QColor::setAlpha(int alpha)
QCOLOR_INT_RANGE_CHECK("QColor::setAlpha", alpha);
if (cspec == ExtendedRgb) {
constexpr float f = 1.0f / 255;
- castF16(ct.argbExtended.alphaF16) = alpha * f;
+ castF16(ct.argbExtended.alphaF16) = qfloat16(alpha * f);
return;
}
ct.argb.alpha = alpha * 0x101;
@@ -1513,7 +1512,7 @@ void QColor::setAlphaF(float alpha)
{
QCOLOR_REAL_RANGE_CHECK("QColor::setAlphaF", alpha);
if (cspec == ExtendedRgb) {
- castF16(ct.argbExtended.alphaF16) = alpha;
+ castF16(ct.argbExtended.alphaF16) = qfloat16(alpha);
return;
}
float tmp = alpha * USHRT_MAX;
@@ -1631,7 +1630,7 @@ void QColor::setRedF(float red)
if (cspec == Rgb && red >= 0.0f && red <= 1.0f)
ct.argb.red = qRound(red * USHRT_MAX);
else if (cspec == ExtendedRgb)
- castF16(ct.argbExtended.redF16) = red;
+ castF16(ct.argbExtended.redF16) = qfloat16(red);
else
setRgbF(red, greenF(), blueF(), alphaF());
}
@@ -1663,7 +1662,7 @@ void QColor::setGreenF(float green)
if (cspec == Rgb && green >= 0.0f && green <= 1.0f)
ct.argb.green = qRound(green * USHRT_MAX);
else if (cspec == ExtendedRgb)
- castF16(ct.argbExtended.greenF16) = green;
+ castF16(ct.argbExtended.greenF16) = qfloat16(green);
else
setRgbF(redF(), green, blueF(), alphaF());
}
@@ -1693,7 +1692,7 @@ void QColor::setBlueF(float blue)
if (cspec == Rgb && blue >= 0.0f && blue <= 1.0f)
ct.argb.blue = qRound(blue * USHRT_MAX);
else if (cspec == ExtendedRgb)
- castF16(ct.argbExtended.blueF16) = blue;
+ castF16(ct.argbExtended.blueF16) = qfloat16(blue);
else
setRgbF(redF(), greenF(), blue, alphaF());
}
diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h
index edeba6fe61..2d6db1a14c 100644
--- a/src/gui/painting/qcolor.h
+++ b/src/gui/painting/qcolor.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLOR_H
#define QCOLOR_H
@@ -83,25 +47,28 @@ public:
0) {}
QColor(QRgb rgb) noexcept;
QColor(QRgba64 rgba64) noexcept;
-#if QT_STRINGVIEW_LEVEL < 2
inline QColor(const QString& name);
-#endif
explicit inline QColor(QStringView name);
- inline QColor(const char *aname) : QColor(QLatin1String(aname)) {}
- inline QColor(QLatin1String name);
+ inline QColor(const char *aname);
+ inline QColor(QLatin1StringView name);
QColor(Spec spec) noexcept;
+ static QColor fromString(QAnyStringView name) noexcept;
+
QColor &operator=(Qt::GlobalColor color) noexcept;
bool isValid() const noexcept;
QString name(NameFormat format = HexRgb) const;
-#if QT_STRINGVIEW_LEVEL < 2
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Use fromString() instead.")
void setNamedColor(const QString& name);
-#endif
+ QT_DEPRECATED_VERSION_X_6_6("Use fromString() instead.")
void setNamedColor(QStringView name);
- void setNamedColor(QLatin1String name);
+ QT_DEPRECATED_VERSION_X_6_6("Use fromString() instead.")
+ void setNamedColor(QLatin1StringView name);
+#endif
static QStringList colorNames();
@@ -225,17 +192,19 @@ public:
operator QVariant() const;
-#if QT_STRINGVIEW_LEVEL < 2
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Use isValidColorName() instead.")
static bool isValidColor(const QString &name);
-#endif
+ QT_DEPRECATED_VERSION_X_6_6("Use isValidColorName() instead.")
static bool isValidColor(QStringView) noexcept;
- static bool isValidColor(QLatin1String) noexcept;
+ QT_DEPRECATED_VERSION_X_6_6("Use isValidColorName() instead.")
+ static bool isValidColor(QLatin1StringView) noexcept;
+#endif
+ static bool isValidColorName(QAnyStringView) noexcept;
private:
void invalidate() noexcept;
- template <typename String>
- bool setColorFromString(String name);
static constexpr bool isRgbaValid(int r, int g, int b, int a = 255) noexcept Q_DECL_CONST_FUNCTION
{
@@ -301,16 +270,17 @@ public: // can't give friendship to a namespace, so it needs to be public
};
Q_DECLARE_TYPEINFO(QColor, Q_RELOCATABLE_TYPE);
-inline QColor::QColor(QLatin1String aname)
-{ setNamedColor(aname); }
+inline QColor::QColor(QLatin1StringView aname)
+ : QColor(fromString(aname)) {}
inline QColor::QColor(QStringView aname)
-{ setNamedColor(aname); }
+ : QColor(fromString(aname)) {}
-#if QT_STRINGVIEW_LEVEL < 2
inline QColor::QColor(const QString& aname)
-{ setNamedColor(aname); }
-#endif
+ : QColor(fromString(aname)) {}
+
+inline QColor::QColor(const char *aname)
+ : QColor(fromString(aname)) {}
inline bool QColor::isValid() const noexcept
{ return cspec != Invalid; }
diff --git a/src/gui/painting/qcolor_p.h b/src/gui/painting/qcolor_p.h
index b44f2b163a..89a31f66a4 100644
--- a/src/gui/painting/qcolor_p.h
+++ b/src/gui/painting/qcolor_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLOR_P_H
#define QCOLOR_P_H
@@ -54,9 +18,11 @@
#include <QtGui/private/qtguiglobal_p.h>
#include "QtGui/qrgb.h"
+#include <optional>
+
QT_BEGIN_NAMESPACE
-bool qt_get_hex_rgb(const char *, QRgb *);
+std::optional<QRgb> qt_get_hex_rgb(const char *) Q_DECL_PURE_FUNCTION;
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolorclut_p.h b/src/gui/painting/qcolorclut_p.h
new file mode 100644
index 0000000000..d95e9701b7
--- /dev/null
+++ b/src/gui/painting/qcolorclut_p.h
@@ -0,0 +1,127 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCOLORCLUT_H
+#define QCOLORCLUT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qlist.h>
+#include <QtGui/private/qcolormatrix_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// A 3/4-dimensional lookup table compatible with ICC lut8, lut16, mAB, and mBA formats.
+class QColorCLUT
+{
+ inline static QColorVector interpolate(const QColorVector &a, const QColorVector &b, float t)
+ {
+ return a + (b - a) * t; // faster than std::lerp by assuming no super large or non-number floats
+ }
+ inline static void interpolateIn(QColorVector &a, const QColorVector &b, float t)
+ {
+ a += (b - a) * t;
+ }
+public:
+ uint32_t gridPointsX = 0;
+ uint32_t gridPointsY = 0;
+ uint32_t gridPointsZ = 0;
+ uint32_t gridPointsW = 1;
+ QList<QColorVector> table;
+
+ bool isEmpty() const { return table.isEmpty(); }
+
+ QColorVector apply(const QColorVector &v) const
+ {
+ Q_ASSERT(table.size() == gridPointsX * gridPointsY * gridPointsZ * gridPointsW);
+ QColorVector frac;
+ const float x = std::clamp(v.x, 0.0f, 1.0f) * (gridPointsX - 1);
+ const float y = std::clamp(v.y, 0.0f, 1.0f) * (gridPointsY - 1);
+ const float z = std::clamp(v.z, 0.0f, 1.0f) * (gridPointsZ - 1);
+ const float w = std::clamp(v.w, 0.0f, 1.0f) * (gridPointsW - 1);
+ const uint32_t lox = static_cast<uint32_t>(std::floor(x));
+ const uint32_t hix = std::min(lox + 1, gridPointsX - 1);
+ const uint32_t loy = static_cast<uint32_t>(std::floor(y));
+ const uint32_t hiy = std::min(loy + 1, gridPointsY - 1);
+ const uint32_t loz = static_cast<uint32_t>(std::floor(z));
+ const uint32_t hiz = std::min(loz + 1, gridPointsZ - 1);
+ const uint32_t low = static_cast<uint32_t>(std::floor(w));
+ const uint32_t hiw = std::min(low + 1, gridPointsW - 1);
+ frac.x = x - static_cast<float>(lox);
+ frac.y = y - static_cast<float>(loy);
+ frac.z = z - static_cast<float>(loz);
+ frac.w = w - static_cast<float>(low);
+ if (gridPointsW > 1) {
+ auto index = [&](qsizetype x, qsizetype y, qsizetype z, qsizetype w) -> qsizetype {
+ return x * gridPointsW * gridPointsZ * gridPointsY
+ + y * gridPointsW * gridPointsZ
+ + z * gridPointsW
+ + w;
+ };
+ QColorVector tmp[8];
+ // interpolate over w
+ tmp[0] = interpolate(table[index(lox, loy, loz, low)],
+ table[index(lox, loy, loz, hiw)], frac.w);
+ tmp[1] = interpolate(table[index(lox, loy, hiz, low)],
+ table[index(lox, loy, hiz, hiw)], frac.w);
+ tmp[2] = interpolate(table[index(lox, hiy, loz, low)],
+ table[index(lox, hiy, loz, hiw)], frac.w);
+ tmp[3] = interpolate(table[index(lox, hiy, hiz, low)],
+ table[index(lox, hiy, hiz, hiw)], frac.w);
+ tmp[4] = interpolate(table[index(hix, loy, loz, low)],
+ table[index(hix, loy, loz, hiw)], frac.w);
+ tmp[5] = interpolate(table[index(hix, loy, hiz, low)],
+ table[index(hix, loy, hiz, hiw)], frac.w);
+ tmp[6] = interpolate(table[index(hix, hiy, loz, low)],
+ table[index(hix, hiy, loz, hiw)], frac.w);
+ tmp[7] = interpolate(table[index(hix, hiy, hiz, low)],
+ table[index(hix, hiy, hiz, hiw)], frac.w);
+ // interpolate over z
+ for (int i = 0; i < 4; ++i)
+ interpolateIn(tmp[i * 2], tmp[i * 2 + 1], frac.z);
+ // interpolate over y
+ for (int i = 0; i < 2; ++i)
+ interpolateIn(tmp[i * 4], tmp[i * 4 + 2], frac.y);
+ // interpolate over x
+ interpolateIn(tmp[0], tmp[4], frac.x);
+ return tmp[0];
+ }
+ auto index = [&](qsizetype x, qsizetype y, qsizetype z) -> qsizetype {
+ return x * gridPointsZ * gridPointsY
+ + y * gridPointsZ
+ + z;
+ };
+ QColorVector tmp[8] = {
+ table[index(lox, loy, loz)],
+ table[index(lox, loy, hiz)],
+ table[index(lox, hiy, loz)],
+ table[index(lox, hiy, hiz)],
+ table[index(hix, loy, loz)],
+ table[index(hix, loy, hiz)],
+ table[index(hix, hiy, loz)],
+ table[index(hix, hiy, hiz)]
+ };
+ // interpolate over z
+ for (int i = 0; i < 4; ++i)
+ interpolateIn(tmp[i * 2], tmp[i * 2 + 1], frac.z);
+ // interpolate over y
+ for (int i = 0; i < 2; ++i)
+ interpolateIn(tmp[i * 4], tmp[i * 4 + 2], frac.y);
+ // interpolate over x
+ interpolateIn(tmp[0], tmp[4], frac.x);
+ return tmp[0];
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOLORCLUT_H
diff --git a/src/gui/painting/qcolormatrix_p.h b/src/gui/painting/qcolormatrix_p.h
index 87a61ab219..6a9b9f4f9a 100644
--- a/src/gui/painting/qcolormatrix_p.h
+++ b/src/gui/painting/qcolormatrix_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLORMATRIX_H
#define QCOLORMATRIX_H
@@ -53,6 +17,8 @@
#include <QtGui/qtguiglobal.h>
#include <QtCore/qpoint.h>
+#include <QtCore/private/qglobal_p.h>
+#include <QtCore/private/qsimd_p.h>
#include <cmath>
QT_BEGIN_NAMESPACE
@@ -62,25 +28,24 @@ class QColorVector
{
public:
QColorVector() = default;
- constexpr QColorVector(float x, float y, float z) : x(x), y(y), z(z) { }
- explicit constexpr QColorVector(const QPointF &chr) // from XY chromaticity
- : x(chr.x() / chr.y())
- , y(1.0f)
- , z((1.0 - chr.x() - chr.y()) / chr.y())
- { }
- float x = 0.0f; // X, x or red
- float y = 0.0f; // Y, y or green
- float z = 0.0f; // Z, Y or blue
- float _unused = 0.0f;
+ constexpr QColorVector(float x, float y, float z, float w = 0.0f) noexcept : x(x), y(y), z(z), w(w) { }
+ static constexpr QColorVector fromXYChromaticity(QPointF chr)
+ { return {float(chr.x() / chr.y()), 1.0f, float((1.0f - chr.x() - chr.y()) / chr.y())}; }
+ float x = 0.0f; // X, x, L, or red/cyan
+ float y = 0.0f; // Y, y, a, or green/magenta
+ float z = 0.0f; // Z, Y, b, or blue/yellow
+ float w = 0.0f; // unused, or black
- friend inline bool operator==(const QColorVector &v1, const QColorVector &v2);
- friend inline bool operator!=(const QColorVector &v1, const QColorVector &v2);
- bool isNull() const
+ constexpr bool isNull() const noexcept
{
- return !x && !y && !z;
+ return !x && !y && !z && !w;
+ }
+ bool isValid() const noexcept
+ {
+ return std::isfinite(x) && std::isfinite(y) && std::isfinite(z);
}
- static bool isValidChromaticity(const QPointF &chr)
+ static constexpr bool isValidChromaticity(const QPointF &chr)
{
if (chr.x() < qreal(0.0) || chr.x() > qreal(1.0))
return false;
@@ -91,26 +56,149 @@ public:
return true;
}
+ constexpr QColorVector operator*(float f) const { return QColorVector(x * f, y * f, z * f, w * f); }
+ constexpr QColorVector operator+(const QColorVector &v) const { return QColorVector(x + v.x, y + v.y, z + v.z, w + v.w); }
+ constexpr QColorVector operator-(const QColorVector &v) const { return QColorVector(x - v.x, y - v.y, z - v.z, w - v.w); }
+ void operator+=(const QColorVector &v) { x += v.x; y += v.y; z += v.z; w += v.w; }
+
+ QPointF toChromaticity() const
+ {
+ if (isNull())
+ return QPointF();
+ float mag = 1.0f / (x + y + z);
+ return QPointF(x * mag, y * mag);
+ }
+
// Common whitepoints:
static constexpr QPointF D50Chromaticity() { return QPointF(0.34567, 0.35850); }
static constexpr QPointF D65Chromaticity() { return QPointF(0.31271, 0.32902); }
- static constexpr QColorVector D50() { return QColorVector(D50Chromaticity()); }
- static constexpr QColorVector D65() { return QColorVector(D65Chromaticity()); }
+ static constexpr QColorVector D50() { return fromXYChromaticity(D50Chromaticity()); }
+ static constexpr QColorVector D65() { return fromXYChromaticity(D65Chromaticity()); }
+
+ QColorVector xyzToLab() const
+ {
+ constexpr QColorVector ref = D50();
+ constexpr float eps = 0.008856f;
+ constexpr float kap = 903.3f;
+#if defined(__SSE2__)
+ const __m128 iref = _mm_setr_ps(1.f / ref.x, 1.f / ref.y, 1.f / ref.z, 0.f);
+ __m128 v = _mm_loadu_ps(&x);
+ v = _mm_mul_ps(v, iref);
+
+ const __m128 f3 = _mm_set1_ps(3.f);
+ __m128 est = _mm_add_ps(_mm_set1_ps(0.25f), _mm_mul_ps(v, _mm_set1_ps(0.75f))); // float est = 0.25f + (x * 0.75f);
+ __m128 estsq = _mm_mul_ps(est, est);
+ est = _mm_sub_ps(est, _mm_mul_ps(_mm_sub_ps(_mm_mul_ps(estsq, est), v),
+ _mm_rcp_ps(_mm_mul_ps(estsq, f3)))); // est -= ((est * est * est) - x) / (3.f * (est * est));
+ estsq = _mm_mul_ps(est, est);
+ est = _mm_sub_ps(est, _mm_mul_ps(_mm_sub_ps(_mm_mul_ps(estsq, est), v),
+ _mm_rcp_ps(_mm_mul_ps(estsq, f3)))); // est -= ((est * est * est) - x) / (3.f * (est * est));
+ estsq = _mm_mul_ps(est, est);
+ est = _mm_sub_ps(est, _mm_mul_ps(_mm_sub_ps(_mm_mul_ps(estsq, est), v),
+ _mm_rcp_ps(_mm_mul_ps(estsq, f3)))); // est -= ((est * est * est) - x) / (3.f * (est * est));
+ estsq = _mm_mul_ps(est, est);
+ est = _mm_sub_ps(est, _mm_mul_ps(_mm_sub_ps(_mm_mul_ps(estsq, est), v),
+ _mm_rcp_ps(_mm_mul_ps(estsq, f3)))); // est -= ((est * est * est) - x) / (3.f * (est * est));
+
+ __m128 kapmul = _mm_mul_ps(_mm_add_ps(_mm_mul_ps(v, _mm_set1_ps(kap)), _mm_set1_ps(16.f)),
+ _mm_set1_ps(1.f / 116.f)); // f_ = (kap * f_ + 16.f) * (1.f / 116.f);
+ __m128 cmpgt = _mm_cmpgt_ps(v, _mm_set1_ps(eps)); // if (f_ > eps)
+#if defined(__SSE4_1__)
+ v = _mm_blendv_ps(kapmul, est, cmpgt); // if (..) f_ =.. else f_ =..
+#else
+ v = _mm_or_ps(_mm_and_ps(cmpgt, est), _mm_andnot_ps(cmpgt, kapmul));
+#endif
+ alignas(16) float out[4];
+ _mm_store_ps(out, v);
+ const float L = 116.f * out[1] - 16.f;
+ const float a = 500.f * (out[0] - out[1]);
+ const float b = 200.f * (out[1] - out[2]);
+#else
+ float xr = x * (1.f / ref.x);
+ float yr = y * (1.f / ref.y);
+ float zr = z * (1.f / ref.z);
+
+ float fx, fy, fz;
+ if (xr > eps)
+ fx = fastCbrt(xr);
+ else
+ fx = (kap * xr + 16.f) * (1.f / 116.f);
+ if (yr > eps)
+ fy = fastCbrt(yr);
+ else
+ fy = (kap * yr + 16.f) * (1.f / 116.f);
+ if (zr > eps)
+ fz = fastCbrt(zr);
+ else
+ fz = (kap * zr + 16.f) * (1.f / 116.f);
+
+ const float L = 116.f * fy - 16.f;
+ const float a = 500.f * (fx - fy);
+ const float b = 200.f * (fy - fz);
+#endif
+ // We output Lab values that has been scaled to 0.0->1.0 values, see also labToXyz.
+ return QColorVector(L * (1.f / 100.f), (a + 128.f) * (1.f / 255.f), (b + 128.f) * (1.f / 255.f));
+ }
+
+ QColorVector labToXyz() const
+ {
+ constexpr QColorVector ref = D50();
+ constexpr float eps = 0.008856f;
+ constexpr float kap = 903.3f;
+ // This transform has been guessed from the ICC spec, but it is not stated
+ // anywhere to be the one to use to map to and from 0.0->1.0 values:
+ const float L = x * 100.f;
+ const float a = (y * 255.f) - 128.f;
+ const float b = (z * 255.f) - 128.f;
+ // From here is official Lab->XYZ conversion:
+ float fy = (L + 16.f) * (1.f / 116.f);
+ float fx = fy + (a * (1.f / 500.f));
+ float fz = fy - (b * (1.f / 200.f));
+
+ float xr, yr, zr;
+ if (fx * fx * fx > eps)
+ xr = fx * fx * fx;
+ else
+ xr = (116.f * fx - 16) * (1.f / kap);
+ if (L > (kap * eps))
+ yr = fy * fy * fy;
+ else
+ yr = L * (1.f / kap);
+ if (fz * fz * fz > eps)
+ zr = fz * fz * fz;
+ else
+ zr = (116.f * fz - 16) * (1.f / kap);
+
+ xr = xr * ref.x;
+ yr = yr * ref.y;
+ zr = zr * ref.z;
+ return QColorVector(xr, yr, zr);
+ }
+ friend inline bool comparesEqual(const QColorVector &lhs, const QColorVector &rhs);
+ Q_DECLARE_EQUALITY_COMPARABLE(QColorVector);
+
+private:
+ static float fastCbrt(float x)
+ {
+ // This gives us cube root within the precision we need.
+ float est = 0.25f + (x * 0.75f); // guessing a cube-root of numbers between 0.01 and 1.
+ est -= ((est * est * est) - x) / (3.f * (est * est));
+ est -= ((est * est * est) - x) / (3.f * (est * est));
+ est -= ((est * est * est) - x) / (3.f * (est * est));
+ est -= ((est * est * est) - x) / (3.f * (est * est));
+ // Q_ASSERT(qAbs(est - std::cbrt(x)) < 0.0001f);
+ return est;
+ }
};
-inline bool operator==(const QColorVector &v1, const QColorVector &v2)
+inline bool comparesEqual(const QColorVector &v1, const QColorVector &v2)
{
return (std::abs(v1.x - v2.x) < (1.0f / 2048.0f))
&& (std::abs(v1.y - v2.y) < (1.0f / 2048.0f))
- && (std::abs(v1.z - v2.z) < (1.0f / 2048.0f));
-}
-
-inline bool operator!=(const QColorVector &v1, const QColorVector &v2)
-{
- return !(v1 == v2);
+ && (std::abs(v1.z - v2.z) < (1.0f / 2048.0f))
+ && (std::abs(v1.w - v2.w) < (1.0f / 2048.0f));
}
-
// A matrix mapping 3 value colors.
// Not using QTransform because only floats are needed and performance is critical.
class QColorMatrix
@@ -121,27 +209,29 @@ public:
QColorVector g;
QColorVector b;
- friend inline bool operator==(const QColorMatrix &m1, const QColorMatrix &m2);
- friend inline bool operator!=(const QColorMatrix &m1, const QColorMatrix &m2);
-
- bool isNull() const
+ constexpr bool isNull() const
{
return r.isNull() && g.isNull() && b.isNull();
}
+ constexpr float determinant() const
+ {
+ return r.x * (b.z * g.y - g.z * b.y) -
+ r.y * (b.z * g.x - g.z * b.x) +
+ r.z * (b.y * g.x - g.y * b.x);
+ }
bool isValid() const
{
// A color matrix must be invertible
- float det = r.x * (b.z * g.y - g.z * b.y) -
- r.y * (b.z * g.x - g.z * b.x) +
- r.z * (b.y * g.x - g.y * b.x);
- return !qFuzzyIsNull(det);
+ return std::isnormal(determinant());
+ }
+ bool isIdentity() const noexcept
+ {
+ return *this == identity();
}
QColorMatrix inverted() const
{
- float det = r.x * (b.z * g.y - g.z * b.y) -
- r.y * (b.z * g.x - g.z * b.x) +
- r.z * (b.y * g.x - g.y * b.x);
+ float det = determinant();
det = 1.0f / det;
QColorMatrix inv;
inv.r.x = (g.y * b.z - b.y * g.z) * det;
@@ -155,20 +245,20 @@ public:
inv.b.z = (r.x * g.y - g.x * r.y) * det;
return inv;
}
- QColorMatrix operator*(const QColorMatrix &o) const
+ friend inline constexpr QColorMatrix operator*(const QColorMatrix &a, const QColorMatrix &o)
{
QColorMatrix comb;
- comb.r.x = r.x * o.r.x + g.x * o.r.y + b.x * o.r.z;
- comb.g.x = r.x * o.g.x + g.x * o.g.y + b.x * o.g.z;
- comb.b.x = r.x * o.b.x + g.x * o.b.y + b.x * o.b.z;
+ comb.r.x = a.r.x * o.r.x + a.g.x * o.r.y + a.b.x * o.r.z;
+ comb.g.x = a.r.x * o.g.x + a.g.x * o.g.y + a.b.x * o.g.z;
+ comb.b.x = a.r.x * o.b.x + a.g.x * o.b.y + a.b.x * o.b.z;
- comb.r.y = r.y * o.r.x + g.y * o.r.y + b.y * o.r.z;
- comb.g.y = r.y * o.g.x + g.y * o.g.y + b.y * o.g.z;
- comb.b.y = r.y * o.b.x + g.y * o.b.y + b.y * o.b.z;
+ comb.r.y = a.r.y * o.r.x + a.g.y * o.r.y + a.b.y * o.r.z;
+ comb.g.y = a.r.y * o.g.x + a.g.y * o.g.y + a.b.y * o.g.z;
+ comb.b.y = a.r.y * o.b.x + a.g.y * o.b.y + a.b.y * o.b.z;
- comb.r.z = r.z * o.r.x + g.z * o.r.y + b.z * o.r.z;
- comb.g.z = r.z * o.g.x + g.z * o.g.y + b.z * o.g.z;
- comb.b.z = r.z * o.b.x + g.z * o.b.y + b.z * o.b.z;
+ comb.r.z = a.r.z * o.r.x + a.g.z * o.r.y + a.b.z * o.r.z;
+ comb.g.z = a.r.z * o.g.x + a.g.z * o.g.y + a.b.z * o.g.z;
+ comb.b.z = a.r.z * o.b.x + a.g.z * o.b.y + a.b.z * o.b.z;
return comb;
}
@@ -195,6 +285,32 @@ public:
{ 0.0f, v.y, 0.0f },
{ 0.0f, 0.0f, v.z } };
}
+ static QColorMatrix chromaticAdaptation(const QColorVector &whitePoint)
+ {
+ constexpr QColorVector whitePointD50 = QColorVector::D50();
+ if (whitePoint != whitePointD50) {
+ // A chromatic adaptation to map a white point to XYZ D50.
+
+ // The Bradford method chromatic adaptation matrix:
+ const QColorMatrix abrad = { { 0.8951f, -0.7502f, 0.0389f },
+ { 0.2664f, 1.7135f, -0.0685f },
+ { -0.1614f, 0.0367f, 1.0296f } };
+ const QColorMatrix abradinv = { { 0.9869929f, 0.4323053f, -0.0085287f },
+ { -0.1470543f, 0.5183603f, 0.0400428f },
+ { 0.1599627f, 0.0492912f, 0.9684867f } };
+
+ const QColorVector srcCone = abrad.map(whitePoint);
+ if (srcCone.x && srcCone.y && srcCone.z) {
+ const QColorVector dstCone = abrad.map(whitePointD50);
+ const QColorMatrix wToD50 = { { dstCone.x / srcCone.x, 0, 0 },
+ { 0, dstCone.y / srcCone.y, 0 },
+ { 0, 0, dstCone.z / srcCone.z } };
+ return abradinv * (wToD50 * abrad);
+ }
+ }
+ return QColorMatrix::identity();
+ }
+
// These are used to recognize matrices from ICC profiles:
static QColorMatrix toXyzFromSRgb()
{
@@ -220,18 +336,15 @@ public:
{ 0.1351922452f, 0.7118769884f, 0.0000000000f },
{ 0.0313525312f, 0.0000856627f, 0.8251883388f } };
}
+ friend inline bool comparesEqual(const QColorMatrix &lhs, const QColorMatrix &rhs);
+ Q_DECLARE_EQUALITY_COMPARABLE(QColorMatrix);
};
-inline bool operator==(const QColorMatrix &m1, const QColorMatrix &m2)
+inline bool comparesEqual(const QColorMatrix &m1, const QColorMatrix &m2)
{
return (m1.r == m2.r) && (m1.g == m2.g) && (m1.b == m2.b);
}
-inline bool operator!=(const QColorMatrix &m1, const QColorMatrix &m2)
-{
- return !(m1 == m2);
-}
-
QT_END_NAMESPACE
#endif // QCOLORMATRIX_P_H
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
index 6a58ea06e2..7a1d34a408 100644
--- a/src/gui/painting/qcolorspace.cpp
+++ b/src/gui/painting/qcolorspace.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcolorspace.h"
#include "qcolorspace_p.h"
#include "qcolortransform.h"
+#include "qcolorclut_p.h"
#include "qcolormatrix_p.h"
#include "qcolortransferfunction_p.h"
#include "qcolortransform_p.h"
@@ -54,9 +19,9 @@
QT_BEGIN_NAMESPACE
-QBasicMutex QColorSpacePrivate::s_lutWriteLock;
+Q_CONSTINIT QBasicMutex QColorSpacePrivate::s_lutWriteLock;
-static QAtomicPointer<QColorSpacePrivate> s_predefinedColorspacePrivates[QColorSpace::ProPhotoRgb] = {};
+Q_CONSTINIT static QAtomicPointer<QColorSpacePrivate> s_predefinedColorspacePrivates[QColorSpace::ProPhotoRgb] = {};
static void cleanupPredefinedColorspaces()
{
for (QAtomicPointer<QColorSpacePrivate> &ptr : s_predefinedColorspacePrivates) {
@@ -116,49 +81,19 @@ bool QColorSpacePrimaries::areValid() const
QColorMatrix QColorSpacePrimaries::toXyzMatrix() const
{
// This converts to XYZ in some undefined scale.
- QColorMatrix toXyz = { QColorVector(redPoint),
- QColorVector(greenPoint),
- QColorVector(bluePoint) };
+ QColorMatrix toXyz = { QColorVector::fromXYChromaticity(redPoint),
+ QColorVector::fromXYChromaticity(greenPoint),
+ QColorVector::fromXYChromaticity(bluePoint) };
// Since the white point should be (1.0, 1.0, 1.0) in the
// input, we can figure out the scale by using the
// inverse conversion on the white point.
- QColorVector wXyz(whitePoint);
+ const auto wXyz = QColorVector::fromXYChromaticity(whitePoint);
QColorVector whiteScale = toXyz.inverted().map(wXyz);
// Now we have scaled conversion to XYZ relative to the given whitepoint
toXyz = toXyz * QColorMatrix::fromScale(whiteScale);
- // But we want a conversion to XYZ relative to D50
- QColorVector wXyzD50 = QColorVector::D50();
-
- if (wXyz != wXyzD50) {
- // Do chromatic adaptation to map our white point to XYZ D50.
-
- // The Bradford method chromatic adaptation matrix:
- QColorMatrix abrad = { { 0.8951f, -0.7502f, 0.0389f },
- { 0.2664f, 1.7135f, -0.0685f },
- { -0.1614f, 0.0367f, 1.0296f } };
- QColorMatrix abradinv = { { 0.9869929f, 0.4323053f, -0.0085287f },
- { -0.1470543f, 0.5183603f, 0.0400428f },
- { 0.1599627f, 0.0492912f, 0.9684867f } };
-
- QColorVector srcCone = abrad.map(wXyz);
- QColorVector dstCone = abrad.map(wXyzD50);
-
- if (srcCone.x && srcCone.y && srcCone.z) {
- QColorMatrix wToD50 = { { dstCone.x / srcCone.x, 0, 0 },
- { 0, dstCone.y / srcCone.y, 0 },
- { 0, 0, dstCone.z / srcCone.z } };
-
-
- QColorMatrix chromaticAdaptation = abradinv * (wToD50 * abrad);
- toXyz = chromaticAdaptation * toXyz;
- } else {
- toXyz.r = {0, 0, 0}; // set to invalid value
- }
- }
-
return toXyz;
}
@@ -168,6 +103,7 @@ QColorSpacePrivate::QColorSpacePrivate()
QColorSpacePrivate::QColorSpacePrivate(QColorSpace::NamedColorSpace namedColorSpace)
: namedColorSpace(namedColorSpace)
+ , colorModel(QColorSpace::ColorModel::Rgb)
{
switch (namedColorSpace) {
case QColorSpace::SRgb:
@@ -205,6 +141,7 @@ QColorSpacePrivate::QColorSpacePrivate(QColorSpace::NamedColorSpace namedColorSp
QColorSpacePrivate::QColorSpacePrivate(QColorSpace::Primaries primaries, QColorSpace::TransferFunction transferFunction, float gamma)
: primaries(primaries)
, transferFunction(transferFunction)
+ , colorModel(QColorSpace::ColorModel::Rgb)
, gamma(gamma)
{
identifyColorSpace();
@@ -216,18 +153,50 @@ QColorSpacePrivate::QColorSpacePrivate(const QColorSpacePrimaries &primaries,
float gamma)
: primaries(QColorSpace::Primaries::Custom)
, transferFunction(transferFunction)
+ , colorModel(QColorSpace::ColorModel::Rgb)
, gamma(gamma)
+ , whitePoint(QColorVector::fromXYChromaticity(primaries.whitePoint))
{
Q_ASSERT(primaries.areValid());
toXyz = primaries.toXyzMatrix();
- whitePoint = QColorVector(primaries.whitePoint);
+ chad = QColorMatrix::chromaticAdaptation(whitePoint);
+ toXyz = chad * toXyz;
+
identifyColorSpace();
setTransferFunction();
}
+QColorSpacePrivate::QColorSpacePrivate(const QPointF &whitePoint,
+ QColorSpace::TransferFunction transferFunction,
+ float gamma)
+ : primaries(QColorSpace::Primaries::Custom)
+ , transferFunction(transferFunction)
+ , colorModel(QColorSpace::ColorModel::Gray)
+ , gamma(gamma)
+ , whitePoint(QColorVector::fromXYChromaticity(whitePoint))
+{
+ chad = QColorMatrix::chromaticAdaptation(this->whitePoint);
+ toXyz = chad;
+ setTransferFunction();
+}
+
+QColorSpacePrivate::QColorSpacePrivate(const QPointF &whitePoint, const QList<uint16_t> &transferFunctionTable)
+ : primaries(QColorSpace::Primaries::Custom)
+ , transferFunction(QColorSpace::TransferFunction::Custom)
+ , colorModel(QColorSpace::ColorModel::Gray)
+ , gamma(0)
+ , whitePoint(QColorVector::fromXYChromaticity(whitePoint))
+{
+ chad = QColorMatrix::chromaticAdaptation(this->whitePoint);
+ toXyz = chad;
+ setTransferFunctionTable(transferFunctionTable);
+ setTransferFunction();
+}
+
QColorSpacePrivate::QColorSpacePrivate(QColorSpace::Primaries primaries, const QList<uint16_t> &transferFunctionTable)
: primaries(primaries)
, transferFunction(QColorSpace::TransferFunction::Custom)
+ , colorModel(QColorSpace::ColorModel::Rgb)
, gamma(0)
{
setTransferFunctionTable(transferFunctionTable);
@@ -238,11 +207,14 @@ QColorSpacePrivate::QColorSpacePrivate(QColorSpace::Primaries primaries, const Q
QColorSpacePrivate::QColorSpacePrivate(const QColorSpacePrimaries &primaries, const QList<uint16_t> &transferFunctionTable)
: primaries(QColorSpace::Primaries::Custom)
, transferFunction(QColorSpace::TransferFunction::Custom)
+ , colorModel(QColorSpace::ColorModel::Rgb)
, gamma(0)
+ , whitePoint(QColorVector::fromXYChromaticity(primaries.whitePoint))
{
Q_ASSERT(primaries.areValid());
toXyz = primaries.toXyzMatrix();
- whitePoint = QColorVector(primaries.whitePoint);
+ chad = QColorMatrix::chromaticAdaptation(whitePoint);
+ toXyz = chad * toXyz;
setTransferFunctionTable(transferFunctionTable);
identifyColorSpace();
initialize();
@@ -254,16 +226,18 @@ QColorSpacePrivate::QColorSpacePrivate(const QColorSpacePrimaries &primaries,
const QList<uint16_t> &blueTransferFunctionTable)
: primaries(QColorSpace::Primaries::Custom)
, transferFunction(QColorSpace::TransferFunction::Custom)
+ , colorModel(QColorSpace::ColorModel::Rgb)
, gamma(0)
{
Q_ASSERT(primaries.areValid());
toXyz = primaries.toXyzMatrix();
- whitePoint = QColorVector(primaries.whitePoint);
+ whitePoint = QColorVector::fromXYChromaticity(primaries.whitePoint);
+ chad = QColorMatrix::chromaticAdaptation(whitePoint);
+ toXyz = chad * toXyz;
setTransferFunctionTables(redTransferFunctionTable,
greenTransferFunctionTable,
blueTransferFunctionTable);
identifyColorSpace();
- setToXyzMatrix();
}
void QColorSpacePrivate::identifyColorSpace()
@@ -340,7 +314,9 @@ void QColorSpacePrivate::setToXyzMatrix()
}
QColorSpacePrimaries colorSpacePrimaries(primaries);
toXyz = colorSpacePrimaries.toXyzMatrix();
- whitePoint = QColorVector(colorSpacePrimaries.whitePoint);
+ whitePoint = QColorVector::fromXYChromaticity(colorSpacePrimaries.whitePoint);
+ chad = QColorMatrix::chromaticAdaptation(whitePoint);
+ toXyz = chad * toXyz;
}
void QColorSpacePrivate::setTransferFunctionTable(const QList<uint16_t> &transferFunctionTable)
@@ -355,7 +331,7 @@ void QColorSpacePrivate::setTransferFunctionTable(const QList<uint16_t> &transfe
QColorTransferFunction curve;
if (table.asColorTransferFunction(&curve)) {
// Table recognized as a specific curve
- if (curve.isLinear()) {
+ if (curve.isIdentity()) {
transferFunction = QColorSpace::TransferFunction::Linear;
gamma = 1.0f;
} else if (curve.isSRgb()) {
@@ -454,7 +430,14 @@ QColorTransform QColorSpacePrivate::transformationToColorSpace(const QColorSpace
combined.d = ptr;
ptr->colorSpaceIn = this;
ptr->colorSpaceOut = out;
- ptr->colorMatrix = out->toXyz.inverted() * toXyz;
+ if (isThreeComponentMatrix())
+ ptr->colorMatrix = toXyz;
+ else
+ ptr->colorMatrix = QColorMatrix::identity();
+ if (out->isThreeComponentMatrix())
+ ptr->colorMatrix = out->toXyz.inverted() * ptr->colorMatrix;
+ if (ptr->isIdentity())
+ return QColorTransform();
return combined;
}
@@ -465,10 +448,32 @@ QColorTransform QColorSpacePrivate::transformationToXYZ() const
transform.d = ptr;
ptr->colorSpaceIn = this;
ptr->colorSpaceOut = this;
- ptr->colorMatrix = toXyz;
+ // Convert to XYZ relative to our white point, not the regular D50 white point.
+ if (isThreeComponentMatrix())
+ ptr->colorMatrix = QColorMatrix::chromaticAdaptation(whitePoint).inverted() * toXyz;
+ else
+ ptr->colorMatrix = QColorMatrix::identity();
return transform;
}
+bool QColorSpacePrivate::isThreeComponentMatrix() const
+{
+ return transformModel == QColorSpace::TransformModel::ThreeComponentMatrix;
+}
+
+void QColorSpacePrivate::clearElementListProcessingForEdit()
+{
+ Q_ASSERT(transformModel == QColorSpace::TransformModel::ElementListProcessing);
+ Q_ASSERT(primaries == QColorSpace::Primaries::Custom);
+ Q_ASSERT(transferFunction == QColorSpace::TransferFunction::Custom);
+
+ transformModel = QColorSpace::TransformModel::ThreeComponentMatrix;
+ colorModel = QColorSpace::ColorModel::Rgb;
+ isPcsLab = false;
+ mAB.clear();
+ mBA.clear();
+}
+
/*!
\class QColorSpace
\brief The QColorSpace class provides a color space abstraction.
@@ -491,9 +496,10 @@ QColorTransform QColorSpacePrivate::transformationToXYZ() const
A color space can generally speaking be conceived as a combination of set of primary
colors and a transfer function. The primaries defines the axes of the color space, and
the transfer function how values are mapped on the axes.
- The primaries are defined by three primary colors that represent exactly how red, green,
- and blue look in this particular color space, and a white color that represents where
- and how bright pure white is. The range of colors expressable by the primary colors is
+ The primaries are for ColorModel::Rgb color spaces defined by three primary colors that
+ represent exactly how red, green, and blue look in this particular color space, and a white
+ color that represents where and how bright pure white is. For grayscale color spaces, only
+ a single white primary is needed. The range of colors expressible by the primary colors is
called the gamut, and a color space that can represent a wider range of colors is also
known as a wide-gamut color space.
@@ -547,6 +553,35 @@ QColorTransform QColorSpacePrivate::transformationToXYZ() const
*/
/*!
+ \enum QColorSpace::TransformModel
+ \since 6.8
+
+ Defines the processing model used for color space transforms.
+
+ \value ThreeComponentMatrix The transform consist of a matrix calculated from primaries and set of transfer functions
+ for each color channel. This is very fast and used by all predefined color spaces. Any color space on this form is
+ reversible and always both valid sources and targets.
+ \value ElementListProcessing The transforms are one or two lists of processing elements that can do many things,
+ each list only process either to the connection color space or from it. This is very flexible, but rather
+ slow, and can only be set by reading ICC profiles (See \l fromIccProfile()). Since the two lists are
+ separate a color space on this form can be a valid source, but not necessarily also a valid target. When changing
+ either primaries or transfer function on a color space on this type it will reset to an empty ThreeComponentMatrix form.
+*/
+
+/*!
+ \enum QColorSpace::ColorModel
+ \since 6.8
+
+ Defines the color model used by the color space data.
+
+ \value Undefined No color model
+ \value Rgb An RGB color model with red, green, and blue colors. Can apply to RGB and grayscale data.
+ \value Gray A gray scale color model. Can only apply to grayscale data.
+ \value Cmyk Can only represent color data defined with cyan, magenta, yellow, and black colors.
+ In effect only QImage::Format_CMYK32. Note Cmyk color spaces will be TransformModel::ElementListProcessing.
+*/
+
+/*!
\fn QColorSpace::QColorSpace()
Creates a new colorspace object that represents an undefined and invalid colorspace.
@@ -609,6 +644,28 @@ QColorSpace::QColorSpace(QColorSpace::Primaries gamut, const QList<uint16_t> &tr
}
/*!
+ Creates a custom grayscale color space with the white point \a whitePoint, using the transfer function \a transferFunction and
+ optionally \a gamma.
+
+ \since 6.8
+*/
+QColorSpace::QColorSpace(const QPointF &whitePoint, TransferFunction transferFunction, float gamma)
+ : d_ptr(new QColorSpacePrivate(whitePoint, transferFunction, gamma))
+{
+}
+
+/*!
+ Creates a custom grayscale color space with white point \a whitePoint, and using the custom transfer function described by
+ \a transferFunctionTable.
+
+ \since 6.8
+*/
+QColorSpace::QColorSpace(const QPointF &whitePoint, const QList<uint16_t> &transferFunctionTable)
+ : d_ptr(new QColorSpacePrivate(whitePoint, transferFunctionTable))
+{
+}
+
+/*!
Creates a custom colorspace with a primaries based on the chromaticities of the primary colors \a whitePoint,
\a redPoint, \a greenPoint and \a bluePoint, and using the transfer function \a transferFunction and optionally \a gamma.
*/
@@ -723,7 +780,10 @@ void QColorSpace::setTransferFunction(QColorSpace::TransferFunction transferFunc
if (d_ptr->transferFunction == transferFunction && d_ptr->gamma == gamma)
return;
detach();
- d_ptr->description.clear();
+ if (d_ptr->transformModel == TransformModel::ElementListProcessing)
+ d_ptr->clearElementListProcessingForEdit();
+ d_ptr->iccProfile = {};
+ d_ptr->description = QString();
d_ptr->transferFunction = transferFunction;
d_ptr->gamma = gamma;
d_ptr->identifyColorSpace();
@@ -744,7 +804,10 @@ void QColorSpace::setTransferFunction(const QList<uint16_t> &transferFunctionTab
return;
}
detach();
- d_ptr->description.clear();
+ if (d_ptr->transformModel == TransformModel::ElementListProcessing)
+ d_ptr->clearElementListProcessingForEdit();
+ d_ptr->iccProfile = {};
+ d_ptr->description = QString();
d_ptr->setTransferFunctionTable(transferFunctionTable);
d_ptr->gamma = 0;
d_ptr->identifyColorSpace();
@@ -771,7 +834,10 @@ void QColorSpace::setTransferFunctions(const QList<uint16_t> &redTransferFunctio
return;
}
detach();
- d_ptr->description.clear();
+ if (d_ptr->transformModel == TransformModel::ElementListProcessing)
+ d_ptr->clearElementListProcessingForEdit();
+ d_ptr->iccProfile = {};
+ d_ptr->description = QString();
d_ptr->setTransferFunctionTables(redTransferFunctionTable,
greenTransferFunctionTable,
blueTransferFunctionTable);
@@ -787,7 +853,7 @@ void QColorSpace::setTransferFunctions(const QList<uint16_t> &redTransferFunctio
*/
QColorSpace QColorSpace::withTransferFunction(QColorSpace::TransferFunction transferFunction, float gamma) const
{
- if (!isValid() || transferFunction == QColorSpace::TransferFunction::Custom)
+ if (!isValid() || transferFunction == TransferFunction::Custom)
return *this;
if (d_ptr->transferFunction == transferFunction && d_ptr->gamma == gamma)
return *this;
@@ -847,8 +913,12 @@ void QColorSpace::setPrimaries(QColorSpace::Primaries primariesId)
if (d_ptr->primaries == primariesId)
return;
detach();
- d_ptr->description.clear();
+ if (d_ptr->transformModel == TransformModel::ElementListProcessing)
+ d_ptr->clearElementListProcessingForEdit();
+ d_ptr->iccProfile = {};
+ d_ptr->description = QString();
d_ptr->primaries = primariesId;
+ d_ptr->colorModel = QColorSpace::ColorModel::Rgb;
d_ptr->identifyColorSpace();
d_ptr->setToXyzMatrix();
}
@@ -870,17 +940,100 @@ void QColorSpace::setPrimaries(const QPointF &whitePoint, const QPointF &redPoin
return;
}
QColorMatrix toXyz = primaries.toXyzMatrix();
- if (QColorVector(primaries.whitePoint) == d_ptr->whitePoint && toXyz == d_ptr->toXyz)
+ QColorMatrix chad = QColorMatrix::chromaticAdaptation(QColorVector::fromXYChromaticity(whitePoint));
+ toXyz = chad * toXyz;
+ if (QColorVector::fromXYChromaticity(primaries.whitePoint) == d_ptr->whitePoint
+ && toXyz == d_ptr->toXyz && chad == d_ptr->chad)
return;
detach();
- d_ptr->description.clear();
+ if (d_ptr->transformModel == TransformModel::ElementListProcessing)
+ d_ptr->clearElementListProcessingForEdit();
+ d_ptr->iccProfile = {};
+ d_ptr->description = QString();
d_ptr->primaries = QColorSpace::Primaries::Custom;
+ d_ptr->colorModel = QColorSpace::ColorModel::Rgb;
d_ptr->toXyz = toXyz;
- d_ptr->whitePoint = QColorVector(primaries.whitePoint);
+ d_ptr->chad = chad;
+ d_ptr->whitePoint = QColorVector::fromXYChromaticity(primaries.whitePoint);
d_ptr->identifyColorSpace();
}
/*!
+ Returns the white point used for this color space. Returns a null QPointF if not defined.
+
+ \since 6.8
+*/
+QPointF QColorSpace::whitePoint() const
+{
+ if (Q_UNLIKELY(!d_ptr))
+ return QPointF();
+ return d_ptr->whitePoint.toChromaticity();
+}
+
+/*!
+ Sets the white point to used for this color space to \a whitePoint.
+
+ \since 6.8
+*/
+void QColorSpace::setWhitePoint(const QPointF &whitePoint)
+{
+ if (Q_UNLIKELY(!d_ptr)) {
+ d_ptr = new QColorSpacePrivate(whitePoint, TransferFunction::Custom, 0.0f);
+ return;
+ }
+ if (QColorVector::fromXYChromaticity(whitePoint) == d_ptr->whitePoint)
+ return;
+ detach();
+ if (d_ptr->transformModel == TransformModel::ElementListProcessing)
+ d_ptr->clearElementListProcessingForEdit();
+ d_ptr->iccProfile = {};
+ d_ptr->description = QString();
+ d_ptr->primaries = QColorSpace::Primaries::Custom;
+ // An RGB color model stays RGB, a gray stays gray, but an undefined one can now be considered gray
+ if (d_ptr->colorModel == QColorSpace::ColorModel::Undefined)
+ d_ptr->colorModel = QColorSpace::ColorModel::Gray;
+ QColorVector wXyz(QColorVector::fromXYChromaticity(whitePoint));
+ if (d_ptr->transformModel == QColorSpace::TransformModel::ThreeComponentMatrix) {
+ if (d_ptr->colorModel == QColorSpace::ColorModel::Rgb) {
+ // Rescale toXyz to new whitepoint
+ QColorMatrix rawToXyz = d_ptr->chad.inverted() * d_ptr->toXyz;
+ QColorVector whiteScale = rawToXyz.inverted().map(wXyz);
+ rawToXyz = rawToXyz * QColorMatrix::fromScale(whiteScale);
+ d_ptr->chad = QColorMatrix::chromaticAdaptation(wXyz);
+ d_ptr->toXyz = d_ptr->chad * rawToXyz;
+ } else if (d_ptr->colorModel == QColorSpace::ColorModel::Gray) {
+ d_ptr->chad = d_ptr->toXyz = QColorMatrix::chromaticAdaptation(wXyz);
+ }
+ }
+ d_ptr->whitePoint = wXyz;
+ d_ptr->identifyColorSpace();
+}
+
+/*!
+ Returns the transfrom processing model used for this color space.
+
+ \since 6.8
+*/
+QColorSpace::TransformModel QColorSpace::transformModel() const noexcept
+{
+ if (Q_UNLIKELY(!d_ptr))
+ return QColorSpace::TransformModel::ThreeComponentMatrix;
+ return d_ptr->transformModel;
+}
+
+/*!
+ Returns the color model this color space can represent
+
+ \since 6.8
+*/
+QColorSpace::ColorModel QColorSpace::colorModel() const noexcept
+{
+ if (Q_UNLIKELY(!d_ptr))
+ return QColorSpace::ColorModel::Undefined;
+ return d_ptr->colorModel;
+}
+
+/*!
\internal
*/
void QColorSpace::detach()
@@ -918,7 +1071,7 @@ QByteArray QColorSpace::iccProfile() const
Creates a QColorSpace from ICC profile \a iccProfile.
\note Not all ICC profiles are supported. QColorSpace only supports
- RGB-XYZ ICC profiles that are three-component matrix-based.
+ RGB or Gray ICC profiles.
If the ICC profile is not supported an invalid QColorSpace is returned
where you can still read the original ICC profile using iccProfile().
@@ -936,13 +1089,51 @@ QColorSpace QColorSpace::fromIccProfile(const QByteArray &iccProfile)
}
/*!
- Returns \c true if the color space is valid.
+ Returns \c true if the color space is valid. For a color space with \c TransformModel::ThreeComponentMatrix
+ that means both primaries and transfer functions set, and implies isValidTarget().
+ For a color space with \c TransformModel::ElementListProcessing it means it has a valid source transform, to
+ check if it also a valid target color space use isValidTarget().
+
+ \sa isValidTarget()
*/
bool QColorSpace::isValid() const noexcept
{
- return d_ptr
- && d_ptr->toXyz.isValid()
- && d_ptr->trc[0].isValid() && d_ptr->trc[1].isValid() && d_ptr->trc[2].isValid();
+ if (!d_ptr)
+ return false;
+ return d_ptr->isValid();
+}
+
+/*!
+ \since 6.8
+
+ Returns \c true if the color space is a valid target color space.
+*/
+bool QColorSpace::isValidTarget() const noexcept
+{
+ if (!d_ptr)
+ return false;
+ if (!d_ptr->isThreeComponentMatrix())
+ return !d_ptr->mBA.isEmpty();
+ return d_ptr->isValid();
+}
+
+/*!
+ \internal
+*/
+bool QColorSpacePrivate::isValid() const noexcept
+{
+ if (!isThreeComponentMatrix())
+ return !mAB.isEmpty();
+ if (!toXyz.isValid())
+ return false;
+ if (colorModel == QColorSpace::ColorModel::Gray) {
+ if (!trc[0].isValid())
+ return false;
+ } else {
+ if (!trc[0].isValid() || !trc[1].isValid() || !trc[2].isValid())
+ return false;
+ }
+ return true;
}
/*!
@@ -959,6 +1150,53 @@ bool QColorSpace::isValid() const noexcept
otherwise returns \c false
*/
+static bool compareElement(const QColorSpacePrivate::TransferElement &element,
+ const QColorSpacePrivate::TransferElement &other)
+{
+ return element.trc[0] == other.trc[0]
+ && element.trc[1] == other.trc[1]
+ && element.trc[2] == other.trc[2]
+ && element.trc[3] == other.trc[3];
+}
+
+static bool compareElement(const QColorMatrix &element,
+ const QColorMatrix &other)
+{
+ return element == other;
+}
+
+static bool compareElement(const QColorVector &element,
+ const QColorVector &other)
+{
+ return element == other;
+}
+
+static bool compareElement(const QColorCLUT &element,
+ const QColorCLUT &other)
+{
+ if (element.gridPointsX != other.gridPointsX)
+ return false;
+ if (element.gridPointsY != other.gridPointsY)
+ return false;
+ if (element.gridPointsZ != other.gridPointsZ)
+ return false;
+ if (element.gridPointsW != other.gridPointsW)
+ return false;
+ if (element.table.size() != other.table.size())
+ return false;
+ for (qsizetype i = 0; i < element.table.size(); ++i) {
+ if (element.table[i] != other.table[i])
+ return false;
+ }
+ return true;
+}
+
+template<typename T>
+static bool compareElements(const T &element, const QColorSpacePrivate::Element &other)
+{
+ return compareElement(element, std::get<T>(other));
+}
+
/*!
\internal
*/
@@ -966,43 +1204,89 @@ bool QColorSpace::equals(const QColorSpace &other) const
{
if (d_ptr == other.d_ptr)
return true;
- if (!d_ptr || !other.d_ptr)
+ if (!d_ptr)
return false;
+ return d_ptr->equals(other.d_ptr.constData());
+}
- if (d_ptr->namedColorSpace && other.d_ptr->namedColorSpace)
- return d_ptr->namedColorSpace == other.d_ptr->namedColorSpace;
+/*!
+ \internal
+*/
+bool QColorSpacePrivate::equals(const QColorSpacePrivate *other) const
+{
+ if (!other)
+ return false;
+
+ if (namedColorSpace && other->namedColorSpace)
+ return namedColorSpace == other->namedColorSpace;
const bool valid1 = isValid();
- const bool valid2 = other.isValid();
+ const bool valid2 = other->isValid();
if (valid1 != valid2)
return false;
if (!valid1 && !valid2) {
- if (!d_ptr->iccProfile.isEmpty() || !other.d_ptr->iccProfile.isEmpty())
- return d_ptr->iccProfile == other.d_ptr->iccProfile;
+ if (!iccProfile.isEmpty() || !other->iccProfile.isEmpty())
+ return iccProfile == other->iccProfile;
+ return false;
}
// At this point one or both color spaces are unknown, and must be compared in detail instead
- if (primaries() != QColorSpace::Primaries::Custom && other.primaries() != QColorSpace::Primaries::Custom) {
- if (primaries() != other.primaries())
+ if (transformModel != other->transformModel)
+ return false;
+
+ if (!isThreeComponentMatrix()) {
+ if (isPcsLab != other->isPcsLab)
+ return false;
+ if (colorModel != other->colorModel)
+ return false;
+ if (mAB.count() != other->mAB.count())
+ return false;
+ if (mBA.count() != other->mBA.count())
+ return false;
+
+ // Compare element types
+ for (qsizetype i = 0; i < mAB.count(); ++i) {
+ if (mAB[i].index() != other->mAB[i].index())
+ return false;
+ }
+ for (qsizetype i = 0; i < mBA.count(); ++i) {
+ if (mBA[i].index() != other->mBA[i].index())
+ return false;
+ }
+
+ // Compare element contents
+ for (qsizetype i = 0; i < mAB.count(); ++i) {
+ if (!std::visit([&](auto &&elm) { return compareElements(elm, other->mAB[i]); }, mAB[i]))
+ return false;
+ }
+ for (qsizetype i = 0; i < mBA.count(); ++i) {
+ if (!std::visit([&](auto &&elm) { return compareElements(elm, other->mBA[i]); }, mBA[i]))
+ return false;
+ }
+
+ return true;
+ }
+
+ if (primaries != QColorSpace::Primaries::Custom && other->primaries != QColorSpace::Primaries::Custom) {
+ if (primaries != other->primaries)
return false;
} else {
- if (d_ptr->toXyz != other.d_ptr->toXyz)
+ if (toXyz != other->toXyz)
return false;
}
- if (transferFunction() != QColorSpace::TransferFunction::Custom &&
- other.transferFunction() != QColorSpace::TransferFunction::Custom) {
- if (transferFunction() != other.transferFunction())
+ if (transferFunction != QColorSpace::TransferFunction::Custom && other->transferFunction != QColorSpace::TransferFunction::Custom) {
+ if (transferFunction != other->transferFunction)
return false;
- if (transferFunction() == QColorSpace::TransferFunction::Gamma)
- return (qAbs(gamma() - other.gamma()) <= (1.0f / 512.0f));
+ if (transferFunction == QColorSpace::TransferFunction::Gamma)
+ return (qAbs(gamma - other->gamma) <= (1.0f / 512.0f));
return true;
}
- if (d_ptr->trc[0] != other.d_ptr->trc[0] ||
- d_ptr->trc[1] != other.d_ptr->trc[1] ||
- d_ptr->trc[2] != other.d_ptr->trc[2])
+ if (trc[0] != other->trc[0] ||
+ trc[1] != other->trc[1] ||
+ trc[2] != other->trc[2])
return false;
return true;
@@ -1014,9 +1298,16 @@ bool QColorSpace::equals(const QColorSpace &other) const
*/
QColorTransform QColorSpace::transformationToColorSpace(const QColorSpace &colorspace) const
{
- if (!isValid() || !colorspace.isValid())
+ if (!isValid())
return QColorTransform();
+ if (*this == colorspace)
+ return QColorTransform();
+ if (!colorspace.isValidTarget()) {
+ qWarning() << "QColorSpace::transformationToColorSpace: colorspace not a valid target";
+ return QColorTransform();
+ }
+
return d_ptr->transformationToColorSpace(colorspace.d_ptr.get());
}
@@ -1055,6 +1346,7 @@ QString QColorSpace::description() const noexcept
void QColorSpace::setDescription(const QString &description)
{
detach();
+ d_ptr->iccProfile = {};
d_ptr->userDescription = description;
}
@@ -1097,6 +1389,28 @@ QDataStream &operator>>(QDataStream &s, QColorSpace &colorSpace)
#endif // QT_NO_DATASTREAM
#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QColorSpacePrivate::TransferElement &)
+{
+ return dbg << ":Transfer";
+}
+QDebug operator<<(QDebug dbg, const QColorMatrix &)
+{
+ return dbg << ":Matrix";
+}
+QDebug operator<<(QDebug dbg, const QColorVector &)
+{
+ return dbg << ":Offset";
+}
+QDebug operator<<(QDebug dbg, const QColorCLUT &)
+{
+ return dbg << ":CLUT";
+}
+QDebug operator<<(QDebug dbg, const QList<QColorSpacePrivate::Element> &elements)
+{
+ for (auto &&element : elements)
+ std::visit([&](auto &&elm) { dbg << elm; }, element);
+ return dbg;
+}
QDebug operator<<(QDebug dbg, const QColorSpace &colorSpace)
{
QDebugStateSaver saver(dbg);
@@ -1105,8 +1419,22 @@ QDebug operator<<(QDebug dbg, const QColorSpace &colorSpace)
if (colorSpace.d_ptr) {
if (colorSpace.d_ptr->namedColorSpace)
dbg << colorSpace.d_ptr->namedColorSpace << ", ";
- dbg << colorSpace.primaries() << ", " << colorSpace.transferFunction();
- dbg << ", gamma=" << colorSpace.gamma();
+ if (!colorSpace.isValid()) {
+ dbg << "Invalid";
+ if (!colorSpace.d_ptr->iccProfile.isEmpty())
+ dbg << " with profile data";
+ } else if (colorSpace.d_ptr->isThreeComponentMatrix()) {
+ dbg << colorSpace.primaries() << ", " << colorSpace.transferFunction();
+ dbg << ", gamma=" << colorSpace.gamma();
+ } else {
+ if (colorSpace.d_ptr->isPcsLab)
+ dbg << "PCSLab, ";
+ else
+ dbg << "PCSXYZ, ";
+ dbg << "A2B" << colorSpace.d_ptr->mAB;
+ if (!colorSpace.d_ptr->mBA.isEmpty())
+ dbg << ", B2A" << colorSpace.d_ptr->mBA;
+ }
}
dbg << ')';
return dbg;
@@ -1114,3 +1442,5 @@ QDebug operator<<(QDebug dbg, const QColorSpace &colorSpace)
#endif
QT_END_NAMESPACE
+
+#include "moc_qcolorspace.cpp"
diff --git a/src/gui/painting/qcolorspace.h b/src/gui/painting/qcolorspace.h
index 43ae2257c0..488cbd6a53 100644
--- a/src/gui/painting/qcolorspace.h
+++ b/src/gui/painting/qcolorspace.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLORSPACE_H
#define QCOLORSPACE_H
@@ -81,9 +45,23 @@ public:
ProPhotoRgb
};
Q_ENUM(TransferFunction)
+ enum class TransformModel : uint8_t {
+ ThreeComponentMatrix = 0,
+ ElementListProcessing,
+ };
+ Q_ENUM(TransformModel)
+ enum class ColorModel : uint8_t {
+ Undefined = 0,
+ Rgb = 1,
+ Gray = 2,
+ Cmyk = 3,
+ };
+ Q_ENUM(ColorModel)
QColorSpace() noexcept = default;
QColorSpace(NamedColorSpace namedColorSpace);
+ QColorSpace(const QPointF &whitePoint, TransferFunction transferFunction, float gamma = 0.0f);
+ QColorSpace(const QPointF &whitePoint, const QList<uint16_t> &transferFunctionTable);
QColorSpace(Primaries primaries, TransferFunction transferFunction, float gamma = 0.0f);
QColorSpace(Primaries primaries, float gamma);
QColorSpace(Primaries primaries, const QList<uint16_t> &transferFunctionTable);
@@ -112,7 +90,7 @@ public:
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QColorSpace)
void swap(QColorSpace &colorSpace) noexcept
- { qSwap(d_ptr, colorSpace.d_ptr); }
+ { d_ptr.swap(colorSpace.d_ptr); }
Primaries primaries() const noexcept;
TransferFunction transferFunction() const noexcept;
@@ -135,9 +113,14 @@ public:
void setPrimaries(Primaries primariesId);
void setPrimaries(const QPointF &whitePoint, const QPointF &redPoint,
const QPointF &greenPoint, const QPointF &bluePoint);
+ void setWhitePoint(const QPointF &whitePoint);
+ QPointF whitePoint() const;
+ TransformModel transformModel() const noexcept;
+ ColorModel colorModel() const noexcept;
void detach();
bool isValid() const noexcept;
+ bool isValidTarget() const noexcept;
friend inline bool operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2)
{ return colorSpace1.equals(colorSpace2); }
diff --git a/src/gui/painting/qcolorspace_p.h b/src/gui/painting/qcolorspace_p.h
index f555ad5169..4ec801b16b 100644
--- a/src/gui/painting/qcolorspace_p.h
+++ b/src/gui/painting/qcolorspace_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLORSPACE_P_H
#define QCOLORSPACE_P_H
@@ -52,6 +16,7 @@
//
#include "qcolorspace.h"
+#include "qcolorclut_p.h"
#include "qcolormatrix_p.h"
#include "qcolortrc_p.h"
#include "qcolortrclut_p.h"
@@ -101,6 +66,8 @@ public:
const QList<uint16_t> &redTransferFunctionTable,
const QList<uint16_t> &greenTransferFunctionTable,
const QList<uint16_t> &blueRransferFunctionTable);
+ QColorSpacePrivate(const QPointF &whitePoint, QColorSpace::TransferFunction transferFunction, float gamma);
+ QColorSpacePrivate(const QPointF &whitePoint, const QList<uint16_t> &transferFunctionTable);
QColorSpacePrivate(const QColorSpacePrivate &other) = default;
static const QColorSpacePrivate *get(const QColorSpace &colorSpace)
@@ -113,6 +80,9 @@ public:
return colorSpace.d_ptr.get();
}
+ bool equals(const QColorSpacePrivate *other) const;
+ bool isValid() const noexcept;
+
void initialize();
void setToXyzMatrix();
void setTransferFunction();
@@ -124,22 +94,40 @@ public:
QColorTransform transformationToColorSpace(const QColorSpacePrivate *out) const;
QColorTransform transformationToXYZ() const;
+ bool isThreeComponentMatrix() const;
+ void clearElementListProcessingForEdit();
+
static constexpr QColorSpace::NamedColorSpace Unknown = QColorSpace::NamedColorSpace(0);
QColorSpace::NamedColorSpace namedColorSpace = Unknown;
QColorSpace::Primaries primaries = QColorSpace::Primaries::Custom;
QColorSpace::TransferFunction transferFunction = QColorSpace::TransferFunction::Custom;
+ QColorSpace::TransformModel transformModel = QColorSpace::TransformModel::ThreeComponentMatrix;
+ QColorSpace::ColorModel colorModel = QColorSpace::ColorModel::Undefined;
float gamma = 0.0f;
QColorVector whitePoint;
+ // Three component matrix data:
QColorTrc trc[3];
QColorMatrix toXyz;
-
+ QColorMatrix chad;
+
+ // Element list processing data:
+ struct TransferElement {
+ QColorTrc trc[4];
+ };
+ using Element = std::variant<TransferElement, QColorMatrix, QColorVector, QColorCLUT>;
+ bool isPcsLab = false;
+ // A = device, B = PCS
+ QList<Element> mAB, mBA;
+
+ // Metadata
QString description;
QString userDescription;
QByteArray iccProfile;
- static QBasicMutex s_lutWriteLock;
+ // Cached tables for three component matrix transform:
+ Q_CONSTINIT static QBasicMutex s_lutWriteLock;
struct LUT {
LUT() = default;
~LUT() = default;
diff --git a/src/gui/painting/qcolortransferfunction_p.h b/src/gui/painting/qcolortransferfunction_p.h
index 0575dbd888..484cc69114 100644
--- a/src/gui/painting/qcolortransferfunction_p.h
+++ b/src/gui/painting/qcolortransferfunction_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLORTRANSFERFUNCTION_P_H
#define QCOLORTRANSFERFUNCTION_P_H
@@ -52,44 +16,52 @@
//
#include <QtGui/private/qtguiglobal_p.h>
+#include <QtCore/QFlags>
#include <cmath>
QT_BEGIN_NAMESPACE
// Defines a ICC parametric curve type 4
-class Q_GUI_EXPORT QColorTransferFunction
+class QColorTransferFunction
{
public:
QColorTransferFunction() noexcept
- : m_a(1.0f), m_b(0.0f), m_c(1.0f), m_d(0.0f), m_e(0.0f), m_f(0.0f), m_g(1.0f), m_flags(0)
+ : m_a(1.0f), m_b(0.0f), m_c(1.0f), m_d(0.0f), m_e(0.0f), m_f(0.0f), m_g(1.0f)
+ , m_flags(Hints(Hint::Calculated) | Hint::IsGamma | Hint::IsIdentity)
{ }
+
QColorTransferFunction(float a, float b, float c, float d, float e, float f, float g) noexcept
- : m_a(a), m_b(b), m_c(c), m_d(d), m_e(e), m_f(f), m_g(g), m_flags(0)
+ : m_a(a), m_b(b), m_c(c), m_d(d), m_e(e), m_f(f), m_g(g), m_flags()
{ }
bool isGamma() const
{
updateHints();
- return m_flags & quint32(Hints::IsGamma);
+ return m_flags & Hint::IsGamma;
}
- bool isLinear() const
+ bool isIdentity() const
{
updateHints();
- return m_flags & quint32(Hints::IsLinear);
+ return m_flags & Hint::IsIdentity;
}
bool isSRgb() const
{
updateHints();
- return m_flags & quint32(Hints::IsSRgb);
+ return m_flags & Hint::IsSRgb;
}
float apply(float x) const
{
if (x < m_d)
return m_c * x + m_f;
+ float t = std::pow(m_a * x + m_b, m_g);
+ if (std::isfinite(t))
+ return t + m_e;
+ if (t > 0.f)
+ return 1.f;
else
- return std::pow(m_a * x + m_b, m_g) + m_e;
+ return 0.f;
}
QColorTransferFunction inverted() const
@@ -98,7 +70,7 @@ public:
d = m_c * m_d + m_f;
- if (!qFuzzyIsNull(m_c)) {
+ if (std::isnormal(m_c)) {
c = 1.0f / m_c;
f = -m_f / m_c;
} else {
@@ -106,8 +78,12 @@ public:
f = 0.0f;
}
- if (!qFuzzyIsNull(m_a) && !qFuzzyIsNull(m_g)) {
+ bool valid_abeg = std::isnormal(m_a) && std::isnormal(m_g);
+ if (valid_abeg)
a = std::pow(1.0f / m_a, m_g);
+ if (valid_abeg && !std::isfinite(a))
+ valid_abeg = false;
+ if (valid_abeg) {
b = -a * m_e;
e = -m_b / m_a;
g = 1.0f / m_g;
@@ -124,15 +100,19 @@ public:
// A few predefined curves:
static QColorTransferFunction fromGamma(float gamma)
{
- return QColorTransferFunction(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, gamma);
+ return QColorTransferFunction(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, gamma,
+ Hints(Hint::Calculated) | Hint::IsGamma |
+ (paramCompare(gamma, 1.0f) ? Hint::IsIdentity : Hint::NoHint));
}
static QColorTransferFunction fromSRgb()
{
- return QColorTransferFunction(1.0f / 1.055f, 0.055f / 1.055f, 1.0f / 12.92f, 0.04045f, 0.0f, 0.0f, 2.4f);
+ return QColorTransferFunction(1.0f / 1.055f, 0.055f / 1.055f, 1.0f / 12.92f, 0.04045f, 0.0f, 0.0f, 2.4f,
+ Hints(Hint::Calculated) | Hint::IsSRgb);
}
static QColorTransferFunction fromProPhotoRgb()
{
- return QColorTransferFunction(1.0f, 0.0f, 1.0f / 16.0f, 16.0f / 512.0f, 0.0f, 0.0f, 1.8f);
+ return QColorTransferFunction(1.0f, 0.0f, 1.0f / 16.0f, 16.0f / 512.0f, 0.0f, 0.0f, 1.8f,
+ Hints(Hint::Calculated));
}
bool matches(const QColorTransferFunction &o) const
{
@@ -152,7 +132,20 @@ public:
float m_f;
float m_g;
+ enum class Hint : quint32 {
+ NoHint = 0,
+ Calculated = 1,
+ IsGamma = 2,
+ IsIdentity = 4,
+ IsSRgb = 8
+ };
+
+ Q_DECLARE_FLAGS(Hints, Hint);
+
private:
+ QColorTransferFunction(float a, float b, float c, float d, float e, float f, float g, Hints flags) noexcept
+ : m_a(a), m_b(b), m_c(c), m_d(d), m_e(e), m_f(f), m_g(g), m_flags(flags)
+ { }
static inline bool paramCompare(float p1, float p2)
{
// Much fuzzier than fuzzy compare.
@@ -163,7 +156,7 @@ private:
void updateHints() const
{
- if (m_flags & quint32(Hints::Calculated))
+ if (m_flags & Hint::Calculated)
return;
// We do not consider the case with m_d = 1.0f linear or simple,
// since it wouldn't be linear for applyExtended().
@@ -171,24 +164,21 @@ private:
&& paramCompare(m_d, 0.0f)
&& paramCompare(m_e, 0.0f);
if (simple) {
- m_flags |= quint32(Hints::IsGamma);
+ m_flags |= Hint::IsGamma;
if (qFuzzyCompare(m_g, 1.0f))
- m_flags |= quint32(Hints::IsLinear);
+ m_flags |= Hint::IsIdentity;
} else {
if (*this == fromSRgb())
- m_flags |= quint32(Hints::IsSRgb);
+ m_flags |= Hint::IsSRgb;
}
- m_flags |= quint32(Hints::Calculated);
+ m_flags |= Hint::Calculated;
}
- enum class Hints : quint32 {
- Calculated = 1,
- IsGamma = 2,
- IsLinear = 4,
- IsSRgb = 8
- };
- mutable quint32 m_flags;
+
+ mutable Hints m_flags;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QColorTransferFunction::Hints);
+
inline bool operator==(const QColorTransferFunction &f1, const QColorTransferFunction &f2)
{
return f1.matches(f2);
diff --git a/src/gui/painting/qcolortransfertable_p.h b/src/gui/painting/qcolortransfertable_p.h
index bbc9f08dcc..51c9cff6d6 100644
--- a/src/gui/painting/qcolortransfertable_p.h
+++ b/src/gui/painting/qcolortransfertable_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLORTRANSFERTABLE_P_H
#define QCOLORTRANSFERTABLE_P_H
@@ -65,25 +29,38 @@ QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QColorTransferTable
{
public:
- QColorTransferTable() noexcept
- : m_tableSize(0)
- { }
- QColorTransferTable(uint32_t size, const QList<uint8_t> &table) noexcept
- : m_tableSize(size), m_table8(table)
+ enum Type : uint8_t {
+ TwoWay = 0,
+ OneWay,
+ };
+ QColorTransferTable() noexcept = default;
+ QColorTransferTable(uint32_t size, const QList<uint8_t> &table, Type type = TwoWay) noexcept
+ : m_type(type), m_tableSize(size), m_table8(table)
{
- Q_ASSERT(qsizetype(size) <= table.count());
+ Q_ASSERT(qsizetype(size) <= table.size());
}
- QColorTransferTable(uint32_t size, const QList<uint16_t> &table) noexcept
- : m_tableSize(size), m_table16(table)
+ QColorTransferTable(uint32_t size, const QList<uint16_t> &table, Type type = TwoWay) noexcept
+ : m_type(type), m_tableSize(size), m_table16(table)
{
- Q_ASSERT(qsizetype(size) <= table.count());
+ Q_ASSERT(qsizetype(size) <= table.size());
}
- bool isEmpty() const
+ bool isEmpty() const noexcept
{
return m_tableSize == 0;
}
+ bool isIdentity() const
+ {
+ if (isEmpty())
+ return true;
+ if (m_tableSize != 2)
+ return false;
+ if (!m_table8.isEmpty())
+ return m_table8[0] == 0 && m_table8[1] == 255;
+ return m_table16[0] == 0 && m_table16[1] == 65535;
+ }
+
bool checkValidity() const
{
if (isEmpty())
@@ -94,7 +71,11 @@ public:
// At least 2 elements
if (m_tableSize < 2)
return false;
- // The table must describe an injective curve:
+ return (m_type == OneWay) || checkInvertibility();
+ }
+ bool checkInvertibility() const
+ {
+ // The two-way tables must describe an injective curve:
if (!m_table8.isEmpty()) {
uint8_t val = 0;
for (uint i = 0; i < m_tableSize; ++i) {
@@ -116,15 +97,17 @@ public:
float apply(float x) const
{
+ if (isEmpty())
+ return x;
x = std::clamp(x, 0.0f, 1.0f);
x *= m_tableSize - 1;
const uint32_t lo = static_cast<uint32_t>(std::floor(x));
const uint32_t hi = std::min(lo + 1, m_tableSize - 1);
const float frac = x - lo;
if (!m_table16.isEmpty())
- return (m_table16[lo] * (1.0f - frac) + m_table16[hi] * frac) * (1.0f/65535.0f);
+ return (m_table16[lo] + (m_table16[hi] - m_table16[lo]) * frac) * (1.0f/65535.0f);
if (!m_table8.isEmpty())
- return (m_table8[lo] * (1.0f - frac) + m_table8[hi] * frac) * (1.0f/255.0f);
+ return (m_table8[lo] + (m_table8[hi] - m_table8[lo]) * frac) * (1.0f/255.0f);
return x;
}
@@ -132,6 +115,7 @@ public:
float applyInverse(float x, float resultLargerThan = 0.0f) const
{
Q_ASSERT(resultLargerThan >= 0.0f && resultLargerThan <= 1.0f);
+ Q_ASSERT(m_type == TwoWay);
if (x <= 0.0f)
return 0.0f;
if (x >= 1.0f)
@@ -141,6 +125,8 @@ public:
uint32_t i = static_cast<uint32_t>(std::floor(resultLargerThan * (m_tableSize - 1)));
auto it = std::lower_bound(m_table16.cbegin() + i, m_table16.cend(), v);
i = it - m_table16.cbegin();
+ if (i == 0)
+ return 0.0f;
if (i >= m_tableSize - 1)
return 1.0f;
const float y1 = m_table16[i - 1];
@@ -148,13 +134,14 @@ public:
Q_ASSERT(v >= y1 && v <= y2);
const float fr = (v - y1) / (y2 - y1);
return (i + fr) * (1.0f / (m_tableSize - 1));
-
}
if (!m_table8.isEmpty()) {
const float v = x * 255.0f;
uint32_t i = static_cast<uint32_t>(std::floor(resultLargerThan * (m_tableSize - 1)));
auto it = std::lower_bound(m_table8.cbegin() + i, m_table8.cend(), v);
i = it - m_table8.cbegin();
+ if (i == 0)
+ return 0.0f;
if (i >= m_tableSize - 1)
return 1.0f;
const float y1 = m_table8[i - 1];
@@ -169,6 +156,10 @@ public:
bool asColorTransferFunction(QColorTransferFunction *transferFn)
{
Q_ASSERT(transferFn);
+ if (isEmpty()) {
+ *transferFn = QColorTransferFunction();
+ return true;
+ }
if (m_tableSize < 2)
return false;
if (!m_table8.isEmpty() && (m_table8[0] != 0 || m_table8[m_tableSize - 1] != 255))
@@ -218,7 +209,8 @@ public:
friend inline bool operator!=(const QColorTransferTable &t1, const QColorTransferTable &t2);
friend inline bool operator==(const QColorTransferTable &t1, const QColorTransferTable &t2);
- uint32_t m_tableSize;
+ Type m_type = TwoWay;
+ uint32_t m_tableSize = 0;
QList<uint8_t> m_table8;
QList<uint16_t> m_table16;
};
@@ -227,6 +219,8 @@ inline bool operator!=(const QColorTransferTable &t1, const QColorTransferTable
{
if (t1.m_tableSize != t2.m_tableSize)
return true;
+ if (t1.m_type != t2.m_type)
+ return true;
if (t1.m_table8.isEmpty() != t2.m_table8.isEmpty())
return true;
if (t1.m_table16.isEmpty() != t2.m_table16.isEmpty())
diff --git a/src/gui/painting/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp
index fa7cb0e6b4..aac07bdc09 100644
--- a/src/gui/painting/qcolortransform.cpp
+++ b/src/gui/painting/qcolortransform.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcolortransform.h"
#include "qcolortransform_p.h"
+#include "qcmyk_p.h"
+#include "qcolorclut_p.h"
#include "qcolormatrix_p.h"
#include "qcolorspace_p.h"
#include "qcolortrc_p.h"
@@ -49,6 +14,7 @@
#include <QtCore/qatomic.h>
#include <QtCore/qmath.h>
#include <QtGui/qcolor.h>
+#include <QtGui/qimage.h>
#include <QtGui/qtransform.h>
#include <QtCore/private/qsimd_p.h>
@@ -141,6 +107,70 @@ QColorTransform::~QColorTransform() = default;
QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QColorTransformPrivate)
/*!
+ \since 6.4
+ Returns true if the color transform is the identity transform.
+*/
+bool QColorTransform::isIdentity() const noexcept
+{
+ return !d || d->isIdentity();
+}
+
+/*!
+ \fn bool QColorTransform::operator==(const QColorTransform &ct1, const QColorTransform &ct2)
+ \since 6.4
+ Returns true if \a ct1 defines the same color transformation as \a ct2.
+*/
+
+/*!
+ \fn bool QColorTransform::operator!=(const QColorTransform &ct1, const QColorTransform &ct2)
+ \since 6.4
+ Returns true if \a ct1 does not define the same transformation as \a ct2.
+*/
+
+/*! \internal
+*/
+bool QColorTransform::compare(const QColorTransform &other) const
+{
+ if (d == other.d)
+ return true;
+ if (bool(d) != bool(other.d))
+ return d ? d->isIdentity() : other.d->isIdentity();
+ if (d->colorMatrix != other.d->colorMatrix)
+ return false;
+ if (bool(d->colorSpaceIn) != bool(other.d->colorSpaceIn))
+ return false;
+ if (bool(d->colorSpaceOut) != bool(other.d->colorSpaceOut))
+ return false;
+ if (d->colorSpaceIn) {
+ if (d->colorSpaceIn->transformModel != other.d->colorSpaceIn->transformModel)
+ return false;
+ if (d->colorSpaceIn->isThreeComponentMatrix()) {
+ for (int i = 0; i < 3; ++i) {
+ if (d->colorSpaceIn && d->colorSpaceIn->trc[i] != other.d->colorSpaceIn->trc[i])
+ return false;
+ }
+ } else {
+ if (!d->colorSpaceIn->equals(other.d->colorSpaceIn.constData()))
+ return false;
+ }
+ }
+ if (d->colorSpaceOut) {
+ if (d->colorSpaceOut->transformModel != other.d->colorSpaceOut->transformModel)
+ return false;
+ if (d->colorSpaceOut->isThreeComponentMatrix()) {
+ for (int i = 0; i < 3; ++i) {
+ if (d->colorSpaceOut && d->colorSpaceOut->trc[i] != other.d->colorSpaceOut->trc[i])
+ return false;
+ }
+ } else {
+ if (!d->colorSpaceOut->equals(other.d->colorSpaceOut.constData()))
+ return false;
+ }
+ }
+ return true;
+}
+
+/*!
Applies the color transformation on the QRgb value \a argb.
The input should be opaque or unpremultiplied.
@@ -151,23 +181,7 @@ QRgb QColorTransform::map(QRgb argb) const
return argb;
constexpr float f = 1.0f / 255.0f;
QColorVector c = { qRed(argb) * f, qGreen(argb) * f, qBlue(argb) * f };
- c.x = d->colorSpaceIn->trc[0].apply(c.x);
- c.y = d->colorSpaceIn->trc[1].apply(c.y);
- c.z = d->colorSpaceIn->trc[2].apply(c.z);
- c = d->colorMatrix.map(c);
- c.x = std::max(0.0f, std::min(1.0f, c.x));
- c.y = std::max(0.0f, std::min(1.0f, c.y));
- c.z = std::max(0.0f, std::min(1.0f, c.z));
- if (d->colorSpaceOut->lut.generated.loadAcquire()) {
- c.x = d->colorSpaceOut->lut[0]->fromLinear(c.x);
- c.y = d->colorSpaceOut->lut[1]->fromLinear(c.y);
- c.z = d->colorSpaceOut->lut[2]->fromLinear(c.z);
- } else {
- c.x = d->colorSpaceOut->trc[0].applyInverse(c.x);
- c.y = d->colorSpaceOut->trc[1].applyInverse(c.y);
- c.z = d->colorSpaceOut->trc[2].applyInverse(c.z);
- }
-
+ c = d->map(c);
return qRgba(c.x * 255 + 0.5f, c.y * 255 + 0.5f, c.z * 255 + 0.5f, qAlpha(argb));
}
@@ -182,24 +196,44 @@ QRgba64 QColorTransform::map(QRgba64 rgba64) const
return rgba64;
constexpr float f = 1.0f / 65535.0f;
QColorVector c = { rgba64.red() * f, rgba64.green() * f, rgba64.blue() * f };
- c.x = d->colorSpaceIn->trc[0].apply(c.x);
- c.y = d->colorSpaceIn->trc[1].apply(c.y);
- c.z = d->colorSpaceIn->trc[2].apply(c.z);
- c = d->colorMatrix.map(c);
- c.x = std::max(0.0f, std::min(1.0f, c.x));
- c.y = std::max(0.0f, std::min(1.0f, c.y));
- c.z = std::max(0.0f, std::min(1.0f, c.z));
- if (d->colorSpaceOut->lut.generated.loadAcquire()) {
- c.x = d->colorSpaceOut->lut[0]->fromLinear(c.x);
- c.y = d->colorSpaceOut->lut[1]->fromLinear(c.y);
- c.z = d->colorSpaceOut->lut[2]->fromLinear(c.z);
- } else {
- c.x = d->colorSpaceOut->trc[0].applyInverse(c.x);
- c.y = d->colorSpaceOut->trc[1].applyInverse(c.y);
- c.z = d->colorSpaceOut->trc[2].applyInverse(c.z);
- }
+ c = d->map(c);
+ return QRgba64::fromRgba64(c.x * 65535.f + 0.5f, c.y * 65535.f + 0.5f, c.z * 65535.f + 0.5f, rgba64.alpha());
+}
+
+/*!
+ Applies the color transformation on the QRgbaFloat16 value \a rgbafp16.
+
+ The input should be opaque or unpremultiplied.
+ \since 6.4
+*/
+QRgbaFloat16 QColorTransform::map(QRgbaFloat16 rgbafp16) const
+{
+ if (!d)
+ return rgbafp16;
+ QColorVector c(rgbafp16.r, rgbafp16.g, rgbafp16.b);
+ c = d->mapExtended(c);
+ rgbafp16.r = qfloat16(c.x);
+ rgbafp16.g = qfloat16(c.y);
+ rgbafp16.b = qfloat16(c.z);
+ return rgbafp16;
+}
- return QRgba64::fromRgba64(c.x * 65535, c.y * 65535, c.z * 65535, rgba64.alpha());
+/*!
+ Applies the color transformation on the QRgbaFloat32 value \a rgbafp32.
+
+ The input should be opaque or unpremultiplied.
+ \since 6.4
+*/
+QRgbaFloat32 QColorTransform::map(QRgbaFloat32 rgbafp32) const
+{
+ if (!d)
+ return rgbafp32;
+ QColorVector c(rgbafp32.r, rgbafp32.g, rgbafp32.b);
+ c = d->mapExtended(c);
+ rgbafp32.r = c.x;
+ rgbafp32.g = c.y;
+ rgbafp32.b = c.z;
+ return rgbafp32;
}
/*!
@@ -211,43 +245,42 @@ QColor QColorTransform::map(const QColor &color) const
if (!d)
return color;
QColor clr = color;
- if (color.spec() != QColor::ExtendedRgb || color.spec() != QColor::Rgb)
- clr = clr.toRgb();
-
- QColorVector c = { (float)clr.redF(), (float)clr.greenF(), (float)clr.blueF() };
- if (clr.spec() == QColor::ExtendedRgb) {
- c.x = d->colorSpaceIn->trc[0].applyExtended(c.x);
- c.y = d->colorSpaceIn->trc[1].applyExtended(c.y);
- c.z = d->colorSpaceIn->trc[2].applyExtended(c.z);
- } else {
- c.x = d->colorSpaceIn->trc[0].apply(c.x);
- c.y = d->colorSpaceIn->trc[1].apply(c.y);
- c.z = d->colorSpaceIn->trc[2].apply(c.z);
- }
- c = d->colorMatrix.map(c);
- bool inGamut = c.x >= 0.0f && c.x <= 1.0f && c.y >= 0.0f && c.y <= 1.0f && c.z >= 0.0f && c.z <= 1.0f;
- if (inGamut) {
- if (d->colorSpaceOut->lut.generated.loadAcquire()) {
- c.x = d->colorSpaceOut->lut[0]->fromLinear(c.x);
- c.y = d->colorSpaceOut->lut[1]->fromLinear(c.y);
- c.z = d->colorSpaceOut->lut[2]->fromLinear(c.z);
- } else {
- c.x = d->colorSpaceOut->trc[0].applyInverse(c.x);
- c.y = d->colorSpaceOut->trc[1].applyInverse(c.y);
- c.z = d->colorSpaceOut->trc[2].applyInverse(c.z);
- }
- } else {
- c.x = d->colorSpaceOut->trc[0].applyInverseExtended(c.x);
- c.y = d->colorSpaceOut->trc[1].applyInverseExtended(c.y);
- c.z = d->colorSpaceOut->trc[2].applyInverseExtended(c.z);
+ if (d->colorSpaceIn->colorModel == QColorSpace::ColorModel::Rgb) {
+ if (color.spec() != QColor::ExtendedRgb && color.spec() != QColor::Rgb)
+ clr = clr.toRgb();
+ } else if (d->colorSpaceIn->colorModel == QColorSpace::ColorModel::Cmyk) {
+ if (color.spec() != QColor::Cmyk)
+ clr = clr.toCmyk();
}
+
+ QColorVector c =
+ (clr.spec() == QColor::Cmyk)
+ ? QColorVector(clr.cyanF(), clr.magentaF(), clr.yellowF(), clr.blackF())
+ : QColorVector(clr.redF(), clr.greenF(), clr.blueF());
+
+ c = d->mapExtended(c);
+
QColor out;
- out.setRgbF(c.x, c.y, c.z, color.alphaF());
+ if (d->colorSpaceOut->colorModel == QColorSpace::ColorModel::Cmyk) {
+ c.x = std::clamp(c.x, 0.f, 1.f);
+ c.y = std::clamp(c.y, 0.f, 1.f);
+ c.z = std::clamp(c.z, 0.f, 1.f);
+ c.w = std::clamp(c.w, 0.f, 1.f);
+ out.setCmykF(c.x, c.y, c.z, c.w, color.alphaF());
+ } else {
+ out.setRgbF(c.x, c.y, c.z, color.alphaF());
+ }
return out;
}
// Optimized sub-routines for fast block based conversion:
+enum ApplyMatrixForm {
+ DoNotClamp = 0,
+ DoClamp = 1
+};
+
+template<ApplyMatrixForm doClamp = DoClamp>
static void applyMatrix(QColorVector *buffer, const qsizetype len, const QColorMatrix &colorMatrix)
{
#if defined(__SSE2__)
@@ -267,8 +300,10 @@ static void applyMatrix(QColorVector *buffer, const qsizetype len, const QColorM
cx = _mm_add_ps(cx, cy);
cx = _mm_add_ps(cx, cz);
// Clamp:
- cx = _mm_min_ps(cx, maxV);
- cx = _mm_max_ps(cx, minV);
+ if (doClamp) {
+ cx = _mm_min_ps(cx, maxV);
+ cx = _mm_max_ps(cx, minV);
+ }
_mm_storeu_ps(&buffer[j].x, cx);
}
#elif defined(__ARM_NEON__)
@@ -285,16 +320,55 @@ static void applyMatrix(QColorVector *buffer, const qsizetype len, const QColorM
cx = vaddq_f32(cx, cy);
cx = vaddq_f32(cx, cz);
// Clamp:
- cx = vminq_f32(cx, maxV);
- cx = vmaxq_f32(cx, minV);
+ if (doClamp) {
+ cx = vminq_f32(cx, maxV);
+ cx = vmaxq_f32(cx, minV);
+ }
vst1q_f32(&buffer[j].x, cx);
}
#else
- for (int j = 0; j < len; ++j) {
+ for (qsizetype j = 0; j < len; ++j) {
const QColorVector cv = colorMatrix.map(buffer[j]);
- buffer[j].x = std::max(0.0f, std::min(1.0f, cv.x));
- buffer[j].y = std::max(0.0f, std::min(1.0f, cv.y));
- buffer[j].z = std::max(0.0f, std::min(1.0f, cv.z));
+ if (doClamp) {
+ buffer[j].x = std::clamp(cv.x, 0.f, 1.f);
+ buffer[j].y = std::clamp(cv.y, 0.f, 1.f);
+ buffer[j].z = std::clamp(cv.z, 0.f, 1.f);
+ } else {
+ buffer[j] = cv;
+ }
+ }
+#endif
+}
+
+template<ApplyMatrixForm doClamp = DoClamp>
+static void clampIfNeeded(QColorVector *buffer, const qsizetype len)
+{
+ if constexpr (doClamp != DoClamp)
+ return;
+#if defined(__SSE2__)
+ const __m128 minV = _mm_set1_ps(0.0f);
+ const __m128 maxV = _mm_set1_ps(1.0f);
+ for (qsizetype j = 0; j < len; ++j) {
+ __m128 c = _mm_loadu_ps(&buffer[j].x);
+ c = _mm_min_ps(c, maxV);
+ c = _mm_max_ps(c, minV);
+ _mm_storeu_ps(&buffer[j].x, c);
+ }
+#elif defined(__ARM_NEON__)
+ const float32x4_t minV = vdupq_n_f32(0.0f);
+ const float32x4_t maxV = vdupq_n_f32(1.0f);
+ for (qsizetype j = 0; j < len; ++j) {
+ float32x4_t c = vld1q_f32(&buffer[j].x);
+ c = vminq_f32(c, maxV);
+ c = vmaxq_f32(c, minV);
+ vst1q_f32(&buffer[j].x, c);
+ }
+#else
+ for (qsizetype j = 0; j < len; ++j) {
+ const QColorVector cv = buffer[j];
+ buffer[j].x = std::clamp(cv.x, 0.f, 1.f);
+ buffer[j].y = std::clamp(cv.y, 0.f, 1.f);
+ buffer[j].z = std::clamp(cv.z, 0.f, 1.f);
}
#endif
}
@@ -315,9 +389,29 @@ inline int getAlpha<QRgb>(const QRgb &p)
template<>
inline int getAlpha<QRgba64>(const QRgba64 &p)
{ return p.alpha(); }
+
#endif
template<typename T>
+static float getAlphaF(const T &);
+template<> float getAlphaF(const QRgb &r)
+{
+ return qAlpha(r) * (1.f / 255.f);
+}
+template<> float getAlphaF(const QCmyk32 &)
+{
+ return 1.f;
+}
+template<> float getAlphaF(const QRgba64 &r)
+{
+ return r.alpha() * (1.f / 65535.f);
+}
+template<> float getAlphaF(const QRgbaFloat32 &r)
+{
+ return r.a;
+}
+
+template<typename T>
static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr);
template<typename T>
static void loadUnpremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr);
@@ -353,7 +447,7 @@ inline void loadP<QRgba64>(const QRgba64 &p, __m128i &v)
template<typename T>
static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
{
- const __m128 v4080 = _mm_set1_ps(4080.f);
+ const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
constexpr bool isARGB = isArgb<T>();
for (qsizetype i = 0; i < len; ++i) {
@@ -372,7 +466,7 @@ static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetyp
vf = _mm_andnot_ps(vAlphaMask, vf);
// LUT
- v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
+ v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
const int ridx = isARGB ? _mm_extract_epi16(v, 4) : _mm_extract_epi16(v, 0);
const int gidx = _mm_extract_epi16(v, 2);
const int bidx = isARGB ? _mm_extract_epi16(v, 0) : _mm_extract_epi16(v, 4);
@@ -385,7 +479,51 @@ static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetyp
}
}
-// Load to [0-4080] in 4x32 SIMD
+template<>
+void loadPremultiplied<QRgbaFloat32>(QColorVector *buffer, const QRgbaFloat32 *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
+ const __m128 viFF00 = _mm_set1_ps(1.0f / (255 * 256));
+ const __m128 vZero = _mm_set1_ps(0.0f);
+ const __m128 vOne = _mm_set1_ps(1.0f);
+ for (qsizetype i = 0; i < len; ++i) {
+ __m128 vf = _mm_loadu_ps(&src[i].r);
+ // Approximate 1/a:
+ __m128 va = _mm_shuffle_ps(vf, vf, _MM_SHUFFLE(3, 3, 3, 3));
+ __m128 via = _mm_rcp_ps(va);
+ via = _mm_sub_ps(_mm_add_ps(via, via), _mm_mul_ps(via, _mm_mul_ps(via, va)));
+ // v * (1/a)
+ vf = _mm_mul_ps(vf, via);
+
+ // Handle zero alpha
+ __m128 vAlphaMask = _mm_cmpeq_ps(va, vZero);
+ vf = _mm_andnot_ps(vAlphaMask, vf);
+
+ // LUT
+ const __m128 under = _mm_cmplt_ps(vf, vZero);
+ const __m128 over = _mm_cmpgt_ps(vf, vOne);
+ if (_mm_movemask_ps(_mm_or_ps(under, over)) == 0) {
+ // Within gamut
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
+ const int ridx = _mm_extract_epi16(v, 0);
+ const int gidx = _mm_extract_epi16(v, 2);
+ const int bidx = _mm_extract_epi16(v, 4);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[0]->m_toLinear[ridx], 0);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[1]->m_toLinear[gidx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[2]->m_toLinear[bidx], 4);
+ vf = _mm_mul_ps(_mm_cvtepi32_ps(v), viFF00);
+ _mm_storeu_ps(&buffer[i].x, vf);
+ } else {
+ // Outside 0.0->1.0 gamut
+ _mm_storeu_ps(&buffer[i].x, vf);
+ buffer[i].x = d_ptr->colorSpaceIn->trc[0].applyExtended(buffer[i].x);
+ buffer[i].y = d_ptr->colorSpaceIn->trc[1].applyExtended(buffer[i].y);
+ buffer[i].z = d_ptr->colorSpaceIn->trc[2].applyExtended(buffer[i].z);
+ }
+ }
+}
+
+// Load to [0->TrcResolution] in 4x32 SIMD
template<typename T>
static inline void loadPU(const T &p, __m128i &v);
@@ -399,7 +537,7 @@ inline void loadPU<QRgb>(const QRgb &p, __m128i &v)
v = _mm_unpacklo_epi8(v, _mm_setzero_si128());
v = _mm_unpacklo_epi16(v, _mm_setzero_si128());
#endif
- v = _mm_slli_epi32(v, 4);
+ v = _mm_slli_epi32(v, QColorTrcLut::ShiftUp);
}
template<>
@@ -412,7 +550,7 @@ inline void loadPU<QRgba64>(const QRgba64 &p, __m128i &v)
#else
v = _mm_unpacklo_epi16(v, _mm_setzero_si128());
#endif
- v = _mm_srli_epi32(v, 4);
+ v = _mm_srli_epi32(v, QColorTrcLut::ShiftDown);
}
template<typename T>
@@ -434,6 +572,37 @@ void loadUnpremultiplied(QColorVector *buffer, const T *src, const qsizetype len
}
}
+template<>
+void loadUnpremultiplied<QRgbaFloat32>(QColorVector *buffer, const QRgbaFloat32 *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
+ const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
+ const __m128 vZero = _mm_set1_ps(0.0f);
+ const __m128 vOne = _mm_set1_ps(1.0f);
+ for (qsizetype i = 0; i < len; ++i) {
+ __m128 vf = _mm_loadu_ps(&src[i].r);
+ const __m128 under = _mm_cmplt_ps(vf, vZero);
+ const __m128 over = _mm_cmpgt_ps(vf, vOne);
+ if (_mm_movemask_ps(_mm_or_ps(under, over)) == 0) {
+ // Within gamut
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
+ const int ridx = _mm_extract_epi16(v, 0);
+ const int gidx = _mm_extract_epi16(v, 2);
+ const int bidx = _mm_extract_epi16(v, 4);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[0]->m_toLinear[ridx], 0);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[1]->m_toLinear[gidx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceIn->lut[2]->m_toLinear[bidx], 4);
+ vf = _mm_mul_ps(_mm_cvtepi32_ps(v), iFF00);
+ _mm_storeu_ps(&buffer[i].x, vf);
+ } else {
+ // Outside 0.0->1.0 gamut
+ buffer[i].x = d_ptr->colorSpaceIn->trc[0].applyExtended(src[i].r);
+ buffer[i].y = d_ptr->colorSpaceIn->trc[1].applyExtended(src[i].g);
+ buffer[i].z = d_ptr->colorSpaceIn->trc[2].applyExtended(src[i].b);
+ }
+ }
+}
+
#elif defined(__ARM_NEON__)
// Load to [0-alpha] in 4x32 SIMD
template<typename T>
@@ -477,7 +646,7 @@ static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetyp
vf = vreinterpretq_f32_u32(vbicq_u32(vreinterpretq_u32_f32(vf), vAlphaMask));
// LUT
- v = vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, 4080.f), vdupq_n_f32(0.5f)));
+ v = vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, float(QColorTrcLut::Resolution)), vdupq_n_f32(0.5f)));
const int ridx = isARGB ? vgetq_lane_u32(v, 2) : vgetq_lane_u32(v, 0);
const int gidx = vgetq_lane_u32(v, 1);
const int bidx = isARGB ? vgetq_lane_u32(v, 0) : vgetq_lane_u32(v, 2);
@@ -490,7 +659,7 @@ static void loadPremultiplied(QColorVector *buffer, const T *src, const qsizetyp
}
}
-// Load to [0-4080] in 4x32 SIMD
+// Load to [0->TrcResultion] in 4x32 SIMD
template<typename T>
static inline void loadPU(const T &p, uint32x4_t &v);
@@ -498,7 +667,7 @@ template<>
inline void loadPU<QRgb>(const QRgb &p, uint32x4_t &v)
{
v = vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vmov_n_u32(p)))));
- v = vshlq_n_u32(v, 4);
+ v = vshlq_n_u32(v, QColorTrcLut::ShiftUp);
}
template<>
@@ -507,7 +676,7 @@ inline void loadPU<QRgba64>(const QRgba64 &p, uint32x4_t &v)
uint16x4_t v16 = vreinterpret_u16_u64(vld1_u64(reinterpret_cast<const uint64_t *>(&p)));
v16 = vsub_u16(v16, vshr_n_u16(v16, 8));
v = vmovl_u16(v16);
- v = vshrq_n_u32(v, 4);
+ v = vshrq_n_u32(v, QColorTrcLut::ShiftDown);
}
template<typename T>
@@ -536,7 +705,7 @@ void loadPremultiplied<QRgb>(QColorVector *buffer, const QRgb *src, const qsizet
const uint p = src[i];
const int a = qAlpha(p);
if (a) {
- const float ia = 4080.0f / a;
+ const float ia = float(QColorTrcLut::Resolution) / a;
const int ridx = int(qRed(p) * ia + 0.5f);
const int gidx = int(qGreen(p) * ia + 0.5f);
const int bidx = int(qBlue(p) * ia + 0.5f);
@@ -556,7 +725,7 @@ void loadPremultiplied<QRgba64>(QColorVector *buffer, const QRgba64 *src, const
const QRgba64 &p = src[i];
const int a = p.alpha();
if (a) {
- const float ia = 4080.0f / a;
+ const float ia = float(QColorTrcLut::Resolution) / a;
const int ridx = int(p.red() * ia + 0.5f);
const int gidx = int(p.green() * ia + 0.5f);
const int bidx = int(p.blue() * ia + 0.5f);
@@ -591,6 +760,35 @@ void loadUnpremultiplied<QRgba64>(QColorVector *buffer, const QRgba64 *src, cons
}
}
#endif
+#if !defined(__SSE2__)
+template<>
+void loadPremultiplied<QRgbaFloat32>(QColorVector *buffer, const QRgbaFloat32 *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const QRgbaFloat32 &p = src[i];
+ const float a = p.a;
+ if (a) {
+ const float ia = 1.0f / a;
+ buffer[i].x = d_ptr->colorSpaceIn->trc[0].applyExtended(p.r * ia);
+ buffer[i].y = d_ptr->colorSpaceIn->trc[1].applyExtended(p.g * ia);
+ buffer[i].z = d_ptr->colorSpaceIn->trc[2].applyExtended(p.b * ia);
+ } else {
+ buffer[i].x = buffer[i].y = buffer[i].z = 0.0f;
+ }
+ }
+}
+
+template<>
+void loadUnpremultiplied<QRgbaFloat32>(QColorVector *buffer, const QRgbaFloat32 *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const QRgbaFloat32 &p = src[i];
+ buffer[i].x = d_ptr->colorSpaceIn->trc[0].applyExtended(p.r);
+ buffer[i].y = d_ptr->colorSpaceIn->trc[1].applyExtended(p.g);
+ buffer[i].z = d_ptr->colorSpaceIn->trc[2].applyExtended(p.b);
+ }
+}
+#endif
#if defined(__SSE2__)
template<typename T>
@@ -617,17 +815,18 @@ inline void storeP<QRgba64>(QRgba64 &p, __m128i &v, int a)
#endif
}
-template<typename T>
-static void storePremultiplied(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
+template<typename D, typename S,
+ typename = std::enable_if_t<!std::is_same_v<D, QRgbaFloat32>, void>>
+static void storePremultiplied(D *dst, const S *src, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
- const __m128 v4080 = _mm_set1_ps(4080.f);
+ const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
- constexpr bool isARGB = isArgb<T>();
+ constexpr bool isARGB = isArgb<D>();
for (qsizetype i = 0; i < len; ++i) {
- const int a = getAlpha<T>(src[i]);
+ const int a = getAlpha<S>(src[i]);
__m128 vf = _mm_loadu_ps(&buffer[i].x);
- __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
__m128 va = _mm_mul_ps(_mm_set1_ps(a), iFF00);
const int ridx = _mm_extract_epi16(v, 0);
const int gidx = _mm_extract_epi16(v, 2);
@@ -638,7 +837,46 @@ static void storePremultiplied(T *dst, const T *src, const QColorVector *buffer,
vf = _mm_cvtepi32_ps(v);
vf = _mm_mul_ps(vf, va);
v = _mm_cvtps_epi32(vf);
- storeP<T>(dst[i], v, a);
+ storeP<D>(dst[i], v, a);
+ }
+}
+
+template<typename S>
+static void storePremultiplied(QRgbaFloat32 *dst, const S *src,
+ const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
+ const __m128 vZero = _mm_set1_ps(0.0f);
+ const __m128 vOne = _mm_set1_ps(1.0f);
+ const __m128 viFF00 = _mm_set1_ps(1.0f / (255 * 256));
+ for (qsizetype i = 0; i < len; ++i) {
+ const float a = getAlphaF<S>(src[i]);
+ __m128 va = _mm_set1_ps(a);
+ __m128 vf = _mm_loadu_ps(&buffer[i].x);
+ const __m128 under = _mm_cmplt_ps(vf, vZero);
+ const __m128 over = _mm_cmpgt_ps(vf, vOne);
+ if (_mm_movemask_ps(_mm_or_ps(under, over)) == 0) {
+ // Within gamut
+ va = _mm_mul_ps(va, viFF00);
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
+ const int ridx = _mm_extract_epi16(v, 0);
+ const int gidx = _mm_extract_epi16(v, 2);
+ const int bidx = _mm_extract_epi16(v, 4);
+ v = _mm_setzero_si128();
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], 0);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], 4);
+ vf = _mm_mul_ps(_mm_cvtepi32_ps(v), va);
+ _mm_store_ps(&dst[i].r, vf);
+ } else {
+ dst[i].r = d_ptr->colorSpaceOut->trc[0].applyInverseExtended(buffer[i].x);
+ dst[i].g = d_ptr->colorSpaceOut->trc[1].applyInverseExtended(buffer[i].y);
+ dst[i].b = d_ptr->colorSpaceOut->trc[2].applyInverseExtended(buffer[i].z);
+ vf = _mm_mul_ps(_mm_load_ps(&dst[i].r), va);
+ _mm_store_ps(&dst[i].r, vf);
+ }
+ dst[i].a = a;
}
}
@@ -660,16 +898,17 @@ inline void storePU<QRgba64>(QRgba64 &p, __m128i &v, int a)
_mm_storel_epi64((__m128i *)&p, v);
}
-template<typename T>
-static void storeUnpremultiplied(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
+template<typename D, typename S,
+ typename = std::enable_if_t<!std::is_same_v<D, QRgbaFloat32>, void>>
+static void storeUnpremultiplied(D *dst, const S *src, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
- const __m128 v4080 = _mm_set1_ps(4080.f);
- constexpr bool isARGB = isArgb<T>();
+ const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
+ constexpr bool isARGB = isArgb<D>();
for (qsizetype i = 0; i < len; ++i) {
- const int a = getAlpha<T>(src[i]);
+ const int a = getAlpha<S>(src[i]);
__m128 vf = _mm_loadu_ps(&buffer[i].x);
- __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
const int ridx = _mm_extract_epi16(v, 0);
const int gidx = _mm_extract_epi16(v, 2);
const int bidx = _mm_extract_epi16(v, 4);
@@ -677,20 +916,54 @@ static void storeUnpremultiplied(T *dst, const T *src, const QColorVector *buffe
v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], isARGB ? 2 : 0);
v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], 1);
v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], isARGB ? 0 : 2);
- storePU<T>(dst[i], v, a);
+ storePU<D>(dst[i], v, a);
+ }
+}
+
+template<typename S>
+void storeUnpremultiplied(QRgbaFloat32 *dst, const S *src,
+ const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
+ const __m128 vZero = _mm_set1_ps(0.0f);
+ const __m128 vOne = _mm_set1_ps(1.0f);
+ const __m128 viFF00 = _mm_set1_ps(1.0f / (255 * 256));
+ for (qsizetype i = 0; i < len; ++i) {
+ const float a = getAlphaF<S>(src[i]);
+ __m128 vf = _mm_loadu_ps(&buffer[i].x);
+ const __m128 under = _mm_cmplt_ps(vf, vZero);
+ const __m128 over = _mm_cmpgt_ps(vf, vOne);
+ if (_mm_movemask_ps(_mm_or_ps(under, over)) == 0) {
+ // Within gamut
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
+ const int ridx = _mm_extract_epi16(v, 0);
+ const int gidx = _mm_extract_epi16(v, 2);
+ const int bidx = _mm_extract_epi16(v, 4);
+ v = _mm_setzero_si128();
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], 0);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], 4);
+ vf = _mm_mul_ps(_mm_cvtepi32_ps(v), viFF00);
+ _mm_storeu_ps(&dst[i].r, vf);
+ } else {
+ dst[i].r = d_ptr->colorSpaceOut->trc[0].applyInverseExtended(buffer[i].x);
+ dst[i].g = d_ptr->colorSpaceOut->trc[1].applyInverseExtended(buffer[i].y);
+ dst[i].b = d_ptr->colorSpaceOut->trc[2].applyInverseExtended(buffer[i].z);
+ }
+ dst[i].a = a;
}
}
template<typename T>
-static void storeOpaque(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
+static void storeOpaque(T *dst, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
- Q_UNUSED(src);
- const __m128 v4080 = _mm_set1_ps(4080.f);
+ const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
constexpr bool isARGB = isArgb<T>();
for (qsizetype i = 0; i < len; ++i) {
__m128 vf = _mm_loadu_ps(&buffer[i].x);
- __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, v4080));
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
const int ridx = _mm_extract_epi16(v, 0);
const int gidx = _mm_extract_epi16(v, 2);
const int bidx = _mm_extract_epi16(v, 4);
@@ -701,6 +974,40 @@ static void storeOpaque(T *dst, const T *src, const QColorVector *buffer, const
storePU<T>(dst[i], v, isARGB ? 255 : 0xffff);
}
}
+
+template<>
+void storeOpaque(QRgbaFloat32 *dst, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
+ const __m128 vZero = _mm_set1_ps(0.0f);
+ const __m128 vOne = _mm_set1_ps(1.0f);
+ const __m128 viFF00 = _mm_set1_ps(1.0f / (255 * 256));
+ for (qsizetype i = 0; i < len; ++i) {
+ __m128 vf = _mm_loadu_ps(&buffer[i].x);
+ const __m128 under = _mm_cmplt_ps(vf, vZero);
+ const __m128 over = _mm_cmpgt_ps(vf, vOne);
+ if (_mm_movemask_ps(_mm_or_ps(under, over)) == 0) {
+ // Within gamut
+ __m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
+ const int ridx = _mm_extract_epi16(v, 0);
+ const int gidx = _mm_extract_epi16(v, 2);
+ const int bidx = _mm_extract_epi16(v, 4);
+ v = _mm_setzero_si128();
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], 0);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], 2);
+ v = _mm_insert_epi16(v, d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], 4);
+ vf = _mm_mul_ps(_mm_cvtepi32_ps(v), viFF00);
+ _mm_store_ps(&dst[i].r, vf);
+ } else {
+ dst[i].r = d_ptr->colorSpaceOut->trc[0].applyInverseExtended(buffer[i].x);
+ dst[i].g = d_ptr->colorSpaceOut->trc[1].applyInverseExtended(buffer[i].y);
+ dst[i].b = d_ptr->colorSpaceOut->trc[2].applyInverseExtended(buffer[i].z);
+ }
+ dst[i].a = 1.0f;
+ }
+}
+
#elif defined(__ARM_NEON__)
template<typename T>
static inline void storeP(T &p, const uint16x4_t &v);
@@ -715,16 +1022,17 @@ inline void storeP<QRgba64>(QRgba64 &p, const uint16x4_t &v)
vst1_u16((uint16_t *)&p, v);
}
-template<typename T>
-static void storePremultiplied(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
+template<typename D, typename S,
+ typename = std::enable_if_t<!std::is_same_v<D, QRgbaFloat32>, void>>
+static void storePremultiplied(D *dst, const S *src, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
const float iFF00 = 1.0f / (255 * 256);
- constexpr bool isARGB = isArgb<T>();
+ constexpr bool isARGB = isArgb<D>();
for (qsizetype i = 0; i < len; ++i) {
- const int a = getAlpha<T>(src[i]);
+ const int a = getAlpha<S>(src[i]);
float32x4_t vf = vld1q_f32(&buffer[i].x);
- uint32x4_t v = vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, 4080.f), vdupq_n_f32(0.5f)));
+ uint32x4_t v = vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, float(QColorTrcLut::Resolution)), vdupq_n_f32(0.5f)));
const int ridx = vgetq_lane_u32(v, 0);
const int gidx = vgetq_lane_u32(v, 1);
const int bidx = vgetq_lane_u32(v, 2);
@@ -737,7 +1045,7 @@ static void storePremultiplied(T *dst, const T *src, const QColorVector *buffer,
v = vcvtq_u32_f32(vf);
uint16x4_t v16 = vmovn_u32(v);
v16 = vset_lane_u16(a, v16, 3);
- storeP<T>(dst[i], v16);
+ storeP<D>(dst[i], v16);
}
}
@@ -759,34 +1067,34 @@ inline void storePU<QRgba64>(QRgba64 &p, uint16x4_t &v, int a)
vst1_u16((uint16_t *)&p, v);
}
-template<typename T>
-static void storeUnpremultiplied(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
+template<typename D, typename S,
+ typename = std::enable_if_t<!std::is_same_v<D, QRgbaFloat32>, void>>
+static void storeUnpremultiplied(D *dst, const S *src, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
- constexpr bool isARGB = isArgb<T>();
+ constexpr bool isARGB = isArgb<D>();
for (qsizetype i = 0; i < len; ++i) {
- const int a = getAlpha<T>(src[i]);
+ const int a = getAlpha<S>(src[i]);
float32x4_t vf = vld1q_f32(&buffer[i].x);
- uint16x4_t v = vmovn_u32(vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, 4080.f), vdupq_n_f32(0.5f))));
+ uint16x4_t v = vmovn_u32(vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, float(QColorTrcLut::Resolution)), vdupq_n_f32(0.5f))));
const int ridx = vget_lane_u16(v, 0);
const int gidx = vget_lane_u16(v, 1);
const int bidx = vget_lane_u16(v, 2);
v = vset_lane_u16(d_ptr->colorSpaceOut->lut[0]->m_fromLinear[ridx], v, isARGB ? 2 : 0);
v = vset_lane_u16(d_ptr->colorSpaceOut->lut[1]->m_fromLinear[gidx], v, 1);
v = vset_lane_u16(d_ptr->colorSpaceOut->lut[2]->m_fromLinear[bidx], v, isARGB ? 0 : 2);
- storePU<T>(dst[i], v, a);
+ storePU<D>(dst[i], v, a);
}
}
template<typename T>
-static void storeOpaque(T *dst, const T *src, const QColorVector *buffer, const qsizetype len,
+static void storeOpaque(T *dst, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
- Q_UNUSED(src);
constexpr bool isARGB = isArgb<T>();
for (qsizetype i = 0; i < len; ++i) {
float32x4_t vf = vld1q_f32(&buffer[i].x);
- uint16x4_t v = vmovn_u32(vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, 4080.f), vdupq_n_f32(0.5f))));
+ uint16x4_t v = vmovn_u32(vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, float(QColorTrcLut::Resolution)), vdupq_n_f32(0.5f))));
const int ridx = vget_lane_u16(v, 0);
const int gidx = vget_lane_u16(v, 1);
const int bidx = vget_lane_u16(v, 2);
@@ -803,9 +1111,9 @@ static void storePremultiplied(QRgb *dst, const QRgb *src, const QColorVector *b
for (qsizetype i = 0; i < len; ++i) {
const int a = qAlpha(src[i]);
const float fa = a / (255.0f * 256.0f);
- const float r = d_ptr->colorSpaceOut->lut[0]->m_fromLinear[int(buffer[i].x * 4080.0f + 0.5f)];
- const float g = d_ptr->colorSpaceOut->lut[1]->m_fromLinear[int(buffer[i].y * 4080.0f + 0.5f)];
- const float b = d_ptr->colorSpaceOut->lut[2]->m_fromLinear[int(buffer[i].z * 4080.0f + 0.5f)];
+ const float r = d_ptr->colorSpaceOut->lut[0]->m_fromLinear[int(buffer[i].x * float(QColorTrcLut::Resolution) + 0.5f)];
+ const float g = d_ptr->colorSpaceOut->lut[1]->m_fromLinear[int(buffer[i].y * float(QColorTrcLut::Resolution) + 0.5f)];
+ const float b = d_ptr->colorSpaceOut->lut[2]->m_fromLinear[int(buffer[i].z * float(QColorTrcLut::Resolution) + 0.5f)];
dst[i] = qRgba(r * fa + 0.5f, g * fa + 0.5f, b * fa + 0.5f, a);
}
}
@@ -821,10 +1129,9 @@ static void storeUnpremultiplied(QRgb *dst, const QRgb *src, const QColorVector
}
}
-static void storeOpaque(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+static void storeOpaque(QRgb *dst, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
- Q_UNUSED(src);
for (qsizetype i = 0; i < len; ++i) {
const int r = d_ptr->colorSpaceOut->lut[0]->u8FromLinearF32(buffer[i].x);
const int g = d_ptr->colorSpaceOut->lut[1]->u8FromLinearF32(buffer[i].y);
@@ -833,34 +1140,36 @@ static void storeOpaque(QRgb *dst, const QRgb *src, const QColorVector *buffer,
}
}
-static void storePremultiplied(QRgba64 *dst, const QRgba64 *src, const QColorVector *buffer, const qsizetype len,
+template<typename S>
+static void storePremultiplied(QRgba64 *dst, const S *src, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
for (qsizetype i = 0; i < len; ++i) {
- const int a = src[i].alpha();
+ const int a = getAlphaF(src[i]) * 65535.f;
const float fa = a / (255.0f * 256.0f);
- const float r = d_ptr->colorSpaceOut->lut[0]->m_fromLinear[int(buffer[i].x * 4080.0f + 0.5f)];
- const float g = d_ptr->colorSpaceOut->lut[1]->m_fromLinear[int(buffer[i].y * 4080.0f + 0.5f)];
- const float b = d_ptr->colorSpaceOut->lut[2]->m_fromLinear[int(buffer[i].z * 4080.0f + 0.5f)];
+ const float r = d_ptr->colorSpaceOut->lut[0]->m_fromLinear[int(buffer[i].x * float(QColorTrcLut::Resolution) + 0.5f)];
+ const float g = d_ptr->colorSpaceOut->lut[1]->m_fromLinear[int(buffer[i].y * float(QColorTrcLut::Resolution) + 0.5f)];
+ const float b = d_ptr->colorSpaceOut->lut[2]->m_fromLinear[int(buffer[i].z * float(QColorTrcLut::Resolution) + 0.5f)];
dst[i] = qRgba64(r * fa + 0.5f, g * fa + 0.5f, b * fa + 0.5f, a);
}
}
-static void storeUnpremultiplied(QRgba64 *dst, const QRgba64 *src, const QColorVector *buffer, const qsizetype len,
+template<typename S>
+static void storeUnpremultiplied(QRgba64 *dst, const S *src, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
for (qsizetype i = 0; i < len; ++i) {
+ const int a = getAlphaF(src[i]) * 65535.f;
const int r = d_ptr->colorSpaceOut->lut[0]->u16FromLinearF32(buffer[i].x);
const int g = d_ptr->colorSpaceOut->lut[1]->u16FromLinearF32(buffer[i].y);
const int b = d_ptr->colorSpaceOut->lut[2]->u16FromLinearF32(buffer[i].z);
- dst[i] = qRgba64(r, g, b, src[i].alpha());
+ dst[i] = qRgba64(r, g, b, a);
}
}
-static void storeOpaque(QRgba64 *dst, const QRgba64 *src, const QColorVector *buffer, const qsizetype len,
+static void storeOpaque(QRgba64 *dst, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
- Q_UNUSED(src);
for (qsizetype i = 0; i < len; ++i) {
const int r = d_ptr->colorSpaceOut->lut[0]->u16FromLinearF32(buffer[i].x);
const int g = d_ptr->colorSpaceOut->lut[1]->u16FromLinearF32(buffer[i].y);
@@ -869,21 +1178,73 @@ static void storeOpaque(QRgba64 *dst, const QRgba64 *src, const QColorVector *bu
}
}
#endif
+#if !defined(__SSE2__)
+template<typename S>
+static void storePremultiplied(QRgbaFloat32 *dst, const S *src, const QColorVector *buffer,
+ const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const float a = getAlphaF(src[i]);
+ dst[i].r = d_ptr->colorSpaceOut->trc[0].applyInverseExtended(buffer[i].x) * a;
+ dst[i].g = d_ptr->colorSpaceOut->trc[1].applyInverseExtended(buffer[i].y) * a;
+ dst[i].b = d_ptr->colorSpaceOut->trc[2].applyInverseExtended(buffer[i].z) * a;
+ dst[i].a = a;
+ }
+}
+
+template<typename S>
+static void storeUnpremultiplied(QRgbaFloat32 *dst, const S *src, const QColorVector *buffer,
+ const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const float a = getAlphaF(src[i]);
+ dst[i].r = d_ptr->colorSpaceOut->trc[0].applyInverseExtended(buffer[i].x);
+ dst[i].g = d_ptr->colorSpaceOut->trc[1].applyInverseExtended(buffer[i].y);
+ dst[i].b = d_ptr->colorSpaceOut->trc[2].applyInverseExtended(buffer[i].z);
+ dst[i].a = a;
+ }
+}
+
+static void storeOpaque(QRgbaFloat32 *dst, const QColorVector *buffer, const qsizetype len,
+ const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ dst[i].r = d_ptr->colorSpaceOut->trc[0].applyInverseExtended(buffer[i].x);
+ dst[i].g = d_ptr->colorSpaceOut->trc[1].applyInverseExtended(buffer[i].y);
+ dst[i].b = d_ptr->colorSpaceOut->trc[2].applyInverseExtended(buffer[i].z);
+ dst[i].a = 1.0f;
+ }
+}
+#endif
-static void storeGray(quint8 *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len,
+static void loadGray(QColorVector *buffer, const quint8 *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const float y = d_ptr->colorSpaceIn->lut[0]->u8ToLinearF32(src[i]);
+ buffer[i] = d_ptr->colorSpaceIn->whitePoint * y;
+ }
+}
+
+static void loadGray(QColorVector *buffer, const quint16 *src, const qsizetype len, const QColorTransformPrivate *d_ptr)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const float y = d_ptr->colorSpaceIn->lut[0]->u16ToLinearF32(src[i]);
+ buffer[i] = d_ptr->colorSpaceIn->whitePoint * y;
+ }
+}
+
+static void storeOpaque(quint8 *dst, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
- Q_UNUSED(src);
for (qsizetype i = 0; i < len; ++i)
- dst[i] = d_ptr->colorSpaceOut->lut[1]->u8FromLinearF32(buffer[i].y);
+ dst[i] = d_ptr->colorSpaceOut->lut[0]->u8FromLinearF32(buffer[i].y);
}
-static void storeGray(quint16 *dst, const QRgba64 *src, const QColorVector *buffer, const qsizetype len,
+static void storeOpaque(quint16 *dst, const QColorVector *buffer, const qsizetype len,
const QColorTransformPrivate *d_ptr)
{
- Q_UNUSED(src);
for (qsizetype i = 0; i < len; ++i)
- dst[i] = d_ptr->colorSpaceOut->lut[1]->u16FromLinearF32(buffer[i].y);
+ dst[i] = d_ptr->colorSpaceOut->lut[0]->u16FromLinearF32(buffer[i].y);
}
static constexpr qsizetype WorkBlockSize = 256;
@@ -897,19 +1258,493 @@ private:
alignas(T) char data[sizeof(T) * Count];
};
+void loadUnpremultipliedLUT(QColorVector *buffer, const QRgb *src, const qsizetype len)
+{
+ const float f = 1.0f / 255.f;
+ for (qsizetype i = 0; i < len; ++i) {
+ const uint p = src[i];
+ buffer[i].x = qRed(p) * f;
+ buffer[i].y = qGreen(p) * f;
+ buffer[i].z = qBlue(p) * f;
+ }
+}
+
+void loadUnpremultipliedLUT(QColorVector *buffer, const QCmyk32 *src, const qsizetype len)
+{
+ const float f = 1.0f / 255.f;
+ for (qsizetype i = 0; i < len; ++i) {
+ const QCmyk32 p = src[i];
+ buffer[i].x = (p.cyan() * f);
+ buffer[i].y = (p.magenta() * f);
+ buffer[i].z = (p.yellow() * f);
+ buffer[i].w = (p.black() * f);
+ }
+}
+
+void loadUnpremultipliedLUT(QColorVector *buffer, const QRgba64 *src, const qsizetype len)
+{
+ const float f = 1.0f / 65535.f;
+ for (qsizetype i = 0; i < len; ++i) {
+ buffer[i].x = src[i].red() * f;
+ buffer[i].y = src[i].green() * f;
+ buffer[i].z = src[i].blue() * f;
+ }
+}
+
+void loadUnpremultipliedLUT(QColorVector *buffer, const QRgbaFloat32 *src, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ buffer[i].x = src[i].r;
+ buffer[i].y = src[i].g;
+ buffer[i].z = src[i].b;
+ }
+}
+
+void loadPremultipliedLUT(QColorVector *buffer, const QRgb *src, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const uint p = src[i];
+ const float f = 1.0f / qAlpha(p);
+ buffer[i].x = (qRed(p) * f);
+ buffer[i].y = (qGreen(p) * f);
+ buffer[i].z = (qBlue(p) * f);
+ }
+}
+
+void loadPremultipliedLUT(QColorVector *, const QCmyk32 *, const qsizetype)
+{
+ Q_UNREACHABLE();
+}
+
+void loadPremultipliedLUT(QColorVector *buffer, const QRgba64 *src, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const float f = 1.0f / src[i].alpha();
+ buffer[i].x = (src[i].red() * f);
+ buffer[i].y = (src[i].green() * f);
+ buffer[i].z = (src[i].blue() * f);
+ }
+}
+
+void loadPremultipliedLUT(QColorVector *buffer, const QRgbaFloat32 *src, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const float f = 1.0f / src[i].a;
+ buffer[i].x = src[i].r * f;
+ buffer[i].y = src[i].g * f;
+ buffer[i].z = src[i].b * f;
+ }
+}
+template<typename T>
+static void storeUnpremultipliedLUT(QRgb *dst, const T *, const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = buffer[i].x * 255.f;
+ const int g = buffer[i].y * 255.f;
+ const int b = buffer[i].z * 255.f;
+ dst[i] = 0xff000000 | (r << 16) | (g << 8) | (b << 0);
+ }
+}
+
+template<>
+void storeUnpremultipliedLUT(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = buffer[i].x * 255.f;
+ const int g = buffer[i].y * 255.f;
+ const int b = buffer[i].z * 255.f;
+ dst[i] = (src[i] & 0xff000000) | (r << 16) | (g << 8) | (b << 0);
+ }
+}
+
+
+template<typename T>
+void storeUnpremultipliedLUT(QCmyk32 *dst, const T *, const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int c = buffer[i].x * 255.f;
+ const int m = buffer[i].y * 255.f;
+ const int y = buffer[i].z * 255.f;
+ const int k = buffer[i].w * 255.f;
+ dst[i] = QCmyk32(c, m, y, k);
+ }
+}
+
+template<typename T>
+static void storeUnpremultipliedLUT(QRgba64 *dst, const T *,
+ const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = buffer[i].x * 65535.f;
+ const int g = buffer[i].y * 65535.f;
+ const int b = buffer[i].z * 65535.f;
+ dst[i] = qRgba64(r, g, b, 65535);
+ }
+}
+
+template<>
+void storeUnpremultipliedLUT(QRgba64 *dst, const QRgb *src,
+ const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = qAlpha(src[i]) * 257;
+ const int r = buffer[i].x * 65535.f;
+ const int g = buffer[i].y * 65535.f;
+ const int b = buffer[i].z * 65535.f;
+ dst[i] = qRgba64(r, g, b, a);
+ }
+}
+
+template<>
+void storeUnpremultipliedLUT(QRgba64 *dst, const QRgba64 *src,
+ const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = buffer[i].x * 65535.f;
+ const int g = buffer[i].y * 65535.f;
+ const int b = buffer[i].z * 65535.f;
+ dst[i] = qRgba64(r, g, b, src[i].alpha());
+ }
+}
+
+template<typename T>
+static void storeUnpremultipliedLUT(QRgbaFloat32 *dst, const T *src,
+ const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const float r = buffer[i].x;
+ const float g = buffer[i].y;
+ const float b = buffer[i].z;
+ dst[i] = QRgbaFloat32{r, g, b, getAlphaF(src[i])};
+ }
+}
+
+template<typename T>
+static void storePremultipliedLUT(QRgb *, const T *, const QColorVector *, const qsizetype);
+
+template<>
+void storePremultipliedLUT(QRgb *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = qAlpha(src[i]);
+ const int r = buffer[i].x * a;
+ const int g = buffer[i].y * a;
+ const int b = buffer[i].z * a;
+ dst[i] = (src[i] & 0xff000000) | (r << 16) | (g << 8) | (b << 0);
+ }
+}
+
+template<>
+void storePremultipliedLUT(QRgb *dst, const QCmyk32 *, const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = buffer[i].x * 255.f;
+ const int g = buffer[i].y * 255.f;
+ const int b = buffer[i].z * 255.f;
+ dst[i] = 0xff000000 | (r << 16) | (g << 8) | (b << 0);
+ }
+}
+
+
+template<typename T>
+static void storePremultipliedLUT(QCmyk32 *dst, const T *src, const QColorVector *buffer, const qsizetype len)
+{
+ storeUnpremultipliedLUT(dst, src, buffer, len);
+}
+
+template<typename T>
+static void storePremultipliedLUT(QRgba64 *, const T *, const QColorVector *, const qsizetype);
+
+template<>
+void storePremultipliedLUT(QRgba64 *dst, const QRgb *src, const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = qAlpha(src[i]) * 257;
+ const int r = buffer[i].x * a;
+ const int g = buffer[i].y * a;
+ const int b = buffer[i].z * a;
+ dst[i] = qRgba64(r, g, b, a);
+ }
+}
+
+template<>
+void storePremultipliedLUT(QRgba64 *dst, const QCmyk32 *, const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int r = buffer[i].x * 65535.f;
+ const int g = buffer[i].y * 65535.f;
+ const int b = buffer[i].z * 65535.f;
+ dst[i] = qRgba64(r, g, b, 65535);
+ }
+}
+
+template<>
+void storePremultipliedLUT(QRgba64 *dst, const QRgba64 *src, const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const int a = src[i].alpha();
+ const int r = buffer[i].x * a;
+ const int g = buffer[i].y * a;
+ const int b = buffer[i].z * a;
+ dst[i] = qRgba64(r, g, b, a);
+ }
+}
+
template<typename T>
-void QColorTransformPrivate::apply(T *dst, const T *src, qsizetype count, TransformFlags flags) const
+static void storePremultipliedLUT(QRgbaFloat32 *dst, const T *src, const QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i) {
+ const float a = getAlphaF(src[i]);
+ const float r = buffer[i].x * a;
+ const float g = buffer[i].y * a;
+ const float b = buffer[i].z * a;
+ dst[i] = QRgbaFloat32{r, g, b, a};
+ }
+}
+
+static void visitElement(const QColorSpacePrivate::TransferElement &element, QColorVector *buffer, const qsizetype len)
+{
+ const bool doW = element.trc[3].isValid();
+ for (qsizetype i = 0; i < len; ++i) {
+ buffer[i].x = element.trc[0].apply(buffer[i].x);
+ buffer[i].y = element.trc[1].apply(buffer[i].y);
+ buffer[i].z = element.trc[2].apply(buffer[i].z);
+ if (doW)
+ buffer[i].w = element.trc[3].apply(buffer[i].w);
+ }
+}
+
+static void visitElement(const QColorMatrix &element, QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i)
+ buffer[i] = element.map(buffer[i]);
+}
+
+static void visitElement(const QColorVector &offset, QColorVector *buffer, const qsizetype len)
+{
+ for (qsizetype i = 0; i < len; ++i)
+ buffer[i] += offset;
+}
+
+static void visitElement(const QColorCLUT &element, QColorVector *buffer, const qsizetype len)
+{
+ if (element.isEmpty())
+ return;
+ for (qsizetype i = 0; i < len; ++i)
+ buffer[i] = element.apply(buffer[i]);
+}
+
+/*!
+ \internal
+*/
+QColorVector QColorTransformPrivate::map(QColorVector c) const
+{
+ if (colorSpaceIn->isThreeComponentMatrix()) {
+ if (colorSpaceIn->lut.generated.loadAcquire()) {
+ c.x = colorSpaceIn->lut[0]->toLinear(c.x);
+ c.y = colorSpaceIn->lut[1]->toLinear(c.y);
+ c.z = colorSpaceIn->lut[2]->toLinear(c.z);
+ } else {
+ c.x = colorSpaceIn->trc[0].apply(c.x);
+ c.y = colorSpaceIn->trc[1].apply(c.y);
+ c.z = colorSpaceIn->trc[2].apply(c.z);
+ }
+ c = colorMatrix.map(c);
+ } else {
+ // Do element based conversion
+ for (auto &&element : colorSpaceIn->mAB)
+ std::visit([&c](auto &&elm) { visitElement(elm, &c, 1); }, element);
+ }
+ c.x = std::clamp(c.x, 0.0f, 1.0f);
+ c.y = std::clamp(c.y, 0.0f, 1.0f);
+ c.z = std::clamp(c.z, 0.0f, 1.0f);
+
+ // Match Profile Connection Spaces (PCS):
+ if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab)
+ c = c.xyzToLab();
+ else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab)
+ c = c.labToXyz();
+
+ if (colorSpaceOut->isThreeComponentMatrix()) {
+ if (!colorSpaceIn->isThreeComponentMatrix()) {
+ c = colorMatrix.map(c);
+ c.x = std::clamp(c.x, 0.0f, 1.0f);
+ c.y = std::clamp(c.y, 0.0f, 1.0f);
+ c.z = std::clamp(c.z, 0.0f, 1.0f);
+ }
+ if (colorSpaceOut->lut.generated.loadAcquire()) {
+ c.x = colorSpaceOut->lut[0]->fromLinear(c.x);
+ c.y = colorSpaceOut->lut[1]->fromLinear(c.y);
+ c.z = colorSpaceOut->lut[2]->fromLinear(c.z);
+ } else {
+ c.x = colorSpaceOut->trc[0].applyInverse(c.x);
+ c.y = colorSpaceOut->trc[1].applyInverse(c.y);
+ c.z = colorSpaceOut->trc[2].applyInverse(c.z);
+ }
+ } else {
+ // Do element based conversion
+ for (auto &&element : colorSpaceOut->mBA)
+ std::visit([&c](auto &&elm) { visitElement(elm, &c, 1); }, element);
+ c.x = std::clamp(c.x, 0.0f, 1.0f);
+ c.y = std::clamp(c.y, 0.0f, 1.0f);
+ c.z = std::clamp(c.z, 0.0f, 1.0f);
+ }
+ return c;
+}
+
+/*!
+ \internal
+*/
+QColorVector QColorTransformPrivate::mapExtended(QColorVector c) const
+{
+ if (colorSpaceIn->isThreeComponentMatrix()) {
+ c.x = colorSpaceIn->trc[0].applyExtended(c.x);
+ c.y = colorSpaceIn->trc[1].applyExtended(c.y);
+ c.z = colorSpaceIn->trc[2].applyExtended(c.z);
+ c = colorMatrix.map(c);
+ } else {
+ // Do element based conversion
+ for (auto &&element : colorSpaceIn->mAB)
+ std::visit([&c](auto &&elm) { visitElement(elm, &c, 1); }, element);
+ }
+
+ // Match Profile Connection Spaces (PCS):
+ if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab)
+ c = c.xyzToLab();
+ else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab)
+ c = c.labToXyz();
+
+ if (colorSpaceOut->isThreeComponentMatrix()) {
+ if (!colorSpaceIn->isThreeComponentMatrix())
+ c = colorMatrix.map(c);
+ c.x = colorSpaceOut->trc[0].applyInverseExtended(c.x);
+ c.y = colorSpaceOut->trc[1].applyInverseExtended(c.y);
+ c.z = colorSpaceOut->trc[2].applyInverseExtended(c.z);
+ } else {
+ // Do element based conversion
+ for (auto &&element : colorSpaceOut->mBA)
+ std::visit([&c](auto &&elm) { visitElement(elm, &c, 1); }, element);
+ }
+ return c;
+}
+
+template<typename S>
+void QColorTransformPrivate::applyConvertIn(const S *src, QColorVector *buffer, qsizetype len, TransformFlags flags) const
+{
+ // Avoid compiling this part for S=QCmyk32:
+ if constexpr (!std::is_same_v<S, QCmyk32>) {
+ if (colorSpaceIn->isThreeComponentMatrix()) {
+ if (flags & InputPremultiplied)
+ loadPremultiplied(buffer, src, len, this);
+ else
+ loadUnpremultiplied(buffer, src, len, this);
+
+ if (!colorSpaceOut->isThreeComponentMatrix())
+ applyMatrix<DoClamp>(buffer, len, colorMatrix); // colorMatrix should have the first half only.
+ return;
+ }
+ }
+ Q_ASSERT(!colorSpaceIn->isThreeComponentMatrix());
+
+ if (flags & InputPremultiplied)
+ loadPremultipliedLUT(buffer, src, len);
+ else
+ loadUnpremultipliedLUT(buffer, src, len);
+
+ if constexpr (std::is_same_v<S, QRgbaFloat16> || std::is_same_v<S, QRgbaFloat32>)
+ clampIfNeeded<DoClamp>(buffer, len);
+
+ // Do element based conversion
+ for (auto &&element : colorSpaceIn->mAB)
+ std::visit([&buffer, len](auto &&elm) { visitElement(elm, buffer, len); }, element);
+}
+
+template<typename D, typename S>
+void QColorTransformPrivate::applyConvertOut(D *dst, const S *src, QColorVector *buffer, qsizetype len, TransformFlags flags) const
{
+ constexpr ApplyMatrixForm doClamp = (std::is_same_v<D, QRgbaFloat16> || std::is_same_v<D, QRgbaFloat32>) ? DoNotClamp : DoClamp;
+ // Avoid compiling this part for D=QCmyk32:
+ if constexpr (!std::is_same_v<D, QCmyk32>) {
+ if (colorSpaceOut->isThreeComponentMatrix()) {
+ applyMatrix<doClamp>(buffer, len, colorMatrix); // colorMatrix should have the latter half only.
+
+ if constexpr (std::is_same_v<S, QCmyk32>) {
+ storeOpaque(dst, buffer, len, this);
+ } else {
+ if (flags & InputOpaque)
+ storeOpaque(dst, buffer, len, this);
+ else if (flags & OutputPremultiplied)
+ storePremultiplied(dst, src, buffer, len, this);
+ else
+ storeUnpremultiplied(dst, src, buffer, len, this);
+ }
+ return;
+ }
+ }
+ Q_ASSERT(!colorSpaceOut->isThreeComponentMatrix());
+
+ // Do element based conversion
+ for (auto &&element : colorSpaceOut->mBA)
+ std::visit([&buffer, len](auto &&elm) { visitElement(elm, buffer, len); }, element);
+
+ clampIfNeeded<doClamp>(buffer, len);
+
+ if (flags & OutputPremultiplied)
+ storePremultipliedLUT(dst, src, buffer, len);
+ else
+ storeUnpremultipliedLUT(dst, src, buffer, len);
+}
+
+template<typename D, typename S>
+void QColorTransformPrivate::applyElementListTransform(D *dst, const S *src, qsizetype count, TransformFlags flags) const
+{
+ Q_ASSERT(!colorSpaceIn->isThreeComponentMatrix() || !colorSpaceOut->isThreeComponentMatrix());
+
+ if (!colorMatrix.isValid())
+ return;
+
+ if (colorSpaceIn->isThreeComponentMatrix())
+ updateLutsIn();
+ if (colorSpaceOut->isThreeComponentMatrix())
+ updateLutsOut();
+
+ QUninitialized<QColorVector, WorkBlockSize> buffer;
+ qsizetype i = 0;
+ while (i < count) {
+ const qsizetype len = qMin(count - i, WorkBlockSize);
+
+ applyConvertIn(src + i, buffer, len, flags);
+
+ // Match Profile Connection Spaces (PCS):
+ if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab) {
+ for (qsizetype j = 0; j < len; ++j)
+ buffer[j] = buffer[j].xyzToLab();
+ } else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab) {
+ for (qsizetype j = 0; j < len; ++j)
+ buffer[j] = buffer[j].labToXyz();
+ }
+
+ applyConvertOut(dst + i, src + i, buffer, len, flags);
+
+ i += len;
+ }
+}
+
+template<typename D, typename S>
+void QColorTransformPrivate::applyThreeComponentMatrix(D *dst, const S *src, qsizetype count, TransformFlags flags) const
+{
+ Q_ASSERT(colorSpaceIn->isThreeComponentMatrix() && colorSpaceOut->isThreeComponentMatrix());
+
if (!colorMatrix.isValid())
return;
updateLutsIn();
updateLutsOut();
- bool doApplyMatrix = (colorMatrix != QColorMatrix::identity());
+ bool doApplyMatrix = !colorMatrix.isIdentity();
+ constexpr ApplyMatrixForm doClamp = (std::is_same_v<D, QRgbaFloat16> || std::is_same_v<D, QRgbaFloat32>) ? DoNotClamp : DoClamp;
QUninitialized<QColorVector, WorkBlockSize> buffer;
-
qsizetype i = 0;
while (i < count) {
const qsizetype len = qMin(count - i, WorkBlockSize);
@@ -919,10 +1754,12 @@ void QColorTransformPrivate::apply(T *dst, const T *src, qsizetype count, Transf
loadUnpremultiplied(buffer, src + i, len, this);
if (doApplyMatrix)
- applyMatrix(buffer, len, colorMatrix);
+ applyMatrix<doClamp>(buffer, len, colorMatrix);
+ else
+ clampIfNeeded<doClamp>(buffer, len);
if (flags & InputOpaque)
- storeOpaque(dst + i, src + i, buffer, len, this);
+ storeOpaque(dst + i, buffer, len, this);
else if (flags & OutputPremultiplied)
storePremultiplied(dst + i, src + i, buffer, len, this);
else
@@ -932,30 +1769,149 @@ void QColorTransformPrivate::apply(T *dst, const T *src, qsizetype count, Transf
}
}
+/*!
+ \internal
+ Applies the color transformation on \a count S pixels starting from
+ \a src and stores the result in \a dst as D pixels .
+
+ Assumes unpremultiplied data by default. Set \a flags to change defaults.
+
+ \sa prepare()
+*/
+template<typename D, typename S>
+void QColorTransformPrivate::apply(D *dst, const S *src, qsizetype count, TransformFlags flags) const
+{
+ if constexpr (!std::is_same_v<D, QCmyk32> && !std::is_same_v<S, QCmyk32>) {
+ if (isThreeComponentMatrix())
+ return applyThreeComponentMatrix<D, S>(dst, src, count, flags);
+ }
+ applyElementListTransform<D, S>(dst, src, count, flags);
+}
+
+/*!
+ \internal
+ Is to be called on a color-transform to XYZ, returns only luminance values.
+
+ */
template<typename D, typename S>
void QColorTransformPrivate::applyReturnGray(D *dst, const S *src, qsizetype count, TransformFlags flags) const
{
- if (!colorMatrix.isValid())
+ Q_ASSERT(colorSpaceOut->isThreeComponentMatrix());
+ updateLutsOut();
+ if (!colorSpaceIn->isThreeComponentMatrix()) {
+ QUninitialized<QColorVector, WorkBlockSize> buffer;
+
+ qsizetype i = 0;
+ while (i < count) {
+ const qsizetype len = qMin(count - i, WorkBlockSize);
+
+ applyConvertIn(src, buffer, len, flags);
+
+ // Match Profile Connection Spaces (PCS):
+ if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab) {
+ for (qsizetype j = 0; j < len; ++j)
+ buffer[j] = buffer[j].xyzToLab();
+ } else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab) {
+ for (qsizetype j = 0; j < len; ++j)
+ buffer[j] = buffer[j].labToXyz();
+ }
+
+ applyMatrix<DoClamp>(buffer, len, colorMatrix);
+ storeOpaque(dst + i, buffer, len, this);
+
+ i += len;
+ }
return;
+ }
+ if constexpr (!std::is_same_v<S, QCmyk32>) {
+ if (!colorMatrix.isValid())
+ return;
+ updateLutsIn();
+
+ QUninitialized<QColorVector, WorkBlockSize> buffer;
+
+ qsizetype i = 0;
+ while (i < count) {
+ const qsizetype len = qMin(count - i, WorkBlockSize);
+ if (flags & InputPremultiplied)
+ loadPremultiplied(buffer, src + i, len, this);
+ else
+ loadUnpremultiplied(buffer, src + i, len, this);
+
+ applyMatrix<DoClamp>(buffer, len, colorMatrix);
+
+ storeOpaque(dst + i, buffer, len, this);
+
+ i += len;
+ }
+ } else {
+ Q_UNREACHABLE();
+ }
+}
+
+/*!
+ \internal
+*/
+template<typename D, typename S>
+void QColorTransformPrivate::applyGray(D *dst, const S *src, qsizetype count, TransformFlags) const
+{
+ Q_ASSERT(colorSpaceIn->isThreeComponentMatrix());
updateLutsIn();
- updateLutsOut();
+ if constexpr (std::is_same_v<D, QRgb> || std::is_same_v<D, QRgba64> || std::is_same_v<D, QRgbaFloat32> || std::is_same_v<D, QCmyk32>) {
+ if (!colorSpaceOut->isThreeComponentMatrix()) {
+ QUninitialized<QColorVector, WorkBlockSize> buffer;
- QUninitialized<QColorVector, WorkBlockSize> buffer;
+ qsizetype i = 0;
+ while (i < count) {
+ const qsizetype len = qMin(count - i, WorkBlockSize);
+ loadGray(buffer, src + i, len, this);
- qsizetype i = 0;
- while (i < count) {
- const qsizetype len = qMin(count - i, WorkBlockSize);
- if (flags & InputPremultiplied)
- loadPremultiplied(buffer, src + i, len, this);
- else
- loadUnpremultiplied(buffer, src + i, len, this);
+ applyMatrix<DoClamp>(buffer, len, colorMatrix);
- applyMatrix(buffer, len, colorMatrix);
+ // Match Profile Connection Spaces (PCS):
+ if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab) {
+ for (qsizetype j = 0; j < len; ++j)
+ buffer[j] = buffer[j].xyzToLab();
+ } else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab) {
+ for (qsizetype j = 0; j < len; ++j)
+ buffer[j] = buffer[j].labToXyz();
+ }
- storeGray(dst + i, src + i, buffer, len, this);
+ // Do element based conversion
+ for (auto &&element : colorSpaceOut->mBA)
+ std::visit([&buffer, len](auto &&elm) { visitElement(elm, buffer, len); }, element);
- i += len;
+ clampIfNeeded<DoClamp>(buffer, len);
+
+ storeUnpremultipliedLUT(dst, src, buffer, len); // input is always opaque
+
+ i += len;
+ }
+ return;
+ }
+ }
+ Q_ASSERT(colorSpaceOut->isThreeComponentMatrix());
+ if constexpr (!std::is_same_v<D, QCmyk32>) {
+ if (!colorMatrix.isValid())
+ return;
+
+ updateLutsOut();
+
+ QUninitialized<QColorVector, WorkBlockSize> buffer;
+
+ qsizetype i = 0;
+ while (i < count) {
+ const qsizetype len = qMin(count - i, WorkBlockSize);
+ loadGray(buffer, src + i, len, this);
+
+ applyMatrix<DoClamp>(buffer, len, colorMatrix);
+
+ storeOpaque(dst + i, buffer, len, this);
+ i += len;
+ }
+ } else {
+ Q_UNREACHABLE();
}
}
@@ -963,7 +1919,7 @@ void QColorTransformPrivate::applyReturnGray(D *dst, const S *src, qsizetype cou
\internal
\enum QColorTransformPrivate::TransformFlag
- Defines how the transform is to be applied.
+ Defines how the transform should handle alpha values.
\value Unpremultiplied The input and output should both be unpremultiplied.
\value InputOpaque The input is guaranteed to be opaque.
@@ -987,57 +1943,72 @@ void QColorTransformPrivate::prepare()
updateLutsOut();
}
-/*!
- \internal
- Applies the color transformation on \a count QRgb pixels starting from
- \a src and stores the result in \a dst.
-
- Thread-safe if prepare() has been called first.
-
- Assumes unpremultiplied data by default. Set \a flags to change defaults.
-
- \sa prepare()
-*/
-void QColorTransformPrivate::apply(QRgb *dst, const QRgb *src, qsizetype count, TransformFlags flags) const
+// Only allow versions increasing precision
+template void QColorTransformPrivate::applyReturnGray<quint8, QRgb>(quint8 *dst, const QRgb *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::applyReturnGray<quint8, QCmyk32>(quint8 *dst, const QCmyk32 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::applyReturnGray<quint16, QCmyk32>(quint16 *dst, const QCmyk32 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::applyReturnGray<quint16, QRgba64>(quint16 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::applyGray<quint8, quint8>(quint8 *dst, const quint8 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::applyGray<quint16, quint8>(quint16 *dst, const quint8 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::applyGray<quint16, quint16>(quint16 *dst, const quint16 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::applyGray<QRgb, quint8>(QRgb *dst, const quint8 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::applyGray<QCmyk32, quint8>(QCmyk32 *dst, const quint8 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::applyGray<QCmyk32, quint16>(QCmyk32 *dst, const quint16 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::applyGray<QRgba64, quint16>(QRgba64 *dst, const quint16 *src, qsizetype count, TransformFlags flags) const;
+
+template void QColorTransformPrivate::apply<QRgb, QRgb>(QRgb *dst, const QRgb *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QRgb, QCmyk32>(QRgb *dst, const QCmyk32 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QCmyk32, QRgb>(QCmyk32 *dst, const QRgb *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QCmyk32, QCmyk32>(QCmyk32 *dst, const QCmyk32 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QCmyk32, QRgba64>(QCmyk32 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QCmyk32, QRgbaFloat32>(QCmyk32 *dst, const QRgbaFloat32 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QRgba64, QRgb>(QRgba64 *dst, const QRgb *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QRgba64, QCmyk32>(QRgba64 *dst, const QCmyk32 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QRgba64, QRgba64>(QRgba64 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QRgbaFloat32, QRgb>(QRgbaFloat32 *dst, const QRgb *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QRgbaFloat32, QCmyk32>(QRgbaFloat32 *dst, const QCmyk32 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QRgbaFloat32, QRgba64>(QRgbaFloat32 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const;
+template void QColorTransformPrivate::apply<QRgbaFloat32, QRgbaFloat32>(QRgbaFloat32 *dst, const QRgbaFloat32 *src, qsizetype count, TransformFlags flags) const;
+
+bool QColorTransformPrivate::isThreeComponentMatrix() const
{
- apply<QRgb>(dst, src, count, flags);
+ if (colorSpaceIn && !colorSpaceIn->isThreeComponentMatrix())
+ return false;
+ if (colorSpaceOut && !colorSpaceOut->isThreeComponentMatrix())
+ return false;
+ return true;
}
/*!
\internal
- Applies the color transformation on \a count QRgba64 pixels starting from
- \a src and stores the result in \a dst.
-
- Thread-safe if prepare() has been called first.
-
- Assumes unpremultiplied data by default. Set \a flags to change defaults.
-
- \sa prepare()
*/
-void QColorTransformPrivate::apply(QRgba64 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const
+bool QColorTransformPrivate::isIdentity() const
{
- apply<QRgba64>(dst, src, count, flags);
-}
-
-/*!
- \internal
- Is to be called on a color-transform to XYZ, returns only luminance values.
-
-*/
-void QColorTransformPrivate::apply(quint8 *dst, const QRgb *src, qsizetype count, TransformFlags flags) const
-{
- applyReturnGray<quint8, QRgb>(dst, src, count, flags);
-}
-
-/*!
- \internal
- Is to be called on a color-transform to XYZ, returns only luminance values.
-
-*/
-void QColorTransformPrivate::apply(quint16 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const
-{
- applyReturnGray<quint16, QRgba64>(dst, src, count, flags);
+ if (colorSpaceIn == colorSpaceOut)
+ return true;
+ if (!colorMatrix.isIdentity())
+ return false;
+ if (colorSpaceIn && colorSpaceOut) {
+ if (colorSpaceIn->equals(colorSpaceOut.constData()))
+ return true;
+ if (!isThreeComponentMatrix())
+ return false;
+ if (colorSpaceIn->transferFunction != colorSpaceOut->transferFunction)
+ return false;
+ if (colorSpaceIn->transferFunction == QColorSpace::TransferFunction::Custom) {
+ return colorSpaceIn->trc[0] == colorSpaceOut->trc[0]
+ && colorSpaceIn->trc[1] == colorSpaceOut->trc[1]
+ && colorSpaceIn->trc[2] == colorSpaceOut->trc[2];
+ }
+ } else {
+ if (!isThreeComponentMatrix())
+ return false;
+ if (colorSpaceIn && colorSpaceIn->transferFunction != QColorSpace::TransferFunction::Linear)
+ return false;
+ if (colorSpaceOut && colorSpaceOut->transferFunction != QColorSpace::TransferFunction::Linear)
+ return false;
+ }
+ return true;
}
-
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolortransform.h b/src/gui/painting/qcolortransform.h
index 7ec58c5617..02f15ee89f 100644
--- a/src/gui/painting/qcolortransform.h
+++ b/src/gui/painting/qcolortransform.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLORTRANSFORM_H
#define QCOLORTRANSFORM_H
@@ -50,6 +14,12 @@ class QColor;
class QRgba64;
class QColorSpacePrivate;
class QColorTransformPrivate;
+class qfloat16;
+template<typename T>
+class QRgbaFloat;
+typedef QRgbaFloat<qfloat16> QRgbaFloat16;
+typedef QRgbaFloat<float> QRgbaFloat32;
+
QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QColorTransformPrivate, Q_GUI_EXPORT)
class QColorTransform
@@ -66,17 +36,24 @@ public:
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QColorTransform)
- void swap(QColorTransform &other) noexcept { qSwap(d, other.d); }
+ void swap(QColorTransform &other) noexcept { d.swap(other.d); }
+ Q_GUI_EXPORT bool isIdentity() const noexcept;
Q_GUI_EXPORT QRgb map(QRgb argb) const;
Q_GUI_EXPORT QRgba64 map(QRgba64 rgba64) const;
+ Q_GUI_EXPORT QRgbaFloat16 map(QRgbaFloat16 rgbafp16) const;
+ Q_GUI_EXPORT QRgbaFloat32 map(QRgbaFloat32 rgbafp32) const;
Q_GUI_EXPORT QColor map(const QColor &color) const;
+ friend bool operator==(const QColorTransform &ct1, const QColorTransform &ct2)
+ { return ct1.compare(ct2); }
+ friend bool operator!=(const QColorTransform &ct1, const QColorTransform &ct2)
+ { return !ct1.compare(ct2); }
+
private:
- friend class QColorSpace;
friend class QColorSpacePrivate;
friend class QColorTransformPrivate;
- friend class QImage;
+ Q_GUI_EXPORT bool compare(const QColorTransform &other) const;
QExplicitlySharedDataPointer<QColorTransformPrivate> d;
};
diff --git a/src/gui/painting/qcolortransform_p.h b/src/gui/painting/qcolortransform_p.h
index b9099fa399..59ea6a2405 100644
--- a/src/gui/painting/qcolortransform_p.h
+++ b/src/gui/painting/qcolortransform_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLORTRANSFORM_P_H
#define QCOLORTRANSFORM_P_H
@@ -55,8 +19,10 @@
#include "qcolorspace_p.h"
#include <QtCore/qshareddata.h>
+#include <QtGui/qrgbafloat.h>
QT_BEGIN_NAMESPACE
+class QCmyk32;
class QColorTransformPrivate : public QSharedData
{
@@ -70,9 +36,10 @@ public:
void updateLutsIn() const;
void updateLutsOut() const;
- bool simpleGammaCorrection() const;
+ bool isIdentity() const;
+ bool isThreeComponentMatrix() const;
- void prepare();
+ Q_GUI_EXPORT void prepare();
enum TransformFlag {
Unpremultiplied = 0,
InputOpaque = 1,
@@ -82,17 +49,25 @@ public:
};
Q_DECLARE_FLAGS(TransformFlags, TransformFlag)
- void apply(QRgb *dst, const QRgb *src, qsizetype count, TransformFlags flags = Unpremultiplied) const;
- void apply(QRgba64 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags = Unpremultiplied) const;
- void apply(quint8 *dst, const QRgb *src, qsizetype count, TransformFlags flags = Unpremultiplied) const;
- void apply(quint16 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags = Unpremultiplied) const;
-
- template<typename T>
- void apply(T *dst, const T *src, qsizetype count, TransformFlags flags) const;
+ QColorVector map(QColorVector color) const;
+ QColorVector mapExtended(QColorVector color) const;
template<typename D, typename S>
+ void apply(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
+ template<typename D, typename S>
+ void applyGray(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
+ template<typename D, typename S>
void applyReturnGray(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
+private:
+ template<typename S>
+ void applyConvertIn(const S *src, QColorVector *buffer, qsizetype len, TransformFlags flags) const;
+ template<typename D, typename S>
+ void applyConvertOut(D *dst, const S *src, QColorVector *buffer, qsizetype len, TransformFlags flags) const;
+ template<typename D, typename S>
+ void applyElementListTransform(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
+ template<typename D, typename S>
+ void applyThreeComponentMatrix(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolortrc_p.h b/src/gui/painting/qcolortrc_p.h
index 058be3c7ce..d1ad1987df 100644
--- a/src/gui/painting/qcolortrc_p.h
+++ b/src/gui/painting/qcolortrc_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLORTRC_P_H
#define QCOLORTRC_P_H
@@ -57,17 +21,15 @@
QT_BEGIN_NAMESPACE
-
-// Defines an ICC TRC (Tone Reproduction Curve)
+// Defines a TRC (Tone Reproduction Curve)
class Q_GUI_EXPORT QColorTrc
{
public:
- QColorTrc() noexcept : m_type(Type::Uninitialized)
- { }
- QColorTrc(const QColorTransferFunction &fun) : m_type(Type::Function), m_fun(fun)
- { }
- QColorTrc(const QColorTransferTable &table) : m_type(Type::Table), m_table(table)
- { }
+ QColorTrc() noexcept : m_type(Type::Uninitialized) { }
+ QColorTrc(const QColorTransferFunction &fun) : m_type(Type::Function), m_fun(fun) { }
+ QColorTrc(const QColorTransferTable &table) : m_type(Type::Table), m_table(table) { }
+ QColorTrc(QColorTransferFunction &&fun) noexcept : m_type(Type::Function), m_fun(std::move(fun)) { }
+ QColorTrc(QColorTransferTable &&table) noexcept : m_type(Type::Table), m_table(std::move(table)) { }
enum class Type {
Uninitialized,
@@ -75,9 +37,10 @@ public:
Table
};
- bool isLinear() const
+ bool isIdentity() const
{
- return m_type == Type::Uninitialized || (m_type == Type::Function && m_fun.isLinear());
+ return (m_type == Type::Function && m_fun.isIdentity())
+ || (m_type == Type::Table && m_table.isIdentity());
}
bool isValid() const
{
diff --git a/src/gui/painting/qcolortrclut.cpp b/src/gui/painting/qcolortrclut.cpp
index 8e2235bfa0..8a7673bc00 100644
--- a/src/gui/painting/qcolortrclut.cpp
+++ b/src/gui/painting/qcolortrclut.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcolortrclut_p.h"
#include "qcolortransferfunction_p.h"
@@ -49,43 +13,80 @@ std::shared_ptr<QColorTrcLut> QColorTrcLut::create()
return std::make_shared<Access>();
}
-std::shared_ptr<QColorTrcLut> QColorTrcLut::fromGamma(qreal gamma)
+std::shared_ptr<QColorTrcLut> QColorTrcLut::fromGamma(qreal gamma, Direction dir)
{
auto cp = create();
+ cp->setFromGamma(gamma, dir);
+ return cp;
+}
- for (int i = 0; i <= (255 * 16); ++i) {
- cp->m_toLinear[i] = ushort(qRound(qPow(i / qreal(255 * 16), gamma) * (255 * 256)));
- cp->m_fromLinear[i] = ushort(qRound(qPow(i / qreal(255 * 16), qreal(1) / gamma) * (255 * 256)));
- }
-
+std::shared_ptr<QColorTrcLut> QColorTrcLut::fromTransferFunction(const QColorTransferFunction &fun, Direction dir)
+{
+ auto cp = create();
+ cp->setFromTransferFunction(fun, dir);
return cp;
}
-std::shared_ptr<QColorTrcLut> QColorTrcLut::fromTransferFunction(const QColorTransferFunction &fun)
+std::shared_ptr<QColorTrcLut> QColorTrcLut::fromTransferTable(const QColorTransferTable &table, Direction dir)
{
auto cp = create();
- QColorTransferFunction inv = fun.inverted();
+ cp->setFromTransferTable(table, dir);
+ return cp;
+}
- for (int i = 0; i <= (255 * 16); ++i) {
- cp->m_toLinear[i] = ushort(qRound(fun.apply(i / qreal(255 * 16)) * (255 * 256)));
- cp->m_fromLinear[i] = ushort(qRound(inv.apply(i / qreal(255 * 16)) * (255 * 256)));
+void QColorTrcLut::setFromGamma(qreal gamma, Direction dir)
+{
+ if (dir & ToLinear) {
+ if (!m_toLinear)
+ m_toLinear.reset(new ushort[Resolution + 1]);
+ for (int i = 0; i <= Resolution; ++i)
+ m_toLinear[i] = ushort(qRound(qPow(i / qreal(Resolution), gamma) * (255 * 256)));
}
- return cp;
+ if (dir & FromLinear) {
+ if (!m_fromLinear)
+ m_fromLinear.reset(new ushort[Resolution + 1]);
+ for (int i = 0; i <= Resolution; ++i)
+ m_fromLinear[i] = ushort(qRound(qPow(i / qreal(Resolution), qreal(1) / gamma) * (255 * 256)));
+ }
}
-std::shared_ptr<QColorTrcLut> QColorTrcLut::fromTransferTable(const QColorTransferTable &table)
+void QColorTrcLut::setFromTransferFunction(const QColorTransferFunction &fun, Direction dir)
{
- auto cp = create();
+ if (dir & ToLinear) {
+ if (!m_toLinear)
+ m_toLinear.reset(new ushort[Resolution + 1]);
+ for (int i = 0; i <= Resolution; ++i)
+ m_toLinear[i] = ushort(qRound(fun.apply(i / qreal(Resolution)) * (255 * 256)));
+ }
- float minInverse = 0.0f;
- for (int i = 0; i <= (255 * 16); ++i) {
- cp->m_toLinear[i] = ushort(qBound(0, qRound(table.apply(i / qreal(255 * 16)) * (255 * 256)), 65280));
- minInverse = table.applyInverse(i / qreal(255 * 16), minInverse);
- cp->m_fromLinear[i] = ushort(qBound(0, qRound(minInverse * (255 * 256)), 65280));
+ if (dir & FromLinear) {
+ if (!m_fromLinear)
+ m_fromLinear.reset(new ushort[Resolution + 1]);
+ QColorTransferFunction inv = fun.inverted();
+ for (int i = 0; i <= Resolution; ++i)
+ m_fromLinear[i] = ushort(qRound(inv.apply(i / qreal(Resolution)) * (255 * 256)));
}
+}
- return cp;
+void QColorTrcLut::setFromTransferTable(const QColorTransferTable &table, Direction dir)
+{
+ if (dir & ToLinear) {
+ if (!m_toLinear)
+ m_toLinear.reset(new ushort[Resolution + 1]);
+ for (int i = 0; i <= Resolution; ++i)
+ m_toLinear[i] = ushort(qBound(0, qRound(table.apply(i / qreal(Resolution)) * (255 * 256)), 65280));
+ }
+
+ if (dir & FromLinear) {
+ if (!m_fromLinear)
+ m_fromLinear.reset(new ushort[Resolution + 1]);
+ float minInverse = 0.0f;
+ for (int i = 0; i <= Resolution; ++i) {
+ minInverse = table.applyInverse(i / qreal(Resolution), minInverse);
+ m_fromLinear[i] = ushort(qBound(0, qRound(minInverse * (255 * 256)), 65280));
+ }
+ }
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcolortrclut_p.h b/src/gui/painting/qcolortrclut_p.h
index 50168652ff..3ebab42809 100644
--- a/src/gui/painting/qcolortrclut_p.h
+++ b/src/gui/painting/qcolortrclut_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOLORTRCLUT_P_H
#define QCOLORTRCLUT_P_H
@@ -72,9 +36,22 @@ class QColorTransferTable;
class Q_GUI_EXPORT QColorTrcLut
{
public:
- static std::shared_ptr<QColorTrcLut> fromGamma(qreal gamma);
- static std::shared_ptr<QColorTrcLut> fromTransferFunction(const QColorTransferFunction &transfn);
- static std::shared_ptr<QColorTrcLut> fromTransferTable(const QColorTransferTable &transTable);
+ static constexpr uint32_t ShiftUp = 4; // Amount to shift up from 1->255
+ static constexpr uint32_t ShiftDown = (8 - ShiftUp); // Amount to shift down from 1->65280
+ static constexpr qsizetype Resolution = (1 << ShiftUp) * 255; // Number of entries in table
+
+ enum Direction {
+ ToLinear = 1,
+ FromLinear = 2,
+ BiLinear = ToLinear | FromLinear
+ };
+
+ static std::shared_ptr<QColorTrcLut> fromGamma(qreal gamma, Direction dir = BiLinear);
+ static std::shared_ptr<QColorTrcLut> fromTransferFunction(const QColorTransferFunction &transFn, Direction dir = BiLinear);
+ static std::shared_ptr<QColorTrcLut> fromTransferTable(const QColorTransferTable &transTable, Direction dir = BiLinear);
+ void setFromGamma(qreal gamma, Direction dir = BiLinear);
+ void setFromTransferFunction(const QColorTransferFunction &transFn, Direction dir = BiLinear);
+ void setFromTransferTable(const QColorTransferTable &transTable, Direction dir = BiLinear);
// The following methods all convert opaque or unpremultiplied colors:
@@ -83,7 +60,7 @@ public:
#if defined(__SSE2__)
__m128i v = _mm_cvtsi32_si128(rgb32);
v = _mm_unpacklo_epi8(v, _mm_setzero_si128());
- const __m128i vidx = _mm_slli_epi16(v, 4);
+ const __m128i vidx = _mm_slli_epi16(v, ShiftUp);
const int ridx = _mm_extract_epi16(vidx, 2);
const int gidx = _mm_extract_epi16(vidx, 1);
const int bidx = _mm_extract_epi16(vidx, 0);
@@ -98,7 +75,7 @@ public:
#elif (defined(__ARM_NEON__) || defined(__ARM_NEON)) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
uint8x8_t v8 = vreinterpret_u8_u32(vmov_n_u32(rgb32));
uint16x4_t v16 = vget_low_u16(vmovl_u8(v8));
- const uint16x4_t vidx = vshl_n_u16(v16, 4);
+ const uint16x4_t vidx = vshl_n_u16(v16, ShiftUp);
const int ridx = vget_lane_u16(vidx, 2);
const int gidx = vget_lane_u16(vidx, 1);
const int bidx = vget_lane_u16(vidx, 0);
@@ -109,42 +86,43 @@ public:
v16 = vadd_u16(v16, vshr_n_u16(v16, 8));
return QRgba64::fromRgba64(vget_lane_u64(vreinterpret_u64_u16(v16), 0));
#else
- uint r = m_toLinear[qRed(rgb32) << 4];
- uint g = m_toLinear[qGreen(rgb32) << 4];
- uint b = m_toLinear[qBlue(rgb32) << 4];
+ uint r = m_toLinear[qRed(rgb32) << ShiftUp];
+ uint g = m_toLinear[qGreen(rgb32) << ShiftUp];
+ uint b = m_toLinear[qBlue(rgb32) << ShiftUp];
r = r + (r >> 8);
g = g + (g >> 8);
b = b + (b >> 8);
return QRgba64::fromRgba64(r, g, b, qAlpha(rgb32) * 257);
#endif
}
+ QRgba64 toLinear64(QRgba64) const = delete;
QRgb toLinear(QRgb rgb32) const
{
- return convertWithTable(rgb32, m_toLinear);
+ return convertWithTable(rgb32, m_toLinear.get());
}
QRgba64 toLinear(QRgba64 rgb64) const
{
- return convertWithTable(rgb64, m_toLinear);
+ return convertWithTable(rgb64, m_toLinear.get());
}
float u8ToLinearF32(int c) const
{
- ushort v = m_toLinear[c << 4];
+ ushort v = m_toLinear[c << ShiftUp];
return v * (1.0f / (255*256));
}
float u16ToLinearF32(int c) const
{
c -= (c >> 8);
- ushort v = m_toLinear[c >> 4];
+ ushort v = m_toLinear[c >> ShiftDown];
return v * (1.0f / (255*256));
}
float toLinear(float f) const
{
- ushort v = m_toLinear[(int)(f * (255 * 16) + 0.5f)];
+ ushort v = m_toLinear[(int)(f * Resolution + 0.5f)];
return v * (1.0f / (255*256));
}
@@ -153,7 +131,7 @@ public:
#if defined(__SSE2__)
__m128i v = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&rgb64));
v = _mm_sub_epi16(v, _mm_srli_epi16(v, 8));
- const __m128i vidx = _mm_srli_epi16(v, 4);
+ const __m128i vidx = _mm_srli_epi16(v, ShiftDown);
const int ridx = _mm_extract_epi16(vidx, 0);
const int gidx = _mm_extract_epi16(vidx, 1);
const int bidx = _mm_extract_epi16(vidx, 2);
@@ -167,7 +145,7 @@ public:
#elif (defined(__ARM_NEON__) || defined(__ARM_NEON)) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
uint16x4_t v = vreinterpret_u16_u64(vmov_n_u64(rgb64));
v = vsub_u16(v, vshr_n_u16(v, 8));
- const uint16x4_t vidx = vshr_n_u16(v, 4);
+ const uint16x4_t vidx = vshr_n_u16(v, ShiftDown);
const int ridx = vget_lane_u16(vidx, 0);
const int gidx = vget_lane_u16(vidx, 1);
const int bidx = vget_lane_u16(vidx, 2);
@@ -186,56 +164,56 @@ public:
g = g - (g >> 8);
b = b - (b >> 8);
a = (a + 0x80) >> 8;
- r = (m_fromLinear[r >> 4] + 0x80) >> 8;
- g = (m_fromLinear[g >> 4] + 0x80) >> 8;
- b = (m_fromLinear[b >> 4] + 0x80) >> 8;
+ r = (m_fromLinear[r >> ShiftDown] + 0x80) >> 8;
+ g = (m_fromLinear[g >> ShiftDown] + 0x80) >> 8;
+ b = (m_fromLinear[b >> ShiftDown] + 0x80) >> 8;
return (a << 24) | (r << 16) | (g << 8) | b;
#endif
}
QRgb fromLinear(QRgb rgb32) const
{
- return convertWithTable(rgb32, m_fromLinear);
+ return convertWithTable(rgb32, m_fromLinear.get());
}
QRgba64 fromLinear(QRgba64 rgb64) const
{
- return convertWithTable(rgb64, m_fromLinear);
+ return convertWithTable(rgb64, m_fromLinear.get());
}
int u8FromLinearF32(float f) const
{
- ushort v = m_fromLinear[(int)(f * (255 * 16) + 0.5f)];
+ ushort v = m_fromLinear[(int)(f * Resolution + 0.5f)];
return (v + 0x80) >> 8;
}
int u16FromLinearF32(float f) const
{
- ushort v = m_fromLinear[(int)(f * (255 * 16) + 0.5f)];
+ ushort v = m_fromLinear[(int)(f * Resolution + 0.5f)];
return v + (v >> 8);
}
float fromLinear(float f) const
{
- ushort v = m_fromLinear[(int)(f * (255 * 16) + 0.5f)];
+ ushort v = m_fromLinear[(int)(f * Resolution + 0.5f)];
return v * (1.0f / (255*256));
}
// We translate to 0-65280 (255*256) instead to 0-65535 to make simple
// shifting an accurate conversion.
- // We translate from 0-4080 (255*16) for the same speed up, and to keep
- // the tables small enough to fit in most inner caches.
- ushort m_toLinear[(255 * 16) + 1]; // [0-4080] -> [0-65280]
- ushort m_fromLinear[(255 * 16) + 1]; // [0-4080] -> [0-65280]
+ // We translate from 0->Resolution (4080 = 255*16) for the same speed up,
+ // and to keep the tables small enough to fit in most inner caches.
+ std::unique_ptr<ushort[]> m_toLinear; // [0->Resolution] -> [0-65280]
+ std::unique_ptr<ushort[]> m_fromLinear; // [0->Resolution] -> [0-65280]
private:
- QColorTrcLut() { } // force uninitialized members
+ QColorTrcLut() = default;
static std::shared_ptr<QColorTrcLut> create();
Q_ALWAYS_INLINE static QRgb convertWithTable(QRgb rgb32, const ushort *table)
{
- const int r = (table[qRed(rgb32) << 4] + 0x80) >> 8;
- const int g = (table[qGreen(rgb32) << 4] + 0x80) >> 8;
- const int b = (table[qBlue(rgb32) << 4] + 0x80) >> 8;
+ const int r = (table[qRed(rgb32) << ShiftUp] + 0x80) >> 8;
+ const int g = (table[qGreen(rgb32) << ShiftUp] + 0x80) >> 8;
+ const int b = (table[qBlue(rgb32) << ShiftUp] + 0x80) >> 8;
return (rgb32 & 0xff000000) | (r << 16) | (g << 8) | b;
}
Q_ALWAYS_INLINE static QRgba64 convertWithTable(QRgba64 rgb64, const ushort *table)
@@ -243,7 +221,7 @@ private:
#if defined(__SSE2__)
__m128i v = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&rgb64));
v = _mm_sub_epi16(v, _mm_srli_epi16(v, 8));
- const __m128i vidx = _mm_srli_epi16(v, 4);
+ const __m128i vidx = _mm_srli_epi16(v, ShiftDown);
const int ridx = _mm_extract_epi16(vidx, 2);
const int gidx = _mm_extract_epi16(vidx, 1);
const int bidx = _mm_extract_epi16(vidx, 0);
@@ -257,7 +235,7 @@ private:
#elif (defined(__ARM_NEON__) || defined(__ARM_NEON)) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
uint16x4_t v = vreinterpret_u16_u64(vmov_n_u64(rgb64));
v = vsub_u16(v, vshr_n_u16(v, 8));
- const uint16x4_t vidx = vshr_n_u16(v, 4);
+ const uint16x4_t vidx = vshr_n_u16(v, ShiftDown);
const int ridx = vget_lane_u16(vidx, 2);
const int gidx = vget_lane_u16(vidx, 1);
const int bidx = vget_lane_u16(vidx, 0);
@@ -273,9 +251,9 @@ private:
r = r - (r >> 8);
g = g - (g >> 8);
b = b - (b >> 8);
- r = table[r >> 4];
- g = table[g >> 4];
- b = table[b >> 4];
+ r = table[r >> ShiftDown];
+ g = table[g >> ShiftDown];
+ b = table[b >> ShiftDown];
r = r + (r >> 8);
g = g + (g >> 8);
b = b + (b >> 8);
diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp
index 560f7b4d2d..00fd749fe6 100644
--- a/src/gui/painting/qcompositionfunctions.cpp
+++ b/src/gui/painting/qcompositionfunctions.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qglobal.h>
@@ -433,25 +397,25 @@ struct RgbaFPOperationsSSE2 : public RgbaFPOperationsBase
typedef __m128 OptimalType;
typedef __m128 OptimalScalar;
- static OptimalType load(const Type *ptr)
+ static OptimalType Q_DECL_VECTORCALL load(const Type *ptr)
{
- return _mm_load_ps(reinterpret_cast<const float *>(ptr));
+ return _mm_loadu_ps(reinterpret_cast<const float *>(ptr));
}
- static OptimalType convert(const Type &value)
+ static OptimalType Q_DECL_VECTORCALL convert(const Type &value)
{
return load(&value);
}
- static void store(Type *ptr, OptimalType value)
+ static void Q_DECL_VECTORCALL store(Type *ptr, OptimalType value)
{
- _mm_store_ps(reinterpret_cast<float *>(ptr), value);
+ _mm_storeu_ps(reinterpret_cast<float *>(ptr), value);
}
- static OptimalType add(OptimalType a, OptimalType b)
+ static OptimalType Q_DECL_VECTORCALL add(OptimalType a, OptimalType b)
{
return _mm_add_ps(a, b);
}
// same as above:
// static OptimalScalar add(OptimalScalar a, OptimalScalar b)
- static OptimalType plus(OptimalType a, OptimalType b)
+ static OptimalType Q_DECL_VECTORCALL plus(OptimalType a, OptimalType b)
{
a = _mm_add_ps(a, b);
__m128 aa = _mm_min_ps(a, _mm_set1_ps(1.0f));
@@ -461,37 +425,37 @@ struct RgbaFPOperationsSSE2 : public RgbaFPOperationsBase
a = _mm_shuffle_ps(a, aa, _MM_SHUFFLE(0, 2, 1, 0));
return a;
}
- static OptimalScalar alpha(OptimalType c)
+ static OptimalScalar Q_DECL_VECTORCALL alpha(OptimalType c)
{
return _mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 3, 3, 3));
}
- static OptimalScalar invAlpha(Scalar c)
+ static OptimalScalar Q_DECL_VECTORCALL invAlpha(Scalar c)
{
return _mm_set1_ps(1.0f - float(c));
}
- static OptimalScalar invAlpha(OptimalType c)
+ static OptimalScalar Q_DECL_VECTORCALL invAlpha(OptimalType c)
{
return _mm_sub_ps(_mm_set1_ps(1.0f), alpha(c));
}
- static OptimalScalar scalar(Scalar n)
+ static OptimalScalar Q_DECL_VECTORCALL scalar(Scalar n)
{
return _mm_set1_ps(float(n));
}
- static OptimalType multiplyAlpha(OptimalType val, OptimalScalar a)
+ static OptimalType Q_DECL_VECTORCALL multiplyAlpha(OptimalType val, OptimalScalar a)
{
return _mm_mul_ps(val, a);
}
- static OptimalType interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
+ static OptimalType Q_DECL_VECTORCALL interpolate(OptimalType x, OptimalScalar a1, OptimalType y, OptimalScalar a2)
{
return add(multiplyAlpha(x, a1), multiplyAlpha(y, a2));
}
- static OptimalType multiplyAlpha8bit(OptimalType val, uint8_t a)
+ static OptimalType Q_DECL_VECTORCALL multiplyAlpha8bit(OptimalType val, uint8_t a)
{
return multiplyAlpha(val, _mm_set1_ps(a * (1.0f / 255.0f)));
}
// same as above:
// static OptimalScalar multiplyAlpha8bit(OptimalScalar a, uint8_t a)
- static OptimalType interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
+ static OptimalType Q_DECL_VECTORCALL interpolate8bit(OptimalType x, uint8_t a1, OptimalType y, uint8_t a2)
{
return add(multiplyAlpha8bit(x, a1), multiplyAlpha8bit(y, a2));
}
@@ -1391,13 +1355,13 @@ private:
static inline int mix_alpha(int da, int sa)
{
- return 255 - ((255 - sa) * (255 - da) >> 8);
+ return 255 - qt_div_255((255 - sa) * (255 - da));
}
#if QT_CONFIG(raster_64bit)
static inline uint mix_alpha_rgb64(uint da, uint sa)
{
- return 65535U - ((65535U - sa) * (65535U - da) >> 16);
+ return 65535U - qt_div_65535((65535U - sa) * (65535U - da));
}
#endif
@@ -1807,7 +1771,7 @@ static inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint
int da = qAlpha(d);
int sa = qAlpha(s);
-#define OP(a, b) 255 - (((255-a) * (255-b)) >> 8)
+#define OP(a, b) 255 - qt_div_255((255-a) * (255-b))
int r = OP( qRed(d), qRed(s));
int b = OP( qBlue(d), qBlue(s));
int g = OP(qGreen(d), qGreen(s));
@@ -1837,7 +1801,7 @@ static inline void comp_func_Screen_impl(QRgba64 *Q_DECL_RESTRICT dest, const QR
uint da = d.alpha();
uint sa = s.alpha();
-#define OP(a, b) 65535U - (((65535U-a) * (65535U-b)) >> 16)
+#define OP(a, b) 65535U - qt_div_65535((65535U-a) * (65535U-b))
uint r = OP( d.red(), s.red());
uint b = OP( d.blue(), s.blue());
uint g = OP(d.green(), s.green());
diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm
index ef29f4a490..27b46202f5 100644
--- a/src/gui/painting/qcoregraphics.mm
+++ b/src/gui/painting/qcoregraphics.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcoregraphics_p.h"
@@ -58,22 +22,22 @@ CGBitmapInfo qt_mac_bitmapInfoForImage(const QImage &image)
CGBitmapInfo bitmapInfo = kCGImageAlphaNone;
switch (image.format()) {
case QImage::Format_ARGB32:
- bitmapInfo = kCGImageAlphaFirst | kCGBitmapByteOrder32Host;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaFirst) | kCGBitmapByteOrder32Host;
break;
case QImage::Format_RGB32:
- bitmapInfo = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaNoneSkipFirst) | kCGBitmapByteOrder32Host;
break;
case QImage::Format_RGBA8888_Premultiplied:
- bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaPremultipliedLast) | kCGBitmapByteOrder32Big;
break;
case QImage::Format_RGBA8888:
- bitmapInfo = kCGImageAlphaLast | kCGBitmapByteOrder32Big;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaLast) | kCGBitmapByteOrder32Big;
break;
case QImage::Format_RGBX8888:
- bitmapInfo = kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaNoneSkipLast) | kCGBitmapByteOrder32Big;
break;
case QImage::Format_ARGB32_Premultiplied:
- bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
+ bitmapInfo = CGBitmapInfo(kCGImageAlphaPremultipliedFirst) | kCGBitmapByteOrder32Host;
break;
default: break;
}
@@ -145,7 +109,7 @@ QT_END_NAMESPACE
// NSImage.
auto nsImage = [[NSImage alloc] initWithSize:NSZeroSize];
auto *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
- imageRep.size = (image.size() / image.devicePixelRatio()).toCGSize();
+ imageRep.size = image.deviceIndependentSize().toCGSize();
[nsImage addRepresentation:[imageRep autorelease]];
Q_ASSERT(CGSizeEqualToSize(nsImage.size, imageRep.size));
@@ -168,7 +132,7 @@ QT_END_NAMESPACE
auto nsImage = [[[NSImage alloc] initWithSize:NSZeroSize] autorelease];
- for (QSize size : qAsConst(availableSizes)) {
+ for (QSize size : std::as_const(availableSizes)) {
QImage image = icon.pixmap(size).toImage();
if (image.isNull())
continue;
@@ -178,7 +142,7 @@ QT_END_NAMESPACE
continue;
auto *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:cgImage];
- imageRep.size = (image.size() / image.devicePixelRatio()).toCGSize();
+ imageRep.size = image.deviceIndependentSize().toCGSize();
[nsImage addRepresentation:[imageRep autorelease]];
}
@@ -198,6 +162,9 @@ QT_BEGIN_NAMESPACE
QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size)
{
+ // ### TODO: add parameter so that we can decide whether to maintain the aspect
+ // ratio of the image (positioning the image inside the pixmap of size \a size),
+ // or whether we want to fill the resulting pixmap by stretching the image.
const NSSize pixmapSize = NSMakeSize(size.width(), size.height());
QPixmap pixmap(pixmapSize.width, pixmapSize.height);
pixmap.fill(Qt::transparent);
@@ -218,6 +185,25 @@ QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size)
#endif // Q_OS_MACOS
+#ifdef QT_PLATFORM_UIKIT
+
+QImage qt_mac_toQImage(const UIImage *image, QSizeF size)
+{
+ // ### TODO: same as above
+ QImage ret(size.width(), size.height(), QImage::Format_ARGB32_Premultiplied);
+ ret.fill(Qt::transparent);
+ QMacCGContext ctx(&ret);
+ if (!ctx)
+ return QImage();
+ UIGraphicsPushContext(ctx);
+ const CGRect rect = CGRectMake(0, 0, size.width(), size.height());
+ [image drawInRect:rect];
+ UIGraphicsPopContext();
+ return ret;
+}
+
+#endif // QT_PLATFORM_UIKIT
+
// ---------------------- Colors and Brushes ----------------------
QColor qt_mac_toQColor(CGColorRef color)
@@ -422,11 +408,14 @@ void QMacCGContext::initialize(QPaintDevice *paintDevice)
// Find the underlying QImage of the paint device
switch (int deviceType = paintDevice->devType()) {
case QInternal::Pixmap: {
- auto *platformPixmap = static_cast<QPixmap*>(paintDevice)->handle();
- if (platformPixmap && platformPixmap->classId() == QPlatformPixmap::RasterClass)
- initialize(platformPixmap->buffer());
- else
- qWarning() << "QMacCGContext: Unsupported pixmap class" << platformPixmap->classId();
+ if (auto *platformPixmap = static_cast<QPixmap*>(paintDevice)->handle()) {
+ if (platformPixmap->classId() == QPlatformPixmap::RasterClass)
+ initialize(platformPixmap->buffer());
+ else
+ qWarning() << "QMacCGContext: Unsupported pixmap class" << platformPixmap->classId();
+ } else {
+ qWarning() << "QMacCGContext: Empty platformPixmap";
+ }
break;
}
case QInternal::Image:
diff --git a/src/gui/painting/qcoregraphics_p.h b/src/gui/painting/qcoregraphics_p.h
index db012d3cda..a35f27a730 100644
--- a/src/gui/painting/qcoregraphics_p.h
+++ b/src/gui/painting/qcoregraphics_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOREGRAPHICS_P_H
#define QCOREGRAPHICS_P_H
@@ -59,19 +23,31 @@
#include <CoreGraphics/CoreGraphics.h>
-#if defined(__OBJC__) && defined(Q_OS_MACOS)
-#include <AppKit/AppKit.h>
-#define HAVE_APPKIT
+#if defined(__OBJC__)
+# if defined(Q_OS_MACOS)
+# include <AppKit/AppKit.h>
+# elif defined(QT_PLATFORM_UIKIT)
+# include <UIKit/UIKit.h>
+# endif
#endif
QT_BEGIN_NAMESPACE
Q_GUI_EXPORT CGBitmapInfo qt_mac_bitmapInfoForImage(const QImage &image);
-#ifdef HAVE_APPKIT
+#ifdef QT_PLATFORM_UIKIT
+Q_GUI_EXPORT QImage qt_mac_toQImage(const UIImage *image, QSizeF size);
+#endif
+
+#ifdef Q_OS_MACOS
Q_GUI_EXPORT QPixmap qt_mac_toQPixmap(const NSImage *image, const QSizeF &size);
QT_END_NAMESPACE
+
+// @compatibility_alias doesn't work with categories or their methods
+#define imageFromQImage QT_MANGLE_NAMESPACE(imageFromQImage)
+#define imageFromQIcon QT_MANGLE_NAMESPACE(imageFromQIcon)
+
@interface NSImage (QtExtras)
+ (instancetype)imageFromQImage:(const QT_PREPEND_NAMESPACE(QImage) &)image;
+ (instancetype)imageFromQIcon:(const QT_PREPEND_NAMESPACE(QIcon) &)icon;
@@ -88,7 +64,7 @@ Q_GUI_EXPORT void qt_mac_drawCGImage(CGContextRef inContext, const CGRect *inBou
Q_GUI_EXPORT void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig_xform);
-#ifdef HAVE_APPKIT
+#ifdef Q_OS_MACOS
Q_GUI_EXPORT QColor qt_mac_toQColor(const NSColor *color);
Q_GUI_EXPORT QBrush qt_mac_toQBrush(const NSColor *color, QPalette::ColorGroup colorGroup = QPalette::Normal);
#endif
@@ -112,6 +88,4 @@ private:
QT_END_NAMESPACE
-#undef HAVE_APPKIT
-
#endif // QCOREGRAPHICS_P_H
diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp
index a584ed5d0c..a0eddf65d9 100644
--- a/src/gui/painting/qcosmeticstroker.cpp
+++ b/src/gui/painting/qcosmeticstroker.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcosmeticstroker_p.h"
#include "private/qpainterpath_p.h"
@@ -299,7 +263,7 @@ void QCosmeticStroker::setup()
drawCaps = state->lastPen.capStyle() != Qt::FlatCap;
if (strokeSelection & FastDraw) {
- color = multiplyAlpha256(state->penData.solidColor, opacity).toArgb32();
+ color = multiplyAlpha256(state->penData.solidColor.rgba64(), opacity).toArgb32();
QRasterBuffer *buffer = state->penData.rasterBuffer;
pixels = reinterpret_cast<uint *>(buffer->buffer());
ppl = buffer->stride<quint32>();
@@ -400,7 +364,7 @@ void QCosmeticStroker::drawPoints(const QPoint *points, int num)
const QPoint *end = points + num;
while (points < end) {
QPointF p = QPointF(*points) * state->matrix;
- drawPixel(this, qRound(p.x()), qRound(p.y()), 255);
+ drawPixel(this, std::floor(p.x()), std::floor(p.y()), 255);
++points;
}
@@ -413,7 +377,7 @@ void QCosmeticStroker::drawPoints(const QPointF *points, int num)
const QPointF *end = points + num;
while (points < end) {
QPointF p = (*points) * state->matrix;
- drawPixel(this, qRound(p.x()), qRound(p.y()), 255);
+ drawPixel(this, std::floor(p.x()), std::floor(p.y()), 255);
++points;
}
diff --git a/src/gui/painting/qcosmeticstroker_p.h b/src/gui/painting/qcosmeticstroker_p.h
index 20ebe7bc1e..cb31ae4b71 100644
--- a/src/gui/painting/qcosmeticstroker_p.h
+++ b/src/gui/painting/qcosmeticstroker_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCOSMETICSTROKER_P_H
#define QCOSMETICSTROKER_P_H
diff --git a/src/gui/painting/qcssutil.cpp b/src/gui/painting/qcssutil.cpp
index 42e14b3d84..caface7d1a 100644
--- a/src/gui/painting/qcssutil.cpp
+++ b/src/gui/painting/qcssutil.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcssutil_p.h"
#include "private/qcssparser_p.h"
@@ -204,28 +168,28 @@ void qDrawEdge(QPainter *p, qreal x1, qreal y1, qreal x2, qreal y2, qreal dw1, q
if (width == 1 || (dw1 == 0 && dw2 == 0)) {
p->drawRect(QRectF(x1, y1, x2-x1, y2-y1));
} else { // draw trapezoid
- QPolygonF quad;
+ std::array<QPointF, 4> quad;
switch (edge) {
case TopEdge:
- quad << QPointF(x1, y1) << QPointF(x1 + dw1, y2)
- << QPointF(x2 - dw2, y2) << QPointF(x2, y1);
+ quad = {QPointF(x1, y1), QPointF(x1 + dw1, y2),
+ QPointF(x2 - dw2, y2), QPointF(x2, y1)};
break;
case BottomEdge:
- quad << QPointF(x1 + dw1, y1) << QPointF(x1, y2)
- << QPointF(x2, y2) << QPointF(x2 - dw2, y1);
+ quad = {QPointF(x1 + dw1, y1), QPointF(x1, y2),
+ QPointF(x2, y2), QPointF(x2 - dw2, y1)};
break;
case LeftEdge:
- quad << QPointF(x1, y1) << QPointF(x1, y2)
- << QPointF(x2, y2 - dw2) << QPointF(x2, y1 + dw1);
+ quad = {QPointF(x1, y1), QPointF(x1, y2),
+ QPointF(x2, y2 - dw2), QPointF(x2, y1 + dw1)};
break;
case RightEdge:
- quad << QPointF(x1, y1 + dw1) << QPointF(x1, y2 - dw2)
- << QPointF(x2, y2) << QPointF(x2, y1);
+ quad = {QPointF(x1, y1 + dw1), QPointF(x1, y2 - dw2),
+ QPointF(x2, y2), QPointF(x2, y1)};
break;
default:
break;
}
- p->drawConvexPolygon(quad);
+ p->drawConvexPolygon(quad.data(), static_cast<int>(quad.size()));
}
break;
}
@@ -304,6 +268,7 @@ void qDrawEdge(QPainter *p, qreal x1, qreal y1, qreal x2, qreal y2, qreal dw1, q
default:
break;
}
+ break;
}
default:
break;
@@ -352,7 +317,7 @@ void qDrawBorder(QPainter *p, const QRect &rect, const QCss::BorderStyle *styles
QSize tlr, trr, blr, brr;
qNormalizeRadii(rect, radii, &tlr, &trr, &blr, &brr);
- // Drawn in increasing order of precendence
+ // Drawn in increasing order of precedence
if (styles[BottomEdge] != BorderStyle_None && borders[BottomEdge] > 0) {
qreal dw1 = (blr.width() || paintsOver(styles, colors, BottomEdge, LeftEdge)) ? 0 : borders[LeftEdge];
qreal dw2 = (brr.width() || paintsOver(styles, colors, BottomEdge, RightEdge)) ? 0 : borders[RightEdge];
diff --git a/src/gui/painting/qcssutil_p.h b/src/gui/painting/qcssutil_p.h
index 3184b7fa22..34cb5170c1 100644
--- a/src/gui/painting/qcssutil_p.h
+++ b/src/gui/painting/qcssutil_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCSSUTIL_P_H
#define QCSSUTIL_P_H
diff --git a/src/gui/painting/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h
index c3b8c0fd85..8f467afe4e 100644
--- a/src/gui/painting/qdatabuffer_p.h
+++ b/src/gui/painting/qdatabuffer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDATABUFFER_P_H
#define QDATABUFFER_P_H
@@ -62,7 +26,7 @@ template <typename Type> class QDataBuffer
{
Q_DISABLE_COPY_MOVE(QDataBuffer)
public:
- QDataBuffer(int res)
+ explicit QDataBuffer(qsizetype res)
{
capacity = res;
if (res) {
@@ -87,11 +51,11 @@ public:
inline bool isEmpty() const { return siz==0; }
- inline int size() const { return siz; }
+ qsizetype size() const { return siz; }
inline Type *data() const { return buffer; }
- inline Type &at(int i) { Q_ASSERT(i >= 0 && i < siz); return buffer[i]; }
- inline const Type &at(int i) const { Q_ASSERT(i >= 0 && i < siz); return buffer[i]; }
+ Type &at(qsizetype i) { Q_ASSERT(i >= 0 && i < siz); return buffer[i]; }
+ const Type &at(qsizetype i) const { Q_ASSERT(i >= 0 && i < siz); return buffer[i]; }
inline Type &last() { Q_ASSERT(!isEmpty()); return buffer[siz-1]; }
inline const Type &last() const { Q_ASSERT(!isEmpty()); return buffer[siz-1]; }
inline Type &first() { Q_ASSERT(!isEmpty()); return buffer[0]; }
@@ -108,12 +72,12 @@ public:
--siz;
}
- inline void resize(int size) {
+ void resize(qsizetype size) {
reserve(size);
siz = size;
}
- inline void reserve(int size) {
+ void reserve(qsizetype size) {
if (size > capacity) {
if (capacity == 0)
capacity = 1;
@@ -124,14 +88,17 @@ public:
}
}
- inline void shrink(int size) {
+ void shrink(qsizetype size) {
+ Q_ASSERT(capacity >= size);
capacity = size;
if (size) {
buffer = (Type*) realloc(static_cast<void*>(buffer), capacity * sizeof(Type));
Q_CHECK_PTR(buffer);
+ siz = std::min(siz, size);
} else {
free(buffer);
buffer = nullptr;
+ siz = 0;
}
}
@@ -144,8 +111,8 @@ public:
inline QDataBuffer &operator<<(const Type &t) { add(t); return *this; }
private:
- int capacity;
- int siz;
+ qsizetype capacity;
+ qsizetype siz;
Type *buffer;
};
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 2029b2d7b9..b7a943be38 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdrawhelper_p.h"
@@ -61,6 +25,16 @@
#include <qloggingcategory.h>
#include <qmath.h>
+#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+#define QT_USE_THREAD_PARALLEL_FILLS
+#endif
+
+#if defined(QT_USE_THREAD_PARALLEL_FILLS)
+#include <qsemaphore.h>
+#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
+#endif
+
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQtGuiDrawHelper, "qt.gui.drawhelper")
@@ -77,8 +51,7 @@ constexpr int half_point = 1 << 15;
template <QPixelLayout::BPP bpp> static
inline uint QT_FASTCALL fetch1Pixel(const uchar *, int)
{
- Q_UNREACHABLE();
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
template <>
@@ -203,7 +176,7 @@ static void QT_FASTCALL convertRGBA32FPMToRGBA64PM(QRgba64 *buffer, int count)
}
}
-static Convert64Func convert64ToRGBA64PM[QImage::NImageFormats] = {
+static Convert64Func convert64ToRGBA64PM[] = {
nullptr,
nullptr,
nullptr,
@@ -240,7 +213,10 @@ static Convert64Func convert64ToRGBA64PM[QImage::NImageFormats] = {
convertRGBA32FPMToRGBA64PM,
convertRGBA32FToRGBA64PM,
convertRGBA32FPMToRGBA64PM,
+ nullptr,
};
+
+static_assert(std::size(convert64ToRGBA64PM) == QImage::NImageFormats);
#endif
#if QT_CONFIG(raster_fp)
@@ -274,7 +250,7 @@ static void QT_FASTCALL convertRGBA16FToRGBA32F(QRgbaFloat32 *buffer, const quin
qFloatFromFloat16((float *)buffer, (const qfloat16 *)src, count * 4);
}
-static Convert64ToFPFunc convert64ToRGBA32F[QImage::NImageFormats] = {
+static Convert64ToFPFunc convert64ToRGBA32F[] = {
nullptr,
nullptr,
nullptr,
@@ -311,8 +287,11 @@ static Convert64ToFPFunc convert64ToRGBA32F[QImage::NImageFormats] = {
nullptr,
nullptr,
nullptr,
+ nullptr,
};
+static_assert(std::size(convert64ToRGBA32F) == QImage::NImageFormats);
+
static void convertRGBA32FToRGBA32FPM(QRgbaFloat32 *buffer, int count)
{
for (int i = 0; i < count; ++i)
@@ -380,7 +359,7 @@ static uint *QT_FASTCALL destFetchUndefined(uint *buffer, QRasterBuffer *, int,
return buffer;
}
-static DestFetchProc destFetchProc[QImage::NImageFormats] =
+static DestFetchProc destFetchProc[] =
{
nullptr, // Format_Invalid
destFetchMono, // Format_Mono,
@@ -418,8 +397,11 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
destFetch, // Format_RGBX32FPx4
destFetch, // Format_RGBA32FPx4
destFetch, // Format_RGBA32FPx4_Premultiplied
+ destFetch, // Format_CMYK8888
};
+static_assert(std::size(destFetchProc) == QImage::NImageFormats);
+
#if QT_CONFIG(raster_64bit)
static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length)
{
@@ -437,7 +419,7 @@ static QRgba64 * QT_FASTCALL destFetch64Undefined(QRgba64 *buffer, QRasterBuffer
return buffer;
}
-static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
+static DestFetchProc64 destFetchProc64[] =
{
nullptr, // Format_Invalid
nullptr, // Format_Mono,
@@ -475,7 +457,10 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
destFetch64, // Format_RGBX32FPx4
destFetch64, // Format_RGBA32FPx4
destFetch64, // Format_RGBA32FPx4_Premultiplied
+ destFetch64, // Format_CMYK8888
};
+
+static_assert(std::size(destFetchProc64) == QImage::NImageFormats);
#endif
#if QT_CONFIG(raster_fp)
@@ -484,10 +469,57 @@ static QRgbaFloat32 *QT_FASTCALL destFetchFP(QRgbaFloat32 *buffer, QRasterBuffer
return const_cast<QRgbaFloat32 *>(qFetchToRGBA32F[rasterBuffer->format](buffer, rasterBuffer->scanLine(y), x, length, nullptr, nullptr));
}
+static QRgbaFloat32 *QT_FASTCALL destFetchRGBFP(QRgbaFloat32 *, QRasterBuffer *rasterBuffer, int x, int y, int)
+{
+ return reinterpret_cast<QRgbaFloat32 *>(rasterBuffer->scanLine(y)) + x;
+}
+
static QRgbaFloat32 *QT_FASTCALL destFetchFPUndefined(QRgbaFloat32 *buffer, QRasterBuffer *, int, int, int)
{
return buffer;
}
+static DestFetchProcFP destFetchProcFP[] =
+{
+ nullptr, // Format_Invalid
+ nullptr, // Format_Mono,
+ nullptr, // Format_MonoLSB
+ nullptr, // Format_Indexed8
+ destFetchFP, // Format_RGB32
+ destFetchFP, // Format_ARGB32,
+ destFetchFP, // Format_ARGB32_Premultiplied
+ destFetchFP, // Format_RGB16
+ destFetchFP, // Format_ARGB8565_Premultiplied
+ destFetchFP, // Format_RGB666
+ destFetchFP, // Format_ARGB6666_Premultiplied
+ destFetchFP, // Format_RGB555
+ destFetchFP, // Format_ARGB8555_Premultiplied
+ destFetchFP, // Format_RGB888
+ destFetchFP, // Format_RGB444
+ destFetchFP, // Format_ARGB4444_Premultiplied
+ destFetchFP, // Format_RGBX8888
+ destFetchFP, // Format_RGBA8888
+ destFetchFP, // Format_RGBA8888_Premultiplied
+ destFetchFP, // Format_BGR30
+ destFetchFP, // Format_A2BGR30_Premultiplied
+ destFetchFP, // Format_RGB30
+ destFetchFP, // Format_A2RGB30_Premultiplied
+ destFetchFP, // Format_Alpha8
+ destFetchFP, // Format_Grayscale8
+ destFetchFP, // Format_RGBX64
+ destFetchFP, // Format_RGBA64
+ destFetchFP, // Format_RGBA64_Premultiplied
+ destFetchFP, // Format_Grayscale16
+ destFetchFP, // Format_BGR888
+ destFetchFP, // Format_RGBX16FPx4
+ destFetchFP, // Format_RGBA16FPx4
+ destFetchFP, // Format_RGBA16FPx4_Premultiplied
+ destFetchRGBFP, // Format_RGBX32FPx4
+ destFetchFP, // Format_RGBA32FPx4
+ destFetchRGBFP, // Format_RGBA32FPx4_Premultiplied
+ destFetchFP, // Format_CMYK8888
+};
+
+static_assert(std::size(destFetchProcFP) == QImage::NImageFormats);
#endif
/*
@@ -496,9 +528,8 @@ static QRgbaFloat32 *QT_FASTCALL destFetchFPUndefined(QRgbaFloat32 *buffer, QRas
*/
static inline QRgb findNearestColor(QRgb color, QRasterBuffer *rbuf)
{
- QRgb color_0 = qPremultiply(rbuf->destColor0);
- QRgb color_1 = qPremultiply(rbuf->destColor1);
- color = qPremultiply(color);
+ const QRgb color_0 = rbuf->destColor0;
+ const QRgb color_1 = rbuf->destColor1;
int r = qRed(color);
int g = qGreen(color);
@@ -613,7 +644,7 @@ static void QT_FASTCALL destStoreGray8(QRasterBuffer *rasterBuffer, int x, int y
QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
- tfd->apply(data, buffer, length, QColorTransformPrivate::InputPremultiplied);
+ tfd->applyReturnGray(data, buffer, length, QColorTransformPrivate::InputPremultiplied);
}
}
@@ -637,11 +668,11 @@ static void QT_FASTCALL destStoreGray16(QRasterBuffer *rasterBuffer, int x, int
QRgba64 tmp_line[BufferSize];
for (int k = 0; k < length; ++k)
tmp_line[k] = QRgba64::fromArgb32(buffer[k]);
- tfd->apply(data, tmp_line, length, QColorTransformPrivate::InputPremultiplied);
+ tfd->applyReturnGray(data, tmp_line, length, QColorTransformPrivate::InputPremultiplied);
}
}
-static DestStoreProc destStoreProc[QImage::NImageFormats] =
+static DestStoreProc destStoreProc[] =
{
nullptr, // Format_Invalid
destStoreMono, // Format_Mono,
@@ -679,8 +710,11 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] =
destStore, // Format_RGBX32FPx4
destStore, // Format_RGBA32FPx4
destStore, // Format_RGBA32FPx4_Premultiplied
+ destStore, // Format_CMYK8888
};
+static_assert(std::size(destStoreProc) == QImage::NImageFormats);
+
#if QT_CONFIG(raster_64bit)
static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length)
{
@@ -715,7 +749,7 @@ static void QT_FASTCALL destStore64Gray8(QRasterBuffer *rasterBuffer, int x, int
QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
quint16 gray_line[BufferSize];
- tfd->apply(gray_line, buffer, length, QColorTransformPrivate::InputPremultiplied);
+ tfd->applyReturnGray(gray_line, buffer, length, QColorTransformPrivate::InputPremultiplied);
for (int k = 0; k < length; ++k)
data[k] = qt_div_257(gray_line[k]);
}
@@ -737,11 +771,11 @@ static void QT_FASTCALL destStore64Gray16(QRasterBuffer *rasterBuffer, int x, in
QColorSpace fromCS = rasterBuffer->colorSpace.isValid() ? rasterBuffer->colorSpace : QColorSpace::SRgb;
QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
- tfd->apply(data, buffer, length, QColorTransformPrivate::InputPremultiplied);
+ tfd->applyReturnGray(data, buffer, length, QColorTransformPrivate::InputPremultiplied);
}
}
-static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
+static DestStoreProc64 destStoreProc64[] =
{
nullptr, // Format_Invalid
nullptr, // Format_Mono,
@@ -779,7 +813,10 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
destStore64, // Format_RGBX32FPx4
destStore64, // Format_RGBA32FPx4
destStore64, // Format_RGBA32FPx4_Premultiplied
+ destStore64, // Format_CMYK8888
};
+
+static_assert(std::size(destStoreProc64) == QImage::NImageFormats);
#endif
#if QT_CONFIG(raster_fp)
@@ -3054,7 +3091,7 @@ static const QRgbaFloat32 *QT_FASTCALL fetchTransformedBilinearFP(QRgbaFloat32 *
#endif // QT_CONFIG(raster_fp)
// FetchUntransformed can have more specialized methods added depending on SIMD features.
-static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
+static SourceFetchProc sourceFetchUntransformed[] = {
nullptr, // Invalid
fetchUntransformed, // Mono
fetchUntransformed, // MonoLsb
@@ -3091,9 +3128,12 @@ static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
fetchUntransformed, // RGBX32Px4
fetchUntransformed, // RGBA32FPx4
fetchUntransformed, // RGBA32FPx4_Premultiplied
+ fetchUntransformed, // CMYK8888
};
-static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = {
+static_assert(std::size(sourceFetchUntransformed) == QImage::NImageFormats);
+
+static const SourceFetchProc sourceFetchGeneric[] = {
fetchUntransformed, // Untransformed
fetchUntransformed, // Tiled
fetchTransformed<BlendTransformed, QPixelLayout::BPPNone>, // Transformed
@@ -3102,7 +3142,9 @@ static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = {
fetchTransformedBilinear<BlendTransformedBilinearTiled, QPixelLayout::BPPNone> // TransformedBilinearTiled
};
-static SourceFetchProc sourceFetchARGB32PM[NBlendTypes] = {
+static_assert(std::size(sourceFetchGeneric) == NBlendTypes);
+
+static SourceFetchProc sourceFetchARGB32PM[] = {
fetchUntransformedARGB32PM, // Untransformed
fetchUntransformedARGB32PM, // Tiled
fetchTransformed<BlendTransformed, QPixelLayout::BPP32>, // Transformed
@@ -3111,7 +3153,9 @@ static SourceFetchProc sourceFetchARGB32PM[NBlendTypes] = {
fetchTransformedBilinearARGB32PM<BlendTransformedBilinearTiled> // BilinearTiled
};
-static SourceFetchProc sourceFetchAny16[NBlendTypes] = {
+static_assert(std::size(sourceFetchARGB32PM) == NBlendTypes);
+
+static SourceFetchProc sourceFetchAny16[] = {
fetchUntransformed, // Untransformed
fetchUntransformed, // Tiled
fetchTransformed<BlendTransformed, QPixelLayout::BPP16>, // Transformed
@@ -3120,7 +3164,9 @@ static SourceFetchProc sourceFetchAny16[NBlendTypes] = {
fetchTransformedBilinear<BlendTransformedBilinearTiled, QPixelLayout::BPP16> // TransformedBilinearTiled
};
-static SourceFetchProc sourceFetchAny32[NBlendTypes] = {
+static_assert(std::size(sourceFetchAny16) == NBlendTypes);
+
+static SourceFetchProc sourceFetchAny32[] = {
fetchUntransformed, // Untransformed
fetchUntransformed, // Tiled
fetchTransformed<BlendTransformed, QPixelLayout::BPP32>, // Transformed
@@ -3129,6 +3175,8 @@ static SourceFetchProc sourceFetchAny32[NBlendTypes] = {
fetchTransformedBilinear<BlendTransformedBilinearTiled, QPixelLayout::BPP32> // TransformedBilinearTiled
};
+static_assert(std::size(sourceFetchAny32) == NBlendTypes);
+
static inline SourceFetchProc getSourceFetch(TextureBlendType blendType, QImage::Format format)
{
if (format == QImage::Format_RGB32 || format == QImage::Format_ARGB32_Premultiplied)
@@ -3143,7 +3191,7 @@ static inline SourceFetchProc getSourceFetch(TextureBlendType blendType, QImage:
}
#if QT_CONFIG(raster_64bit)
-static const SourceFetchProc64 sourceFetchGeneric64[NBlendTypes] = {
+static const SourceFetchProc64 sourceFetchGeneric64[] = {
fetchUntransformed64, // Untransformed
fetchUntransformed64, // Tiled
fetchTransformed64<BlendTransformed>, // Transformed
@@ -3152,7 +3200,9 @@ static const SourceFetchProc64 sourceFetchGeneric64[NBlendTypes] = {
fetchTransformedBilinear64<BlendTransformedBilinearTiled> // BilinearTiled
};
-static const SourceFetchProc64 sourceFetchRGBA64PM[NBlendTypes] = {
+static_assert(std::size(sourceFetchGeneric64) == NBlendTypes);
+
+static const SourceFetchProc64 sourceFetchRGBA64PM[] = {
fetchUntransformedRGBA64PM, // Untransformed
fetchUntransformedRGBA64PM, // Tiled
fetchTransformed64<BlendTransformed>, // Transformed
@@ -3161,6 +3211,8 @@ static const SourceFetchProc64 sourceFetchRGBA64PM[NBlendTypes] = {
fetchTransformedBilinear64<BlendTransformedBilinearTiled> // BilinearTiled
};
+static_assert(std::size(sourceFetchRGBA64PM) == NBlendTypes);
+
static inline SourceFetchProc64 getSourceFetch64(TextureBlendType blendType, QImage::Format format)
{
if (format == QImage::Format_RGBX64 || format == QImage::Format_RGBA64_Premultiplied)
@@ -3170,7 +3222,7 @@ static inline SourceFetchProc64 getSourceFetch64(TextureBlendType blendType, QIm
#endif
#if QT_CONFIG(raster_fp)
-static const SourceFetchProcFP sourceFetchGenericFP[NBlendTypes] = {
+static const SourceFetchProcFP sourceFetchGenericFP[] = {
fetchUntransformedFP, // Untransformed
fetchUntransformedFP, // Tiled
fetchTransformedFP<BlendTransformed>, // Transformed
@@ -3179,6 +3231,8 @@ static const SourceFetchProcFP sourceFetchGenericFP[NBlendTypes] = {
fetchTransformedBilinearFP<BlendTransformedBilinearTiled> // BilinearTiled
};
+static_assert(std::size(sourceFetchGenericFP) == NBlendTypes);
+
static inline SourceFetchProcFP getSourceFetchFP(TextureBlendType blendType, QImage::Format /*format*/)
{
return sourceFetchGenericFP[blendType];
@@ -3239,6 +3293,7 @@ public:
static Type null() { return 0; }
static Type fetchSingle(const QGradientData& gradient, qreal v)
{
+ Q_ASSERT(std::isfinite(v));
return qt_gradient_pixel(&gradient, v);
}
static Type fetchSingle(const QGradientData& gradient, int v)
@@ -3259,6 +3314,7 @@ public:
static Type null() { return QRgba64::fromRgba64(0); }
static Type fetchSingle(const QGradientData& gradient, qreal v)
{
+ Q_ASSERT(std::isfinite(v));
return qt_gradient_pixel64(&gradient, v);
}
static Type fetchSingle(const QGradientData& gradient, int v)
@@ -3280,6 +3336,7 @@ public:
static Type null() { return QRgbaFloat32::fromRgba64(0,0,0,0); }
static Type fetchSingle(const QGradientData& gradient, qreal v)
{
+ Q_ASSERT(std::isfinite(v));
return qt_gradient_pixelFP(&gradient, v);
}
static Type fetchSingle(const QGradientData& gradient, int v)
@@ -3397,7 +3454,6 @@ static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const Q
v->sqrfr = data->gradient.radial.focal.radius * data->gradient.radial.focal.radius;
v->a = v->dr * v->dr - v->dx*v->dx - v->dy*v->dy;
- v->inv2a = 1 / (2 * v->a);
v->extended = !qFuzzyIsNull(data->gradient.radial.focal.radius) || v->a <= 0;
}
@@ -3430,7 +3486,13 @@ public:
}
} else {
while (buffer < end) {
- *buffer++ = GradientBase::fetchSingle(data->gradient, qSqrt(det) - b);
+ BlendType result = GradientBase::null();
+ if (det >= 0) {
+ qreal w = qSqrt(det) - b;
+ result = GradientBase::fetchSingle(data->gradient, w);
+ }
+
+ *buffer++ = result;
det += delta_det;
delta_det += delta_delta_det;
@@ -3564,34 +3626,33 @@ static const CompositionFunctionFP *functionForModeFP = qt_functionForModeFP_C;
static TextureBlendType getBlendType(const QSpanData *data)
{
TextureBlendType ft;
- if (data->txop <= QTransform::TxTranslate)
- if (data->texture.type == QTextureData::Tiled || data->texture.type == QTextureData::Pattern)
+ if (data->texture.type == QTextureData::Pattern)
+ ft = BlendTiled;
+ else if (data->txop <= QTransform::TxTranslate)
+ if (data->texture.type == QTextureData::Tiled)
ft = BlendTiled;
else
ft = BlendUntransformed;
else if (data->bilinear)
- if (data->texture.type == QTextureData::Tiled || data->texture.type == QTextureData::Pattern)
+ if (data->texture.type == QTextureData::Tiled)
ft = BlendTransformedBilinearTiled;
else
ft = BlendTransformedBilinear;
else
- if (data->texture.type == QTextureData::Pattern)
- ft = BlendTiled;
- else if (data->texture.type == QTextureData::Tiled)
+ if (data->texture.type == QTextureData::Tiled)
ft = BlendTransformedTiled;
else
ft = BlendTransformed;
return ft;
}
-static inline Operator getOperator(const QSpanData *data, const QSpan *spans, int spanCount)
+static inline Operator getOperator(const QSpanData *data, const QT_FT_Span *spans, int spanCount)
{
Operator op;
bool solidSource = false;
-
switch(data->type) {
case QSpanData::Solid:
- solidSource = data->solidColor.isOpaque();
+ solidSource = data->solidColor.alphaF() >= 1.0f;
op.srcFetch = nullptr;
op.srcFetch64 = nullptr;
op.srcFetchFP = nullptr;
@@ -3632,7 +3693,7 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
solidSource = !data->texture.hasAlpha;
op.srcFetch = getSourceFetch(getBlendType(data), data->texture.format);
#if QT_CONFIG(raster_64bit)
- op.srcFetch64 = getSourceFetch64(getBlendType(data), data->texture.format);;
+ op.srcFetch64 = getSourceFetch64(getBlendType(data), data->texture.format);
#endif
#if QT_CONFIG(raster_fp)
op.srcFetchFP = getSourceFetchFP(getBlendType(data), data->texture.format);
@@ -3660,14 +3721,13 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
op.destFetch64 = nullptr;
#endif
#if QT_CONFIG(raster_fp)
- if (data->rasterBuffer->format > QImage::Format_Indexed8)
- op.destFetchFP = destFetchFP;
- else
+ op.destFetchFP = destFetchProcFP[data->rasterBuffer->format];
+#else
+ op.destFetchFP = nullptr;
#endif
- op.destFetchFP = nullptr;
if (op.mode == QPainter::CompositionMode_Source &&
(data->type != QSpanData::Texture || data->texture.const_alpha == 256)) {
- const QSpan *lastSpan = spans + spanCount;
+ const QT_FT_Span *lastSpan = spans + spanCount;
bool alphaSpans = false;
while (spans < lastSpan) {
if (spans->coverage != 255) {
@@ -3686,7 +3746,8 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in
op.destFetch64 = destFetch64Undefined;
#endif
#if QT_CONFIG(raster_fp)
- op.destFetchFP = destFetchFPUndefined;
+ if (op.destFetchFP != destFetchRGBFP)
+ op.destFetchFP = destFetchFPUndefined;
#endif
}
}
@@ -3758,44 +3819,69 @@ static void spanfill_from_first(QRasterBuffer *rasterBuffer, QPixelLayout::BPP b
// -------------------- blend methods ---------------------
-static void blend_color_generic(int count, const QSpan *spans, void *userData)
+#if defined(QT_USE_THREAD_PARALLEL_FILLS)
+#define QT_THREAD_PARALLEL_FILLS(function) \
+ const int segments = (count + 32) / 64; \
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance(); \
+ if (segments > 1 && qPixelLayouts[data->rasterBuffer->format].bpp >= QPixelLayout::BPP8 \
+ && threadPool && !threadPool->contains(QThread::currentThread())) { \
+ QSemaphore semaphore; \
+ int c = 0; \
+ for (int i = 0; i < segments; ++i) { \
+ int cn = (count - c) / (segments - i); \
+ threadPool->start([&, c, cn]() { \
+ function(c, c + cn); \
+ semaphore.release(1); \
+ }, 1); \
+ c += cn; \
+ } \
+ semaphore.acquire(segments); \
+ } else \
+ function(0, count)
+#else
+#define QT_THREAD_PARALLEL_FILLS(function) function(0, count)
+#endif
+
+static void blend_color_generic(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- uint buffer[BufferSize];
- Operator op = getOperator(data, nullptr, 0);
- const uint color = data->solidColor.toArgb32();
+ const Operator op = getOperator(data, nullptr, 0);
+ const uint color = data->solidColor.rgba();
const bool solidFill = op.mode == QPainter::CompositionMode_Source;
const QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp;
- while (count--) {
- int x = spans->x;
- int length = spans->len;
- if (solidFill && bpp >= QPixelLayout::BPP8 && spans->coverage == 255 && length) {
- // If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
- op.destStore(data->rasterBuffer, x, spans->y, &color, 1);
- spanfill_from_first(data->rasterBuffer, bpp, x, spans->y, length);
- length = 0;
- }
+ auto function = [=] (int cStart, int cEnd) {
+ alignas(16) uint buffer[BufferSize];
+ for (int c = cStart; c < cEnd; ++c) {
+ int x = spans[c].x;
+ int length = spans[c].len;
+ if (solidFill && bpp >= QPixelLayout::BPP8 && spans[c].coverage == 255 && length && op.destStore) {
+ // If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
+ op.destStore(data->rasterBuffer, x, spans[c].y, &color, 1);
+ spanfill_from_first(data->rasterBuffer, bpp, x, spans[c].y, length);
+ length = 0;
+ }
- while (length) {
- int l = qMin(BufferSize, length);
- uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans->y, l);
- op.funcSolid(dest, l, color, spans->coverage);
- if (op.destStore)
- op.destStore(data->rasterBuffer, x, spans->y, dest, l);
- length -= l;
- x += l;
+ while (length) {
+ int l = qMin(BufferSize, length);
+ uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans[c].y, l);
+ op.funcSolid(dest, l, color, spans[c].coverage);
+ if (op.destStore)
+ op.destStore(data->rasterBuffer, x, spans[c].y, dest, l);
+ length -= l;
+ x += l;
+ }
}
- ++spans;
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
-static void blend_color_argb(int count, const QSpan *spans, void *userData)
+static void blend_color_argb(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
const Operator op = getOperator(data, nullptr, 0);
- const uint color = data->solidColor.toArgb32();
+ const uint color = data->solidColor.rgba();
if (op.mode == QPainter::CompositionMode_Source) {
// inline for performance
@@ -3817,155 +3903,167 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
}
return;
}
-
- while (count--) {
- uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
- op.funcSolid(target, spans->len, color, spans->coverage);
- ++spans;
- }
+ const auto funcSolid = op.funcSolid;
+ auto function = [=] (int cStart, int cEnd) {
+ for (int c = cStart; c < cEnd; ++c) {
+ uint *target = ((uint *)data->rasterBuffer->scanLine(spans[c].y)) + spans[c].x;
+ funcSolid(target, spans[c].len, color, spans[c].coverage);
+ }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
-static void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
+static void blend_color_generic_rgb64(int count, const QT_FT_Span *spans, void *userData)
{
#if QT_CONFIG(raster_64bit)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, nullptr, 0);
+ const Operator op = getOperator(data, nullptr, 0);
if (!op.funcSolid64) {
qCDebug(lcQtGuiDrawHelper, "blend_color_generic_rgb64: unsupported 64bit blend attempted, falling back to 32-bit");
return blend_color_generic(count, spans, userData);
}
- alignas(8) QRgba64 buffer[BufferSize];
- const QRgba64 color = data->solidColor;
+ const QRgba64 color = data->solidColor.rgba64();
const bool solidFill = op.mode == QPainter::CompositionMode_Source;
const QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp;
- while (count--) {
- int x = spans->x;
- int length = spans->len;
- if (solidFill && bpp >= QPixelLayout::BPP8 && spans->coverage == 255 && length && op.destStore64) {
- // If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
- op.destStore64(data->rasterBuffer, x, spans->y, &color, 1);
- spanfill_from_first(data->rasterBuffer, bpp, x, spans->y, length);
- length = 0;
- }
+ auto function = [=, &op] (int cStart, int cEnd)
+ {
+ alignas(16) QRgba64 buffer[BufferSize];
+ for (int c = cStart; c < cEnd; ++c) {
+ int x = spans[c].x;
+ int length = spans[c].len;
+ if (solidFill && bpp >= QPixelLayout::BPP8 && spans[c].coverage == 255 && length && op.destStore64) {
+ // If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
+ op.destStore64(data->rasterBuffer, x, spans[c].y, &color, 1);
+ spanfill_from_first(data->rasterBuffer, bpp, x, spans[c].y, length);
+ length = 0;
+ }
- while (length) {
- int l = qMin(BufferSize, length);
- QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
- op.funcSolid64(dest, l, color, spans->coverage);
- if (op.destStore64)
- op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
- length -= l;
- x += l;
+ while (length) {
+ int l = qMin(BufferSize, length);
+ QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans[c].y, l);
+ op.funcSolid64(dest, l, color, spans[c].coverage);
+ if (op.destStore64)
+ op.destStore64(data->rasterBuffer, x, spans[c].y, dest, l);
+ length -= l;
+ x += l;
+ }
}
- ++spans;
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
#else
blend_color_generic(count, spans, userData);
#endif
}
-static void blend_color_generic_fp(int count, const QSpan *spans, void *userData)
+static void blend_color_generic_fp(int count, const QT_FT_Span *spans, void *userData)
{
#if QT_CONFIG(raster_fp)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, nullptr, 0);
+ const Operator op = getOperator(data, nullptr, 0);
if (!op.funcSolidFP || !op.destFetchFP) {
qCDebug(lcQtGuiDrawHelper, "blend_color_generic_fp: unsupported 4xF16 blend attempted, falling back to 32-bit");
return blend_color_generic(count, spans, userData);
}
- QRgbaFloat32 buffer[BufferSize];
- const QRgbaFloat32 color = qConvertRgb64ToRgbaF32(data->solidColor);
+ float r, g, b, a;
+ data->solidColor.getRgbF(&r, &g, &b, &a);
+ const QRgbaFloat32 color{r, g, b, a};
const bool solidFill = op.mode == QPainter::CompositionMode_Source;
QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp;
- while (count--) {
- int x = spans->x;
- int length = spans->len;
- if (solidFill && bpp >= QPixelLayout::BPP8 && spans->coverage == 255 && length && op.destStoreFP) {
- // If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
- op.destStoreFP(data->rasterBuffer, x, spans->y, &color, 1);
- spanfill_from_first(data->rasterBuffer, bpp, x, spans->y, length);
- length = 0;
- }
+ auto function = [=, &op] (int cStart, int cEnd)
+ {
+ alignas(16) QRgbaFloat32 buffer[BufferSize];
+ for (int c = cStart; c < cEnd; ++c) {
+ int x = spans[c].x;
+ int length = spans[c].len;
+ if (solidFill && bpp >= QPixelLayout::BPP8 && spans[c].coverage == 255 && length && op.destStoreFP) {
+ // If dest doesn't matter we don't need to bother with blending or converting all the identical pixels
+ op.destStoreFP(data->rasterBuffer, x, spans[c].y, &color, 1);
+ spanfill_from_first(data->rasterBuffer, bpp, x, spans[c].y, length);
+ length = 0;
+ }
- while (length) {
- int l = qMin(BufferSize, length);
- QRgbaFloat32 *dest = op.destFetchFP(buffer, data->rasterBuffer, x, spans->y, l);
- op.funcSolidFP(dest, l, color, spans->coverage);
- if (op.destStoreFP)
- op.destStoreFP(data->rasterBuffer, x, spans->y, dest, l);
- length -= l;
- x += l;
+ while (length) {
+ int l = qMin(BufferSize, length);
+ QRgbaFloat32 *dest = op.destFetchFP(buffer, data->rasterBuffer, x, spans[c].y, l);
+ op.funcSolidFP(dest, l, color, spans[c].coverage);
+ if (op.destStoreFP)
+ op.destStoreFP(data->rasterBuffer, x, spans[c].y, dest, l);
+ length -= l;
+ x += l;
+ }
}
- ++spans;
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
#else
blend_color_generic(count, spans, userData);
#endif
}
template <typename T>
-void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handler)
+void handleSpans(int count, const QT_FT_Span *spans, const QSpanData *data, const Operator &op)
{
- uint const_alpha = 256;
- if (data->type == QSpanData::Texture)
- const_alpha = data->texture.const_alpha;
+ const int const_alpha = (data->type == QSpanData::Texture) ? data->texture.const_alpha : 256;
+ const bool solidSource = op.mode == QPainter::CompositionMode_Source && const_alpha == 256;
- int coverage = 0;
- while (count) {
- if (!spans->len) {
- ++spans;
- --count;
- continue;
- }
- int x = spans->x;
- const int y = spans->y;
- int right = x + spans->len;
+ auto function = [=, &op] (int cStart, int cEnd)
+ {
+ T handler(data, op);
+ int coverage = 0;
+ for (int c = cStart; c < cEnd;) {
+ if (!spans[c].len) {
+ ++c;
+ continue;
+ }
+ int x = spans[c].x;
+ const int y = spans[c].y;
+ int right = x + spans[c].len;
+ const bool fetchDest = !solidSource || spans[c].coverage < 255;
- // compute length of adjacent spans
- for (int i = 1; i < count && spans[i].y == y && spans[i].x == right; ++i)
- right += spans[i].len;
- int length = right - x;
+ // compute length of adjacent spans
+ for (int i = c + 1; i < cEnd && spans[i].y == y && spans[i].x == right && fetchDest == (!solidSource || spans[i].coverage < 255); ++i)
+ right += spans[i].len;
+ int length = right - x;
- while (length) {
- int l = qMin(BufferSize, length);
- length -= l;
+ while (length) {
+ int l = qMin(BufferSize, length);
+ length -= l;
- int process_length = l;
- int process_x = x;
+ int process_length = l;
+ int process_x = x;
- const auto *src = handler.fetch(process_x, y, process_length);
- int offset = 0;
- while (l > 0) {
- if (x == spans->x) // new span?
- coverage = (spans->coverage * const_alpha) >> 8;
+ const auto *src = handler.fetch(process_x, y, process_length, fetchDest);
+ int offset = 0;
+ while (l > 0) {
+ if (x == spans[c].x) // new span?
+ coverage = (spans[c].coverage * const_alpha) >> 8;
- int right = spans->x + spans->len;
- int len = qMin(l, right - x);
+ int right = spans[c].x + spans[c].len;
+ int len = qMin(l, right - x);
- handler.process(x, y, len, coverage, src, offset);
+ handler.process(x, y, len, coverage, src, offset);
- l -= len;
- x += len;
- offset += len;
+ l -= len;
+ x += len;
+ offset += len;
- if (x == right) { // done with current span?
- ++spans;
- --count;
+ if (x == right) // done with current span?
+ ++c;
}
+ handler.store(process_x, y, process_length);
}
- handler.store(process_x, y, process_length);
}
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
struct QBlendBase
{
- QSpanData *data;
- Operator op;
+ const QSpanData *data;
+ const Operator &op;
};
class BlendSrcGeneric : public QBlendBase
@@ -3974,14 +4072,17 @@ public:
uint *dest = nullptr;
alignas(16) uint buffer[BufferSize];
alignas(16) uint src_buffer[BufferSize];
- BlendSrcGeneric(QSpanData *d, const Operator &o)
+ BlendSrcGeneric(const QSpanData *d, const Operator &o)
: QBlendBase{d, o}
{
}
- const uint *fetch(int x, int y, int len)
+ const uint *fetch(int x, int y, int len, bool fetchDest)
{
- dest = op.destFetch(buffer, data->rasterBuffer, x, y, len);
+ if (fetchDest || op.destFetch == destFetchARGB32P)
+ dest = op.destFetch(buffer, data->rasterBuffer, x, y, len);
+ else
+ dest = buffer;
return op.srcFetch(src_buffer, &op, data, y, x, len);
}
@@ -4004,7 +4105,7 @@ public:
QRgba64 *dest = nullptr;
alignas(16) QRgba64 buffer[BufferSize];
alignas(16) QRgba64 src_buffer[BufferSize];
- BlendSrcGenericRGB64(QSpanData *d, const Operator &o)
+ BlendSrcGenericRGB64(const QSpanData *d, const Operator &o)
: QBlendBase{d, o}
{
}
@@ -4014,9 +4115,12 @@ public:
return op.func64 && op.destFetch64;
}
- const QRgba64 *fetch(int x, int y, int len)
+ const QRgba64 *fetch(int x, int y, int len, bool fetchDest)
{
- dest = op.destFetch64(buffer, data->rasterBuffer, x, y, len);
+ if (fetchDest || op.destFetch64 == destFetchRGB64)
+ dest = op.destFetch64(buffer, data->rasterBuffer, x, y, len);
+ else
+ dest = buffer;
return op.srcFetch64(src_buffer, &op, data, y, x, len);
}
@@ -4040,7 +4144,7 @@ public:
QRgbaFloat32 *dest = nullptr;
alignas(16) QRgbaFloat32 buffer[BufferSize];
alignas(16) QRgbaFloat32 src_buffer[BufferSize];
- BlendSrcGenericRGBFP(QSpanData *d, const Operator &o)
+ BlendSrcGenericRGBFP(const QSpanData *d, const Operator &o)
: QBlendBase{d, o}
{
}
@@ -4050,9 +4154,12 @@ public:
return op.funcFP && op.destFetchFP && op.srcFetchFP;
}
- const QRgbaFloat32 *fetch(int x, int y, int len)
+ const QRgbaFloat32 *fetch(int x, int y, int len, bool fetchDest)
{
- dest = op.destFetchFP(buffer, data->rasterBuffer, x, y, len);
+ if (fetchDest || op.destFetchFP == destFetchRGBFP)
+ dest = op.destFetchFP(buffer, data->rasterBuffer, x, y, len);
+ else
+ dest = buffer;
return op.srcFetchFP(src_buffer, &op, data, y, x, len);
}
@@ -4069,196 +4176,212 @@ public:
};
#endif
-static void blend_src_generic(int count, const QSpan *spans, void *userData)
+static void blend_src_generic(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- BlendSrcGeneric blend(data, getOperator(data, spans, count));
- handleSpans(count, spans, data, blend);
+ const Operator op = getOperator(data, nullptr, 0);
+ handleSpans<BlendSrcGeneric>(count, spans, data, op);
}
#if QT_CONFIG(raster_64bit)
-static void blend_src_generic_rgb64(int count, const QSpan *spans, void *userData)
+static void blend_src_generic_rgb64(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, spans, count);
- BlendSrcGenericRGB64 blend64(data, op);
- if (blend64.isSupported())
- handleSpans(count, spans, data, blend64);
- else {
+ const Operator op = getOperator(data, nullptr, 0);
+ if (op.func64 && op.destFetch64) {
+ handleSpans<BlendSrcGenericRGB64>(count, spans, data, op);
+ } else {
qCDebug(lcQtGuiDrawHelper, "blend_src_generic_rgb64: unsupported 64-bit blend attempted, falling back to 32-bit");
- BlendSrcGeneric blend32(data, op);
- handleSpans(count, spans, data, blend32);
+ handleSpans<BlendSrcGeneric>(count, spans, data, op);
}
}
#endif
#if QT_CONFIG(raster_fp)
-static void blend_src_generic_fp(int count, const QSpan *spans, void *userData)
+static void blend_src_generic_fp(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, spans, count);
- BlendSrcGenericRGBFP blendFP(data, op);
- if (blendFP.isSupported())
- handleSpans(count, spans, data, blendFP);
- else {
+ const Operator op = getOperator(data, spans, count);
+ if (op.funcFP && op.destFetchFP && op.srcFetchFP) {
+ handleSpans<BlendSrcGenericRGBFP>(count, spans, data, op);
+ } else {
qCDebug(lcQtGuiDrawHelper, "blend_src_generic_fp: unsupported 4xFP blend attempted, falling back to 32-bit");
- BlendSrcGeneric blend32(data, op);
- handleSpans(count, spans, data, blend32);
+ handleSpans<BlendSrcGeneric>(count, spans, data, op);
}
}
#endif
-static void blend_untransformed_generic(int count, const QSpan *spans, void *userData)
+static void blend_untransformed_generic(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- uint buffer[BufferSize];
- uint src_buffer[BufferSize];
- Operator op = getOperator(data, spans, count);
+ const Operator op = getOperator(data, spans, count);
const int image_width = data->texture.width;
const int image_height = data->texture.height;
- int xoff = -qRound(-data->dx);
- int yoff = -qRound(-data->dy);
+ const int const_alpha = data->texture.const_alpha;
+ const int xoff = -qRound(-data->dx);
+ const int yoff = -qRound(-data->dy);
+ const bool solidSource = op.mode == QPainter::CompositionMode_Source && const_alpha == 256 && op.destFetch != destFetchARGB32P;
- for (; count--; spans++) {
- if (!spans->len)
- continue;
- int x = spans->x;
- int length = spans->len;
- int sx = xoff + x;
- int sy = yoff + spans->y;
- if (sy >= 0 && sy < image_height && sx < image_width) {
- if (sx < 0) {
- x -= sx;
- length += sx;
- sx = 0;
- }
- if (sx + length > image_width)
- length = image_width - sx;
- if (length > 0) {
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(BufferSize, length);
- const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l);
- uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans->y, l);
- op.func(dest, src, l, coverage);
- if (op.destStore)
- op.destStore(data->rasterBuffer, x, spans->y, dest, l);
- x += l;
- sx += l;
- length -= l;
+ auto function = [=, &op] (int cStart, int cEnd)
+ {
+ alignas(16) uint buffer[BufferSize];
+ alignas(16) uint src_buffer[BufferSize];
+ for (int c = cStart; c < cEnd; ++c) {
+ if (!spans[c].len)
+ continue;
+ int x = spans[c].x;
+ int length = spans[c].len;
+ int sx = xoff + x;
+ int sy = yoff + spans[c].y;
+ const bool fetchDest = !solidSource || spans[c].coverage < 255;
+ if (sy >= 0 && sy < image_height && sx < image_width) {
+ if (sx < 0) {
+ x -= sx;
+ length += sx;
+ sx = 0;
+ }
+ if (sx + length > image_width)
+ length = image_width - sx;
+ if (length > 0) {
+ const int coverage = (spans[c].coverage * const_alpha) >> 8;
+ while (length) {
+ int l = qMin(BufferSize, length);
+ const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l);
+ uint *dest = fetchDest ? op.destFetch(buffer, data->rasterBuffer, x, spans[c].y, l) : buffer;
+ op.func(dest, src, l, coverage);
+ if (op.destStore)
+ op.destStore(data->rasterBuffer, x, spans[c].y, dest, l);
+ x += l;
+ sx += l;
+ length -= l;
+ }
}
}
}
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
#if QT_CONFIG(raster_64bit)
-static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, void *userData)
+static void blend_untransformed_generic_rgb64(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, spans, count);
+ const Operator op = getOperator(data, spans, count);
if (!op.func64) {
qCDebug(lcQtGuiDrawHelper, "blend_untransformed_generic_rgb64: unsupported 64-bit blend attempted, falling back to 32-bit");
return blend_untransformed_generic(count, spans, userData);
}
- alignas(8) QRgba64 buffer[BufferSize];
- alignas(8) QRgba64 src_buffer[BufferSize];
const int image_width = data->texture.width;
const int image_height = data->texture.height;
- int xoff = -qRound(-data->dx);
- int yoff = -qRound(-data->dy);
+ const int const_alpha = data->texture.const_alpha;
+ const int xoff = -qRound(-data->dx);
+ const int yoff = -qRound(-data->dy);
+ const bool solidSource = op.mode == QPainter::CompositionMode_Source && const_alpha == 256 && op.destFetch64 != destFetchRGB64;
- for (; count--; spans++) {
- if (!spans->len)
- continue;
- int x = spans->x;
- int length = spans->len;
- int sx = xoff + x;
- int sy = yoff + spans->y;
- if (sy >= 0 && sy < image_height && sx < image_width) {
- if (sx < 0) {
- x -= sx;
- length += sx;
- sx = 0;
- }
- if (sx + length > image_width)
- length = image_width - sx;
- if (length > 0) {
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(BufferSize, length);
- const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
- QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
- op.func64(dest, src, l, coverage);
- if (op.destStore64)
- op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
- x += l;
- sx += l;
- length -= l;
+ auto function = [=, &op] (int cStart, int cEnd)
+ {
+ alignas(16) QRgba64 buffer[BufferSize];
+ alignas(16) QRgba64 src_buffer[BufferSize];
+ for (int c = cStart; c < cEnd; ++c) {
+ if (!spans[c].len)
+ continue;
+ int x = spans[c].x;
+ int length = spans[c].len;
+ int sx = xoff + x;
+ int sy = yoff + spans[c].y;
+ const bool fetchDest = !solidSource || spans[c].coverage < 255;
+ if (sy >= 0 && sy < image_height && sx < image_width) {
+ if (sx < 0) {
+ x -= sx;
+ length += sx;
+ sx = 0;
+ }
+ if (sx + length > image_width)
+ length = image_width - sx;
+ if (length > 0) {
+ const int coverage = (spans[c].coverage * const_alpha) >> 8;
+ while (length) {
+ int l = qMin(BufferSize, length);
+ const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
+ QRgba64 *dest = fetchDest ? op.destFetch64(buffer, data->rasterBuffer, x, spans[c].y, l) : buffer;
+ op.func64(dest, src, l, coverage);
+ if (op.destStore64)
+ op.destStore64(data->rasterBuffer, x, spans[c].y, dest, l);
+ x += l;
+ sx += l;
+ length -= l;
+ }
}
}
}
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
#endif
#if QT_CONFIG(raster_fp)
-static void blend_untransformed_generic_fp(int count, const QSpan *spans, void *userData)
+static void blend_untransformed_generic_fp(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, spans, count);
+ const Operator op = getOperator(data, spans, count);
if (!op.funcFP) {
qCDebug(lcQtGuiDrawHelper, "blend_untransformed_generic_rgbaf16: unsupported 4xFP16 blend attempted, falling back to 32-bit");
return blend_untransformed_generic(count, spans, userData);
}
- QRgbaFloat32 buffer[BufferSize];
- QRgbaFloat32 src_buffer[BufferSize];
const int image_width = data->texture.width;
const int image_height = data->texture.height;
- int xoff = -qRound(-data->dx);
- int yoff = -qRound(-data->dy);
+ const int xoff = -qRound(-data->dx);
+ const int yoff = -qRound(-data->dy);
+ const bool solidSource = op.mode == QPainter::CompositionMode_Source && data->texture.const_alpha == 256 && op.destFetchFP != destFetchRGBFP;
- for (; count--; spans++) {
- if (!spans->len)
- continue;
- int x = spans->x;
- int length = spans->len;
- int sx = xoff + x;
- int sy = yoff + spans->y;
- if (sy >= 0 && sy < image_height && sx < image_width) {
- if (sx < 0) {
- x -= sx;
- length += sx;
- sx = 0;
- }
- if (sx + length > image_width)
- length = image_width - sx;
- if (length > 0) {
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(BufferSize, length);
- const QRgbaFloat32 *src = op.srcFetchFP(src_buffer, &op, data, sy, sx, l);
- QRgbaFloat32 *dest = op.destFetchFP(buffer, data->rasterBuffer, x, spans->y, l);
- op.funcFP(dest, src, l, coverage);
- if (op.destStoreFP)
- op.destStoreFP(data->rasterBuffer, x, spans->y, dest, l);
- x += l;
- sx += l;
- length -= l;
+ auto function = [=, &op] (int cStart, int cEnd)
+ {
+ alignas(16) QRgbaFloat32 buffer[BufferSize];
+ alignas(16) QRgbaFloat32 src_buffer[BufferSize];
+ for (int c = cStart; c < cEnd; ++c) {
+ if (!spans[c].len)
+ continue;
+ int x = spans[c].x;
+ int length = spans[c].len;
+ int sx = xoff + x;
+ int sy = yoff + spans[c].y;
+ const bool fetchDest = !solidSource || spans[c].coverage < 255;
+ if (sy >= 0 && sy < image_height && sx < image_width) {
+ if (sx < 0) {
+ x -= sx;
+ length += sx;
+ sx = 0;
+ }
+ if (sx + length > image_width)
+ length = image_width - sx;
+ if (length > 0) {
+ const int coverage = (spans[c].coverage * data->texture.const_alpha) >> 8;
+ while (length) {
+ int l = qMin(BufferSize, length);
+ const QRgbaFloat32 *src = op.srcFetchFP(src_buffer, &op, data, sy, sx, l);
+ QRgbaFloat32 *dest = fetchDest ? op.destFetchFP(buffer, data->rasterBuffer, x, spans[c].y, l) : buffer;
+ op.funcFP(dest, src, l, coverage);
+ if (op.destStoreFP)
+ op.destStoreFP(data->rasterBuffer, x, spans[c].y, dest, l);
+ x += l;
+ sx += l;
+ length -= l;
+ }
}
}
}
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
#endif
-static void blend_untransformed_argb(int count, const QSpan *spans, void *userData)
+static void blend_untransformed_argb(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
@@ -4267,36 +4390,41 @@ static void blend_untransformed_argb(int count, const QSpan *spans, void *userDa
return;
}
- Operator op = getOperator(data, spans, count);
+ const Operator op = getOperator(data, spans, count);
const int image_width = data->texture.width;
const int image_height = data->texture.height;
- int xoff = -qRound(-data->dx);
- int yoff = -qRound(-data->dy);
+ const int const_alpha = data->texture.const_alpha;
+ const int xoff = -qRound(-data->dx);
+ const int yoff = -qRound(-data->dy);
- for (; count--; spans++) {
- if (!spans->len)
- continue;
- int x = spans->x;
- int length = spans->len;
- int sx = xoff + x;
- int sy = yoff + spans->y;
- if (sy >= 0 && sy < image_height && sx < image_width) {
- if (sx < 0) {
- x -= sx;
- length += sx;
- sx = 0;
- }
- if (sx + length > image_width)
- length = image_width - sx;
- if (length > 0) {
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- const uint *src = (const uint *)data->texture.scanLine(sy) + sx;
- uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x;
- op.func(dest, src, length, coverage);
+ auto function = [=, &op] (int cStart, int cEnd)
+ {
+ for (int c = cStart; c < cEnd; ++c) {
+ if (!spans[c].len)
+ continue;
+ int x = spans[c].x;
+ int length = spans[c].len;
+ int sx = xoff + x;
+ int sy = yoff + spans[c].y;
+ if (sy >= 0 && sy < image_height && sx < image_width) {
+ if (sx < 0) {
+ x -= sx;
+ length += sx;
+ sx = 0;
+ }
+ if (sx + length > image_width)
+ length = image_width - sx;
+ if (length > 0) {
+ const int coverage = (spans[c].coverage * const_alpha) >> 8;
+ const uint *src = (const uint *)data->texture.scanLine(sy) + sx;
+ uint *dest = ((uint *)data->rasterBuffer->scanLine(spans[c].y)) + x;
+ op.func(dest, src, length, coverage);
+ }
}
}
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
static inline quint16 interpolate_pixel_rgb16_255(quint16 x, quint8 a,
@@ -4350,7 +4478,7 @@ static inline void blend_sourceOver_rgb16_rgb16(quint16 *Q_DECL_RESTRICT dest,
}
}
-static void blend_untransformed_rgb565(int count, const QSpan *spans, void *userData)
+static void blend_untransformed_rgb565(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData*>(userData);
QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
@@ -4368,57 +4496,54 @@ static void blend_untransformed_rgb565(int count, const QSpan *spans, void *user
int xoff = -qRound(-data->dx);
int yoff = -qRound(-data->dy);
- const QSpan *end = spans + count;
- while (spans < end) {
- if (!spans->len) {
- ++spans;
- continue;
- }
- const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8;
- if (coverage == 0) {
- ++spans;
- continue;
- }
-
- int x = spans->x;
- int length = spans->len;
- int sx = xoff + x;
- int sy = yoff + spans->y;
- if (sy >= 0 && sy < image_height && sx < image_width) {
- if (sx < 0) {
- x -= sx;
- length += sx;
- sx = 0;
- }
- if (sx + length > image_width)
- length = image_width - sx;
- if (length > 0) {
- quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + x;
- const quint16 *src = (const quint16 *)data->texture.scanLine(sy) + sx;
- if (coverage == 255) {
- memcpy(dest, src, length * sizeof(quint16));
- } else {
- const quint8 alpha = (coverage + 1) >> 3;
- const quint8 ialpha = 0x20 - alpha;
- if (alpha > 0)
- blend_sourceOver_rgb16_rgb16(dest, src, length, alpha, ialpha);
+ auto function = [=](int cStart, int cEnd)
+ {
+ for (int c = cStart; c < cEnd; ++c) {
+ if (!spans[c].len)
+ continue;
+ const quint8 coverage = (data->texture.const_alpha * spans[c].coverage) >> 8;
+ if (coverage == 0)
+ continue;
+
+ int x = spans[c].x;
+ int length = spans[c].len;
+ int sx = xoff + x;
+ int sy = yoff + spans[c].y;
+ if (sy >= 0 && sy < image_height && sx < image_width) {
+ if (sx < 0) {
+ x -= sx;
+ length += sx;
+ sx = 0;
+ }
+ if (sx + length > image_width)
+ length = image_width - sx;
+ if (length > 0) {
+ quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans[c].y) + x;
+ const quint16 *src = (const quint16 *)data->texture.scanLine(sy) + sx;
+ if (coverage == 255) {
+ memcpy(dest, src, length * sizeof(quint16));
+ } else {
+ const quint8 alpha = (coverage + 1) >> 3;
+ const quint8 ialpha = 0x20 - alpha;
+ if (alpha > 0)
+ blend_sourceOver_rgb16_rgb16(dest, src, length, alpha, ialpha);
+ }
}
}
}
- ++spans;
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
-static void blend_tiled_generic(int count, const QSpan *spans, void *userData)
+static void blend_tiled_generic(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- uint buffer[BufferSize];
- uint src_buffer[BufferSize];
- Operator op = getOperator(data, spans, count);
+ const Operator op = getOperator(data, spans, count);
const int image_width = data->texture.width;
const int image_height = data->texture.height;
+ const int const_alpha = data->texture.const_alpha;
int xoff = -qRound(-data->dx) % image_width;
int yoff = -qRound(-data->dy) % image_height;
@@ -4427,48 +4552,51 @@ static void blend_tiled_generic(int count, const QSpan *spans, void *userData)
if (yoff < 0)
yoff += image_height;
- while (count--) {
- int x = spans->x;
- int length = spans->len;
- int sx = (xoff + spans->x) % image_width;
- int sy = (spans->y + yoff) % image_height;
- if (sx < 0)
- sx += image_width;
- if (sy < 0)
- sy += image_height;
-
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(image_width - sx, length);
- if (BufferSize < l)
- l = BufferSize;
- const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l);
- uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans->y, l);
- op.func(dest, src, l, coverage);
- if (op.destStore)
- op.destStore(data->rasterBuffer, x, spans->y, dest, l);
- x += l;
- sx += l;
- length -= l;
- if (sx >= image_width)
- sx = 0;
+ auto function = [=, &op](int cStart, int cEnd)
+ {
+ alignas(16) uint buffer[BufferSize];
+ alignas(16) uint src_buffer[BufferSize];
+ for (int c = cStart; c < cEnd; ++c) {
+ int x = spans[c].x;
+ int length = spans[c].len;
+ int sx = (xoff + spans[c].x) % image_width;
+ int sy = (spans[c].y + yoff) % image_height;
+ if (sx < 0)
+ sx += image_width;
+ if (sy < 0)
+ sy += image_height;
+
+ const int coverage = (spans[c].coverage * const_alpha) >> 8;
+ while (length) {
+ int l = qMin(image_width - sx, length);
+ if (BufferSize < l)
+ l = BufferSize;
+ const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l);
+ uint *dest = op.destFetch(buffer, data->rasterBuffer, x, spans[c].y, l);
+ op.func(dest, src, l, coverage);
+ if (op.destStore)
+ op.destStore(data->rasterBuffer, x, spans[c].y, dest, l);
+ x += l;
+ sx += l;
+ length -= l;
+ if (sx >= image_width)
+ sx = 0;
+ }
}
- ++spans;
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
#if QT_CONFIG(raster_64bit)
-static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userData)
+static void blend_tiled_generic_rgb64(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, spans, count);
+ const Operator op = getOperator(data, spans, count);
if (!op.func64) {
qCDebug(lcQtGuiDrawHelper, "blend_tiled_generic_rgb64: unsupported 64-bit blend attempted, falling back to 32-bit");
return blend_tiled_generic(count, spans, userData);
}
- alignas(8) QRgba64 buffer[BufferSize];
- alignas(8) QRgba64 src_buffer[BufferSize];
const int image_width = data->texture.width;
const int image_height = data->texture.height;
@@ -4483,6 +4611,7 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
bool isBpp32 = qPixelLayouts[data->rasterBuffer->format].bpp == QPixelLayout::BPP32;
bool isBpp64 = qPixelLayouts[data->rasterBuffer->format].bpp == QPixelLayout::BPP64;
if (op.destFetch64 == destFetch64Undefined && image_width <= BufferSize && (isBpp32 || isBpp64)) {
+ alignas(16) QRgba64 src_buffer[BufferSize];
// If destination isn't blended into the result, we can do the tiling directly on destination pixels.
while (count--) {
int x = spans->x;
@@ -4530,49 +4659,52 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
return;
}
- while (count--) {
- int x = spans->x;
- int length = spans->len;
- int sx = (xoff + spans->x) % image_width;
- int sy = (spans->y + yoff) % image_height;
- if (sx < 0)
- sx += image_width;
- if (sy < 0)
- sy += image_height;
-
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(image_width - sx, length);
- if (BufferSize < l)
- l = BufferSize;
- const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
- QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l);
- op.func64(dest, src, l, coverage);
- if (op.destStore64)
- op.destStore64(data->rasterBuffer, x, spans->y, dest, l);
- x += l;
- sx += l;
- length -= l;
- if (sx >= image_width)
- sx = 0;
+ auto function = [=, &op](int cStart, int cEnd)
+ {
+ alignas(16) QRgba64 buffer[BufferSize];
+ alignas(16) QRgba64 src_buffer[BufferSize];
+ for (int c = cStart; c < cEnd; ++c) {
+ int x = spans[c].x;
+ int length = spans[c].len;
+ int sx = (xoff + spans[c].x) % image_width;
+ int sy = (spans[c].y + yoff) % image_height;
+ if (sx < 0)
+ sx += image_width;
+ if (sy < 0)
+ sy += image_height;
+
+ const int coverage = (spans[c].coverage * data->texture.const_alpha) >> 8;
+ while (length) {
+ int l = qMin(image_width - sx, length);
+ if (BufferSize < l)
+ l = BufferSize;
+ const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l);
+ QRgba64 *dest = op.destFetch64(buffer, data->rasterBuffer, x, spans[c].y, l);
+ op.func64(dest, src, l, coverage);
+ if (op.destStore64)
+ op.destStore64(data->rasterBuffer, x, spans[c].y, dest, l);
+ x += l;
+ sx += l;
+ length -= l;
+ if (sx >= image_width)
+ sx = 0;
+ }
}
- ++spans;
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
#endif
#if QT_CONFIG(raster_fp)
-static void blend_tiled_generic_fp(int count, const QSpan *spans, void *userData)
+static void blend_tiled_generic_fp(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
- Operator op = getOperator(data, spans, count);
+ const Operator op = getOperator(data, spans, count);
if (!op.funcFP) {
qCDebug(lcQtGuiDrawHelper, "blend_tiled_generic_fp: unsupported 4xFP blend attempted, falling back to 32-bit");
return blend_tiled_generic(count, spans, userData);
}
- QRgbaFloat32 buffer[BufferSize];
- QRgbaFloat32 src_buffer[BufferSize];
const int image_width = data->texture.width;
const int image_height = data->texture.height;
@@ -4586,38 +4718,43 @@ static void blend_tiled_generic_fp(int count, const QSpan *spans, void *userData
// Consider tiling optimizing like the other versions.
- while (count--) {
- int x = spans->x;
- int length = spans->len;
- int sx = (xoff + spans->x) % image_width;
- int sy = (spans->y + yoff) % image_height;
- if (sx < 0)
- sx += image_width;
- if (sy < 0)
- sy += image_height;
-
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(image_width - sx, length);
- if (BufferSize < l)
- l = BufferSize;
- const QRgbaFloat32 *src = op.srcFetchFP(src_buffer, &op, data, sy, sx, l);
- QRgbaFloat32 *dest = op.destFetchFP(buffer, data->rasterBuffer, x, spans->y, l);
- op.funcFP(dest, src, l, coverage);
- if (op.destStoreFP)
- op.destStoreFP(data->rasterBuffer, x, spans->y, dest, l);
- x += l;
- sx += l;
- length -= l;
- if (sx >= image_width)
- sx = 0;
+ auto function = [=, &op](int cStart, int cEnd)
+ {
+ alignas(16) QRgbaFloat32 buffer[BufferSize];
+ alignas(16) QRgbaFloat32 src_buffer[BufferSize];
+ for (int c = cStart; c < cEnd; ++c) {
+ int x = spans[c].x;
+ int length = spans[c].len;
+ int sx = (xoff + spans[c].x) % image_width;
+ int sy = (spans[c].y + yoff) % image_height;
+ if (sx < 0)
+ sx += image_width;
+ if (sy < 0)
+ sy += image_height;
+
+ const int coverage = (spans[c].coverage * data->texture.const_alpha) >> 8;
+ while (length) {
+ int l = qMin(image_width - sx, length);
+ if (BufferSize < l)
+ l = BufferSize;
+ const QRgbaFloat32 *src = op.srcFetchFP(src_buffer, &op, data, sy, sx, l);
+ QRgbaFloat32 *dest = op.destFetchFP(buffer, data->rasterBuffer, x, spans[c].y, l);
+ op.funcFP(dest, src, l, coverage);
+ if (op.destStoreFP)
+ op.destStoreFP(data->rasterBuffer, x, spans[c].y, dest, l);
+ x += l;
+ sx += l;
+ length -= l;
+ if (sx >= image_width)
+ sx = 0;
+ }
}
- ++spans;
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
#endif
-static void blend_tiled_argb(int count, const QSpan *spans, void *userData)
+static void blend_tiled_argb(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
@@ -4626,10 +4763,10 @@ static void blend_tiled_argb(int count, const QSpan *spans, void *userData)
return;
}
- Operator op = getOperator(data, spans, count);
+ const Operator op = getOperator(data, spans, count);
- int image_width = data->texture.width;
- int image_height = data->texture.height;
+ const int image_width = data->texture.width;
+ const int image_height = data->texture.height;
int xoff = -qRound(-data->dx) % image_width;
int yoff = -qRound(-data->dy) % image_height;
@@ -4637,36 +4774,40 @@ static void blend_tiled_argb(int count, const QSpan *spans, void *userData)
xoff += image_width;
if (yoff < 0)
yoff += image_height;
+ const auto func = op.func;
+ const int const_alpha = data->texture.const_alpha;
+
+ auto function = [=] (int cStart, int cEnd) {
+ for (int c = cStart; c < cEnd; ++c) {
+ int x = spans[c].x;
+ int length = spans[c].len;
+ int sx = (xoff + spans[c].x) % image_width;
+ int sy = (spans[c].y + yoff) % image_height;
+ if (sx < 0)
+ sx += image_width;
+ if (sy < 0)
+ sy += image_height;
- while (count--) {
- int x = spans->x;
- int length = spans->len;
- int sx = (xoff + spans->x) % image_width;
- int sy = (spans->y + yoff) % image_height;
- if (sx < 0)
- sx += image_width;
- if (sy < 0)
- sy += image_height;
-
- const int coverage = (spans->coverage * data->texture.const_alpha) >> 8;
- while (length) {
- int l = qMin(image_width - sx, length);
- if (BufferSize < l)
- l = BufferSize;
- const uint *src = (const uint *)data->texture.scanLine(sy) + sx;
- uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x;
- op.func(dest, src, l, coverage);
- x += l;
- sx += l;
- length -= l;
- if (sx >= image_width)
- sx = 0;
+ const int coverage = (spans[c].coverage * const_alpha) >> 8;
+ while (length) {
+ int l = qMin(image_width - sx, length);
+ if (BufferSize < l)
+ l = BufferSize;
+ const uint *src = (const uint *)data->texture.scanLine(sy) + sx;
+ uint *dest = ((uint *)data->rasterBuffer->scanLine(spans[c].y)) + x;
+ func(dest, src, l, coverage);
+ x += l;
+ sx += l;
+ length -= l;
+ if (sx >= image_width)
+ sx = 0;
+ }
}
- ++spans;
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
-static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
+static void blend_tiled_rgb565(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData*>(userData);
QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
@@ -4689,79 +4830,80 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
if (yoff < 0)
yoff += image_height;
- while (count--) {
- const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8;
- if (coverage == 0) {
- ++spans;
- continue;
- }
-
- int x = spans->x;
- int length = spans->len;
- int sx = (xoff + spans->x) % image_width;
- int sy = (spans->y + yoff) % image_height;
- if (sx < 0)
- sx += image_width;
- if (sy < 0)
- sy += image_height;
-
- if (coverage == 255) {
- // Copy the first texture block
- length = qMin(image_width,length);
- int tx = x;
- while (length) {
- int l = qMin(image_width - sx, length);
- if (BufferSize < l)
- l = BufferSize;
- quint16 *dest = ((quint16 *)data->rasterBuffer->scanLine(spans->y)) + tx;
- const quint16 *src = (const quint16 *)data->texture.scanLine(sy) + sx;
- memcpy(dest, src, l * sizeof(quint16));
- length -= l;
- tx += l;
- sx += l;
- if (sx >= image_width)
- sx = 0;
- }
+ const int const_alpha = data->texture.const_alpha;
+ auto function = [=] (int cStart, int cEnd) {
+ for (int c = cStart; c < cEnd; ++c) {
+ const quint8 coverage = (const_alpha * spans[c].coverage) >> 8;
+ if (coverage == 0)
+ continue;
+
+ int x = spans[c].x;
+ int length = spans[c].len;
+ int sx = (xoff + spans[c].x) % image_width;
+ int sy = (spans[c].y + yoff) % image_height;
+ if (sx < 0)
+ sx += image_width;
+ if (sy < 0)
+ sy += image_height;
- // Now use the rasterBuffer as the source of the texture,
- // We can now progressively copy larger blocks
- // - Less cpu time in code figuring out what to copy
- // We are dealing with one block of data
- // - More likely to fit in the cache
- // - can use memcpy
- int copy_image_width = qMin(image_width, int(spans->len));
- length = spans->len - copy_image_width;
- quint16 *src = ((quint16 *)data->rasterBuffer->scanLine(spans->y)) + x;
- quint16 *dest = src + copy_image_width;
- while (copy_image_width < length) {
- memcpy(dest, src, copy_image_width * sizeof(quint16));
- dest += copy_image_width;
- length -= copy_image_width;
- copy_image_width *= 2;
- }
- if (length > 0)
- memcpy(dest, src, length * sizeof(quint16));
- } else {
- const quint8 alpha = (coverage + 1) >> 3;
- const quint8 ialpha = 0x20 - alpha;
- if (alpha > 0) {
+ if (coverage == 255) {
+ // Copy the first texture block
+ length = qMin(image_width,length);
+ int tx = x;
while (length) {
int l = qMin(image_width - sx, length);
if (BufferSize < l)
l = BufferSize;
- quint16 *dest = ((quint16 *)data->rasterBuffer->scanLine(spans->y)) + x;
+ quint16 *dest = ((quint16 *)data->rasterBuffer->scanLine(spans[c].y)) + tx;
const quint16 *src = (const quint16 *)data->texture.scanLine(sy) + sx;
- blend_sourceOver_rgb16_rgb16(dest, src, l, alpha, ialpha);
- x += l;
- sx += l;
+ memcpy(dest, src, l * sizeof(quint16));
length -= l;
+ tx += l;
+ sx += l;
if (sx >= image_width)
sx = 0;
}
+
+ // Now use the rasterBuffer as the source of the texture,
+ // We can now progressively copy larger blocks
+ // - Less cpu time in code figuring out what to copy
+ // We are dealing with one block of data
+ // - More likely to fit in the cache
+ // - can use memcpy
+ int copy_image_width = qMin(image_width, int(spans[c].len));
+ length = spans[c].len - copy_image_width;
+ quint16 *src = ((quint16 *)data->rasterBuffer->scanLine(spans[c].y)) + x;
+ quint16 *dest = src + copy_image_width;
+ while (copy_image_width < length) {
+ memcpy(dest, src, copy_image_width * sizeof(quint16));
+ dest += copy_image_width;
+ length -= copy_image_width;
+ copy_image_width *= 2;
+ }
+ if (length > 0)
+ memcpy(dest, src, length * sizeof(quint16));
+ } else {
+ const quint8 alpha = (coverage + 1) >> 3;
+ const quint8 ialpha = 0x20 - alpha;
+ if (alpha > 0) {
+ while (length) {
+ int l = qMin(image_width - sx, length);
+ if (BufferSize < l)
+ l = BufferSize;
+ quint16 *dest = ((quint16 *)data->rasterBuffer->scanLine(spans[c].y)) + x;
+ const quint16 *src = (const quint16 *)data->texture.scanLine(sy) + sx;
+ blend_sourceOver_rgb16_rgb16(dest, src, l, alpha, ialpha);
+ x += l;
+ sx += l;
+ length -= l;
+ if (sx >= image_width)
+ sx = 0;
+ }
+ }
}
}
- ++spans;
- }
+ };
+ QT_THREAD_PARALLEL_FILLS(function);
}
/* Image formats here are target formats */
@@ -4813,15 +4955,14 @@ static const ProcessSpans processTextureSpansGenericFP[NBlendTypes] = {
blend_src_generic_fp // TransformedBilinearTiled
};
#endif
-void qBlendTexture(int count, const QSpan *spans, void *userData)
+void qBlendTexture(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
TextureBlendType blendType = getBlendType(data);
ProcessSpans proc;
switch (data->rasterBuffer->format) {
case QImage::Format_Invalid:
- Q_UNREACHABLE();
- return;
+ Q_UNREACHABLE_RETURN();
case QImage::Format_ARGB32_Premultiplied:
proc = processTextureSpansARGB32PM[blendType];
break;
@@ -4869,16 +5010,11 @@ void qBlendTexture(int count, const QSpan *spans, void *userData)
proc(count, spans, userData);
}
-static void blend_vertical_gradient_argb(int count, const QSpan *spans, void *userData)
+static inline bool calculate_fixed_gradient_factors(int count, const QT_FT_Span *spans,
+ const QSpanData *data,
+ const LinearGradientValues &linear,
+ int *pyinc, int *poff)
{
- QSpanData *data = reinterpret_cast<QSpanData *>(userData);
-
- LinearGradientValues linear;
- getLinearGradientValues(&linear, data);
-
- CompositionFunctionSolid funcSolid =
- functionForModeSolid[data->rasterBuffer->compositionMode];
-
/*
The logic for vertical gradient calculations is a mathematically
reduced copy of that in fetchLinearGradient() - which is basically:
@@ -4893,8 +5029,32 @@ static void blend_vertical_gradient_argb(int count, const QSpan *spans, void *us
This has then been converted to fixed point to improve performance.
*/
const int gss = GRADIENT_STOPTABLE_SIZE - 1;
- int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
- int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
+ qreal ryinc = linear.dy * data->m22 * gss * FIXPT_SIZE;
+ qreal roff = (linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss * FIXPT_SIZE;
+ const int limit = std::numeric_limits<int>::max() - FIXPT_SIZE;
+ if (count && (std::fabs(ryinc) < limit) && (std::fabs(roff) < limit)
+ && (std::fabs(ryinc * spans->y + roff) < limit)
+ && (std::fabs(ryinc * (spans + count - 1)->y + roff) < limit)) {
+ *pyinc = int(ryinc);
+ *poff = int(roff);
+ return true;
+ }
+ return false;
+}
+
+static bool blend_vertical_gradient_argb(int count, const QT_FT_Span *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+
+ LinearGradientValues linear;
+ getLinearGradientValues(&linear, data);
+
+ CompositionFunctionSolid funcSolid =
+ functionForModeSolid[data->rasterBuffer->compositionMode];
+
+ int yinc(0), off(0);
+ if (!calculate_fixed_gradient_factors(count, spans, data, linear, &yinc, &off))
+ return false;
while (count--) {
int y = spans->y;
@@ -4907,21 +5067,20 @@ static void blend_vertical_gradient_argb(int count, const QSpan *spans, void *us
funcSolid(dst, spans->len, color, spans->coverage);
++spans;
}
+ return true;
}
template<ProcessSpans blend_color>
-static void blend_vertical_gradient(int count, const QSpan *spans, void *userData)
+static bool blend_vertical_gradient(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
LinearGradientValues linear;
getLinearGradientValues(&linear, data);
- // Based on the same logic as blend_vertical_gradient_argb.
-
- const int gss = GRADIENT_STOPTABLE_SIZE - 1;
- int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE);
- int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE));
+ int yinc(0), off(0);
+ if (!calculate_fixed_gradient_factors(count, spans, data, linear, &yinc, &off))
+ return false;
while (count--) {
int y = spans->y;
@@ -4929,14 +5088,15 @@ static void blend_vertical_gradient(int count, const QSpan *spans, void *userDat
#if QT_CONFIG(raster_64bit)
data->solidColor = qt_gradient_pixel64_fixed(&data->gradient, yinc * y + off);
#else
- data->solidColor = QRgba64::fromArgb32(qt_gradient_pixel_fixed(&data->gradient, yinc * y + off));
+ data->solidColor = qt_gradient_pixel_fixed(&data->gradient, yinc * y + off);
#endif
blend_color(1, spans, userData);
++spans;
}
+ return true;
}
-void qBlendGradient(int count, const QSpan *spans, void *userData)
+void qBlendGradient(int count, const QT_FT_Span *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
bool isVerticalGradient =
@@ -4948,8 +5108,8 @@ void qBlendGradient(int count, const QSpan *spans, void *userData)
break;
case QImage::Format_RGB32:
case QImage::Format_ARGB32_Premultiplied:
- if (isVerticalGradient)
- return blend_vertical_gradient_argb(count, spans, userData);
+ if (isVerticalGradient && blend_vertical_gradient_argb(count, spans, userData))
+ return;
return blend_src_generic(count, spans, userData);
#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
case QImage::Format_ARGB32:
@@ -4971,8 +5131,8 @@ void qBlendGradient(int count, const QSpan *spans, void *userData)
case QImage::Format_RGBA32FPx4_Premultiplied:
#endif
#if QT_CONFIG(raster_64bit)
- if (isVerticalGradient)
- return blend_vertical_gradient<blend_color_generic_rgb64>(count, spans, userData);
+ if (isVerticalGradient && blend_vertical_gradient<blend_color_generic_rgb64>(count, spans, userData))
+ return;
return blend_src_generic_rgb64(count, spans, userData);
#endif // QT_CONFIG(raster_64bit)
#if QT_CONFIG(raster_fp)
@@ -4982,13 +5142,13 @@ void qBlendGradient(int count, const QSpan *spans, void *userData)
case QImage::Format_RGBX32FPx4:
case QImage::Format_RGBA32FPx4:
case QImage::Format_RGBA32FPx4_Premultiplied:
- if (isVerticalGradient)
- return blend_vertical_gradient<blend_color_generic_fp>(count, spans, userData);
+ if (isVerticalGradient && blend_vertical_gradient<blend_color_generic_fp>(count, spans, userData))
+ return;
return blend_src_generic_fp(count, spans, userData);
#endif
default:
- if (isVerticalGradient)
- return blend_vertical_gradient<blend_color_generic>(count, spans, userData);
+ if (isVerticalGradient && blend_vertical_gradient<blend_color_generic>(count, spans, userData))
+ return;
return blend_src_generic(count, spans, userData);
}
Q_UNREACHABLE();
@@ -5004,7 +5164,7 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer,
const int destStride = rasterBuffer->stride<DST>();
if (mapWidth > 8) {
- while (mapHeight--) {
+ while (--mapHeight >= 0) {
int x0 = 0;
int n = 0;
for (int x = 0; x < mapWidth; x += 8) {
@@ -5034,7 +5194,7 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer,
map += mapStride;
}
} else {
- while (mapHeight--) {
+ while (--mapHeight >= 0) {
int x0 = 0;
int n = 0;
for (uchar s = *map; s; s <<= 1) {
@@ -5218,7 +5378,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
const QClipData::ClipLine &line = clip->m_clipLines[yp];
for (int i=0; i<line.count; ++i) {
- const QSpan &clip = line.spans[i];
+ const QT_FT_Span &clip = line.spans[i];
int start = qMax<int>(x, clip.x);
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
@@ -5292,7 +5452,7 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer,
const QClipData::ClipLine &line = clip->m_clipLines[yp];
for (int i=0; i<line.count; ++i) {
- const QSpan &clip = line.spans[i];
+ const QT_FT_Span &clip = line.spans[i];
int start = qMax<int>(x, clip.x);
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
@@ -5342,7 +5502,7 @@ void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
if (!clip) {
quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
const int destStride = rasterBuffer->stride<quint16>();
- while (mapHeight--) {
+ while (--mapHeight >= 0) {
for (int i = 0; i < mapWidth; ++i)
alphamapblend_quint16(map[i], dest, i, c);
dest += destStride;
@@ -5360,7 +5520,7 @@ void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(yp));
for (int i=0; i<line.count; ++i) {
- const QSpan &clip = line.spans[i];
+ const QT_FT_Span &clip = line.spans[i];
int start = qMax<int>(x, clip.x);
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
@@ -5396,7 +5556,7 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
if (!clip) {
quint32 *dest = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x;
- while (mapHeight--) {
+ while (--mapHeight >= 0) {
for (int i = 0; i < mapWidth; ++i) {
const int coverage = map[i];
alphamapblend_argb32(dest + i, coverage, srcColor, c, colorProfile);
@@ -5417,7 +5577,7 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
quint32 *dest = reinterpret_cast<quint32 *>(rasterBuffer->scanLine(yp));
for (int i=0; i<line.count; ++i) {
- const QSpan &clip = line.spans[i];
+ const QT_FT_Span &clip = line.spans[i];
int start = qMax<int>(x, clip.x);
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
@@ -5518,7 +5678,7 @@ static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba
static inline void rgbBlendPixel(QRgba64 &dst, int coverage, QRgba64 slinear, const QColorTrcLut *colorProfile)
{
// Do a gammacorrected RGB alphablend...
- const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(dst) : dst;
+ const QRgba64 dlinear = colorProfile ? colorProfile->toLinear(dst) : dst;
QRgba64 blend = rgbBlend(dlinear, slinear, coverage);
@@ -5597,7 +5757,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
const QClipData::ClipLine &line = clip->m_clipLines[yp];
for (int i=0; i<line.count; ++i) {
- const QSpan &clip = line.spans[i];
+ const QT_FT_Span &clip = line.spans[i];
int start = qMax<int>(x, clip.x);
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
@@ -5670,7 +5830,7 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer,
const QClipData::ClipLine &line = clip->m_clipLines[yp];
for (int i=0; i<line.count; ++i) {
- const QSpan &clip = line.spans[i];
+ const QT_FT_Span &clip = line.spans[i];
int start = qMax<int>(x, clip.x);
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
@@ -5714,7 +5874,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
if (!clip) {
quint32 *dst = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x;
const int destStride = rasterBuffer->stride<quint32>();
- while (mapHeight--) {
+ while (--mapHeight >= 0) {
for (int i = 0; i < mapWidth; ++i) {
const uint coverage = src[i];
alphargbblend_argb32(dst + i, coverage, srcColor, c, colorProfile);
@@ -5736,7 +5896,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
quint32 *dst = reinterpret_cast<quint32 *>(rasterBuffer->scanLine(yp));
for (int i=0; i<line.count; ++i) {
- const QSpan &clip = line.spans[i];
+ const QT_FT_Span &clip = line.spans[i];
int start = qMax<int>(x, clip.x);
int end = qMin<int>(x + mapWidth, clip.x + clip.len);
@@ -5858,7 +6018,7 @@ static void qt_rectfill_fp32x4(QRasterBuffer *rasterBuffer,
// Map table for destination image format. Contains function pointers
// for blends of various types unto the destination
-DrawHelper qDrawHelper[QImage::NImageFormats] =
+DrawHelper qDrawHelper[] =
{
// Format_Invalid,
{ nullptr, nullptr, nullptr, nullptr, nullptr },
@@ -6135,14 +6295,16 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
},
};
-#if !defined(__SSE2__)
+static_assert(std::size(qDrawHelper) == QImage::NImageFormats);
+
+#if !defined(Q_PROCESSOR_X86)
void qt_memfill64(quint64 *dest, quint64 color, qsizetype count)
{
qt_memfill_template<quint64>(dest, color, count);
}
#endif
-#if defined(QT_COMPILER_SUPPORTS_SSSE3) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
+#if defined(QT_COMPILER_SUPPORTS_SSSE3) && defined(Q_CC_GNU) && !defined(Q_CC_CLANG)
__attribute__((optimize("no-tree-vectorize")))
#endif
void qt_memfill24(quint24 *dest, quint24 color, qsizetype count)
@@ -6202,16 +6364,15 @@ void qt_memfill16(quint16 *dest, quint16 value, qsizetype count)
qt_memfill32(reinterpret_cast<quint32*>(dest), value32, count / 2);
}
-#if !defined(__SSE2__) && !defined(__ARM_NEON__) && !defined(__MIPS_DSP__)
+#if defined(Q_PROCESSOR_X86)
+void (*qt_memfill32)(quint32 *dest, quint32 value, qsizetype count) = nullptr;
+void (*qt_memfill64)(quint64 *dest, quint64 value, qsizetype count) = nullptr;
+#elif !defined(__ARM_NEON__) && !defined(__MIPS_DSP__)
void qt_memfill32(quint32 *dest, quint32 color, qsizetype count)
{
qt_memfill_template<quint32>(dest, color, count);
}
#endif
-#ifdef __SSE2__
-decltype(qt_memfill32_sse2) *qt_memfill32 = nullptr;
-decltype(qt_memfill64_sse2) *qt_memfill64 = nullptr;
-#endif
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
template<QtPixelOrder> void QT_FASTCALL storeA2RGB30PMFromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count, const QList<QRgb> *, QDitherInfo *);
@@ -6224,8 +6385,11 @@ static void qInitDrawhelperFunctions()
// Set up basic blend function tables.
qInitBlendFunctions();
-#ifdef __SSE2__
-# ifndef __AVX2__
+#if defined(Q_PROCESSOR_X86) && !defined(__SSE2__)
+ qt_memfill32 = qt_memfill_template<quint32>;
+ qt_memfill64 = qt_memfill_template<quint64>;
+#elif defined(__SSE2__)
+# ifndef __haswell__
qt_memfill32 = qt_memfill32_sse2;
qt_memfill64 = qt_memfill64_sse2;
# endif
@@ -6332,7 +6496,7 @@ static void qInitDrawhelperFunctions()
extern void QT_FASTCALL storeRGBx64FromRGBA64PM_sse4(uchar *, const QRgba64 *, int, int, const QList<QRgb> *, QDitherInfo *);
extern void QT_FASTCALL destStore64ARGB32_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
extern void QT_FASTCALL destStore64RGBA8888_sse4(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length);
-# ifndef __AVX2__
+# ifndef __haswell__
qPixelLayouts[QImage::Format_ARGB32].fetchToARGB32PM = fetchARGB32ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBA8888].fetchToARGB32PM = fetchRGBA8888ToARGB32PM_sse4;
diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp
index c58d0804c7..34de69ecf4 100644
--- a/src/gui/painting/qdrawhelper_avx2.cpp
+++ b/src/gui/painting/qdrawhelper_avx2.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdrawhelper_p.h"
#include "qdrawhelper_x86_p.h"
@@ -359,7 +323,7 @@ void Q_DECL_VECTORCALL qt_memfillXX_avx2(uchar *dest, __m256i value256, qsizetyp
void qt_memfill64_avx2(quint64 *dest, quint64 value, qsizetype count)
{
-#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
+#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG)
// work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80820
__m128i value64 = _mm_set_epi64x(0, value); // _mm_cvtsi64_si128(value);
# ifdef Q_PROCESSOR_X86_64
@@ -478,14 +442,14 @@ void QT_FASTCALL comp_func_SourceOver_rgbafp_avx2(QRgbaFloat32 *dst, const QRgba
_mm256_storeu_ps((float *)(dst + x), dstVector);
}
if (x < length) {
- __m128 srcVector = _mm_load_ps((float *)(src + x));
- __m128 dstVector = _mm_load_ps((const float *)(dst + x));
+ __m128 srcVector = _mm_loadu_ps((const float *)&src[x]);
+ __m128 dstVector = _mm_loadu_ps((const float *)&dst[x]);
srcVector = _mm_mul_ps(srcVector, constAlphaVector);
__m128 alphaChannel = _mm_permute_ps(srcVector, _MM_SHUFFLE(3, 3, 3, 3));
alphaChannel = _mm_sub_ps(one, alphaChannel);
dstVector = _mm_mul_ps(dstVector, alphaChannel);
dstVector = _mm_add_ps(dstVector, srcVector);
- _mm_store_ps((float *)(dst + x), dstVector);
+ _mm_storeu_ps((float *)(dst + x), dstVector);
}
}
#endif
@@ -580,12 +544,12 @@ void QT_FASTCALL comp_func_Source_rgbafp_avx2(QRgbaFloat32 *dst, const QRgbaFloa
_mm256_storeu_ps((float *)&dst[x], dstVector);
}
if (x < length) {
- __m128 srcVector = _mm_load_ps((const float *)&src[x]);
- __m128 dstVector = _mm_load_ps((const float *)&dst[x]);
+ __m128 srcVector = _mm_loadu_ps((const float *)&src[x]);
+ __m128 dstVector = _mm_loadu_ps((const float *)&dst[x]);
srcVector = _mm_mul_ps(srcVector, constAlphaVector);
dstVector = _mm_mul_ps(dstVector, oneMinusConstAlpha);
dstVector = _mm_add_ps(dstVector, srcVector);
- _mm_store_ps((float *)&dst[x], dstVector);
+ _mm_storeu_ps((float *)&dst[x], dstVector);
}
}
}
@@ -666,7 +630,7 @@ void QT_FASTCALL comp_func_solid_Source_rgbafp_avx2(QRgbaFloat32 *dst, int lengt
const float a = const_alpha / 255.0f;
const __m128 alphaVector = _mm_set1_ps(a);
const __m128 minusAlphaVector = _mm_set1_ps(1.0f - a);
- __m128 colorVector = _mm_load_ps((const float *)&color);
+ __m128 colorVector = _mm_loadu_ps((const float *)&color);
colorVector = _mm_mul_ps(colorVector, alphaVector);
const __m256 colorVector256 = _mm256_insertf128_ps(_mm256_castps128_ps256(colorVector), colorVector, 1);
const __m256 minusAlphaVector256 = _mm256_set1_ps(1.0f - a);
@@ -678,10 +642,10 @@ void QT_FASTCALL comp_func_solid_Source_rgbafp_avx2(QRgbaFloat32 *dst, int lengt
_mm256_storeu_ps((float *)&dst[x], dstVector);
}
if (x < length) {
- __m128 dstVector = _mm_load_ps((const float *)&dst[x]);
+ __m128 dstVector = _mm_loadu_ps((const float *)&dst[x]);
dstVector = _mm_mul_ps(dstVector, minusAlphaVector);
dstVector = _mm_add_ps(dstVector, colorVector);
- _mm_store_ps((float *)&dst[x], dstVector);
+ _mm_storeu_ps((float *)&dst[x], dstVector);
}
}
}
@@ -693,7 +657,7 @@ void QT_FASTCALL comp_func_solid_SourceOver_rgbafp_avx2(QRgbaFloat32 *dst, int l
for (int i = 0; i < length; ++i)
dst[i] = color;
} else {
- __m128 colorVector = _mm_load_ps((const float *)&color);
+ __m128 colorVector = _mm_loadu_ps((const float *)&color);
if (const_alpha != 255)
colorVector = _mm_mul_ps(colorVector, _mm_set1_ps(const_alpha / 255.f));
__m128 minusAlphaOfColorVector =
@@ -709,10 +673,10 @@ void QT_FASTCALL comp_func_solid_SourceOver_rgbafp_avx2(QRgbaFloat32 *dst, int l
_mm256_storeu_ps((float *)&dst[x], dstVector);
}
if (x < length) {
- __m128 dstVector = _mm_load_ps((const float *)&dst[x]);
+ __m128 dstVector = _mm_loadu_ps((const float *)&dst[x]);
dstVector = _mm_mul_ps(dstVector, minusAlphaOfColorVector);
dstVector = _mm_add_ps(dstVector, colorVector);
- _mm_store_ps((float *)&dst[x], dstVector);
+ _mm_storeu_ps((float *)&dst[x], dstVector);
}
}
}
@@ -1381,13 +1345,16 @@ const QRgba64 *QT_FASTCALL fetchRGBA64ToRGBA64PM_avx2(QRgba64 *buffer, const uch
vslo = _mm256_srli_epi32(vslo, 16);
vshi = _mm256_srli_epi32(vshi, 16);
vs256 = _mm256_packus_epi32(vslo, vshi);
+ vs256 = _mm256_blend_epi16(vs256, va256, 0x88);
_mm256_storeu_si256((__m256i *)(buffer + i), vs256);
}
for (; i < count; ++i) {
+ const auto a = s[i].alpha();
__m128i vs = _mm_loadl_epi64((const __m128i *)(s + i));
__m128i va = _mm_shufflelo_epi16(vs, _MM_SHUFFLE(3, 3, 3, 3));
vs = multiplyAlpha65535(vs, va);
_mm_storel_epi64((__m128i *)(buffer + i), vs);
+ buffer[i].setAlpha(a);
}
return buffer;
}
@@ -1590,7 +1557,7 @@ const QRgbaFloat32 *QT_FASTCALL fetchRGBA16FToRGBA32F_avx2(QRgbaFloat32 *buffer,
__m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
vsf = _mm_mul_ps(vsf, vsa);
vsf = _mm_insert_ps(vsf, vsa, 0x30);
- _mm_store_ps((float *)(buffer + i), vsf);
+ _mm_storeu_ps((float *)(buffer + i), vsf);
}
return buffer;
}
@@ -1602,7 +1569,7 @@ void QT_FASTCALL storeRGBX16FFromRGBA32F_avx2(uchar *dest, const QRgbaFloat32 *s
const __m128 *s = reinterpret_cast<const __m128 *>(src);
const __m128 zero = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f);
for (int i = 0; i < count; ++i) {
- __m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(s + i));
+ __m128 vsf = _mm_loadu_ps(reinterpret_cast<const float *>(s + i));
const __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
const float a = _mm_cvtss_f32(vsa);
if (a == 1.0f)
@@ -1626,7 +1593,7 @@ void QT_FASTCALL storeRGBA16FFromRGBA32F_avx2(uchar *dest, const QRgbaFloat32 *s
const __m128 *s = reinterpret_cast<const __m128 *>(src);
const __m128 zero = _mm_set1_ps(0.0f);
for (int i = 0; i < count; ++i) {
- __m128 vsf = _mm_load_ps(reinterpret_cast<const float *>(s + i));
+ __m128 vsf = _mm_loadu_ps(reinterpret_cast<const float *>(s + i));
const __m128 vsa = _mm_permute_ps(vsf, _MM_SHUFFLE(3, 3, 3, 3));
const float a = _mm_cvtss_f32(vsa);
if (a == 1.0f)
diff --git a/src/gui/painting/qdrawhelper_mips_dsp.cpp b/src/gui/painting/qdrawhelper_mips_dsp.cpp
index 17597deb1d..86dcde2b58 100644
--- a/src/gui/painting/qdrawhelper_mips_dsp.cpp
+++ b/src/gui/painting/qdrawhelper_mips_dsp.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qdrawhelper_p.h>
#include <private/qdrawhelper_mips_dsp_p.h>
@@ -131,7 +95,7 @@ void qt_blend_rgb16_on_rgb16_mips_dspr2(uchar *destPixels, int dbpl,
}
else {
int length = w << 1;
- while (h--) {
+ while (--h >= 0) {
memcpy(destPixels, srcPixels, length);
destPixels += dbpl;
srcPixels += sbpl;
@@ -166,7 +130,7 @@ void qt_blend_rgb16_on_rgb16_mips_dsp(uchar *destPixels, int dbpl,
}
else {
int length = w << 1;
- while (h--) {
+ while (--h >= 0) {
memcpy(destPixels, srcPixels, length);
destPixels += dbpl;
srcPixels += sbpl;
diff --git a/src/gui/painting/qdrawhelper_mips_dsp_asm.S b/src/gui/painting/qdrawhelper_mips_dsp_asm.S
index c6b34293b6..8e0530aa9d 100644
--- a/src/gui/painting/qdrawhelper_mips_dsp_asm.S
+++ b/src/gui/painting/qdrawhelper_mips_dsp_asm.S
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qt_mips_asm_dsp_p.h"
@@ -1970,7 +1934,7 @@ LEAF_MIPS_DSP(fetchUntransformed_444_asm_mips_dsp)
2:
andi t0, a1, 0x3
beqz t0, 3f /* memory is word aligned */
- andi a3, a2, 0x1 /* set the a3 register as the comparation
+ andi a3, a2, 0x1 /* set the a3 register as the comparison
* for ending the unrolled loop
* (1 if odd, 0 if even) */
b 1b /* not word aligned,
diff --git a/src/gui/painting/qdrawhelper_mips_dsp_p.h b/src/gui/painting/qdrawhelper_mips_dsp_p.h
index a3d0410274..2a371b3b46 100644
--- a/src/gui/painting/qdrawhelper_mips_dsp_p.h
+++ b/src/gui/painting/qdrawhelper_mips_dsp_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDRAWHELPER_MIPS_DSP_P_H
#define QDRAWHELPER_MIPS_DSP_P_H
diff --git a/src/gui/painting/qdrawhelper_mips_dspr2_asm.S b/src/gui/painting/qdrawhelper_mips_dspr2_asm.S
index 4921365e36..edcaa5d0a9 100644
--- a/src/gui/painting/qdrawhelper_mips_dspr2_asm.S
+++ b/src/gui/painting/qdrawhelper_mips_dspr2_asm.S
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qt_mips_asm_dsp_p.h"
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
index db803e87c8..1fceb83710 100644
--- a/src/gui/painting/qdrawhelper_neon.cpp
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qdrawhelper_neon_p.h>
#include <private/qblendfunctions_p.h>
@@ -221,7 +185,7 @@ void qt_blend_rgb16_on_argb32_neon(uchar *destPixels, int dbpl,
quint8 a = (255 * const_alpha) >> 8;
quint8 ia = 255 - a;
- while (h--) {
+ while (--h >= 0) {
for (int x=0; x<w; ++x)
dst[x] = INTERPOLATE_PIXEL_255(qConvertRgb16To32(src[x]), a, dst[x], ia);
dst += dbpl;
@@ -264,7 +228,7 @@ static inline void blockBlit16(quint16 *dst, quint16 *src, int dstride, int sstr
u.pointer = dst;
if (u.address & 2) {
- while (h--) {
+ while (--h >= 0) {
// align dst
dst[0] = src[0];
if (Width > 1)
@@ -273,7 +237,7 @@ static inline void blockBlit16(quint16 *dst, quint16 *src, int dstride, int sstr
src += sstride;
}
} else {
- while (h--) {
+ while (--h >= 0) {
scanLineBlit16<Width>(dst, src, dstride);
dst += dstride;
diff --git a/src/gui/painting/qdrawhelper_neon_asm.S b/src/gui/painting/qdrawhelper_neon_asm.S
index 1830fd2fc0..3b6568403f 100644
--- a/src/gui/painting/qdrawhelper_neon_asm.S
+++ b/src/gui/painting/qdrawhelper_neon_asm.S
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#if defined(ENABLE_PIXMAN_DRAWHELPERS)
@@ -296,4 +260,4 @@ qt_rotate90_16_neon:
.endfunc
-#endif \ No newline at end of file
+#endif
diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h
index 19e1f21a3b..193499f223 100644
--- a/src/gui/painting/qdrawhelper_neon_p.h
+++ b/src/gui/painting/qdrawhelper_neon_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDRAWHELPER_NEON_P_H
#define QDRAWHELPER_NEON_P_H
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 2881d8a4f4..833ddd7b16 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDRAWHELPER_P_H
#define QDRAWHELPER_P_H
@@ -65,13 +29,13 @@
#include "private/qrasterdefs_p.h"
#include <private/qsimd_p.h>
-#include <QtCore/qsharedpointer.h>
+#include <memory>
QT_BEGIN_NAMESPACE
#if defined(Q_CC_GNU)
# define Q_DECL_RESTRICT __restrict__
-# if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
+# if defined(Q_PROCESSOR_X86_32) && defined(Q_CC_GNU) && !defined(Q_CC_CLANG)
# define Q_DECL_VECTORCALL __attribute__((sseregparm,regparm(3)))
# else
# define Q_DECL_VECTORCALL
@@ -89,13 +53,6 @@ static const uint RMASK = 0x00ff0000;
static const uint GMASK = 0x0000ff00;
static const uint BMASK = 0x000000ff;
-/*******************************************************************************
- * QSpan
- *
- * duplicate definition of FT_Span
- */
-typedef QT_FT_Span QSpan;
-
struct QSolidData;
struct QTextureData;
struct QGradientData;
@@ -183,9 +140,9 @@ struct quint24 {
uchar data[3];
};
-void qBlendGradient(int count, const QSpan *spans, void *userData);
-void qBlendTexture(int count, const QSpan *spans, void *userData);
-#ifdef __SSE2__
+void qBlendGradient(int count, const QT_FT_Span *spans, void *userData);
+void qBlendTexture(int count, const QT_FT_Span *spans, void *userData);
+#ifdef Q_PROCESSOR_X86
extern void (*qt_memfill64)(quint64 *dest, quint64 value, qsizetype count);
extern void (*qt_memfill32)(quint32 *dest, quint32 value, qsizetype count);
#else
@@ -217,7 +174,6 @@ struct RadialGradientValues
qreal dr;
qreal sqrfr;
qreal a;
- qreal inv2a;
bool extended;
};
@@ -368,20 +324,16 @@ struct QSpanData
uint fast_matrix : 1;
bool bilinear;
QImage *tempImage;
- QRgba64 solidColor;
+ QColor solidColor;
union {
QGradientData gradient;
QTextureData texture;
};
- class Pinnable {
- protected:
- ~Pinnable() {}
- }; // QSharedPointer<const void> is not supported
- QSharedPointer<const Pinnable> cachedGradient;
+ std::shared_ptr<const void> cachedGradient;
void init(QRasterBuffer *rb, const QRasterPaintEngine *pe);
- void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode);
+ void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode, bool isCosmetic);
void setupMatrix(const QTransform &matrix, int bilinear);
void initTexture(const QImage *image, int alpha, QTextureData::Type = QTextureData::Plain, const QRect &sourceRect = QRect());
void adjustSpanMethods();
@@ -449,12 +401,12 @@ const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffe
bool affine = !data->m13 && !data->m23;
BlendType *end = buffer + length;
+ qreal inv_a = 1 / qreal(2 * op->radial.a);
+
if (affine) {
rx -= data->gradient.radial.focal.x;
ry -= data->gradient.radial.focal.y;
- qreal inv_a = 1 / qreal(2 * op->radial.a);
-
const qreal delta_rx = data->m11;
const qreal delta_ry = data->m12;
@@ -499,8 +451,8 @@ const BlendType * QT_FASTCALL qt_fetch_radial_gradient_template(BlendType *buffe
if (det >= 0) {
qreal detSqrt = qSqrt(det);
- qreal s0 = (-b - detSqrt) * op->radial.inv2a;
- qreal s1 = (-b + detSqrt) * op->radial.inv2a;
+ qreal s0 = (-b - detSqrt) * inv_a;
+ qreal s1 = (-b + detSqrt) * inv_a;
qreal s = qMax(s0, s1);
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp
index 77b5ab42c5..79590534f3 100644
--- a/src/gui/painting/qdrawhelper_sse2.cpp
+++ b/src/gui/painting/qdrawhelper_sse2.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qdrawhelper_x86_p.h>
@@ -233,7 +197,7 @@ void QT_FASTCALL comp_func_Source_sse2(uint *dst, const uint *src, int length, u
}
}
-#ifndef __AVX2__
+#ifndef __haswell__
static Q_NEVER_INLINE
void Q_DECL_VECTORCALL qt_memfillXX_aligned(void *dest, __m128i value128, quintptr bytecount)
{
@@ -317,7 +281,7 @@ void qt_memfill32_sse2(quint32 *dest, quint32 value, qsizetype count)
qt_memfillXX_aligned(dest, _mm_set1_epi32(value), count * sizeof(quint32));
}
-#endif // !__AVX2__
+#endif // !__haswell__
void QT_FASTCALL comp_func_solid_Source_sse2(uint *destPixels, int length, uint color, uint const_alpha)
{
@@ -397,7 +361,7 @@ void qt_bitmapblit32_sse2_base(QRasterBuffer *rasterBuffer, int x, int y,
0x04040404, 0x08080808);
const __m128i maskadd2 = _mm_set_epi32(0x7f7f7f7f, 0x7e7e7e7e,
0x7c7c7c7c, 0x78787878);
- while (height--) {
+ while (--height >= 0) {
for (int x = 0; x < width; x += 8) {
const quint8 s = src[x >> 3];
if (!s)
@@ -416,7 +380,7 @@ void qt_bitmapblit32_sse2_base(QRasterBuffer *rasterBuffer, int x, int y,
src += stride;
}
} else {
- while (height--) {
+ while (--height >= 0) {
const quint8 s = *src;
if (s) {
__m128i mask1 = _mm_set1_epi8(s);
@@ -459,7 +423,7 @@ QT_WARNING_DISABLE_MSVC(4309) // truncation of constant value
const __m128i maskadd = _mm_set_epi16(0x7f7f, 0x7e7e, 0x7c7c, 0x7878,
0x7070, 0x6060, 0x4040, 0x0000);
- while (height--) {
+ while (--height >= 0) {
for (int x = 0; x < width; x += 8) {
const quint8 s = src[x >> 3];
if (!s)
@@ -533,66 +497,42 @@ void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
return qt_scale_image_argb32_on_argb32(destPixels, dbpl, srcPixels, sbpl, srch, targetRect, sourceRect, clip, const_alpha);
}
- qreal sx = targetRect.width() / (qreal) sourceRect.width();
- qreal sy = targetRect.height() / (qreal) sourceRect.height();
+ qreal sx = sourceRect.width() / (qreal)targetRect.width();
+ qreal sy = sourceRect.height() / (qreal)targetRect.height();
- int ix = 0x00010000 / sx;
- int iy = 0x00010000 / sy;
+ const int ix = 0x00010000 * sx;
+ const int iy = 0x00010000 * sy;
- int cx1 = clip.x();
- int cx2 = clip.x() + clip.width();
- int cy1 = clip.top();
- int cy2 = clip.y() + clip.height();
-
- int tx1 = qRound(targetRect.left());
- int tx2 = qRound(targetRect.right());
- int ty1 = qRound(targetRect.top());
- int ty2 = qRound(targetRect.bottom());
-
- if (tx2 < tx1)
- qSwap(tx2, tx1);
- if (ty2 < ty1)
- qSwap(ty2, ty1);
-
- if (tx1 < cx1)
- tx1 = cx1;
- if (tx2 >= cx2)
- tx2 = cx2;
-
- if (tx1 >= tx2)
+ QRect tr = targetRect.normalized().toRect();
+ tr = tr.intersected(clip);
+ if (tr.isEmpty())
return;
-
- if (ty1 < cy1)
- ty1 = cy1;
- if (ty2 >= cy2)
- ty2 = cy2;
- if (ty1 >= ty2)
- return;
-
- int h = ty2 - ty1;
- int w = tx2 - tx1;
+ const int tx1 = tr.left();
+ const int ty1 = tr.top();
+ int h = tr.height();
+ int w = tr.width();
quint32 basex;
quint32 srcy;
if (sx < 0) {
- int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1;
+ int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * sx * 65536) + 1;
basex = quint32(sourceRect.right() * 65536) + dstx;
} else {
- int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1;
+ int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * sx * 65536) - 1;
basex = quint32(sourceRect.left() * 65536) + dstx;
}
if (sy < 0) {
- int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1;
+ int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * sy * 65536) + 1;
srcy = quint32(sourceRect.bottom() * 65536) + dsty;
} else {
- int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1;
+ int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * sy * 65536) - 1;
srcy = quint32(sourceRect.top() * 65536) + dsty;
}
quint32 *dst = ((quint32 *) (destPixels + ty1 * dbpl)) + tx1;
- const __m128i nullVector = _mm_set1_epi32(0);
+ const __m128i nullVector = _mm_setzero_si128();
const __m128i half = _mm_set1_epi16(0x80);
const __m128i one = _mm_set1_epi16(0xff);
const __m128i colorMask = _mm_set1_epi32(0x00ff00ff);
@@ -618,7 +558,7 @@ void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
if (xend < 0 || xend >= (int)(sbpl/sizeof(quint32)))
--w;
- while (h--) {
+ while (--h >= 0) {
const uint *src = (const quint32 *) (srcPixels + (srcy >> 16) * sbpl);
int srcx = basex;
int x = 0;
@@ -631,13 +571,14 @@ void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl,
__m128i srcxVector = _mm_set_epi32(srcx, srcx + ix, srcx + ix + ix, srcx + ix + ix + ix);
- for (; x<w - 3; x += 4) {
- union Vect_buffer { __m128i vect; quint32 i[4]; };
- Vect_buffer addr;
- addr.vect = _mm_srli_epi32(srcxVector, 16);
+ for (; x < (w - 3); x += 4) {
+ const int idx0 = _mm_extract_epi16(srcxVector, 1);
+ const int idx1 = _mm_extract_epi16(srcxVector, 3);
+ const int idx2 = _mm_extract_epi16(srcxVector, 5);
+ const int idx3 = _mm_extract_epi16(srcxVector, 7);
srcxVector = _mm_add_epi32(srcxVector, ixVector);
- const __m128i srcVector = _mm_set_epi32(src[addr.i[0]], src[addr.i[1]], src[addr.i[2]], src[addr.i[3]]);
+ const __m128i srcVector = _mm_set_epi32(src[idx0], src[idx1], src[idx2], src[idx3]);
BLEND_SOURCE_OVER_ARGB32_SSE2_helper(dst, srcVector, nullVector, half, one, colorMask, alphaMask);
}
diff --git a/src/gui/painting/qdrawhelper_sse4.cpp b/src/gui/painting/qdrawhelper_sse4.cpp
index c4c11cd1ff..a7b4e6ba76 100644
--- a/src/gui/painting/qdrawhelper_sse4.cpp
+++ b/src/gui/painting/qdrawhelper_sse4.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qdrawhelper_p.h>
#include <private/qdrawingprimitive_sse2_p.h>
@@ -46,7 +10,7 @@
QT_BEGIN_NAMESPACE
-#ifndef __AVX2__
+#ifndef __haswell__
template<bool RGBA>
static void convertARGBToARGB32PM_sse4(uint *buffer, const uint *src, int count)
{
@@ -142,7 +106,7 @@ static void convertARGBToRGBA64PM_sse4(QRgba64 *buffer, const uint *src, int cou
buffer[i] = QRgba64::fromArgb32(s).premultiplied();
}
}
-#endif // __AVX2__
+#endif // __haswell__
static inline __m128 Q_DECL_VECTORCALL reciprocal_mul_ps(__m128 a, float mul)
{
@@ -411,7 +375,7 @@ static inline void convertRGBA64FromRGBA64PM_sse4(QRgba64 *buffer, const QRgba64
}
}
-#ifndef __AVX2__
+#ifndef __haswell__
void QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, int count, const QList<QRgb> *)
{
convertARGBToARGB32PM_sse4<false>(buffer, buffer, count);
@@ -463,7 +427,7 @@ const QRgba64 *QT_FASTCALL fetchRGBA8888ToRGBA64PM_sse4(QRgba64 *buffer, const u
convertARGBToRGBA64PM_sse4<true>(buffer, reinterpret_cast<const uint *>(src) + index, count);
return buffer;
}
-#endif // __AVX2__
+#endif // __haswell__
void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count,
const QList<QRgb> *, QDitherInfo *)
diff --git a/src/gui/painting/qdrawhelper_ssse3.cpp b/src/gui/painting/qdrawhelper_ssse3.cpp
index a175b591dd..6e905c7f84 100644
--- a/src/gui/painting/qdrawhelper_ssse3.cpp
+++ b/src/gui/painting/qdrawhelper_ssse3.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qdrawhelper_x86_p.h>
@@ -47,7 +11,7 @@
QT_BEGIN_NAMESPACE
/* The instruction palignr uses direct arguments, so we have to generate the code fo the different
- shift (4, 8, 12). Checking the alignment inside the loop is unfortunatelly way too slow.
+ shift (4, 8, 12). Checking the alignment inside the loop is unfortunately way too slow.
*/
#define BLENDING_LOOP(palignrOffset, length)\
for (; x-minusOffsetToAlignSrcOn16Bytes < length-7; x += 4) { \
diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h
index 869abcc637..15773fe014 100644
--- a/src/gui/painting/qdrawhelper_x86_p.h
+++ b/src/gui/painting/qdrawhelper_x86_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDRAWHELPER_X86_P_H
#define QDRAWHELPER_X86_P_H
diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h
index b3bb22fe1b..2233b73e56 100644
--- a/src/gui/painting/qdrawingprimitive_sse2_p.h
+++ b/src/gui/painting/qdrawingprimitive_sse2_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDRAWINGPRIMITIVE_SSE2_P_H
#define QDRAWINGPRIMITIVE_SSE2_P_H
@@ -64,7 +28,7 @@ QT_BEGIN_NAMESPACE
* Multiply the components of pixelVector by alphaChannel
* Each 32bits components of alphaChannel must be in the form 0x00AA00AA
* colorMask must have 0x00ff00ff on each 32 bits component
- * half must have the value 128 (0x80) for each 32 bits compnent
+ * half must have the value 128 (0x80) for each 32 bits component
*/
#define BYTE_MUL_SSE2(result, pixelVector, alphaChannel, colorMask, half) \
{ \
@@ -102,7 +66,7 @@ QT_BEGIN_NAMESPACE
* Each 32bits components of alphaChannel must be in the form 0x00AA00AA
* oneMinusAlphaChannel must be 255 - alpha for each 32 bits component
* colorMask must have 0x00ff00ff on each 32 bits component
- * half must have the value 128 (0x80) for each 32 bits compnent
+ * half must have the value 128 (0x80) for each 32 bits component
*/
#define INTERPOLATE_PIXEL_255_SSE2(result, srcVector, dstVector, alphaChannel, oneMinusAlphaChannel, colorMask, half) { \
/* interpolate AG */\
diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp
index e3c34ed533..8e871238cc 100644
--- a/src/gui/painting/qemulationpaintengine.cpp
+++ b/src/gui/painting/qemulationpaintengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qemulationpaintengine_p.h>
#include <private/qpainter_p.h>
diff --git a/src/gui/painting/qemulationpaintengine_p.h b/src/gui/painting/qemulationpaintengine_p.h
index a2eb9b008c..cabb8485cb 100644
--- a/src/gui/painting/qemulationpaintengine_p.h
+++ b/src/gui/painting/qemulationpaintengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEMULATIONPAINTENGINE_P_H
#define QEMULATIONPAINTENGINE_P_H
diff --git a/src/gui/painting/qfixed_p.h b/src/gui/painting/qfixed_p.h
index 7580069153..c0a13d057f 100644
--- a/src/gui/painting/qfixed_p.h
+++ b/src/gui/painting/qfixed_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFIXED_P_H
#define QFIXED_P_H
@@ -54,6 +18,7 @@
#include <QtGui/private/qtguiglobal_p.h>
#include "QtCore/qdebug.h"
#include "QtCore/qpoint.h"
+#include "QtCore/qnumeric.h"
#include "QtCore/qsize.h"
QT_BEGIN_NAMESPACE
@@ -65,8 +30,7 @@ public:
constexpr QFixed() : val(0) {}
constexpr QFixed(int i) : val(i * 64) {}
constexpr QFixed(long i) : val(i * 64) {}
- QFixed &operator=(int i) { val = i * 64; return *this; }
- QFixed &operator=(long i) { val = i * 64; return *this; }
+ constexpr QFixed(long long i) : val(i * 64) {}
constexpr static QFixed fromReal(qreal r) { return fromFixed((int)(r*qreal(64))); }
constexpr static QFixed fromFixed(int fixed) { return QFixed(fixed,0); } // uses private ctor
@@ -84,28 +48,33 @@ public:
constexpr inline QFixed operator+(int i) const { return fromFixed(val + i * 64); }
constexpr inline QFixed operator+(uint i) const { return fromFixed((val + (i<<6))); }
- constexpr inline QFixed operator+(const QFixed &other) const { return fromFixed((val + other.val)); }
+ constexpr inline QFixed operator+(QFixed other) const { return fromFixed((val + other.val)); }
inline QFixed &operator+=(int i) { val += i * 64; return *this; }
inline QFixed &operator+=(uint i) { val += (i<<6); return *this; }
- inline QFixed &operator+=(const QFixed &other) { val += other.val; return *this; }
+ inline QFixed &operator+=(QFixed other) { val += other.val; return *this; }
constexpr inline QFixed operator-(int i) const { return fromFixed(val - i * 64); }
constexpr inline QFixed operator-(uint i) const { return fromFixed((val - (i<<6))); }
- constexpr inline QFixed operator-(const QFixed &other) const { return fromFixed((val - other.val)); }
+ constexpr inline QFixed operator-(QFixed other) const { return fromFixed((val - other.val)); }
inline QFixed &operator-=(int i) { val -= i * 64; return *this; }
inline QFixed &operator-=(uint i) { val -= (i<<6); return *this; }
- inline QFixed &operator-=(const QFixed &other) { val -= other.val; return *this; }
+ inline QFixed &operator-=(QFixed other) { val -= other.val; return *this; }
constexpr inline QFixed operator-() const { return fromFixed(-val); }
- constexpr inline bool operator==(const QFixed &other) const { return val == other.val; }
- constexpr inline bool operator!=(const QFixed &other) const { return val != other.val; }
- constexpr inline bool operator<(const QFixed &other) const { return val < other.val; }
- constexpr inline bool operator>(const QFixed &other) const { return val > other.val; }
- constexpr inline bool operator<=(const QFixed &other) const { return val <= other.val; }
- constexpr inline bool operator>=(const QFixed &other) const { return val >= other.val; }
+#define REL_OP(op) \
+ friend constexpr bool operator op(QFixed lhs, QFixed rhs) noexcept \
+ { return lhs.val op rhs.val; }
+ REL_OP(==)
+ REL_OP(!=)
+ REL_OP(< )
+ REL_OP(> )
+ REL_OP(<=)
+ REL_OP(>=)
+#undef REL_OP
+
constexpr inline bool operator!() const { return !val; }
inline QFixed &operator/=(int x) { val /= x; return *this; }
- inline QFixed &operator/=(const QFixed &o) {
+ inline QFixed &operator/=(QFixed o) {
if (o.val == 0) {
val = 0x7FFFFFFFL;
} else {
@@ -126,7 +95,7 @@ public:
inline QFixed operator>>(int d) const { QFixed f = *this; f.val >>= d; return f; }
inline QFixed &operator*=(int i) { val *= i; return *this; }
inline QFixed &operator*=(uint i) { val *= i; return *this; }
- inline QFixed &operator*=(const QFixed &o) {
+ inline QFixed &operator*=(QFixed o) {
bool neg = false;
qint64 a = val;
qint64 b = o.val;
@@ -139,11 +108,10 @@ public:
}
constexpr inline QFixed operator*(int i) const { return fromFixed(val * i); }
constexpr inline QFixed operator*(uint i) const { return fromFixed(val * i); }
- inline QFixed operator*(const QFixed &o) const { QFixed f = *this; return (f *= o); }
+ inline QFixed operator*(QFixed o) const { QFixed f = *this; return (f *= o); }
private:
constexpr QFixed(qreal i) : val((int)(i*qreal(64))) {}
- QFixed &operator=(qreal i) { val = (int)(i*qreal(64)); return *this; }
constexpr inline QFixed operator+(qreal i) const { return fromFixed((val + (int)(i*qreal(64)))); }
inline QFixed &operator+=(qreal i) { val += (int)(i*64); return *this; }
constexpr inline QFixed operator-(qreal i) const { return fromFixed((val - (int)(i*qreal(64)))); }
@@ -158,32 +126,35 @@ Q_DECLARE_TYPEINFO(QFixed, Q_PRIMITIVE_TYPE);
#define QFIXED_MAX (INT_MAX/256)
-constexpr inline int qRound(const QFixed &f) { return f.toInt(); }
-constexpr inline int qFloor(const QFixed &f) { return f.floor().truncate(); }
-
-constexpr inline QFixed operator*(int i, const QFixed &d) { return d*i; }
-constexpr inline QFixed operator+(int i, const QFixed &d) { return d+i; }
-constexpr inline QFixed operator-(int i, const QFixed &d) { return -(d-i); }
-constexpr inline QFixed operator*(uint i, const QFixed &d) { return d*i; }
-constexpr inline QFixed operator+(uint i, const QFixed &d) { return d+i; }
-constexpr inline QFixed operator-(uint i, const QFixed &d) { return -(d-i); }
-// constexpr inline QFixed operator*(qreal d, const QFixed &d2) { return d2*d; }
-
-constexpr inline bool operator==(const QFixed &f, int i) { return f.value() == i * 64; }
-constexpr inline bool operator==(int i, const QFixed &f) { return f.value() == i * 64; }
-constexpr inline bool operator!=(const QFixed &f, int i) { return f.value() != i * 64; }
-constexpr inline bool operator!=(int i, const QFixed &f) { return f.value() != i * 64; }
-constexpr inline bool operator<=(const QFixed &f, int i) { return f.value() <= i * 64; }
-constexpr inline bool operator<=(int i, const QFixed &f) { return i * 64 <= f.value(); }
-constexpr inline bool operator>=(const QFixed &f, int i) { return f.value() >= i * 64; }
-constexpr inline bool operator>=(int i, const QFixed &f) { return i * 64 >= f.value(); }
-constexpr inline bool operator<(const QFixed &f, int i) { return f.value() < i * 64; }
-constexpr inline bool operator<(int i, const QFixed &f) { return i * 64 < f.value(); }
-constexpr inline bool operator>(const QFixed &f, int i) { return f.value() > i * 64; }
-constexpr inline bool operator>(int i, const QFixed &f) { return i * 64 > f.value(); }
+constexpr inline int qRound(QFixed f) { return f.toInt(); }
+constexpr inline int qFloor(QFixed f) { return f.floor().truncate(); }
+
+constexpr inline QFixed operator*(int i, QFixed d) { return d*i; }
+constexpr inline QFixed operator+(int i, QFixed d) { return d+i; }
+constexpr inline QFixed operator-(int i, QFixed d) { return -(d-i); }
+constexpr inline QFixed operator*(uint i, QFixed d) { return d*i; }
+constexpr inline QFixed operator+(uint i, QFixed d) { return d+i; }
+constexpr inline QFixed operator-(uint i, QFixed d) { return -(d-i); }
+// constexpr inline QFixed operator*(qreal d, QFixed d2) { return d2*d; }
+
+inline bool qAddOverflow(QFixed v1, QFixed v2, QFixed *r)
+{
+ int val;
+ bool result = qAddOverflow(v1.value(), v2.value(), &val);
+ r->setValue(val);
+ return result;
+}
+
+inline bool qMulOverflow(QFixed v1, QFixed v2, QFixed *r)
+{
+ int val;
+ bool result = qMulOverflow(v1.value(), v2.value(), &val);
+ r->setValue(val);
+ return result;
+}
#ifndef QT_NO_DEBUG_STREAM
-inline QDebug &operator<<(QDebug &dbg, const QFixed &f)
+inline QDebug &operator<<(QDebug &dbg, QFixed f)
{ return dbg << f.toReal(); }
#endif
@@ -191,7 +162,7 @@ struct QFixedPoint {
QFixed x;
QFixed y;
constexpr inline QFixedPoint() {}
- constexpr inline QFixedPoint(const QFixed &_x, const QFixed &_y) : x(_x), y(_y) {}
+ constexpr inline QFixedPoint(QFixed _x, QFixed _y) : x(_x), y(_y) {}
constexpr QPointF toPointF() const { return QPointF(x.toReal(), y.toReal()); }
constexpr static QFixedPoint fromPointF(const QPointF &p) {
return QFixedPoint(QFixed::fromReal(p.x()), QFixed::fromReal(p.y()));
diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c
index c6b9aa679e..3c222c49e1 100644
--- a/src/gui/painting/qgrayraster.c
+++ b/src/gui/painting/qgrayraster.c
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/***************************************************************************/
/* */
diff --git a/src/gui/painting/qgrayraster_p.h b/src/gui/painting/qgrayraster_p.h
index 86d54d4379..f9aae18e9d 100644
--- a/src/gui/painting/qgrayraster_p.h
+++ b/src/gui/painting/qgrayraster_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/***************************************************************************/
/* */
diff --git a/src/gui/painting/qicc.cpp b/src/gui/painting/qicc.cpp
index 8f6a204caa..c01fa433ea 100644
--- a/src/gui/painting/qicc.cpp
+++ b/src/gui/painting/qicc.cpp
@@ -1,51 +1,19 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qicc_p.h"
#include <qbuffer.h>
#include <qbytearray.h>
+#include <qvarlengtharray.h>
+#include <qhash.h>
#include <qdatastream.h>
#include <qendian.h>
#include <qloggingcategory.h>
#include <qstring.h>
+#include "qcolorclut_p.h"
+#include "qcolormatrix_p.h"
#include "qcolorspace_p.h"
#include "qcolortrc_p.h"
@@ -54,6 +22,8 @@
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcIcc, "qt.gui.icc", QtWarningMsg)
+namespace QIcc {
+
struct ICCProfileHeader
{
quint32_be profileSize;
@@ -92,18 +62,23 @@ constexpr quint32 IccTag(uchar a, uchar b, uchar c, uchar d)
enum class ColorSpaceType : quint32 {
Rgb = IccTag('R', 'G', 'B', ' '),
Gray = IccTag('G', 'R', 'A', 'Y'),
+ Cmyk = IccTag('C', 'M', 'Y', 'K'),
};
enum class ProfileClass : quint32 {
- Input = IccTag('s', 'c', 'r', 'n'),
+ Input = IccTag('s', 'c', 'n', 'r'),
Display = IccTag('m', 'n', 't', 'r'),
- // Not supported:
Output = IccTag('p', 'r', 't', 'r'),
ColorSpace = IccTag('s', 'p', 'a', 'c'),
+ // Not supported:
+ DeviceLink = IccTag('l', 'i', 'n', 'k'),
+ Abstract = IccTag('a', 'b', 's', 't'),
+ NamedColor = IccTag('n', 'm', 'c', 'l'),
};
enum class Tag : quint32 {
acsp = IccTag('a', 'c', 's', 'p'),
+ Lab_ = IccTag('L', 'a', 'b', ' '),
RGB_ = IccTag('R', 'G', 'B', ' '),
XYZ_ = IccTag('X', 'Y', 'Z', ' '),
rXYZ = IccTag('r', 'X', 'Y', 'Z'),
@@ -115,8 +90,18 @@ enum class Tag : quint32 {
kTRC = IccTag('k', 'T', 'R', 'C'),
A2B0 = IccTag('A', '2', 'B', '0'),
A2B1 = IccTag('A', '2', 'B', '1'),
+ A2B2 = IccTag('A', '2', 'B', '2'),
B2A0 = IccTag('B', '2', 'A', '0'),
B2A1 = IccTag('B', '2', 'A', '1'),
+ B2A2 = IccTag('B', '2', 'A', '2'),
+ B2D0 = IccTag('B', '2', 'D', '0'),
+ B2D1 = IccTag('B', '2', 'D', '1'),
+ B2D2 = IccTag('B', '2', 'D', '2'),
+ B2D3 = IccTag('B', '2', 'D', '3'),
+ D2B0 = IccTag('D', '2', 'B', '0'),
+ D2B1 = IccTag('D', '2', 'B', '1'),
+ D2B2 = IccTag('D', '2', 'B', '2'),
+ D2B3 = IccTag('D', '2', 'B', '3'),
desc = IccTag('d', 'e', 's', 'c'),
text = IccTag('t', 'e', 'x', 't'),
cprt = IccTag('c', 'p', 'r', 't'),
@@ -127,9 +112,11 @@ enum class Tag : quint32 {
mft1 = IccTag('m', 'f', 't', '1'),
mft2 = IccTag('m', 'f', 't', '2'),
mluc = IccTag('m', 'l', 'u', 'c'),
+ mpet = IccTag('m', 'p', 'e', 't'),
mAB_ = IccTag('m', 'A', 'B', ' '),
mBA_ = IccTag('m', 'B', 'A', ' '),
chad = IccTag('c', 'h', 'a', 'd'),
+ gamt = IccTag('g', 'a', 'm', 't'),
sf32 = IccTag('s', 'f', '3', '2'),
// Apple extensions for ICCv2:
@@ -138,7 +125,9 @@ enum class Tag : quint32 {
aabg = IccTag('a', 'a', 'b', 'g'),
};
-inline size_t qHash(const Tag &key, size_t seed = 0)
+} // namespace QIcc
+
+inline size_t qHash(const QIcc::Tag &key, size_t seed = 0)
{
return qHash(quint32(key), seed);
}
@@ -193,6 +182,46 @@ struct MlucTagData : GenericTagData {
MlucTagRecord records[1];
};
+struct Lut8TagData : GenericTagData {
+ quint8 inputChannels;
+ quint8 outputChannels;
+ quint8 clutGridPoints;
+ quint8 padding;
+ qint32_be e1;
+ qint32_be e2;
+ qint32_be e3;
+ qint32_be e4;
+ qint32_be e5;
+ qint32_be e6;
+ qint32_be e7;
+ qint32_be e8;
+ qint32_be e9;
+ // followed by parameter values: quint8[inputChannels * 256];
+ // followed by parameter values: quint8[outputChannels * clutGridPoints^inputChannels];
+ // followed by parameter values: quint8[outputChannels * 256];
+};
+
+struct Lut16TagData : GenericTagData {
+ quint8 inputChannels;
+ quint8 outputChannels;
+ quint8 clutGridPoints;
+ quint8 padding;
+ qint32_be e1;
+ qint32_be e2;
+ qint32_be e3;
+ qint32_be e4;
+ qint32_be e5;
+ qint32_be e6;
+ qint32_be e7;
+ qint32_be e8;
+ qint32_be e9;
+ quint16_be inputTableEntries;
+ quint16_be outputTableEntries;
+ // followed by parameter values: quint16_be[inputChannels * inputTableEntries];
+ // followed by parameter values: quint16_be[outputChannels * clutGridPoints^inputChannels];
+ // followed by parameter values: quint16_be[outputChannels * outputTableEntries];
+};
+
// For both mAB and mBA
struct mABTagData : GenericTagData {
quint8 inputChannels;
@@ -203,10 +232,34 @@ struct mABTagData : GenericTagData {
quint32_be mCurvesOffset;
quint32_be clutOffset;
quint32_be aCurvesOffset;
+ // followed by embedded data for the offsets above
+};
+
+struct mpetTagData : GenericTagData {
+ quint16_be inputChannels;
+ quint16_be outputChannels;
+ quint32_be processingElements;
+ // element offset table
+ // element data
};
struct Sf32TagData : GenericTagData {
- quint32_be value[1];
+ quint32_be value[9];
+};
+
+struct MatrixElement {
+ qint32_be e0;
+ qint32_be e1;
+ qint32_be e2;
+ qint32_be e3;
+ qint32_be e4;
+ qint32_be e5;
+ qint32_be e6;
+ qint32_be e7;
+ qint32_be e8;
+ qint32_be e9;
+ qint32_be e10;
+ qint32_be e11;
};
static int toFixedS1516(float x)
@@ -238,19 +291,19 @@ static bool isValidIccProfile(const ICCProfileHeader &header)
if (header.profileClass != uint(ProfileClass::Input)
&& header.profileClass != uint(ProfileClass::Display)
- && (header.profileClass != uint(ProfileClass::Output)
- || header.inputColorSpace != uint(ColorSpaceType::Gray))) {
+ && header.profileClass != uint(ProfileClass::Output)
+ && header.profileClass != uint(ProfileClass::ColorSpace)) {
qCInfo(lcIcc, "Unsupported ICC profile class 0x%x", quint32(header.profileClass));
return false;
}
if (header.inputColorSpace != uint(ColorSpaceType::Rgb)
- && header.inputColorSpace != uint(ColorSpaceType::Gray)) {
+ && header.inputColorSpace != uint(ColorSpaceType::Gray)
+ && header.inputColorSpace != uint(ColorSpaceType::Cmyk)) {
qCInfo(lcIcc, "Unsupported ICC input color space 0x%x", quint32(header.inputColorSpace));
return false;
}
- if (header.pcs != 0x58595a20 /* 'XYZ '*/) {
- // ### support PCSLAB
- qCInfo(lcIcc, "Unsupported ICC profile connection space 0x%x", quint32(header.pcs));
+ if (header.pcs != uint(Tag::XYZ_) && header.pcs != uint(Tag::Lab_)) {
+ qCInfo(lcIcc, "Invalid ICC profile connection space 0x%x", quint32(header.pcs));
return false;
}
@@ -268,7 +321,7 @@ static bool isValidIccProfile(const ICCProfileHeader &header)
static int writeColorTrc(QDataStream &stream, const QColorTrc &trc)
{
- if (trc.isLinear()) {
+ if (trc.isIdentity()) {
stream << uint(Tag::curv) << uint(0);
stream << uint(0);
return 12;
@@ -308,6 +361,10 @@ static int writeColorTrc(QDataStream &stream, const QColorTrc &trc)
stream << ushort(trc.m_table.m_table8[i] * 257U);
}
}
+ if (trc.m_table.m_tableSize & 1) {
+ stream << ushort(0);
+ return 12 + 2 * trc.m_table.m_tableSize + 2;
+ }
return 12 + 2 * trc.m_table.m_tableSize;
}
@@ -317,10 +374,21 @@ QByteArray toIccProfile(const QColorSpace &space)
return QByteArray();
const QColorSpacePrivate *spaceDPtr = QColorSpacePrivate::get(space);
+ // This should catch anything not three component matrix based as we can only get that from parsed ICC
+ if (!spaceDPtr->iccProfile.isEmpty())
+ return spaceDPtr->iccProfile;
+ Q_ASSERT(spaceDPtr->isThreeComponentMatrix());
+
+ int fixedLengthTagCount = 5;
+ bool writeChad = false;
+ if (!spaceDPtr->whitePoint.isNull() && spaceDPtr->whitePoint != QColorVector::D50()) {
+ writeChad = true;
+ fixedLengthTagCount++;
+ }
- constexpr int tagCount = 9;
- constexpr uint profileDataOffset = 128 + 4 + 12 * tagCount;
- constexpr uint variableTagTableOffsets = 128 + 4 + 12 * 5;
+ const int tagCount = fixedLengthTagCount + 4;
+ const uint profileDataOffset = 128 + 4 + 12 * tagCount;
+ const uint variableTagTableOffsets = 128 + 4 + 12 * fixedLengthTagCount;
uint currentOffset = 0;
uint rTrcOffset, gTrcOffset, bTrcOffset;
uint rTrcSize, gTrcSize, bTrcSize;
@@ -333,10 +401,10 @@ QByteArray toIccProfile(const QColorSpace &space)
// Profile header:
stream << uint(0); // Size, we will update this later
stream << uint(0);
- stream << uint(0x02400000); // Version 2.4 (note we use 'para' from version 4)
+ stream << uint(0x04400000); // Version 4.4
stream << uint(ProfileClass::Display);
stream << uint(Tag::RGB_);
- stream << uint(Tag::XYZ_);
+ stream << (spaceDPtr->isPcsLab ? uint(Tag::Lab_) : uint(Tag::XYZ_));
stream << uint(0) << uint(0) << uint(0);
stream << uint(Tag::acsp);
stream << uint(0) << uint(0) << uint(0);
@@ -350,19 +418,23 @@ QByteArray toIccProfile(const QColorSpace &space)
stream << uint(0) << uint(0) << uint(0) << uint(0) << uint(0) << uint(0) << uint(0);
// Tag table:
+ currentOffset = profileDataOffset;
stream << uint(tagCount);
stream << uint(Tag::rXYZ) << uint(profileDataOffset + 00) << uint(20);
stream << uint(Tag::gXYZ) << uint(profileDataOffset + 20) << uint(20);
stream << uint(Tag::bXYZ) << uint(profileDataOffset + 40) << uint(20);
stream << uint(Tag::wtpt) << uint(profileDataOffset + 60) << uint(20);
- stream << uint(Tag::cprt) << uint(profileDataOffset + 80) << uint(12);
+ stream << uint(Tag::cprt) << uint(profileDataOffset + 80) << uint(34);
+ currentOffset += 20 + 20 + 20 + 20 + 34 + 2;
+ if (writeChad) {
+ stream << uint(Tag::chad) << uint(currentOffset) << uint(44);
+ currentOffset += 44;
+ }
// From here the offset and size will be updated later:
stream << uint(Tag::rTRC) << uint(0) << uint(0);
stream << uint(Tag::gTRC) << uint(0) << uint(0);
stream << uint(Tag::bTRC) << uint(0) << uint(0);
stream << uint(Tag::desc) << uint(0) << uint(0);
- // TODO: consider adding 'chad' tag (required in ICC >=4 when we have non-D50 whitepoint)
- currentOffset = profileDataOffset;
// Tag data:
stream << uint(Tag::XYZ_) << uint(0);
@@ -381,9 +453,25 @@ QByteArray toIccProfile(const QColorSpace &space)
stream << toFixedS1516(spaceDPtr->whitePoint.x);
stream << toFixedS1516(spaceDPtr->whitePoint.y);
stream << toFixedS1516(spaceDPtr->whitePoint.z);
- stream << uint(Tag::text) << uint(0);
- stream << uint(IccTag('N', '/', 'A', '\0'));
- currentOffset += 92;
+ stream << uint(Tag::mluc) << uint(0);
+ stream << uint(1) << uint(12);
+ stream << uchar('e') << uchar('n') << uchar('U') << uchar('S');
+ stream << uint(6) << uint(28);
+ stream << ushort('N') << ushort('/') << ushort('A');
+ stream << ushort(0); // 4-byte alignment
+ if (writeChad) {
+ QColorMatrix chad = QColorMatrix::chromaticAdaptation(spaceDPtr->whitePoint);
+ stream << uint(Tag::sf32) << uint(0);
+ stream << toFixedS1516(chad.r.x);
+ stream << toFixedS1516(chad.g.x);
+ stream << toFixedS1516(chad.b.x);
+ stream << toFixedS1516(chad.r.y);
+ stream << toFixedS1516(chad.g.y);
+ stream << toFixedS1516(chad.b.y);
+ stream << toFixedS1516(chad.r.z);
+ stream << toFixedS1516(chad.g.z);
+ stream << toFixedS1516(chad.b.z);
+ }
// From now on the data is variable sized:
rTrcOffset = currentOffset;
@@ -406,16 +494,20 @@ QByteArray toIccProfile(const QColorSpace &space)
currentOffset += bTrcSize;
}
+ // Writing description
descOffset = currentOffset;
- QByteArray description = space.description().toUtf8();
- stream << uint(Tag::desc) << uint(0);
- stream << uint(description.size() + 1);
- stream.writeRawData(description.constData(), description.size() + 1);
- stream << uint(0) << uint(0);
- stream << ushort(0) << uchar(0);
- QByteArray macdesc(67, '\0');
- stream.writeRawData(macdesc.constData(), 67);
- descSize = 90 + description.size() + 1;
+ const QString description = space.description();
+ stream << uint(Tag::mluc) << uint(0);
+ stream << uint(1) << uint(12);
+ stream << uchar('e') << uchar('n') << uchar('U') << uchar('S');
+ stream << uint(description.size() * 2) << uint(28);
+ for (QChar ch : description)
+ stream << ushort(ch.unicode());
+ descSize = 28 + description.size() * 2;
+ if (description.size() & 1) {
+ stream << ushort(0);
+ currentOffset += 2;
+ }
currentOffset += descSize;
buffer.close();
@@ -446,7 +538,7 @@ struct TagEntry {
quint32 size;
};
-bool parseXyzData(const QByteArray &data, const TagEntry &tagEntry, QColorVector &colorVector)
+static bool parseXyzData(const QByteArray &data, const TagEntry &tagEntry, QColorVector &colorVector)
{
if (tagEntry.size < sizeof(XYZTagData)) {
qCWarning(lcIcc) << "Undersized XYZ tag";
@@ -465,23 +557,22 @@ bool parseXyzData(const QByteArray &data, const TagEntry &tagEntry, QColorVector
return true;
}
-bool parseTRC(const QByteArray &data, const TagEntry &tagEntry, QColorTrc &gamma)
+static quint32 parseTRC(const QByteArrayView &tagData, QColorTrc &gamma, QColorTransferTable::Type type = QColorTransferTable::TwoWay)
{
- const GenericTagData trcData = qFromUnaligned<GenericTagData>(data.constData()
- + tagEntry.offset);
+ const GenericTagData trcData = qFromUnaligned<GenericTagData>(tagData.constData());
if (trcData.type == quint32(Tag::curv)) {
Q_STATIC_ASSERT(sizeof(CurvTagData) == 12);
- const CurvTagData curv = qFromUnaligned<CurvTagData>(data.constData() + tagEntry.offset);
+ const CurvTagData curv = qFromUnaligned<CurvTagData>(tagData.constData());
if (curv.valueCount > (1 << 16))
- return false;
- if (tagEntry.size - 12 < 2 * curv.valueCount)
- return false;
- const auto valueOffset = tagEntry.offset + sizeof(CurvTagData);
+ return 0;
+ if (tagData.size() < qsizetype(12 + 2 * curv.valueCount))
+ return 0;
+ const auto valueOffset = sizeof(CurvTagData);
if (curv.valueCount == 0) {
gamma.m_type = QColorTrc::Type::Function;
gamma.m_fun = QColorTransferFunction(); // Linear
} else if (curv.valueCount == 1) {
- const quint16 v = qFromBigEndian<quint16>(data.constData() + valueOffset);
+ const quint16 v = qFromBigEndian<quint16>(tagData.constData() + valueOffset);
gamma.m_type = QColorTrc::Type::Function;
gamma.m_fun = QColorTransferFunction::fromGamma(v * (1.0f / 256.0f));
} else {
@@ -489,12 +580,12 @@ bool parseTRC(const QByteArray &data, const TagEntry &tagEntry, QColorTrc &gamma
tabl.resize(curv.valueCount);
static_assert(sizeof(GenericTagData) == 2 * sizeof(quint32_be),
"GenericTagData has padding. The following code is a subject to UB.");
- qFromBigEndian<quint16>(data.constData() + valueOffset, curv.valueCount, tabl.data());
- QColorTransferTable table = QColorTransferTable(curv.valueCount, std::move(tabl));
+ qFromBigEndian<quint16>(tagData.constData() + valueOffset, curv.valueCount, tabl.data());
+ QColorTransferTable table(curv.valueCount, tabl, type);
QColorTransferFunction curve;
if (!table.checkValidity()) {
qCWarning(lcIcc) << "Invalid curv table";
- return false;
+ return 0;
} else if (!table.asColorTransferFunction(&curve)) {
gamma.m_type = QColorTrc::Type::Table;
gamma.m_table = table;
@@ -504,43 +595,43 @@ bool parseTRC(const QByteArray &data, const TagEntry &tagEntry, QColorTrc &gamma
gamma.m_fun = curve;
}
}
- return true;
+ return 12 + 2 * curv.valueCount;
}
if (trcData.type == quint32(Tag::para)) {
Q_STATIC_ASSERT(sizeof(ParaTagData) == 12);
- const ParaTagData para = qFromUnaligned<ParaTagData>(data.constData() + tagEntry.offset);
- const auto parametersOffset = tagEntry.offset + sizeof(ParaTagData);
+ const ParaTagData para = qFromUnaligned<ParaTagData>(tagData.constData());
+ const auto parametersOffset = sizeof(ParaTagData);
quint32 parameters[7];
switch (para.curveType) {
case 0: {
- if (tagEntry.size < sizeof(ParaTagData) + 1 * 4)
- return false;
- qFromBigEndian<quint32>(data.constData() + parametersOffset, 1, parameters);
+ if (tagData.size() < 12 + 1 * 4)
+ return 0;
+ qFromBigEndian<quint32>(tagData.constData() + parametersOffset, 1, parameters);
float g = fromFixedS1516(parameters[0]);
gamma.m_type = QColorTrc::Type::Function;
gamma.m_fun = QColorTransferFunction::fromGamma(g);
- break;
+ return 12 + 1 * 4;
}
case 1: {
- if (tagEntry.size < sizeof(ParaTagData) + 3 * 4)
- return false;
- qFromBigEndian<quint32>(data.constData() + parametersOffset, 3, parameters);
+ if (tagData.size() < 12 + 3 * 4)
+ return 0;
+ qFromBigEndian<quint32>(tagData.constData() + parametersOffset, 3, parameters);
if (parameters[1] == 0)
- return false;
+ return 0;
float g = fromFixedS1516(parameters[0]);
float a = fromFixedS1516(parameters[1]);
float b = fromFixedS1516(parameters[2]);
float d = -b / a;
gamma.m_type = QColorTrc::Type::Function;
gamma.m_fun = QColorTransferFunction(a, b, 0.0f, d, 0.0f, 0.0f, g);
- break;
+ return 12 + 3 * 4;
}
case 2: {
- if (tagEntry.size < sizeof(ParaTagData) + 4 * 4)
- return false;
- qFromBigEndian<quint32>(data.constData() + parametersOffset, 4, parameters);
+ if (tagData.size() < 12 + 4 * 4)
+ return 0;
+ qFromBigEndian<quint32>(tagData.constData() + parametersOffset, 4, parameters);
if (parameters[1] == 0)
- return false;
+ return 0;
float g = fromFixedS1516(parameters[0]);
float a = fromFixedS1516(parameters[1]);
float b = fromFixedS1516(parameters[2]);
@@ -548,12 +639,12 @@ bool parseTRC(const QByteArray &data, const TagEntry &tagEntry, QColorTrc &gamma
float d = -b / a;
gamma.m_type = QColorTrc::Type::Function;
gamma.m_fun = QColorTransferFunction(a, b, 0.0f, d, c, c, g);
- break;
+ return 12 + 4 * 4;
}
case 3: {
- if (tagEntry.size < sizeof(ParaTagData) + 5 * 4)
- return false;
- qFromBigEndian<quint32>(data.constData() + parametersOffset, 5, parameters);
+ if (tagData.size() < 12 + 5 * 4)
+ return 0;
+ qFromBigEndian<quint32>(tagData.constData() + parametersOffset, 5, parameters);
float g = fromFixedS1516(parameters[0]);
float a = fromFixedS1516(parameters[1]);
float b = fromFixedS1516(parameters[2]);
@@ -561,12 +652,12 @@ bool parseTRC(const QByteArray &data, const TagEntry &tagEntry, QColorTrc &gamma
float d = fromFixedS1516(parameters[4]);
gamma.m_type = QColorTrc::Type::Function;
gamma.m_fun = QColorTransferFunction(a, b, c, d, 0.0f, 0.0f, g);
- break;
+ return 12 + 5 * 4;
}
case 4: {
- if (tagEntry.size < sizeof(ParaTagData) + 7 * 4)
- return false;
- qFromBigEndian<quint32>(data.constData() + parametersOffset, 7, parameters);
+ if (tagData.size() < 12 + 7 * 4)
+ return 0;
+ qFromBigEndian<quint32>(tagData.constData() + parametersOffset, 7, parameters);
float g = fromFixedS1516(parameters[0]);
float a = fromFixedS1516(parameters[1]);
float b = fromFixedS1516(parameters[2]);
@@ -576,19 +667,401 @@ bool parseTRC(const QByteArray &data, const TagEntry &tagEntry, QColorTrc &gamma
float f = fromFixedS1516(parameters[6]);
gamma.m_type = QColorTrc::Type::Function;
gamma.m_fun = QColorTransferFunction(a, b, c, d, e, f, g);
- break;
+ return 12 + 7 * 4;
}
default:
qCWarning(lcIcc) << "Unknown para type" << uint(para.curveType);
+ return 0;
+ }
+ return true;
+ }
+ qCWarning(lcIcc) << "Invalid TRC data type" << Qt::hex << trcData.type;
+ return 0;
+}
+
+template<typename T>
+static void parseCLUT(const T *tableData, const float f, QColorCLUT *clut, uchar outputChannels)
+{
+ if (outputChannels == 4) {
+ for (qsizetype index = 0; index < clut->table.size(); ++index) {
+ QColorVector v(tableData[index * 4 + 0] * f,
+ tableData[index * 4 + 1] * f,
+ tableData[index * 4 + 2] * f,
+ tableData[index * 4 + 3] * f);
+ clut->table[index] = v;
+ };
+ } else {
+ for (qsizetype index = 0; index < clut->table.size(); ++index) {
+ QColorVector v(tableData[index * 3 + 0] * f,
+ tableData[index * 3 + 1] * f,
+ tableData[index * 3 + 2] * f);
+ clut->table[index] = v;
+ };
+ }
+}
+
+// very simple version for small values (<=4) of exp.
+static constexpr qsizetype intPow(qsizetype x, qsizetype exp)
+{
+ return (exp <= 1) ? x : x * intPow(x, exp - 1);
+}
+
+// Parses lut8 and lut16 type elements
+template<typename T>
+static bool parseLutData(const QByteArray &data, const TagEntry &tagEntry, QColorSpacePrivate *colorSpacePrivate, bool isAb)
+{
+ if (tagEntry.size < sizeof(T)) {
+ qCWarning(lcIcc) << "Undersized lut8/lut16 tag";
+ return false;
+ }
+ if (qsizetype(tagEntry.size) > data.size()) {
+ qCWarning(lcIcc) << "Truncated lut8/lut16 tag";
+ return false;
+ }
+ using S = std::conditional_t<std::is_same_v<T, Lut8TagData>, uint8_t, uint16_t>;
+ const T lut = qFromUnaligned<T>(data.constData() + tagEntry.offset);
+ int inputTableEntries, outputTableEntries, precision;
+ if constexpr (std::is_same_v<T, Lut8TagData>) {
+ Q_ASSERT(lut.type == quint32(Tag::mft1));
+ if (!colorSpacePrivate->isPcsLab && isAb) {
+ qCWarning(lcIcc) << "Lut8 can not output XYZ values";
+ return false;
+ }
+ inputTableEntries = 256;
+ outputTableEntries = 256;
+ precision = 1;
+ } else {
+ Q_ASSERT(lut.type == quint32(Tag::mft2));
+ inputTableEntries = lut.inputTableEntries;
+ outputTableEntries = lut.outputTableEntries;
+ if (inputTableEntries < 2 || inputTableEntries > 4096)
+ return false;
+ if (outputTableEntries < 2 || outputTableEntries > 4096)
+ return false;
+ precision = 2;
+ }
+
+ bool inTableIsLinear = true, outTableIsLinear = true;
+ QColorSpacePrivate::TransferElement inTableElement;
+ QColorSpacePrivate::TransferElement outTableElement;
+ QColorCLUT clutElement;
+ QColorMatrix matrixElement;
+
+ matrixElement.r.x = fromFixedS1516(lut.e1);
+ matrixElement.g.x = fromFixedS1516(lut.e2);
+ matrixElement.b.x = fromFixedS1516(lut.e3);
+ matrixElement.r.y = fromFixedS1516(lut.e4);
+ matrixElement.g.y = fromFixedS1516(lut.e5);
+ matrixElement.b.y = fromFixedS1516(lut.e6);
+ matrixElement.r.z = fromFixedS1516(lut.e7);
+ matrixElement.g.z = fromFixedS1516(lut.e8);
+ matrixElement.b.z = fromFixedS1516(lut.e9);
+ if (!colorSpacePrivate->isPcsLab && !isAb && !matrixElement.isValid()) {
+ qCWarning(lcIcc) << "Invalid matrix values in lut8/lut16";
+ return false;
+ }
+
+ if (lut.inputChannels != 3 && !(isAb && colorSpacePrivate->colorModel == QColorSpace::ColorModel::Cmyk && lut.inputChannels == 4)) {
+ qCWarning(lcIcc) << "Unsupported lut8/lut16 input channel count" << lut.inputChannels;
+ return false;
+ }
+
+ if (lut.outputChannels != 3 && !(!isAb && colorSpacePrivate->colorModel == QColorSpace::ColorModel::Cmyk && lut.outputChannels == 4)) {
+ qCWarning(lcIcc) << "Unsupported lut8/lut16 output channel count" << lut.outputChannels;
+ return false;
+ }
+
+ const qsizetype clutTableSize = intPow(lut.clutGridPoints, lut.inputChannels);
+ if (tagEntry.size < (sizeof(T) + precision * lut.inputChannels * inputTableEntries
+ + precision * lut.outputChannels * outputTableEntries
+ + precision * lut.outputChannels * clutTableSize)) {
+ qCWarning(lcIcc) << "Undersized lut8/lut16 tag, no room for tables";
+ return false;
+ }
+ if (colorSpacePrivate->colorModel == QColorSpace::ColorModel::Cmyk && clutTableSize == 0) {
+ qCWarning(lcIcc) << "Cmyk conversion must have a CLUT";
+ return false;
+ }
+
+ const uint8_t *tableData = reinterpret_cast<const uint8_t *>(data.constData() + tagEntry.offset + sizeof(T));
+
+ for (int j = 0; j < lut.inputChannels; ++j) {
+ QList<S> input(inputTableEntries);
+ qFromBigEndian<S>(tableData, inputTableEntries, input.data());
+ QColorTransferTable table(inputTableEntries, input, QColorTransferTable::OneWay);
+ if (!table.checkValidity()) {
+ qCWarning(lcIcc) << "Bad input table in lut8/lut16";
+ return false;
+ }
+ if (!table.isIdentity())
+ inTableIsLinear = false;
+ inTableElement.trc[j] = std::move(table);
+ tableData += inputTableEntries * precision;
+ }
+
+ clutElement.table.resize(clutTableSize);
+ clutElement.gridPointsX = clutElement.gridPointsY = clutElement.gridPointsZ = lut.clutGridPoints;
+ if (lut.inputChannels == 4)
+ clutElement.gridPointsW = lut.clutGridPoints;
+
+ if constexpr (std::is_same_v<T, Lut8TagData>) {
+ parseCLUT(tableData, 1.f / 255.f, &clutElement, lut.outputChannels);
+ } else {
+ float f = 1.0f / 65535.f;
+ if (colorSpacePrivate->isPcsLab && isAb) // Legacy lut16 conversion to Lab
+ f = 1.0f / 65280.f;
+ QList<S> clutTable(clutTableSize * lut.outputChannels);
+ qFromBigEndian<S>(tableData, clutTable.size(), clutTable.data());
+ parseCLUT(clutTable.constData(), f, &clutElement, lut.outputChannels);
+ }
+ tableData += clutTableSize * lut.outputChannels * precision;
+
+ for (int j = 0; j < lut.outputChannels; ++j) {
+ QList<S> output(outputTableEntries);
+ qFromBigEndian<S>(tableData, outputTableEntries, output.data());
+ QColorTransferTable table(outputTableEntries, output, QColorTransferTable::OneWay);
+ if (!table.checkValidity()) {
+ qCWarning(lcIcc) << "Bad output table in lut8/lut16";
return false;
}
+ if (!table.isIdentity())
+ outTableIsLinear = false;
+ outTableElement.trc[j] = std::move(table);
+ tableData += outputTableEntries * precision;
+ }
+
+ if (isAb) {
+ if (!inTableIsLinear)
+ colorSpacePrivate->mAB.append(inTableElement);
+ if (!clutElement.isEmpty())
+ colorSpacePrivate->mAB.append(clutElement);
+ if (!outTableIsLinear || colorSpacePrivate->mAB.isEmpty())
+ colorSpacePrivate->mAB.append(outTableElement);
+ } else {
+ // The matrix is only to be applied if the input color-space is XYZ
+ if (!colorSpacePrivate->isPcsLab && !matrixElement.isIdentity())
+ colorSpacePrivate->mBA.append(matrixElement);
+ if (!inTableIsLinear)
+ colorSpacePrivate->mBA.append(inTableElement);
+ if (!clutElement.isEmpty())
+ colorSpacePrivate->mBA.append(clutElement);
+ if (!outTableIsLinear || colorSpacePrivate->mBA.isEmpty())
+ colorSpacePrivate->mBA.append(outTableElement);
+ }
+ return true;
+}
+
+// Parses mAB and mBA type elements
+static bool parseMabData(const QByteArray &data, const TagEntry &tagEntry, QColorSpacePrivate *colorSpacePrivate, bool isAb)
+{
+ if (tagEntry.size < sizeof(mABTagData)) {
+ qCWarning(lcIcc) << "Undersized mAB/mBA tag";
+ return false;
+ }
+ if (qsizetype(tagEntry.size) > data.size()) {
+ qCWarning(lcIcc) << "Truncated mAB/mBA tag";
+ return false;
+ }
+ const mABTagData mab = qFromUnaligned<mABTagData>(data.constData() + tagEntry.offset);
+ if ((mab.type != quint32(Tag::mAB_) && isAb) || (mab.type != quint32(Tag::mBA_) && !isAb)){
+ qCWarning(lcIcc) << "Bad mAB/mBA content type";
+ return false;
+ }
+
+ if (mab.inputChannels != 3 && !(isAb && colorSpacePrivate->colorModel == QColorSpace::ColorModel::Cmyk && mab.inputChannels == 4)) {
+ qCWarning(lcIcc) << "Unsupported mAB/mBA input channel count" << mab.inputChannels;
+ return false;
+ }
+
+ if (mab.outputChannels != 3 && !(!isAb && colorSpacePrivate->colorModel == QColorSpace::ColorModel::Cmyk && mab.outputChannels == 4)) {
+ qCWarning(lcIcc) << "Unsupported mAB/mBA output channel count" << mab.outputChannels;
+ return false;
+ }
+
+ // These combinations are legal: B, M + Matrix + B, A + Clut + B, A + Clut + M + Matrix + B
+ if (!mab.bCurvesOffset) {
+ qCWarning(lcIcc) << "Illegal mAB/mBA without B table";
+ return false;
+ }
+ if (((bool)mab.matrixOffset != (bool)mab.mCurvesOffset) ||
+ ((bool)mab.aCurvesOffset != (bool)mab.clutOffset)) {
+ qCWarning(lcIcc) << "Illegal mAB/mBA element combination";
+ return false;
+ }
+
+ if (mab.aCurvesOffset > (tagEntry.size - 3 * sizeof(GenericTagData)) ||
+ mab.bCurvesOffset > (tagEntry.size - 3 * sizeof(GenericTagData)) ||
+ mab.mCurvesOffset > (tagEntry.size - 3 * sizeof(GenericTagData)) ||
+ mab.matrixOffset > (tagEntry.size - 4 * 12) ||
+ mab.clutOffset > (tagEntry.size - 20)) {
+ qCWarning(lcIcc) << "Illegal mAB/mBA element offset";
+ return false;
+ }
+
+ QColorSpacePrivate::TransferElement bTableElement;
+ QColorSpacePrivate::TransferElement aTableElement;
+ QColorCLUT clutElement;
+ QColorSpacePrivate::TransferElement mTableElement;
+ QColorMatrix matrixElement;
+ QColorVector offsetElement;
+
+ auto parseCurves = [&data, &tagEntry] (uint curvesOffset, QColorTrc *table, int channels) {
+ for (int i = 0; i < channels; ++i) {
+ if (qsizetype(tagEntry.offset + curvesOffset + 12) > data.size() || curvesOffset + 12 > tagEntry.size) {
+ qCWarning(lcIcc) << "Space missing for channel curves in mAB/mBA";
+ return false;
+ }
+ auto size = parseTRC(QByteArrayView(data).sliced(tagEntry.offset + curvesOffset, tagEntry.size - curvesOffset), table[i], QColorTransferTable::OneWay);
+ if (!size)
+ return false;
+ if (size & 2) size += 2; // possible padding
+ curvesOffset += size;
+ }
return true;
+ };
+
+ bool bCurvesAreLinear = true, aCurvesAreLinear = true, mCurvesAreLinear = true;
+
+ // B Curves
+ if (!parseCurves(mab.bCurvesOffset, bTableElement.trc, isAb ? mab.outputChannels : mab.inputChannels)) {
+ qCWarning(lcIcc) << "Invalid B curves";
+ return false;
+ } else {
+ bCurvesAreLinear = bTableElement.trc[0].isIdentity() && bTableElement.trc[1].isIdentity() && bTableElement.trc[2].isIdentity();
}
- qCWarning(lcIcc) << "Invalid TRC data type";
+
+ // A Curves
+ if (mab.aCurvesOffset) {
+ if (!parseCurves(mab.aCurvesOffset, aTableElement.trc, isAb ? mab.inputChannels : mab.outputChannels)) {
+ qCWarning(lcIcc) << "Invalid A curves";
+ return false;
+ } else {
+ aCurvesAreLinear = aTableElement.trc[0].isIdentity() && aTableElement.trc[1].isIdentity() && aTableElement.trc[2].isIdentity();
+ }
+ }
+
+ // M Curves
+ if (mab.mCurvesOffset) {
+ if (!parseCurves(mab.mCurvesOffset, mTableElement.trc, 3)) {
+ qCWarning(lcIcc) << "Invalid M curves";
+ return false;
+ } else {
+ mCurvesAreLinear = mTableElement.trc[0].isIdentity() && mTableElement.trc[1].isIdentity() && mTableElement.trc[2].isIdentity();
+ }
+ }
+
+ // Matrix
+ if (mab.matrixOffset) {
+ const MatrixElement matrix = qFromUnaligned<MatrixElement>(data.constData() + tagEntry.offset + mab.matrixOffset);
+ matrixElement.r.x = fromFixedS1516(matrix.e0);
+ matrixElement.g.x = fromFixedS1516(matrix.e1);
+ matrixElement.b.x = fromFixedS1516(matrix.e2);
+ matrixElement.r.y = fromFixedS1516(matrix.e3);
+ matrixElement.g.y = fromFixedS1516(matrix.e4);
+ matrixElement.b.y = fromFixedS1516(matrix.e5);
+ matrixElement.r.z = fromFixedS1516(matrix.e6);
+ matrixElement.g.z = fromFixedS1516(matrix.e7);
+ matrixElement.b.z = fromFixedS1516(matrix.e8);
+ offsetElement.x = fromFixedS1516(matrix.e9);
+ offsetElement.y = fromFixedS1516(matrix.e10);
+ offsetElement.z = fromFixedS1516(matrix.e11);
+ if (!matrixElement.isValid() || !offsetElement.isValid()) {
+ qCWarning(lcIcc) << "Invalid matrix values in mAB/mBA element";
+ return false;
+ }
+ }
+
+ // CLUT
+ if (mab.clutOffset) {
+ clutElement.gridPointsX = uint8_t(data[tagEntry.offset + mab.clutOffset]);
+ clutElement.gridPointsY = uint8_t(data[tagEntry.offset + mab.clutOffset + 1]);
+ clutElement.gridPointsZ = uint8_t(data[tagEntry.offset + mab.clutOffset + 2]);
+ clutElement.gridPointsW = std::max(uint8_t(data[tagEntry.offset + mab.clutOffset + 3]), uint8_t(1));
+ const uchar precision = data[tagEntry.offset + mab.clutOffset + 16];
+ if (precision > 2 || precision < 1) {
+ qCWarning(lcIcc) << "Invalid mAB/mBA element CLUT precision";
+ return false;
+ }
+ if (clutElement.gridPointsX < 2 || clutElement.gridPointsY < 2 || clutElement.gridPointsZ < 2) {
+ qCWarning(lcIcc) << "Empty CLUT";
+ return false;
+ }
+ const qsizetype clutTableSize = clutElement.gridPointsX * clutElement.gridPointsY * clutElement.gridPointsZ * clutElement.gridPointsW;
+ if ((mab.clutOffset + 20 + clutTableSize * mab.outputChannels * precision) > tagEntry.size) {
+ qCWarning(lcIcc) << "CLUT oversized for tag";
+ return false;
+ }
+
+ clutElement.table.resize(clutTableSize);
+ if (precision == 2) {
+ QList<uint16_t> clutTable(clutTableSize * mab.outputChannels);
+ qFromBigEndian<uint16_t>(data.constData() + tagEntry.offset + mab.clutOffset + 20, clutTable.size(), clutTable.data());
+ parseCLUT(clutTable.constData(), (1.f/65535.f), &clutElement, mab.outputChannels);
+ } else {
+ const uint8_t *clutTable = reinterpret_cast<const uint8_t *>(data.constData() + tagEntry.offset + mab.clutOffset + 20);
+ parseCLUT(clutTable, (1.f/255.f), &clutElement, mab.outputChannels);
+ }
+ } else if (colorSpacePrivate->colorModel == QColorSpace::ColorModel::Cmyk) {
+ qCWarning(lcIcc) << "Cmyk conversion must have a CLUT";
+ return false;
+ }
+
+ if (isAb) {
+ if (mab.aCurvesOffset) {
+ if (!aCurvesAreLinear)
+ colorSpacePrivate->mAB.append(std::move(aTableElement));
+ if (!clutElement.isEmpty())
+ colorSpacePrivate->mAB.append(std::move(clutElement));
+ }
+ if (mab.mCurvesOffset && mab.outputChannels == 3) {
+ if (!mCurvesAreLinear)
+ colorSpacePrivate->mAB.append(std::move(mTableElement));
+ if (!matrixElement.isIdentity())
+ colorSpacePrivate->mAB.append(std::move(matrixElement));
+ if (!offsetElement.isNull())
+ colorSpacePrivate->mAB.append(std::move(offsetElement));
+ }
+ if (!bCurvesAreLinear|| colorSpacePrivate->mAB.isEmpty())
+ colorSpacePrivate->mAB.append(std::move(bTableElement));
+ } else {
+ if (!bCurvesAreLinear)
+ colorSpacePrivate->mBA.append(std::move(bTableElement));
+ if (mab.mCurvesOffset && mab.inputChannels == 3) {
+ if (!matrixElement.isIdentity())
+ colorSpacePrivate->mBA.append(std::move(matrixElement));
+ if (!offsetElement.isNull())
+ colorSpacePrivate->mBA.append(std::move(offsetElement));
+ if (!mCurvesAreLinear)
+ colorSpacePrivate->mBA.append(std::move(mTableElement));
+ }
+ if (mab.aCurvesOffset) {
+ if (!clutElement.isEmpty())
+ colorSpacePrivate->mBA.append(std::move(clutElement));
+ if (!aCurvesAreLinear)
+ colorSpacePrivate->mBA.append(std::move(aTableElement));
+ }
+ if (colorSpacePrivate->mBA.isEmpty()) // Ensure non-empty to indicate valid empty transform
+ colorSpacePrivate->mBA.append(std::move(bTableElement));
+ }
+
+ return true;
+}
+
+static bool parseA2B(const QByteArray &data, const TagEntry &tagEntry, QColorSpacePrivate *privat, bool isAb)
+{
+ const GenericTagData a2bData = qFromUnaligned<GenericTagData>(data.constData() + tagEntry.offset);
+ if (a2bData.type == quint32(Tag::mft1))
+ return parseLutData<Lut8TagData>(data, tagEntry, privat, isAb);
+ else if (a2bData.type == quint32(Tag::mft2))
+ return parseLutData<Lut16TagData>(data, tagEntry, privat, isAb);
+ else if (a2bData.type == quint32(Tag::mAB_) || a2bData.type == quint32(Tag::mBA_))
+ return parseMabData(data, tagEntry, privat, isAb);
+
+ qCWarning(lcIcc) << "fromIccProfile: Unknown A2B/B2A data type";
return false;
}
-bool parseDesc(const QByteArray &data, const TagEntry &tagEntry, QString &descName)
+static bool parseDesc(const QByteArray &data, const TagEntry &tagEntry, QString &descName)
{
const GenericTagData tag = qFromUnaligned<GenericTagData>(data.constData() + tagEntry.offset);
@@ -615,7 +1088,7 @@ bool parseDesc(const QByteArray &data, const TagEntry &tagEntry, QString &descNa
const MlucTagData mluc = qFromUnaligned<MlucTagData>(data.constData() + tagEntry.offset);
if (mluc.recordCount < 1)
return false;
- if (mluc.recordSize < 12)
+ if (mluc.recordSize != 12)
return false;
// We just use the primary record regardless of language or country.
const quint32 stringOffset = mluc.records[0].offset;
@@ -635,6 +1108,147 @@ bool parseDesc(const QByteArray &data, const TagEntry &tagEntry, QString &descNa
return true;
}
+static bool parseRgbMatrix(const QByteArray &data, const QHash<Tag, TagEntry> &tagIndex, QColorSpacePrivate *colorspaceDPtr)
+{
+ // Parse XYZ tags
+ if (!parseXyzData(data, tagIndex[Tag::rXYZ], colorspaceDPtr->toXyz.r))
+ return false;
+ if (!parseXyzData(data, tagIndex[Tag::gXYZ], colorspaceDPtr->toXyz.g))
+ return false;
+ if (!parseXyzData(data, tagIndex[Tag::bXYZ], colorspaceDPtr->toXyz.b))
+ return false;
+ if (!parseXyzData(data, tagIndex[Tag::wtpt], colorspaceDPtr->whitePoint))
+ return false;
+ if (!colorspaceDPtr->toXyz.isValid() || !colorspaceDPtr->whitePoint.isValid() || colorspaceDPtr->whitePoint.isNull()) {
+ qCWarning(lcIcc) << "Invalid XYZ values in RGB matrix";
+ return false;
+ }
+
+ colorspaceDPtr->primaries = QColorSpace::Primaries::Custom;
+ if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromSRgb()) {
+ qCDebug(lcIcc) << "fromIccProfile: sRGB primaries detected";
+ colorspaceDPtr->primaries = QColorSpace::Primaries::SRgb;
+ } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromAdobeRgb()) {
+ qCDebug(lcIcc) << "fromIccProfile: Adobe RGB primaries detected";
+ colorspaceDPtr->primaries = QColorSpace::Primaries::AdobeRgb;
+ } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromDciP3D65()) {
+ qCDebug(lcIcc) << "fromIccProfile: DCI-P3 D65 primaries detected";
+ colorspaceDPtr->primaries = QColorSpace::Primaries::DciP3D65;
+ }
+ if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromProPhotoRgb()) {
+ qCDebug(lcIcc) << "fromIccProfile: ProPhoto RGB primaries detected";
+ colorspaceDPtr->primaries = QColorSpace::Primaries::ProPhotoRgb;
+ }
+ return true;
+}
+
+static bool parseGrayMatrix(const QByteArray &data, const QHash<Tag, TagEntry> &tagIndex, QColorSpacePrivate *colorspaceDPtr)
+{
+ QColorVector whitePoint;
+ if (!parseXyzData(data, tagIndex[Tag::wtpt], whitePoint))
+ return false;
+ if (!whitePoint.isValid() || !qFuzzyCompare(whitePoint.y, 1.0f) || (1.0f + whitePoint.z + whitePoint.x) == 0.0f) {
+ qCWarning(lcIcc) << "fromIccProfile: Invalid ICC profile - gray white-point not normalized";
+ return false;
+ }
+ colorspaceDPtr->primaries = QColorSpace::Primaries::Custom;
+ colorspaceDPtr->whitePoint = whitePoint;
+ return true;
+}
+
+static bool parseChad(const QByteArray &data, const TagEntry &tagEntry, QColorSpacePrivate *colorspaceDPtr)
+{
+ if (tagEntry.size < sizeof(Sf32TagData) || qsizetype(tagEntry.size) > data.size())
+ return false;
+ const Sf32TagData chadtag = qFromUnaligned<Sf32TagData>(data.constData() + tagEntry.offset);
+ if (chadtag.type != uint32_t(Tag::sf32)) {
+ qCWarning(lcIcc, "fromIccProfile: bad chad data type");
+ return false;
+ }
+ QColorMatrix chad;
+ chad.r.x = fromFixedS1516(chadtag.value[0]);
+ chad.g.x = fromFixedS1516(chadtag.value[1]);
+ chad.b.x = fromFixedS1516(chadtag.value[2]);
+ chad.r.y = fromFixedS1516(chadtag.value[3]);
+ chad.g.y = fromFixedS1516(chadtag.value[4]);
+ chad.b.y = fromFixedS1516(chadtag.value[5]);
+ chad.r.z = fromFixedS1516(chadtag.value[6]);
+ chad.g.z = fromFixedS1516(chadtag.value[7]);
+ chad.b.z = fromFixedS1516(chadtag.value[8]);
+
+ if (!chad.isValid()) {
+ qCWarning(lcIcc, "fromIccProfile: invalid chad matrix");
+ return false;
+ }
+ colorspaceDPtr->chad = chad;
+ return true;
+}
+
+static bool parseTRCs(const QByteArray &data, const QHash<Tag, TagEntry> &tagIndex, QColorSpacePrivate *colorspaceDPtr, bool isColorSpaceTypeGray)
+{
+ TagEntry rTrc;
+ TagEntry gTrc;
+ TagEntry bTrc;
+ if (isColorSpaceTypeGray) {
+ rTrc = tagIndex[Tag::kTRC];
+ gTrc = tagIndex[Tag::kTRC];
+ bTrc = tagIndex[Tag::kTRC];
+ } else if (tagIndex.contains(Tag::aarg) && tagIndex.contains(Tag::aagg) && tagIndex.contains(Tag::aabg)) {
+ // Apple extension for parametric version of TRCs in ICCv2:
+ rTrc = tagIndex[Tag::aarg];
+ gTrc = tagIndex[Tag::aagg];
+ bTrc = tagIndex[Tag::aabg];
+ } else {
+ rTrc = tagIndex[Tag::rTRC];
+ gTrc = tagIndex[Tag::gTRC];
+ bTrc = tagIndex[Tag::bTRC];
+ }
+
+ QColorTrc rCurve;
+ QColorTrc gCurve;
+ QColorTrc bCurve;
+ if (!parseTRC(QByteArrayView(data).sliced(rTrc.offset, rTrc.size), rCurve, QColorTransferTable::TwoWay)) {
+ qCWarning(lcIcc) << "fromIccProfile: Invalid rTRC";
+ return false;
+ }
+ if (!parseTRC(QByteArrayView(data).sliced(gTrc.offset, gTrc.size), gCurve, QColorTransferTable::TwoWay)) {
+ qCWarning(lcIcc) << "fromIccProfile: Invalid gTRC";
+ return false;
+ }
+ if (!parseTRC(QByteArrayView(data).sliced(bTrc.offset, bTrc.size), bCurve, QColorTransferTable::TwoWay)) {
+ qCWarning(lcIcc) << "fromIccProfile: Invalid bTRC";
+ return false;
+ }
+ if (rCurve == gCurve && gCurve == bCurve) {
+ if (rCurve.isIdentity()) {
+ qCDebug(lcIcc) << "fromIccProfile: Linear gamma detected";
+ colorspaceDPtr->trc[0] = QColorTransferFunction();
+ colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Linear;
+ colorspaceDPtr->gamma = 1.0f;
+ } else if (rCurve.m_type == QColorTrc::Type::Function && rCurve.m_fun.isGamma()) {
+ qCDebug(lcIcc) << "fromIccProfile: Simple gamma detected";
+ colorspaceDPtr->trc[0] = QColorTransferFunction::fromGamma(rCurve.m_fun.m_g);
+ colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Gamma;
+ colorspaceDPtr->gamma = rCurve.m_fun.m_g;
+ } else if (rCurve.m_type == QColorTrc::Type::Function && rCurve.m_fun.isSRgb()) {
+ qCDebug(lcIcc) << "fromIccProfile: sRGB gamma detected";
+ colorspaceDPtr->trc[0] = QColorTransferFunction::fromSRgb();
+ colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::SRgb;
+ } else {
+ colorspaceDPtr->trc[0] = rCurve;
+ colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Custom;
+ }
+ colorspaceDPtr->trc[1] = colorspaceDPtr->trc[0];
+ colorspaceDPtr->trc[2] = colorspaceDPtr->trc[0];
+ } else {
+ colorspaceDPtr->trc[0] = rCurve;
+ colorspaceDPtr->trc[1] = gCurve;
+ colorspaceDPtr->trc[2] = bCurve;
+ colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Custom;
+ }
+ return true;
+}
+
bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace)
{
if (data.size() < qsizetype(sizeof(ICCProfileHeader))) {
@@ -691,146 +1305,92 @@ bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace)
tagIndex.insert(Tag(quint32(tagTable.signature)), { tagTable.offset, tagTable.size });
}
- // Check the profile is three-component matrix based (what we currently support):
+ bool threeComponentMatrix = true;
+
if (header.inputColorSpace == uint(ColorSpaceType::Rgb)) {
+ // Check the profile is three-component matrix based:
if (!tagIndex.contains(Tag::rXYZ) || !tagIndex.contains(Tag::gXYZ) || !tagIndex.contains(Tag::bXYZ) ||
!tagIndex.contains(Tag::rTRC) || !tagIndex.contains(Tag::gTRC) || !tagIndex.contains(Tag::bTRC) ||
- !tagIndex.contains(Tag::wtpt)) {
- qCInfo(lcIcc) << "fromIccProfile: Unsupported ICC profile - not three component matrix based";
- return false;
+ !tagIndex.contains(Tag::wtpt) || header.pcs == uint(Tag::Lab_)) {
+ threeComponentMatrix = false;
+ // Check if the profile is valid n-LUT based:
+ if (!tagIndex.contains(Tag::A2B0)) {
+ qCWarning(lcIcc) << "fromIccProfile: Invalid ICC profile - neither valid three component nor n-LUT";
+ return false;
+ }
}
- } else {
- Q_ASSERT(header.inputColorSpace == uint(ColorSpaceType::Gray));
+ } else if (header.inputColorSpace == uint(ColorSpaceType::Gray)) {
if (!tagIndex.contains(Tag::kTRC) || !tagIndex.contains(Tag::wtpt)) {
qCWarning(lcIcc) << "fromIccProfile: Invalid ICC profile - not valid gray scale based";
return false;
}
+ } else if (header.inputColorSpace == uint(ColorSpaceType::Cmyk)) {
+ threeComponentMatrix = false;
+ if (!tagIndex.contains(Tag::A2B0)) {
+ qCWarning(lcIcc) << "fromIccProfile: Invalid ICC profile - CMYK, not n-LUT";
+ return false;
+ }
+ } else {
+ Q_UNREACHABLE();
}
colorSpace->detach();
QColorSpacePrivate *colorspaceDPtr = QColorSpacePrivate::get(*colorSpace);
- if (header.inputColorSpace == uint(ColorSpaceType::Rgb)) {
- // Parse XYZ tags
- if (!parseXyzData(data, tagIndex[Tag::rXYZ], colorspaceDPtr->toXyz.r))
- return false;
- if (!parseXyzData(data, tagIndex[Tag::gXYZ], colorspaceDPtr->toXyz.g))
- return false;
- if (!parseXyzData(data, tagIndex[Tag::bXYZ], colorspaceDPtr->toXyz.b))
- return false;
- if (!parseXyzData(data, tagIndex[Tag::wtpt], colorspaceDPtr->whitePoint))
- return false;
+ if (threeComponentMatrix) {
+ colorspaceDPtr->isPcsLab = false;
+ colorspaceDPtr->transformModel = QColorSpace::TransformModel::ThreeComponentMatrix;
- colorspaceDPtr->primaries = QColorSpace::Primaries::Custom;
- if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromSRgb()) {
- qCDebug(lcIcc) << "fromIccProfile: sRGB primaries detected";
- colorspaceDPtr->primaries = QColorSpace::Primaries::SRgb;
- } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromAdobeRgb()) {
- qCDebug(lcIcc) << "fromIccProfile: Adobe RGB primaries detected";
- colorspaceDPtr->primaries = QColorSpace::Primaries::AdobeRgb;
- } else if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromDciP3D65()) {
- qCDebug(lcIcc) << "fromIccProfile: DCI-P3 D65 primaries detected";
- colorspaceDPtr->primaries = QColorSpace::Primaries::DciP3D65;
- }
- if (colorspaceDPtr->toXyz == QColorMatrix::toXyzFromProPhotoRgb()) {
- qCDebug(lcIcc) << "fromIccProfile: ProPhoto RGB primaries detected";
- colorspaceDPtr->primaries = QColorSpace::Primaries::ProPhotoRgb;
- }
- } else {
- // We will use sRGB primaries and fit to match the given white-point if
- // it doesn't match sRGB's.
- QColorVector whitePoint;
- if (!parseXyzData(data, tagIndex[Tag::wtpt], whitePoint))
- return false;
- if (!qFuzzyCompare(whitePoint.y, 1.0f) || (1.0f + whitePoint.z + whitePoint.x) == 0.0f) {
- qCWarning(lcIcc) << "fromIccProfile: Invalid ICC profile - gray white-point not normalized";
- return false;
- }
- if (whitePoint == QColorVector::D65()) {
- colorspaceDPtr->primaries = QColorSpace::Primaries::SRgb;
+ if (header.inputColorSpace == uint(ColorSpaceType::Rgb)) {
+ if (!parseRgbMatrix(data, tagIndex, colorspaceDPtr))
+ return false;
+ colorspaceDPtr->colorModel = QColorSpace::ColorModel::Rgb;
+ } else if (header.inputColorSpace == uint(ColorSpaceType::Gray)) {
+ if (!parseGrayMatrix(data, tagIndex, colorspaceDPtr))
+ return false;
+ colorspaceDPtr->colorModel = QColorSpace::ColorModel::Gray;
} else {
- colorspaceDPtr->primaries = QColorSpace::Primaries::Custom;
- // Calculate chromaticity from xyz (assuming y == 1.0f).
- float y = 1.0f / (1.0f + whitePoint.z + whitePoint.x);
- float x = whitePoint.x * y;
- QColorSpacePrimaries primaries(QColorSpace::Primaries::SRgb);
- primaries.whitePoint = QPointF(x,y);
- if (!primaries.areValid()) {
- qCWarning(lcIcc, "fromIccProfile: Invalid ICC profile - invalid white-point(%f, %f)", x, y);
+ Q_UNREACHABLE();
+ }
+ if (auto it = tagIndex.constFind(Tag::chad); it != tagIndex.constEnd()) {
+ if (!parseChad(data, it.value(), colorspaceDPtr))
return false;
- }
- colorspaceDPtr->toXyz = primaries.toXyzMatrix();
+ } else {
+ colorspaceDPtr->chad = QColorMatrix::chromaticAdaptation(colorspaceDPtr->whitePoint);
}
- }
- // Reset the matrix to our canonical values:
- if (colorspaceDPtr->primaries != QColorSpace::Primaries::Custom)
- colorspaceDPtr->setToXyzMatrix();
+ if (colorspaceDPtr->colorModel == QColorSpace::ColorModel::Gray)
+ colorspaceDPtr->toXyz = colorspaceDPtr->chad;
- // Parse TRC tags
- TagEntry rTrc;
- TagEntry gTrc;
- TagEntry bTrc;
- if (header.inputColorSpace == uint(ColorSpaceType::Gray)) {
- rTrc = tagIndex[Tag::kTRC];
- gTrc = tagIndex[Tag::kTRC];
- bTrc = tagIndex[Tag::kTRC];
- } else if (tagIndex.contains(Tag::aarg) && tagIndex.contains(Tag::aagg) && tagIndex.contains(Tag::aabg)) {
- // Apple extension for parametric version of TRCs in ICCv2:
- rTrc = tagIndex[Tag::aarg];
- gTrc = tagIndex[Tag::aagg];
- bTrc = tagIndex[Tag::aabg];
+ // Reset the matrix to our canonical values:
+ if (colorspaceDPtr->primaries != QColorSpace::Primaries::Custom)
+ colorspaceDPtr->setToXyzMatrix();
+
+ if (!parseTRCs(data, tagIndex, colorspaceDPtr, header.inputColorSpace == uint(ColorSpaceType::Gray)))
+ return false;
} else {
- rTrc = tagIndex[Tag::rTRC];
- gTrc = tagIndex[Tag::gTRC];
- bTrc = tagIndex[Tag::bTRC];
- }
+ colorspaceDPtr->isPcsLab = (header.pcs == uint(Tag::Lab_));
+ colorspaceDPtr->transformModel = QColorSpace::TransformModel::ElementListProcessing;
+ if (header.inputColorSpace == uint(ColorSpaceType::Cmyk))
+ colorspaceDPtr->colorModel = QColorSpace::ColorModel::Cmyk;
+ else
+ colorspaceDPtr->colorModel = QColorSpace::ColorModel::Rgb;
- QColorTrc rCurve;
- QColorTrc gCurve;
- QColorTrc bCurve;
- if (!parseTRC(data, rTrc, rCurve)) {
- qCWarning(lcIcc) << "fromIccProfile: Invalid rTRC";
- return false;
- }
- if (!parseTRC(data, gTrc, gCurve)) {
- qCWarning(lcIcc) << "fromIccProfile: Invalid gTRC";
- return false;
- }
- if (!parseTRC(data, bTrc, bCurve)) {
- qCWarning(lcIcc) << "fromIccProfile: Invalid bTRC";
- return false;
- }
- if (rCurve == gCurve && gCurve == bCurve && rCurve.m_type == QColorTrc::Type::Function) {
- if (rCurve.m_fun.isLinear()) {
- qCDebug(lcIcc) << "fromIccProfile: Linear gamma detected";
- colorspaceDPtr->trc[0] = QColorTransferFunction();
- colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Linear;
- colorspaceDPtr->gamma = 1.0f;
- } else if (rCurve.m_fun.isGamma()) {
- qCDebug(lcIcc) << "fromIccProfile: Simple gamma detected";
- colorspaceDPtr->trc[0] = QColorTransferFunction::fromGamma(rCurve.m_fun.m_g);
- colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Gamma;
- colorspaceDPtr->gamma = rCurve.m_fun.m_g;
- } else if (rCurve.m_fun.isSRgb()) {
- qCDebug(lcIcc) << "fromIccProfile: sRGB gamma detected";
- colorspaceDPtr->trc[0] = QColorTransferFunction::fromSRgb();
- colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::SRgb;
- } else {
- colorspaceDPtr->trc[0] = rCurve;
- colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Custom;
+ // Only parse the default perceptual transform for now
+ if (!parseA2B(data, tagIndex[Tag::A2B0], colorspaceDPtr, true))
+ return false;
+ if (auto it = tagIndex.constFind(Tag::B2A0); it != tagIndex.constEnd()) {
+ if (!parseA2B(data, it.value(), colorspaceDPtr, false))
+ return false;
}
- colorspaceDPtr->trc[1] = colorspaceDPtr->trc[0];
- colorspaceDPtr->trc[2] = colorspaceDPtr->trc[0];
- } else {
- colorspaceDPtr->trc[0] = rCurve;
- colorspaceDPtr->trc[1] = gCurve;
- colorspaceDPtr->trc[2] = bCurve;
- colorspaceDPtr->transferFunction = QColorSpace::TransferFunction::Custom;
+ if (auto it = tagIndex.constFind(Tag::wtpt); it != tagIndex.constEnd()) {
+ if (!parseXyzData(data, it.value(), colorspaceDPtr->whitePoint))
+ return false;
+ }
}
- if (tagIndex.contains(Tag::desc)) {
- if (!parseDesc(data, tagIndex[Tag::desc], colorspaceDPtr->description))
+ if (auto it = tagIndex.constFind(Tag::desc); it != tagIndex.constEnd()) {
+ if (!parseDesc(data, it.value(), colorspaceDPtr->description))
qCWarning(lcIcc) << "fromIccProfile: Failed to parse description";
else
qCDebug(lcIcc) << "fromIccProfile: Description" << colorspaceDPtr->description;
@@ -842,6 +1402,7 @@ bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace)
colorspaceDPtr->iccProfile = data;
+ Q_ASSERT(colorspaceDPtr->isValid());
return true;
}
diff --git a/src/gui/painting/qicc_p.h b/src/gui/painting/qicc_p.h
index 2a4658b84b..fd9b53b045 100644
--- a/src/gui/painting/qicc_p.h
+++ b/src/gui/painting/qicc_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICC_P_H
#define QICC_P_H
@@ -53,6 +17,7 @@
#include <QtCore/qbytearray.h>
#include <QtGui/qtguiglobal.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/painting/qimageeffects.cpp b/src/gui/painting/qimageeffects.cpp
new file mode 100644
index 0000000000..7c2b947e08
--- /dev/null
+++ b/src/gui/painting/qimageeffects.cpp
@@ -0,0 +1,327 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qmath.h"
+#include "qdrawhelper_p.h"
+#include "qmemrotate_p.h"
+#include "qpainter.h"
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+
+template <int shift>
+inline int qt_static_shift(int value)
+{
+ if (shift == 0)
+ return value;
+ else if (shift > 0)
+ return value << (uint(shift) & 0x1f);
+ else
+ return value >> (uint(-shift) & 0x1f);
+}
+
+template<int aprec, int zprec>
+inline void qt_blurinner(uchar *bptr, int &zR, int &zG, int &zB, int &zA, int alpha)
+{
+ QRgb *pixel = (QRgb *)bptr;
+
+#define Z_MASK (0xff << zprec)
+ const int A_zprec = qt_static_shift<zprec - 24>(*pixel) & Z_MASK;
+ const int R_zprec = qt_static_shift<zprec - 16>(*pixel) & Z_MASK;
+ const int G_zprec = qt_static_shift<zprec - 8>(*pixel) & Z_MASK;
+ const int B_zprec = qt_static_shift<zprec>(*pixel) & Z_MASK;
+#undef Z_MASK
+
+ const int zR_zprec = zR >> aprec;
+ const int zG_zprec = zG >> aprec;
+ const int zB_zprec = zB >> aprec;
+ const int zA_zprec = zA >> aprec;
+
+ zR += alpha * (R_zprec - zR_zprec);
+ zG += alpha * (G_zprec - zG_zprec);
+ zB += alpha * (B_zprec - zB_zprec);
+ zA += alpha * (A_zprec - zA_zprec);
+
+#define ZA_MASK (0xff << (zprec + aprec))
+ *pixel =
+ qt_static_shift<24 - zprec - aprec>(zA & ZA_MASK)
+ | qt_static_shift<16 - zprec - aprec>(zR & ZA_MASK)
+ | qt_static_shift<8 - zprec - aprec>(zG & ZA_MASK)
+ | qt_static_shift<-zprec - aprec>(zB & ZA_MASK);
+#undef ZA_MASK
+}
+
+const int alphaIndex = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3);
+
+template<int aprec, int zprec>
+inline void qt_blurinner_alphaOnly(uchar *bptr, int &z, int alpha)
+{
+ const int A_zprec = int(*(bptr)) << zprec;
+ const int z_zprec = z >> aprec;
+ z += alpha * (A_zprec - z_zprec);
+ *(bptr) = z >> (zprec + aprec);
+}
+
+template<int aprec, int zprec, bool alphaOnly>
+inline void qt_blurrow(QImage & im, int line, int alpha)
+{
+ uchar *bptr = im.scanLine(line);
+
+ int zR = 0, zG = 0, zB = 0, zA = 0;
+
+ if (alphaOnly && im.format() != QImage::Format_Indexed8)
+ bptr += alphaIndex;
+
+ const int stride = im.depth() >> 3;
+ const int im_width = im.width();
+ for (int index = 0; index < im_width; ++index) {
+ if (alphaOnly)
+ qt_blurinner_alphaOnly<aprec, zprec>(bptr, zA, alpha);
+ else
+ qt_blurinner<aprec, zprec>(bptr, zR, zG, zB, zA, alpha);
+ bptr += stride;
+ }
+
+ bptr -= stride;
+
+ for (int index = im_width - 2; index >= 0; --index) {
+ bptr -= stride;
+ if (alphaOnly)
+ qt_blurinner_alphaOnly<aprec, zprec>(bptr, zA, alpha);
+ else
+ qt_blurinner<aprec, zprec>(bptr, zR, zG, zB, zA, alpha);
+ }
+}
+
+/*
+* expblur(QImage &img, int radius)
+*
+* Based on exponential blur algorithm by Jani Huhtanen
+*
+* In-place blur of image 'img' with kernel
+* of approximate radius 'radius'.
+*
+* Blurs with two sided exponential impulse
+* response.
+*
+* aprec = precision of alpha parameter
+* in fixed-point format 0.aprec
+*
+* zprec = precision of state parameters
+* zR,zG,zB and zA in fp format 8.zprec
+*/
+template <int aprec, int zprec, bool alphaOnly>
+void expblur(QImage &img, qreal radius, bool improvedQuality = false, int transposed = 0)
+{
+ // halve the radius if we're using two passes
+ if (improvedQuality)
+ radius *= qreal(0.5);
+
+ Q_ASSERT(img.format() == QImage::Format_ARGB32_Premultiplied
+ || img.format() == QImage::Format_RGB32
+ || img.format() == QImage::Format_Indexed8
+ || img.format() == QImage::Format_Grayscale8);
+
+ // choose the alpha such that pixels at radius distance from a fully
+ // saturated pixel will have an alpha component of no greater than
+ // the cutOffIntensity
+ const qreal cutOffIntensity = 2;
+ int alpha = radius <= qreal(1e-5)
+ ? ((1 << aprec)-1)
+ : qRound((1<<aprec)*(1 - qPow(cutOffIntensity * (1 / qreal(255)), 1 / radius)));
+
+ int img_height = img.height();
+ for (int row = 0; row < img_height; ++row) {
+ for (int i = 0; i <= int(improvedQuality); ++i)
+ qt_blurrow<aprec, zprec, alphaOnly>(img, row, alpha);
+ }
+
+ QImage temp(img.height(), img.width(), img.format());
+ temp.setDevicePixelRatio(img.devicePixelRatio());
+ if (transposed >= 0) {
+ if (img.depth() == 8) {
+ qt_memrotate270(reinterpret_cast<const quint8*>(img.bits()),
+ img.width(), img.height(), img.bytesPerLine(),
+ reinterpret_cast<quint8*>(temp.bits()),
+ temp.bytesPerLine());
+ } else {
+ qt_memrotate270(reinterpret_cast<const quint32*>(img.bits()),
+ img.width(), img.height(), img.bytesPerLine(),
+ reinterpret_cast<quint32*>(temp.bits()),
+ temp.bytesPerLine());
+ }
+ } else {
+ if (img.depth() == 8) {
+ qt_memrotate90(reinterpret_cast<const quint8*>(img.bits()),
+ img.width(), img.height(), img.bytesPerLine(),
+ reinterpret_cast<quint8*>(temp.bits()),
+ temp.bytesPerLine());
+ } else {
+ qt_memrotate90(reinterpret_cast<const quint32*>(img.bits()),
+ img.width(), img.height(), img.bytesPerLine(),
+ reinterpret_cast<quint32*>(temp.bits()),
+ temp.bytesPerLine());
+ }
+ }
+
+ img_height = temp.height();
+ for (int row = 0; row < img_height; ++row) {
+ for (int i = 0; i <= int(improvedQuality); ++i)
+ qt_blurrow<aprec, zprec, alphaOnly>(temp, row, alpha);
+ }
+
+ if (transposed == 0) {
+ if (img.depth() == 8) {
+ qt_memrotate90(reinterpret_cast<const quint8*>(temp.bits()),
+ temp.width(), temp.height(), temp.bytesPerLine(),
+ reinterpret_cast<quint8*>(img.bits()),
+ img.bytesPerLine());
+ } else {
+ qt_memrotate90(reinterpret_cast<const quint32*>(temp.bits()),
+ temp.width(), temp.height(), temp.bytesPerLine(),
+ reinterpret_cast<quint32*>(img.bits()),
+ img.bytesPerLine());
+ }
+ } else {
+ img = temp;
+ }
+}
+
+} // namespace
+
+#define AVG(a,b) ( ((((a)^(b)) & 0xfefefefeUL) >> 1) + ((a)&(b)) )
+#define AVG16(a,b) ( ((((a)^(b)) & 0xf7deUL) >> 1) + ((a)&(b)) )
+
+QImage qt_halfScaled(const QImage &source)
+{
+ if (source.width() < 2 || source.height() < 2)
+ return QImage();
+
+ QImage srcImage = source;
+
+ if (source.format() == QImage::Format_Indexed8 || source.format() == QImage::Format_Grayscale8) {
+ // assumes grayscale
+ QImage dest(source.width() / 2, source.height() / 2, srcImage.format());
+ dest.setDevicePixelRatio(source.devicePixelRatio());
+
+ const uchar *src = reinterpret_cast<const uchar*>(const_cast<const QImage &>(srcImage).bits());
+ qsizetype sx = srcImage.bytesPerLine();
+ qsizetype sx2 = sx << 1;
+
+ uchar *dst = reinterpret_cast<uchar*>(dest.bits());
+ qsizetype dx = dest.bytesPerLine();
+ int ww = dest.width();
+ int hh = dest.height();
+
+ for (int y = hh; y; --y, dst += dx, src += sx2) {
+ const uchar *p1 = src;
+ const uchar *p2 = src + sx;
+ uchar *q = dst;
+ for (int x = ww; x; --x, ++q, p1 += 2, p2 += 2)
+ *q = ((int(p1[0]) + int(p1[1]) + int(p2[0]) + int(p2[1])) + 2) >> 2;
+ }
+
+ return dest;
+ } else if (source.format() == QImage::Format_ARGB8565_Premultiplied) {
+ QImage dest(source.width() / 2, source.height() / 2, srcImage.format());
+ dest.setDevicePixelRatio(source.devicePixelRatio());
+
+ const uchar *src = reinterpret_cast<const uchar*>(const_cast<const QImage &>(srcImage).bits());
+ qsizetype sx = srcImage.bytesPerLine();
+ qsizetype sx2 = sx << 1;
+
+ uchar *dst = reinterpret_cast<uchar*>(dest.bits());
+ qsizetype dx = dest.bytesPerLine();
+ int ww = dest.width();
+ int hh = dest.height();
+
+ for (int y = hh; y; --y, dst += dx, src += sx2) {
+ const uchar *p1 = src;
+ const uchar *p2 = src + sx;
+ uchar *q = dst;
+ for (int x = ww; x; --x, q += 3, p1 += 6, p2 += 6) {
+ // alpha
+ q[0] = AVG(AVG(p1[0], p1[3]), AVG(p2[0], p2[3]));
+ // rgb
+ const quint16 p16_1 = (p1[2] << 8) | p1[1];
+ const quint16 p16_2 = (p1[5] << 8) | p1[4];
+ const quint16 p16_3 = (p2[2] << 8) | p2[1];
+ const quint16 p16_4 = (p2[5] << 8) | p2[4];
+ const quint16 result = AVG16(AVG16(p16_1, p16_2), AVG16(p16_3, p16_4));
+ q[1] = result & 0xff;
+ q[2] = result >> 8;
+ }
+ }
+
+ return dest;
+ } else if (source.format() != QImage::Format_ARGB32_Premultiplied
+ && source.format() != QImage::Format_RGB32)
+ {
+ srcImage = source.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ }
+
+ QImage dest(source.width() / 2, source.height() / 2, srcImage.format());
+ dest.setDevicePixelRatio(source.devicePixelRatio());
+
+ const quint32 *src = reinterpret_cast<const quint32*>(const_cast<const QImage &>(srcImage).bits());
+ qsizetype sx = srcImage.bytesPerLine() >> 2;
+ qsizetype sx2 = sx << 1;
+
+ quint32 *dst = reinterpret_cast<quint32*>(dest.bits());
+ qsizetype dx = dest.bytesPerLine() >> 2;
+ int ww = dest.width();
+ int hh = dest.height();
+
+ for (int y = hh; y; --y, dst += dx, src += sx2) {
+ const quint32 *p1 = src;
+ const quint32 *p2 = src + sx;
+ quint32 *q = dst;
+ for (int x = ww; x; --x, q++, p1 += 2, p2 += 2)
+ *q = AVG(AVG(p1[0], p1[1]), AVG(p2[0], p2[1]));
+ }
+
+ return dest;
+}
+
+#undef AVG
+#undef AVG16
+
+Q_GUI_EXPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0)
+{
+ if (blurImage.format() != QImage::Format_ARGB32_Premultiplied
+ && blurImage.format() != QImage::Format_RGB32)
+ {
+ blurImage = std::move(blurImage).convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ }
+
+ qreal scale = 1;
+ if (radius >= 4 && blurImage.width() >= 2 && blurImage.height() >= 2) {
+ blurImage = qt_halfScaled(blurImage);
+ scale = 2;
+ radius *= qreal(0.5);
+ }
+
+ if (alphaOnly)
+ expblur<12, 10, true>(blurImage, radius, quality, transposed);
+ else
+ expblur<12, 10, false>(blurImage, radius, quality, transposed);
+
+ if (p) {
+ p->scale(scale, scale);
+ p->setRenderHint(QPainter::SmoothPixmapTransform);
+ p->drawImage(QRect(QPoint(0, 0), blurImage.deviceIndependentSize().toSize()), blurImage);
+ }
+}
+
+Q_GUI_EXPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0)
+{
+ if (blurImage.format() == QImage::Format_Indexed8 || blurImage.format() == QImage::Format_Grayscale8)
+ expblur<12, 10, true>(blurImage, radius, quality, transposed);
+ else
+ expblur<12, 10, false>(blurImage, radius, quality, transposed);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 8e6abf8f0d..a636635fd5 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qimagescale_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qimage_p.h>
@@ -46,8 +10,9 @@
#include "qrgbafloat.h"
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
-#include "qsemaphore.h"
-#include "qthreadpool.h"
+#include <qsemaphore.h>
+#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
QT_BEGIN_NAMESPACE
@@ -309,7 +274,7 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/painting/qimagescale_neon.cpp b/src/gui/painting/qimagescale_neon.cpp
index 3c87ac8773..074b819862 100644
--- a/src/gui/painting/qimagescale_neon.cpp
+++ b/src/gui/painting/qimagescale_neon.cpp
@@ -1,49 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qimagescale_p.h"
#include "qimage.h"
#include <private/qsimd_p.h>
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
-#include "qsemaphore.h"
-#include "qthreadpool.h"
+#include <qsemaphore.h>
+#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
#if defined(__ARM_NEON__)
@@ -58,7 +23,7 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/painting/qimagescale_p.h b/src/gui/painting/qimagescale_p.h
index a9a4c0f858..d297443091 100644
--- a/src/gui/painting/qimagescale_p.h
+++ b/src/gui/painting/qimagescale_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGESCALE_P_H
#define QIMAGESCALE_P_H
@@ -51,6 +15,7 @@
//
#include <qimage.h>
+#include <private/qglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp
index a5c9e68fad..982e533a32 100644
--- a/src/gui/painting/qimagescale_sse4.cpp
+++ b/src/gui/painting/qimagescale_sse4.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qimagescale_p.h"
#include "qimage.h"
@@ -43,8 +7,9 @@
#include <private/qsimd_p.h>
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
-#include "qsemaphore.h"
-#include "qthreadpool.h"
+#include <qsemaphore.h>
+#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
@@ -59,7 +24,7 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
diff --git a/src/gui/painting/qmath_p.h b/src/gui/painting/qmath_p.h
index 7cc3612113..d4e5be8339 100644
--- a/src/gui/painting/qmath_p.h
+++ b/src/gui/painting/qmath_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMATH_P_H
#define QMATH_P_H
@@ -52,12 +16,28 @@
//
#include <qmath.h>
+#include <private/qglobal_p.h>
+#include <qtransform.h>
QT_BEGIN_NAMESPACE
static const qreal Q_PI = qreal(M_PI); // pi
static const qreal Q_MM_PER_INCH = 25.4;
+inline QRect qt_mapFillRect(const QRectF &rect, const QTransform &xf)
+{
+ // Only for xf <= scaling or 90 degree rotations
+ Q_ASSERT(xf.type() <= QTransform::TxScale
+ || (xf.type() == QTransform::TxRotate && qFuzzyIsNull(xf.m11()) && qFuzzyIsNull(xf.m22())));
+ // Transform the corners instead of the rect to avoid hitting numerical accuracy limit
+ // when transforming topleft and size separately and adding afterwards,
+ // as that can sometimes be slightly off around the .5 point, leading to wrong rounding
+ QPoint pt1 = xf.map(rect.topLeft()).toPoint();
+ QPoint pt2 = xf.map(rect.bottomRight()).toPoint();
+ // Normalize and adjust for the QRect vs. QRectF bottomright
+ return QRect::span(pt1, pt2).adjusted(0, 0, -1, -1);
+}
+
QT_END_NAMESPACE
#endif // QMATH_P_H
diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp
index 67c570fa71..9752069931 100644
--- a/src/gui/painting/qmemrotate.cpp
+++ b/src/gui/painting/qmemrotate.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qmemrotate_p.h"
#include "qpixellayout_p.h"
diff --git a/src/gui/painting/qmemrotate_p.h b/src/gui/painting/qmemrotate_p.h
index 1b25655b68..70711223d1 100644
--- a/src/gui/painting/qmemrotate_p.h
+++ b/src/gui/painting/qmemrotate_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMEMROTATE_P_H
#define QMEMROTATE_P_H
diff --git a/src/gui/painting/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp
index f7bc2d743f..2f87ff43b7 100644
--- a/src/gui/painting/qoutlinemapper.cpp
+++ b/src/gui/painting/qoutlinemapper.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qoutlinemapper_p.h"
@@ -73,6 +37,24 @@ static const QRectF boundingRect(const QPointF *points, int pointCount)
return QRectF(QPointF(minx, miny), QPointF(maxx, maxy));
}
+void QOutlineMapper::setClipRect(QRect clipRect)
+{
+ auto limitCoords = [](QRect r) {
+ const QRect limitRect(QPoint(-QT_RASTER_COORD_LIMIT, -QT_RASTER_COORD_LIMIT),
+ QPoint(QT_RASTER_COORD_LIMIT, QT_RASTER_COORD_LIMIT));
+ r &= limitRect;
+ r.setWidth(qMin(r.width(), QT_RASTER_COORD_LIMIT));
+ r.setHeight(qMin(r.height(), QT_RASTER_COORD_LIMIT));
+ return r;
+ };
+
+ if (clipRect != m_clip_rect) {
+ m_clip_rect = limitCoords(clipRect);
+ const int mw = 1 << 10; // margin width. No need to trigger clipping for slight overshooting
+ m_clip_trigger_rect = QRectF(limitCoords(m_clip_rect.adjusted(-mw, -mw, mw, mw)));
+ }
+}
+
void QOutlineMapper::curveTo(const QPointF &cp1, const QPointF &cp2, const QPointF &ep) {
#ifdef QT_DEBUG_CONVERT
printf("QOutlineMapper::curveTo() (%f, %f)\n", ep.x(), ep.y());
@@ -236,16 +218,8 @@ void QOutlineMapper::endOutline()
m_clip_rect.x(), m_clip_rect.y(), m_clip_rect.width(), m_clip_rect.height());
#endif
-
- // Check for out of dev bounds...
- const bool do_clip = !m_in_clip_elements && ((controlPointRect.left() < -QT_RASTER_COORD_LIMIT
- || controlPointRect.right() > QT_RASTER_COORD_LIMIT
- || controlPointRect.top() < -QT_RASTER_COORD_LIMIT
- || controlPointRect.bottom() > QT_RASTER_COORD_LIMIT
- || controlPointRect.width() > QT_RASTER_COORD_LIMIT
- || controlPointRect.height() > QT_RASTER_COORD_LIMIT));
-
- if (do_clip) {
+ // Avoid rasterizing outside cliprect: faster, and ensures coords < QT_RASTER_COORD_LIMIT
+ if (!m_in_clip_elements && !m_clip_trigger_rect.contains(controlPointRect)) {
clipElements(elements, elementTypes(), m_elements.size());
} else {
convertElements(elements, elementTypes(), m_elements.size());
@@ -354,7 +328,7 @@ void QOutlineMapper::clipElements(const QPointF *elements,
int element_count)
{
// We could save a bit of time by actually implementing them fully
- // instead of going through convenience functionallity, but since
+ // instead of going through convenience functionality, but since
// this part of code hardly every used, it shouldn't matter.
QScopedValueRollback<bool> in_clip_elements(m_in_clip_elements, true);
diff --git a/src/gui/painting/qoutlinemapper_p.h b/src/gui/painting/qoutlinemapper_p.h
index b796fcca4b..ff2fff6bac 100644
--- a/src/gui/painting/qoutlinemapper_p.h
+++ b/src/gui/painting/qoutlinemapper_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QOUTLINEMAPPER_P_H
#define QOUTLINEMAPPER_P_H
@@ -81,7 +45,7 @@ Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale
* class QOutlineMapper
*
* Used to map between QPainterPath and the QT_FT_Outline structure used by the
- * freetype scanconvertor.
+ * freetype scanconverter.
*
* The outline mapper uses a path iterator to get points from the path,
* so that it is possible to transform the points as they are converted. The
@@ -115,6 +79,8 @@ public:
m_curve_threshold = scale == 0 ? qreal(0.25) : (qreal(0.25) / scale);
}
+ void setClipRect(QRect clipRect);
+
void beginOutline(Qt::FillRule fillRule)
{
#ifdef QT_DEBUG_CONVERT
@@ -199,6 +165,7 @@ public:
QDataBuffer<int> m_contours;
QRect m_clip_rect;
+ QRectF m_clip_trigger_rect;
QRectF controlPointRect; // only valid after endOutline()
QT_FT_Outline m_outline;
diff --git a/src/gui/painting/qpagedpaintdevice.cpp b/src/gui/painting/qpagedpaintdevice.cpp
index 1e32f2c2bc..4dc5f035e6 100644
--- a/src/gui/painting/qpagedpaintdevice.cpp
+++ b/src/gui/painting/qpagedpaintdevice.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpagedpaintdevice_p.h"
#include <qpagedpaintdevice.h>
diff --git a/src/gui/painting/qpagedpaintdevice.h b/src/gui/painting/qpagedpaintdevice.h
index dedff446b8..ffe82f6555 100644
--- a/src/gui/painting/qpagedpaintdevice.h
+++ b/src/gui/painting/qpagedpaintdevice.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAGEDPAINTDEVICE_H
#define QPAGEDPAINTDEVICE_H
diff --git a/src/gui/painting/qpagedpaintdevice_p.h b/src/gui/painting/qpagedpaintdevice_p.h
index 4099846de5..8e2205344e 100644
--- a/src/gui/painting/qpagedpaintdevice_p.h
+++ b/src/gui/painting/qpagedpaintdevice_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAGEDPAINTDEVICE_P_H
#define QPAGEDPAINTDEVICE_P_H
diff --git a/src/gui/painting/qpagelayout.cpp b/src/gui/painting/qpagelayout.cpp
index def9751aa6..ec505f2cce 100644
--- a/src/gui/painting/qpagelayout.cpp
+++ b/src/gui/painting/qpagelayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpagelayout.h"
@@ -48,6 +12,10 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QPageLayout)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QPageLayout::Unit, QPageLayout__Unit)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QPageLayout::Orientation, QPageLayout__Orientation)
+
// Multiplier for converting units to points.
Q_GUI_EXPORT qreal qt_pointMultiplier(QPageLayout::Unit unit)
{
@@ -71,41 +39,19 @@ Q_GUI_EXPORT qreal qt_pointMultiplier(QPageLayout::Unit unit)
// Multiplier for converting pixels to points.
extern qreal qt_pixelMultiplier(int resolution);
-QPointF qt_convertPoint(const QPointF &xy, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits)
-{
- // If the size have the same units, or are all 0, then don't need to convert
- if (fromUnits == toUnits || xy.isNull())
- return xy;
-
- // If converting to points then convert and round to 0 decimal places
- if (toUnits == QPageLayout::Point) {
- const qreal multiplier = qt_pointMultiplier(fromUnits);
- return QPointF(qRound(xy.x() * multiplier),
- qRound(xy.y() * multiplier));
- }
-
- // If converting to other units, need to convert to unrounded points first
- QPointF pointXy = (fromUnits == QPageLayout::Point) ? xy : xy * qt_pointMultiplier(fromUnits);
-
- // Then convert from points to required units rounded to 2 decimal places
- const qreal multiplier = qt_pointMultiplier(toUnits);
- return QPointF(qRound(pointXy.x() * 100 / multiplier) / 100.0,
- qRound(pointXy.y() * 100 / multiplier) / 100.0);
-}
-
Q_GUI_EXPORT QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits)
{
// If the margins have the same units, or are all 0, then don't need to convert
if (fromUnits == toUnits || margins.isNull())
return margins;
- // If converting to points then convert and round to 0 decimal places
+ // If converting to points then convert and round up to 2 decimal places
if (toUnits == QPageLayout::Point) {
- const qreal multiplier = qt_pointMultiplier(fromUnits);
- return QMarginsF(qRound(margins.left() * multiplier),
- qRound(margins.top() * multiplier),
- qRound(margins.right() * multiplier),
- qRound(margins.bottom() * multiplier));
+ const qreal multiplierX100 = qt_pointMultiplier(fromUnits) * 100;
+ return QMarginsF(qCeil(margins.left() * multiplierX100) / 100.0,
+ qCeil(margins.top() * multiplierX100) / 100.0,
+ qCeil(margins.right() * multiplierX100) / 100.0,
+ qCeil(margins.bottom() * multiplierX100) / 100.0);
}
// If converting to other units, need to convert to unrounded points first
@@ -136,7 +82,7 @@ public:
void clampMargins(const QMarginsF &margins);
QMarginsF margins(QPageLayout::Unit units) const;
- QMargins marginsPoints() const;
+ QMarginsF marginsPoints() const;
QMargins marginsPixels(int resolution) const;
void setDefaultMargins(const QMarginsF &minMargins);
@@ -218,23 +164,23 @@ QMarginsF QPageLayoutPrivate::margins(QPageLayout::Unit units) const
return qt_convertMargins(m_margins, m_units, units);
}
-QMargins QPageLayoutPrivate::marginsPoints() const
+QMarginsF QPageLayoutPrivate::marginsPoints() const
{
- return qt_convertMargins(m_margins, m_units, QPageLayout::Point).toMargins();
+ return qt_convertMargins(m_margins, m_units, QPageLayout::Point);
}
QMargins QPageLayoutPrivate::marginsPixels(int resolution) const
{
- return marginsPoints() / qt_pixelMultiplier(resolution);
+ return QMarginsF(marginsPoints() / qt_pixelMultiplier(resolution)).toMargins();
}
void QPageLayoutPrivate::setDefaultMargins(const QMarginsF &minMargins)
{
m_minMargins = minMargins;
- m_maxMargins = QMarginsF(m_fullSize.width() - m_minMargins.right(),
- m_fullSize.height() - m_minMargins.bottom(),
- m_fullSize.width() - m_minMargins.left(),
- m_fullSize.height() - m_minMargins.top());
+ m_maxMargins = QMarginsF(qMax(m_fullSize.width() - m_minMargins.right(), qreal(0)),
+ qMax(m_fullSize.height() - m_minMargins.bottom(), qreal(0)),
+ qMax(m_fullSize.width() - m_minMargins.left(), qreal(0)),
+ qMax(m_fullSize.height() - m_minMargins.top(), qreal(0)));
if (m_mode == QPageLayout::StandardMode)
clampMargins(m_margins);
}
@@ -753,7 +699,7 @@ QMarginsF QPageLayout::margins(Unit units) const
QMargins QPageLayout::marginsPoints() const
{
- return d->marginsPoints();
+ return d->marginsPoints().toMargins();
}
/*!
@@ -920,7 +866,7 @@ QRect QPageLayout::paintRectPoints() const
if (!isValid())
return QRect();
return d->m_mode == FullPageMode ? d->fullRectPoints()
- : d->fullRectPoints() - d->marginsPoints();
+ : d->fullRectPoints() - d->marginsPoints().toMargins();
}
/*!
diff --git a/src/gui/painting/qpagelayout.h b/src/gui/painting/qpagelayout.h
index 469436ce59..29be2f9725 100644
--- a/src/gui/painting/qpagelayout.h
+++ b/src/gui/painting/qpagelayout.h
@@ -1,47 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAGELAYOUT_H
#define QPAGELAYOUT_H
#include <QtGui/qtguiglobal.h>
-#include <QtCore/qsharedpointer.h>
+#include <QtCore/qshareddata.h>
#include <QtCore/qstring.h>
#include <QtCore/qmargins.h>
@@ -85,7 +49,7 @@ public:
QPageLayout &operator=(const QPageLayout &other);
~QPageLayout();
- void swap(QPageLayout &other) noexcept { qSwap(d, other.d); }
+ void swap(QPageLayout &other) noexcept { d.swap(other.d); }
bool isEquivalentTo(const QPageLayout &other) const;
@@ -149,8 +113,8 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QPageLayout &pageLayout);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QPageLayout)
-Q_DECLARE_METATYPE(QPageLayout::Unit)
-Q_DECLARE_METATYPE(QPageLayout::Orientation)
+QT_DECL_METATYPE_EXTERN(QPageLayout, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN_TAGGED(QPageLayout::Unit, QPageLayout__Unit, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN_TAGGED(QPageLayout::Orientation, QPageLayout__Orientation, Q_GUI_EXPORT)
#endif // QPAGELAYOUT_H
diff --git a/src/gui/painting/qpageranges.cpp b/src/gui/painting/qpageranges.cpp
index dc43143d9c..99a0009883 100644
--- a/src/gui/painting/qpageranges.cpp
+++ b/src/gui/painting/qpageranges.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpageranges.h"
#include "qpageranges_p.h"
@@ -46,9 +10,11 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QPageRanges)
+
void QPageRangesPrivate::mergeIntervals()
{
- const int count = intervals.count();
+ const int count = intervals.size();
if (count <= 1)
return;
@@ -194,9 +160,9 @@ QPageRanges QPageRanges::fromString(const QString &ranges)
if (item.isEmpty())
return QPageRanges();
- if (item.contains(QLatin1Char('-'))) {
+ if (item.contains(u'-')) {
const QStringList rangeItems = item.split(u'-');
- if (rangeItems.count() != 2)
+ if (rangeItems.size() != 2)
return QPageRanges();
bool ok;
@@ -244,7 +210,7 @@ QString QPageRanges::toString() const
QString result;
for (const Range &range : d->intervals) {
if (!result.isEmpty())
- result += QLatin1Char(',');
+ result += u',';
if (range.from == range.to)
result += QString::number(range.from);
@@ -289,7 +255,7 @@ int QPageRanges::firstPage() const
{
if (isEmpty())
return 0;
- return d->intervals.first().from;
+ return d->intervals.constFirst().from;
}
/*!
@@ -300,7 +266,7 @@ int QPageRanges::lastPage() const
{
if (isEmpty())
return 0;
- return d->intervals.last().to;
+ return d->intervals.constLast().to;
}
/*!
@@ -374,6 +340,7 @@ QDebug operator<<(QDebug dbg, const QPageRanges &pageRanges)
/*!
\struct QPageRanges::Range
+ \inmodule QtGui
\brief The QPageRanges::Range struct holds the \c from and \c to endpoints of a range.
\sa QPageRanges::toRangeList()
diff --git a/src/gui/painting/qpageranges.h b/src/gui/painting/qpageranges.h
index d525124a62..d0e282fbf2 100644
--- a/src/gui/painting/qpageranges.h
+++ b/src/gui/painting/qpageranges.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAGERANGES_H
#define QPAGERANGES_H
@@ -65,7 +29,7 @@ public:
QPageRanges(QPageRanges &&other) noexcept = default;
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPageRanges)
void swap(QPageRanges &other) noexcept
- { qSwap(d, other.d); }
+ { d.swap(other.d); }
friend bool operator==(const QPageRanges &lhs, const QPageRanges &rhs) noexcept
{ return lhs.isEqual(rhs); }
@@ -120,6 +84,6 @@ Q_DECLARE_TYPEINFO(QPageRanges::Range, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QPageRanges)
+QT_DECL_METATYPE_EXTERN(QPageRanges, Q_GUI_EXPORT)
#endif // QPAGERANGES_H
diff --git a/src/gui/painting/qpageranges_p.h b/src/gui/painting/qpageranges_p.h
index 82b03224f3..37f41a1e11 100644
--- a/src/gui/painting/qpageranges_p.h
+++ b/src/gui/painting/qpageranges_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAGERANGES_P_H
#define QPAGERANGES_P_H
diff --git a/src/gui/painting/qpagesize.cpp b/src/gui/painting/qpagesize.cpp
index fb7eb45b93..37f66fe63d 100644
--- a/src/gui/painting/qpagesize.cpp
+++ b/src/gui/painting/qpagesize.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpagesize.h"
@@ -48,6 +12,12 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+QT_IMPL_METATYPE_EXTERN(QPageSize)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QPageSize::PageSizeId, QPageSize__PageSizeId)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QPageSize::Unit, QPageSize__Unit)
+
// Define the Windows DMPAPER sizes for use in the look-up table
// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd319099.aspx
@@ -224,16 +194,16 @@ static const int qt_windowsConversion[][2] = {
// Standard sizes data
struct StandardPageSize {
- QPageSize::PageSizeId id;
- int windowsId; // Windows DMPAPER value
- QPageSize::Unit definitionUnits; // Standard definition size, e.g. ISO uses mm, ANSI uses inches
- int widthPoints;
- int heightPoints;
+ QPageSize::PageSizeId id : 8;
+ int windowsId : 16; // Windows DMPAPER value
+ QPageSize::Unit definitionUnits : 8; // Standard definition size, e.g. ISO uses mm, ANSI uses inches
+ int widthPoints : 16;
+ int heightPoints : 16;
qreal widthMillimeters;
qreal heightMillimeters;
qreal widthInches;
qreal heightInches;
- const char *mediaOption; // PPD standard mediaOption ID
+ const char mediaOption[20]; // PPD standard mediaOption ID
};
// Standard page sizes taken from the Postscript PPD Standard v4.3
@@ -386,6 +356,7 @@ static const StandardPageSize qt_pageSizes[] = {
static const int pageSizesCount = int(sizeof(qt_pageSizes) / sizeof(qt_pageSizes[0]));
static_assert(pageSizesCount == QPageSize::LastPageSize + 1);
+static_assert(QPageSize::LastPageSize < 256);
// Return key name for PageSize
static QString qt_keyForPageSizeId(QPageSize::PageSizeId id)
@@ -400,12 +371,12 @@ static QPageSize::PageSizeId qt_idForPpdKey(const QString &ppdKey, QSize *match
return QPageSize::Custom;
QStringView key(ppdKey);
// Remove any Rotated or Tranverse modifiers
- if (key.endsWith(QLatin1String("Rotated")))
+ if (key.endsWith("Rotated"_L1))
key.chop(7);
- else if (key.endsWith(QLatin1String(".Transverse")))
+ else if (key.endsWith(".Transverse"_L1))
key.chop(11);
for (int i = 0; i <= int(QPageSize::LastPageSize); ++i) {
- if (QLatin1String(qt_pageSizes[i].mediaOption) == key) {
+ if (QLatin1StringView(qt_pageSizes[i].mediaOption) == key) {
if (match)
*match = QSize(qt_pageSizes[i].widthPoints, qt_pageSizes[i].heightPoints);
return qt_pageSizes[i].id;
@@ -572,7 +543,7 @@ static QSize qt_convertPointsToPixels(const QSize &size, int resolution)
if (!size.isValid() || resolution <= 0)
return QSize();
const qreal multiplier = qt_pixelMultiplier(resolution);
- return QSize(qRound(size.width() / multiplier), qRound(size.height() / multiplier));
+ return QSize(qFloor(size.width() / multiplier), qFloor(size.height() / multiplier));
}
static QSizeF qt_convertPointsToUnits(const QSize &size, QPageSize::Unit units)
@@ -898,7 +869,7 @@ QSizeF QPageSizePrivate::size(QPageSize::Unit units) const
QSize QPageSizePrivate::sizePixels(int resolution) const
{
- return qt_convertPointsToPixels(m_pointSize, resolution);;
+ return qt_convertPointsToPixels(m_pointSize, resolution);
}
diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h
index f4e7af0f6c..b3629bb8d2 100644
--- a/src/gui/painting/qpagesize.h
+++ b/src/gui/painting/qpagesize.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 John Layt <jlayt@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2014 John Layt <jlayt@kde.org>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAGESIZE_H
#define QPAGESIZE_H
@@ -237,7 +201,7 @@ public:
~QPageSize();
- void swap(QPageSize &other) noexcept { qSwap(d, other.d); }
+ void swap(QPageSize &other) noexcept { d.swap(other.d); }
friend Q_GUI_EXPORT bool operator==(const QPageSize &lhs, const QPageSize &rhs);
bool isEquivalentTo(const QPageSize &other) const;
@@ -304,8 +268,8 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QPageSize &pageSize);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QPageSize)
-Q_DECLARE_METATYPE(QPageSize::PageSizeId)
-Q_DECLARE_METATYPE(QPageSize::Unit)
+QT_DECL_METATYPE_EXTERN(QPageSize, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN_TAGGED(QPageSize::PageSizeId, QPageSize__PageSizeId, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN_TAGGED(QPageSize::Unit, QPageSize__Unit, Q_GUI_EXPORT)
#endif // QPAGESIZE_H
diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp
index 07991f2d71..14e2d7cd8e 100644
--- a/src/gui/painting/qpaintdevice.cpp
+++ b/src/gui/painting/qpaintdevice.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpaintdevice.h"
diff --git a/src/gui/painting/qpaintdevice.h b/src/gui/painting/qpaintdevice.h
index 5a3b6e600e..ceccac5e7e 100644
--- a/src/gui/painting/qpaintdevice.h
+++ b/src/gui/painting/qpaintdevice.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTDEVICE_H
#define QPAINTDEVICE_H
diff --git a/src/gui/painting/qpaintdevice.qdoc b/src/gui/painting/qpaintdevice.qdoc
index 9fbe5956af..d63fdcb92b 100644
--- a/src/gui/painting/qpaintdevice.qdoc
+++ b/src/gui/painting/qpaintdevice.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QPaintDevice
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index 42606a93f0..aface3744d 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpaintengine.h"
#include "qpaintengine_p.h"
#include "qpainter_p.h"
@@ -52,6 +16,7 @@
#include <private/qpaintengineex_p.h>
#include <private/qtextengine_p.h>
+#include <memory>
QT_BEGIN_NAMESPACE
@@ -185,7 +150,7 @@ QFont QTextItem::font() const
emulated results. Some features cannot be emulated: AlphaBlend and PorterDuff.
\value AlphaBlend The engine can alpha blend primitives.
- \value Antialiasing The engine can use antialising to improve the appearance
+ \value Antialiasing The engine can use antialiasing to improve the appearance
of rendered primitives.
\value BlendModes The engine supports blending modes.
\value BrushStroke The engine supports drawing strokes that
@@ -516,6 +481,8 @@ void QPaintEngine::drawEllipse(const QRectF &rect)
}
/*!
+ \overload
+
The default implementation of this function calls the floating
point version of this function
*/
@@ -1009,9 +976,9 @@ QPixmap QPaintEngine::createPixmap(QSize size)
return QPixmap();
}
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
+ std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->resize(size.width(), size.height());
- return QPixmap(data.take());
+ return QPixmap(data.release());
}
/*!
@@ -1026,12 +993,12 @@ QPixmap QPaintEngine::createPixmapFromImage(QImage image, Qt::ImageConversionFla
return QPixmap();
}
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
+ std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
if (image.isDetached())
data->fromImageInPlace(image, flags);
else
data->fromImage(image, flags);
- return QPixmap(data.take());
+ return QPixmap(data.release());
}
QPaintEnginePrivate::~QPaintEnginePrivate()
diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h
index 64170c513e..f624dda5c7 100644
--- a/src/gui/painting/qpaintengine.h
+++ b/src/gui/painting/qpaintengine.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTENGINE_H
#define QPAINTENGINE_H
@@ -218,7 +182,7 @@ public:
inline void setDirty(DirtyFlags df);
inline void clearDirty(DirtyFlags df);
- bool hasFeature(PaintEngineFeatures feature) const { return gccaps & feature; }
+ bool hasFeature(PaintEngineFeatures feature) const { return bool(gccaps & feature); }
QPainter *painter() const;
@@ -320,7 +284,7 @@ inline void QPaintEngine::fix_neg_rect(int *x, int *y, int *w, int *h)
inline bool QPaintEngine::testDirty(DirtyFlags df) {
Q_ASSERT(state);
- return state->dirtyFlags & df;
+ return bool(state->dirtyFlags & df);
}
inline void QPaintEngine::setDirty(DirtyFlags df) {
@@ -331,7 +295,7 @@ inline void QPaintEngine::setDirty(DirtyFlags df) {
inline void QPaintEngine::clearDirty(DirtyFlags df)
{
Q_ASSERT(state);
- state->dirtyFlags &= ~static_cast<uint>(df);
+ state->dirtyFlags &= ~df;
}
Q_DECLARE_OPERATORS_FOR_FLAGS(QTextItem::RenderFlags)
diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp
index a50d1dfd73..4e6931de09 100644
--- a/src/gui/painting/qpaintengine_blitter.cpp
+++ b/src/gui/painting/qpaintengine_blitter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qpaintengine_blitter_p.h"
diff --git a/src/gui/painting/qpaintengine_blitter_p.h b/src/gui/painting/qpaintengine_blitter_p.h
index fb5dfe2318..0eb8703b08 100644
--- a/src/gui/painting/qpaintengine_blitter_p.h
+++ b/src/gui/painting/qpaintengine_blitter_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTENGINE_BLITTER_P_H
#define QPAINTENGINE_BLITTER_P_H
diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h
index 40b9474165..210e577950 100644
--- a/src/gui/painting/qpaintengine_p.h
+++ b/src/gui/painting/qpaintengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTENGINE_P_H
#define QPAINTENGINE_P_H
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 5ac1f748e5..f62373d4ef 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qglobal.h>
#include <QtCore/qmutex.h>
@@ -49,7 +13,7 @@
#include <qpainterpath.h>
#include <qdebug.h>
#include <qbitmap.h>
-#include <qmath.h>
+#include "qmath_p.h"
#include <qrandom.h>
// #include <private/qdatabuffer_p.h>
@@ -134,7 +98,6 @@ public:
Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
-#define qreal_to_fixed_26_6(f) (int(f * 64))
#define qt_swap_int(x, y) { int tmp = (x); (x) = (y); (y) = tmp; }
#define qt_swap_qreal(x, y) { qreal tmp = (x); (x) = (y); (y) = tmp; }
@@ -180,9 +143,9 @@ bool QRasterPaintEngine::clearTypeFontsEnabled()
/********************************************************************************
* Span functions
*/
-static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData);
-static void qt_span_fill_clipped(int count, const QSpan *spans, void *userData);
-static void qt_span_clip(int count, const QSpan *spans, void *userData);
+static void qt_span_fill_clipRect(int count, const QT_FT_Span *spans, void *userData);
+static void qt_span_fill_clipped(int count, const QT_FT_Span *spans, void *userData);
+static void qt_span_clip(int count, const QT_FT_Span *spans, void *userData);
struct ClipData
{
@@ -277,8 +240,7 @@ QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() :
/*!
\class QRasterPaintEngine
- \preliminary
- \ingroup qws
+ \internal
\inmodule QtGui
\since 4.2
@@ -313,15 +275,6 @@ QRasterPaintEnginePrivate::QRasterPaintEnginePrivate() :
*/
/*!
- \typedef QSpan
- \relates QRasterPaintEngine
-
- A struct equivalent to QT_FT_Span, containing a position (x,
- y), the span's length in pixels and its color/coverage (a value
- ranging from 0 to 255).
-*/
-
-/*!
\since 4.5
Creates a raster based paint engine for operating on the given
@@ -452,22 +405,16 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
QRasterPaintEngineState *s = state();
ensureOutlineMapper();
- d->outlineMapper->m_clip_rect = d->deviceRect;
-
- if (d->outlineMapper->m_clip_rect.width() > QT_RASTER_COORD_LIMIT)
- d->outlineMapper->m_clip_rect.setWidth(QT_RASTER_COORD_LIMIT);
- if (d->outlineMapper->m_clip_rect.height() > QT_RASTER_COORD_LIMIT)
- d->outlineMapper->m_clip_rect.setHeight(QT_RASTER_COORD_LIMIT);
-
+ d->outlineMapper->setClipRect(d->deviceRect);
d->rasterizer->setClipRect(d->deviceRect);
s->penData.init(d->rasterBuffer.data(), this);
- s->penData.setup(s->pen.brush(), s->intOpacity, s->composition_mode);
+ s->penData.setup(s->pen.brush(), s->intOpacity, s->composition_mode, s->flags.cosmetic_brush);
s->stroker = &d->basicStroker;
d->basicStroker.setClipRect(d->deviceRect);
s->brushData.init(d->rasterBuffer.data(), this);
- s->brushData.setup(s->brush, s->intOpacity, s->composition_mode);
+ s->brushData.setup(s->brush, s->intOpacity, s->composition_mode, s->flags.cosmetic_brush);
d->rasterBuffer->compositionMode = QPainter::CompositionMode_SourceOver;
@@ -526,31 +473,6 @@ void QRasterPaintEngine::updateMatrix(const QTransform &matrix)
QRasterPaintEngineState *s = state();
// FALCON: get rid of this line, see drawImage call below.
s->matrix = matrix;
- QTransform::TransformationType txop = s->matrix.type();
-
- switch (txop) {
-
- case QTransform::TxNone:
- s->flags.int_xform = true;
- break;
-
- case QTransform::TxTranslate:
- s->flags.int_xform = qreal(int(s->matrix.dx())) == s->matrix.dx()
- && qreal(int(s->matrix.dy())) == s->matrix.dy();
- break;
-
- case QTransform::TxScale:
- s->flags.int_xform = qreal(int(s->matrix.dx())) == s->matrix.dx()
- && qreal(int(s->matrix.dy())) == s->matrix.dy()
- && qreal(int(s->matrix.m11())) == s->matrix.m11()
- && qreal(int(s->matrix.m22())) == s->matrix.m22();
- break;
-
- default: // shear / perspective...
- s->flags.int_xform = false;
- break;
- }
-
s->flags.tx_noshear = qt_scaleForTransform(s->matrix, &s->txscale);
ensureOutlineMapper();
@@ -577,14 +499,15 @@ QRasterPaintEngineState::QRasterPaintEngineState()
txscale = 1.;
+ flag_bits = 0;
flags.fast_pen = true;
flags.non_complex_pen = false;
flags.antialiased = false;
flags.bilinear = false;
flags.fast_text = true;
- flags.int_xform = true;
flags.tx_noshear = true;
flags.fast_images = true;
+ flags.cosmetic_brush = true;
clip = nullptr;
flags.has_clip_ownership = false;
@@ -683,7 +606,8 @@ void QRasterPaintEngine::updatePen(const QPen &pen)
s->strokeFlags = 0;
s->penData.clip = d->clip();
- s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, s->composition_mode);
+ s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity,
+ s->composition_mode, s->flags.cosmetic_brush);
if (s->strokeFlags & QRasterPaintEngine::DirtyTransform
|| pen.brush().transform().type() >= QTransform::TxNone) {
@@ -782,7 +706,7 @@ void QRasterPaintEngine::updateBrush(const QBrush &brush)
QRasterPaintEngineState *s = state();
// must set clip prior to setup, as setup uses it...
s->brushData.clip = d->clip();
- s->brushData.setup(brush, s->intOpacity, s->composition_mode);
+ s->brushData.setup(brush, s->intOpacity, s->composition_mode, s->flags.cosmetic_brush);
if (s->fillFlags & DirtyTransform
|| brush.transform().type() >= QTransform::TxNone)
d_func()->updateMatrixData(&s->brushData, brush, d->brushMatrix());
@@ -809,7 +733,8 @@ void QRasterPaintEngine::updateRasterState()
&& s->intOpacity == 256
&& (mode == QPainter::CompositionMode_SourceOver
|| (mode == QPainter::CompositionMode_Source
- && s->penData.solidColor.isOpaque()));
+ && (s->penData.solidColor.spec() != QColor::ExtendedRgb &&
+ s->penData.solidColor.alphaF() >= 1.0f)));
}
s->dirty = 0;
@@ -868,20 +793,25 @@ void QRasterPaintEngine::renderHintsChanged()
bool was_aa = s->flags.antialiased;
bool was_bilinear = s->flags.bilinear;
+ bool was_cosmetic_brush = s->flags.cosmetic_brush;
s->flags.antialiased = bool(s->renderHints & QPainter::Antialiasing);
s->flags.bilinear = bool(s->renderHints & QPainter::SmoothPixmapTransform);
+ s->flags.cosmetic_brush = !bool(s->renderHints & QPainter::NonCosmeticBrushPatterns);
if (was_aa != s->flags.antialiased)
s->strokeFlags |= DirtyHints;
- if (was_bilinear != s->flags.bilinear) {
+ if (was_bilinear != s->flags.bilinear || was_cosmetic_brush != s->flags.cosmetic_brush) {
s->strokeFlags |= DirtyPen;
s->fillFlags |= DirtyBrush;
}
Q_D(QRasterPaintEngine);
d->recalculateFastImages();
+
+ if (was_aa != s->flags.antialiased)
+ d->updateClipping();
}
/*!
@@ -969,7 +899,7 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt,
if (iw <= 0)
return;
- // adapt the y paremeters...
+ // adapt the y parameters...
int cy1 = clip.y();
int cy2 = clip.y() + clip.height();
int y = qRound(pt.y());
@@ -1039,7 +969,7 @@ void QRasterPaintEnginePrivate::blitImage(const QPointF &pt,
if (iw <= 0)
return;
- // adapt the y paremeters...
+ // adapt the y parameters...
int cy1 = clip.y();
int cy2 = clip.y() + clip.height();
int y = qRound(pt.y());
@@ -1217,7 +1147,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
#endif
const qreal *points = path.points();
QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]);
- if (setClipRectInDeviceCoords(s->matrix.mapRect(r).toAlignedRect(), op))
+ if (setClipRectInDeviceCoords(qt_mapFillRect(r, s->matrix), op))
return;
}
}
@@ -1276,7 +1206,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
QPaintEngineEx::clip(rect, op);
return;
- } else if (!setClipRectInDeviceCoords(s->matrix.mapRect(QRectF(rect)).toRect(), op)) {
+ } else if (!setClipRectInDeviceCoords(qt_mapFillRect(rect, s->matrix), op)) {
QPaintEngineEx::clip(rect, op);
return;
}
@@ -1469,16 +1399,17 @@ static void fillRect_normalized(const QRect &r, QSpanData *data,
if (data->fillRect && (mode == QPainter::CompositionMode_Source
|| (mode == QPainter::CompositionMode_SourceOver
- && data->solidColor.isOpaque())))
+ && (data->solidColor.spec() != QColor::ExtendedRgb &&
+ data->solidColor.alphaF() >= 1.0f))))
{
- data->fillRect(data->rasterBuffer, x1, y1, width, height, data->solidColor);
+ data->fillRect(data->rasterBuffer, x1, y1, width, height, data->solidColor.rgba64());
return;
}
}
ProcessSpans blend = isUnclipped ? data->unclipped_blend : data->blend;
- const int nspans = 256;
+ const int nspans = 512;
QT_FT_Span spans[nspans];
Q_ASSERT(data->blend);
@@ -1633,8 +1564,9 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
patternLength += pattern.at(i);
if (patternLength > 0) {
- int n = qFloor(dashOffset / patternLength);
- dashOffset -= n * patternLength;
+ dashOffset = std::fmod(dashOffset, patternLength);
+ if (dashOffset < 0)
+ dashOffset += patternLength;
while (dashOffset >= pattern.at(dashIndex)) {
dashOffset -= pattern.at(dashIndex);
if (++dashIndex >= pattern.size())
@@ -1742,7 +1674,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
QRectF cpRect = path.controlPointRect();
const QRectF pathDeviceRect = s->matrix.mapRect(cpRect);
// Skip paths that by conservative estimates are completely outside the paint device.
- if (!pathDeviceRect.intersects(QRectF(d->deviceRect)))
+ if (!pathDeviceRect.intersects(QRectF(d->deviceRect)) || !pathDeviceRect.isValid())
return;
ProcessSpans blend = d->getBrushFunc(pathDeviceRect, &s->brushData);
@@ -1819,6 +1751,19 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QBrush &brush)
fillRect(r, &s->brushData);
}
+static QColor qPremultiplyWithExtraAlpha(const QColor &c, int alpha)
+{
+ if (alpha == 0)
+ return Qt::transparent;
+ if (c.spec() == QColor::ExtendedRgb) {
+ float r, g, b, a;
+ c.getRgbF(&r, &g, &b, &a);
+ a = a * alpha * (1.f / 256.f);
+ return QColor::fromRgbF(r * a, g * a, b * a, a);
+ }
+ return qPremultiply(combineAlpha256(c.rgba64(), alpha));
+}
+
/*!
\reimp
*/
@@ -1830,9 +1775,9 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color)
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
- d->solid_color_filler.solidColor = qPremultiply(combineAlpha256(color.rgba64(), s->intOpacity));
+ d->solid_color_filler.solidColor = qPremultiplyWithExtraAlpha(color, s->intOpacity);
- if (d->solid_color_filler.solidColor.isTransparent()
+ if (d->solid_color_filler.solidColor.alphaF() <= 0.0f
&& s->composition_mode == QPainter::CompositionMode_SourceOver) {
return;
}
@@ -2293,7 +2238,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
break;
}
- if (d->solid_color_filler.solidColor.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver)
+ if (d->solid_color_filler.solidColor.alphaF() <= 0.0f && s->composition_mode == QPainter::CompositionMode_SourceOver)
return;
d->solid_color_filler.clip = d->clip();
@@ -2316,6 +2261,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
|| d->rasterBuffer->compositionMode == QPainter::CompositionMode_Source))
{
RotationType rotationType = qRotationType(s->matrix);
+ Q_ASSERT(d->rasterBuffer->format < QImage::NImageFormats);
const QPixelLayout::BPP plBpp = qPixelLayouts[d->rasterBuffer->format].bpp;
if (rotationType != NoRotation && qMemRotateFunctions[plBpp][rotationType] && img.rect().contains(sr.toAlignedRect())) {
@@ -2396,9 +2342,16 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
}
SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()];
if (func && (!clip || clip->hasRectClip)) {
+ QRectF tr = qt_mapRect_non_normalizing(r, s->matrix);
+ if (!s->flags.antialiased) {
+ tr.setX(qRound(tr.x()));
+ tr.setY(qRound(tr.y()));
+ tr.setWidth(qRound(tr.width()));
+ tr.setHeight(qRound(tr.height()));
+ }
func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(),
img.bits(), img.bytesPerLine(), img.height(),
- qt_mapRect_non_normalizing(r, s->matrix), sr,
+ tr, sr,
!clip ? d->deviceRect : clip->clipRect,
s->intOpacity);
return;
@@ -2637,20 +2590,20 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
if (unclipped) {
if (depth == 1) {
if (s->penData.bitmapBlit) {
- s->penData.bitmapBlit(rb, rx, ry, s->penData.solidColor,
+ s->penData.bitmapBlit(rb, rx, ry, s->penData.solidColor.rgba64(),
scanline, w, h, bpl);
return;
}
} else if (depth == 8) {
if (s->penData.alphamapBlit) {
- s->penData.alphamapBlit(rb, rx, ry, s->penData.solidColor,
+ s->penData.alphamapBlit(rb, rx, ry, s->penData.solidColor.rgba64(),
scanline, w, h, bpl, nullptr, useGammaCorrection);
return;
}
} else if (depth == 32) {
// (A)RGB Alpha mask where the alpha component is not used.
if (s->penData.alphaRGBBlit) {
- s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solidColor,
+ s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solidColor.rgba64(),
(const uint *) scanline, w, h, bpl / 4, nullptr, useGammaCorrection);
return;
}
@@ -2679,10 +2632,10 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
ry = ny;
}
if (depth == 8)
- s->penData.alphamapBlit(rb, rx, ry, s->penData.solidColor,
+ s->penData.alphamapBlit(rb, rx, ry, s->penData.solidColor.rgba64(),
scanline, w, h, bpl, clip, useGammaCorrection);
else if (depth == 32)
- s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solidColor,
+ s->penData.alphaRGBBlit(rb, rx, ry, s->penData.solidColor.rgba64(),
(const uint *) scanline, w, h, bpl / 4, clip, useGammaCorrection);
return;
}
@@ -2707,8 +2660,8 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx
if (w <= 0 || h <= 0)
return;
- const int NSPANS = 256;
- QSpan spans[NSPANS];
+ const int NSPANS = 512;
+ QT_FT_Span spans[NSPANS];
int current = 0;
const int x1 = x0 + w;
@@ -2875,9 +2828,9 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat != QFontEngine::Format_None ? fontEngine->glyphFormat : d->glyphCacheFormat;
QImageTextureGlyphCache *cache =
- static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(nullptr, glyphFormat, s->matrix, QColor(s->penData.solidColor)));
+ static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(nullptr, glyphFormat, s->matrix, s->penData.solidColor));
if (!cache) {
- cache = new QImageTextureGlyphCache(glyphFormat, s->matrix, QColor(s->penData.solidColor));
+ cache = new QImageTextureGlyphCache(glyphFormat, s->matrix, s->penData.solidColor);
fontEngine->setGlyphCache(nullptr, cache);
}
@@ -3012,7 +2965,7 @@ inline bool QRasterPaintEnginePrivate::isUnclipped(const QRectF &rect,
int penWidth) const
{
const QRectF norm = rect.normalized();
- if (norm.left() < INT_MIN || norm.top() < INT_MIN
+ if (norm.left() <= INT_MIN || norm.top() <= INT_MIN
|| norm.right() > INT_MAX || norm.bottom() > INT_MAX
|| norm.width() > INT_MAX || norm.height() > INT_MAX)
return false;
@@ -3046,13 +2999,19 @@ QRasterPaintEnginePrivate::getPenFunc(const QRectF &rect,
return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend;
}
-static QPair<int, int> visibleGlyphRange(const QRectF &clip, QFontEngine *fontEngine,
- glyph_t *glyphs, QFixedPoint *positions, int numGlyphs)
+struct VisibleGlyphRange
+{
+ int begin;
+ int end;
+};
+
+static VisibleGlyphRange visibleGlyphRange(const QRectF &clip, QFontEngine *fontEngine,
+ glyph_t *glyphs, QFixedPoint *positions, int numGlyphs)
{
- QFixed clipLeft = QFixed::fromReal(clip.left());
- QFixed clipRight = QFixed::fromReal(clip.right());
- QFixed clipTop = QFixed::fromReal(clip.top());
- QFixed clipBottom = QFixed::fromReal(clip.bottom());
+ QFixed clipLeft = QFixed::fromReal(clip.left() - 1);
+ QFixed clipRight = QFixed::fromReal(clip.right() + 1);
+ QFixed clipTop = QFixed::fromReal(clip.top() - 1);
+ QFixed clipBottom = QFixed::fromReal(clip.bottom() + 1);
int first = 0;
while (first < numGlyphs) {
@@ -3076,7 +3035,7 @@ static QPair<int, int> visibleGlyphRange(const QRectF &clip, QFontEngine *fontEn
break;
--last;
}
- return QPair<int, int>(first, last + 1);
+ return {first, last + 1};
}
/*!
@@ -3102,13 +3061,13 @@ void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
if (!invertible)
return;
- QPair<int, int> range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()),
- textItem->fontEngine(), textItem->glyphs,
- textItem->glyphPositions, textItem->numGlyphs);
+ const auto range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()),
+ textItem->fontEngine(), textItem->glyphs,
+ textItem->glyphPositions, textItem->numGlyphs);
QStaticTextItem copy = *textItem;
- copy.glyphs += range.first;
- copy.glyphPositions += range.first;
- copy.numGlyphs = range.second - range.first;
+ copy.glyphs += range.begin;
+ copy.glyphPositions += range.begin;
+ copy.numGlyphs = range.end - range.begin;
QPaintEngineEx::drawStaticTextItem(&copy);
} else {
QPaintEngineEx::drawStaticTextItem(textItem);
@@ -3157,20 +3116,20 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
ti.fontEngine->getGlyphPositions(ti.glyphs, QTransform::fromTranslate(p.x(), p.y()),
ti.flags, glyphs, positions);
- QPair<int, int> range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()),
- ti.fontEngine, glyphs.data(), positions.data(),
- glyphs.size());
+ const auto range = visibleGlyphRange(invMat.mapRect(clipBoundingRect()),
+ ti.fontEngine, glyphs.data(), positions.data(),
+ glyphs.size());
- if (range.first >= range.second)
+ if (range.begin >= range.end)
return;
QStaticTextItem staticTextItem;
staticTextItem.color = s->pen.color();
staticTextItem.font = s->font;
staticTextItem.setFontEngine(ti.fontEngine);
- staticTextItem.numGlyphs = range.second - range.first;
- staticTextItem.glyphs = glyphs.data() + range.first;
- staticTextItem.glyphPositions = positions.data() + range.first;
+ staticTextItem.numGlyphs = range.end - range.begin;
+ staticTextItem.glyphs = glyphs.data() + range.begin;
+ staticTextItem.glyphPositions = positions.data() + range.begin;
QPaintEngineEx::drawStaticTextItem(&staticTextItem);
} else {
QPaintEngineEx::drawTextItem(p, ti);
@@ -3265,6 +3224,11 @@ void QRasterPaintEnginePrivate::rasterizeLine_dashed(QLineF line,
qreal length = line.length();
Q_ASSERT(length > 0);
+ if (length / (patternLength * width) > QDashStroker::repetitionLimit()) {
+ rasterizer->rasterizeLine(line.p1(), line.p2(), width / length, squareCap);
+ return;
+ }
+
while (length > 0) {
const bool rasterize = *inDash;
qreal dash = (pattern.at(*dashIndex) - *dashOffset) * width;
@@ -3426,23 +3390,25 @@ void QRasterPaintEngine::drawBitmap(const QPointF &pos, const QImage &image, QSp
Q_ASSERT(image.depth() == 1);
- const int spanCount = 256;
+ const int spanCount = 512;
QT_FT_Span spans[spanCount];
int n = 0;
// Boundaries
int w = image.width();
int h = image.height();
- int ymax = qMin(qRound(pos.y() + h), d->rasterBuffer->height());
- int ymin = qMax(qRound(pos.y()), 0);
- int xmax = qMin(qRound(pos.x() + w), d->rasterBuffer->width());
- int xmin = qMax(qRound(pos.x()), 0);
+ int px = qRound(pos.x());
+ int py = qRound(pos.y());
+ int ymax = qMin(py + h, d->rasterBuffer->height());
+ int ymin = qMax(py, 0);
+ int xmax = qMin(px + w, d->rasterBuffer->width());
+ int xmin = qMax(px, 0);
- int x_offset = xmin - qRound(pos.x());
+ int x_offset = xmin - px;
QImage::Format format = image.format();
for (int y = ymin; y < ymax; ++y) {
- const uchar *src = image.scanLine(y - qRound(pos.y()));
+ const uchar *src = image.scanLine(y - py);
if (format == QImage::Format_MonoLSB) {
for (int x = 0; x < xmax - xmin; ++x) {
int src_x = x + x_offset;
@@ -3530,7 +3496,7 @@ QRasterPaintEngine::ClipType QRasterPaintEngine::clipType() const
\internal
Returns the bounding rect of the currently set clip.
*/
-QRect QRasterPaintEngine::clipBoundingRect() const
+QRectF QRasterPaintEngine::clipBoundingRect() const
{
Q_D(const QRasterPaintEngine);
@@ -3542,7 +3508,7 @@ QRect QRasterPaintEngine::clipBoundingRect() const
if (clip->hasRectClip)
return clip->clipRect;
- return QRect(clip->xmin, clip->ymin, clip->xmax - clip->xmin, clip->ymax - clip->ymin);
+ return QRectF(clip->xmin, clip->ymin, clip->xmax - clip->xmin, clip->ymax - clip->ymin);
}
void QRasterPaintEnginePrivate::initializeRasterizer(QSpanData *data)
@@ -3695,6 +3661,18 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
free(rasterPoolOnHeap);
}
+void QRasterPaintEnginePrivate::updateClipping()
+{
+ Q_Q(QRasterPaintEngine);
+ QRasterPaintEngineState *s = q->state();
+
+ if (!s->clipEnabled)
+ return;
+
+ qrasterpaintengine_state_setNoClip(s);
+ replayClipOperations();
+}
+
void QRasterPaintEnginePrivate::recalculateFastImages()
{
Q_Q(QRasterPaintEngine);
@@ -3735,15 +3713,9 @@ bool QRasterPaintEnginePrivate::canUseImageBlitting(QPainter::CompositionMode mo
QImage::Format dFormat = rasterBuffer->format;
QImage::Format sFormat = image.format();
- // Formats must match or source format must be a subset of destination format
- if (dFormat != sFormat && image.pixelFormat().alphaUsage() == QPixelFormat::IgnoresAlpha) {
- if ((sFormat == QImage::Format_RGB32 && dFormat == QImage::Format_ARGB32)
- || (sFormat == QImage::Format_RGBX8888 && dFormat == QImage::Format_RGBA8888)
- || (sFormat == QImage::Format_RGBX64 && dFormat == QImage::Format_RGBA64))
- sFormat = dFormat;
- else
- sFormat = qt_maybeAlphaVersionWithSameDepth(sFormat); // this returns premul formats
- }
+ // Formats must match or source format must be an opaque version of destination format
+ if (dFormat != sFormat && image.pixelFormat().alphaUsage() == QPixelFormat::IgnoresAlpha)
+ dFormat = qt_maybeDataCompatibleOpaqueVersion(dFormat);
return (dFormat == sFormat);
}
@@ -3830,7 +3802,7 @@ void QClipData::initialize()
return;
if (!m_clipLines)
- m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
+ m_clipLines = (ClipLine *)calloc(clipSpanHeight, sizeof(ClipLine));
Q_CHECK_PTR(m_clipLines);
QT_TRY {
@@ -3842,7 +3814,7 @@ void QClipData::initialize()
const int numRects = clipRegion.rectCount();
const int maxSpans = (ymax - ymin) * numRects;
allocated = qMax(allocated, maxSpans);
- m_spans = (QSpan *)malloc(allocated * sizeof(QSpan));
+ m_spans = (QT_FT_Span *)malloc(allocated * sizeof(QT_FT_Span));
Q_CHECK_PTR(m_spans);
int y = 0;
@@ -3868,7 +3840,7 @@ void QClipData::initialize()
for (int r = firstInBand; r <= lastInBand; ++r) {
const QRect &currRect = rects[r];
- QSpan *span = m_spans + count;
+ QT_FT_Span *span = m_spans + count;
span->x = currRect.x();
span->len = currRect.width();
span->y = y;
@@ -3892,7 +3864,7 @@ void QClipData::initialize()
return;
}
- m_spans = (QSpan *)malloc(allocated * sizeof(QSpan));
+ m_spans = (QT_FT_Span *)malloc(allocated * sizeof(QT_FT_Span));
Q_CHECK_PTR(m_spans);
if (hasRectClip) {
@@ -3905,7 +3877,7 @@ void QClipData::initialize()
const int len = clipRect.width();
while (y < ymax) {
- QSpan *span = m_spans + count;
+ QT_FT_Span *span = m_spans + count;
span->x = xmin;
span->len = len;
span->y = y;
@@ -4044,16 +4016,16 @@ void QClipData::setClipRegion(const QRegion &region)
\internal
spans must be sorted on y
*/
-static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip,
- const QSpan *spans, const QSpan *end,
- QSpan **outSpans, int available)
+static const QT_FT_Span *qt_intersect_spans(const QClipData *clip, int *currentClip,
+ const QT_FT_Span *spans, const QT_FT_Span *end,
+ QT_FT_Span **outSpans, int available)
{
const_cast<QClipData *>(clip)->initialize();
- QSpan *out = *outSpans;
+ QT_FT_Span *out = *outSpans;
- const QSpan *clipSpans = clip->m_spans + *currentClip;
- const QSpan *clipEnd = clip->m_spans + clip->count;
+ const QT_FT_Span *clipSpans = clip->m_spans + *currentClip;
+ const QT_FT_Span *clipEnd = clip->m_spans + clip->count;
while (available && spans < end ) {
if (clipSpans >= clipEnd) {
@@ -4107,19 +4079,19 @@ static const QSpan *qt_intersect_spans(const QClipData *clip, int *currentClip,
return spans;
}
-static void qt_span_fill_clipped(int spanCount, const QSpan *spans, void *userData)
+static void qt_span_fill_clipped(int spanCount, const QT_FT_Span *spans, void *userData)
{
// qDebug() << "qt_span_fill_clipped" << spanCount;
QSpanData *fillData = reinterpret_cast<QSpanData *>(userData);
Q_ASSERT(fillData->blend && fillData->unclipped_blend);
- const int NSPANS = 256;
- QSpan cspans[NSPANS];
+ const int NSPANS = 512;
+ QT_FT_Span cspans[NSPANS];
int currentClip = 0;
- const QSpan *end = spans + spanCount;
+ const QT_FT_Span *end = spans + spanCount;
while (spans < end) {
- QSpan *clipped = cspans;
+ QT_FT_Span *clipped = cspans;
spans = qt_intersect_spans(fillData->clip, &currentClip, spans, end, &clipped, NSPANS);
// qDebug() << "processed " << spanCount - (end - spans) << "clipped" << clipped-cspans
// << "span:" << cspans->x << cspans->y << cspans->len << spans->coverage;
@@ -4171,7 +4143,7 @@ static int qt_intersect_spans(QT_FT_Span *&spans, int numSpans,
}
-static void qt_span_fill_clipRect(int count, const QSpan *spans,
+static void qt_span_fill_clipRect(int count, const QT_FT_Span *spans,
void *userData)
{
QSpanData *fillData = reinterpret_cast<QSpanData *>(userData);
@@ -4180,7 +4152,7 @@ static void qt_span_fill_clipRect(int count, const QSpan *spans,
Q_ASSERT(fillData->clip);
Q_ASSERT(!fillData->clip->clipRect.isEmpty());
- QSpan *s = const_cast<QSpan *>(spans);
+ QT_FT_Span *s = const_cast<QT_FT_Span *>(spans);
// hw: check if this const_cast<> is safe!!!
count = qt_intersect_spans(s, count,
fillData->clip->clipRect);
@@ -4188,7 +4160,7 @@ static void qt_span_fill_clipRect(int count, const QSpan *spans,
fillData->unclipped_blend(count, s, fillData);
}
-static void qt_span_clip(int count, const QSpan *spans, void *userData)
+static void qt_span_clip(int count, const QT_FT_Span *spans, void *userData)
{
ClipData *clipData = reinterpret_cast<ClipData *>(userData);
@@ -4205,14 +4177,14 @@ static void qt_span_clip(int count, const QSpan *spans, void *userData)
newClip->initialize();
int currentClip = 0;
- const QSpan *end = spans + count;
+ const QT_FT_Span *end = spans + count;
while (spans < end) {
- QSpan *newspans = newClip->m_spans + newClip->count;
+ QT_FT_Span *newspans = newClip->m_spans + newClip->count;
spans = qt_intersect_spans(clipData->oldClip, &currentClip, spans, end,
&newspans, newClip->allocated - newClip->count);
newClip->count = newspans - newClip->m_spans;
if (spans < end) {
- newClip->m_spans = q_check_ptr((QSpan *)realloc(newClip->m_spans, newClip->allocated*2*sizeof(QSpan)));
+ newClip->m_spans = q_check_ptr((QT_FT_Span *)realloc(newClip->m_spans, newClip->allocated * 2 * sizeof(QT_FT_Span)));
newClip->allocated *= 2;
}
}
@@ -4230,7 +4202,7 @@ static void qt_span_clip(int count, const QSpan *spans, void *userData)
class QGradientCache
{
public:
- struct CacheInfo : QSpanData::Pinnable
+ struct CacheInfo
{
inline CacheInfo(QGradientStops s, int op, QGradient::InterpolationMode mode) :
stops(std::move(s)), opacity(op), interpolationMode(mode) {}
@@ -4241,9 +4213,9 @@ public:
QGradient::InterpolationMode interpolationMode;
};
- typedef QMultiHash<quint64, QSharedPointer<const CacheInfo>> QGradientColorTableHash;
+ using QGradientColorTableHash = QMultiHash<quint64, std::shared_ptr<const CacheInfo>>;
- inline QSharedPointer<const CacheInfo> getBuffer(const QGradient &gradient, int opacity) {
+ std::shared_ptr<const CacheInfo> getBuffer(const QGradient &gradient, int opacity) {
quint64 hash_val = 0;
const QGradientStops stops = gradient.stops();
@@ -4273,16 +4245,16 @@ protected:
inline void generateGradientColorTable(const QGradient& g,
QRgba64 *colorTable,
int size, int opacity) const;
- QSharedPointer<const CacheInfo> addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) {
+ std::shared_ptr<const CacheInfo> addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) {
if (cache.size() == maxCacheSize()) {
// may remove more than 1, but OK
cache.erase(std::next(cache.begin(), QRandomGenerator::global()->bounded(maxCacheSize())));
}
- auto cache_entry = QSharedPointer<CacheInfo>::create(gradient.stops(), opacity, gradient.interpolationMode());
+ auto cache_entry = std::make_shared<CacheInfo>(gradient.stops(), opacity, gradient.interpolationMode());
generateGradientColorTable(gradient, cache_entry->buffer64, paletteSize(), opacity);
for (int i = 0; i < GRADIENT_STOPTABLE_SIZE; ++i)
cache_entry->buffer32[i] = cache_entry->buffer64[i].toArgb32();
- return cache.insert(hash_val, cache_entry).value();
+ return cache.insert(hash_val, std::move(cache_entry)).value();
}
QGradientColorTableHash cache;
@@ -4292,7 +4264,7 @@ protected:
void QGradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, int opacity) const
{
const QGradientStops stops = gradient.stops();
- int stopCount = stops.count();
+ int stopCount = stops.size();
Q_ASSERT(stopCount > 0);
bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
@@ -4498,7 +4470,8 @@ void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe)
Q_GUI_EXPORT extern QImage qt_imageForBrush(int brushStyle, bool invert);
-void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode)
+void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode,
+ bool isCosmetic)
{
Qt::BrushStyle brushStyle = qbrush_style(brush);
cachedGradient.reset();
@@ -4506,8 +4479,8 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
case Qt::SolidPattern: {
type = Solid;
QColor c = qbrush_color(brush);
- solidColor = qPremultiply(combineAlpha256(c.rgba64(), alpha));
- if (solidColor.isTransparent() && compositionMode == QPainter::CompositionMode_SourceOver)
+ solidColor = qPremultiplyWithExtraAlpha(c, alpha);
+ if (solidColor.alphaF() <= 0.0f && compositionMode == QPainter::CompositionMode_SourceOver)
type = None;
break;
}
@@ -4605,7 +4578,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode
if (!tempImage)
tempImage = new QImage();
*tempImage = rasterBuffer->colorizeBitmap(qt_imageForBrush(brushStyle, true), brush.color());
- initTexture(tempImage, alpha, QTextureData::Pattern);
+ initTexture(tempImage, alpha, isCosmetic ? QTextureData::Pattern : QTextureData::Tiled);
break;
case Qt::TexturePattern:
type = Texture;
@@ -4892,7 +4865,7 @@ void dumpClip(int width, int height, const QClipData *clip)
((QClipData *) clip)->spans(); // Force allocation of the spans structure...
for (int i = 0; i < clip->count; ++i) {
- const QSpan *span = ((QClipData *) clip)->spans() + i;
+ const QT_FT_Span *span = ((QClipData *) clip)->spans() + i;
for (int j = 0; j < span->len; ++j)
clipImg.setPixel(span->x + j, span->y, 0xffffff00);
x0 = qMin(x0, int(span->x));
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index d25fe4c3b3..ab0048af52 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTENGINE_RASTER_P_H
#define QPAINTENGINE_RASTER_P_H
@@ -110,9 +74,9 @@ public:
uint antialiased : 1;
uint bilinear : 1;
uint fast_text : 1;
- uint int_xform : 1;
uint tx_noshear : 1;
uint fast_images : 1;
+ uint cosmetic_brush : 1;
};
union {
@@ -205,7 +169,7 @@ public:
ComplexClip
};
ClipType clipType() const;
- QRect clipBoundingRect() const;
+ QRectF clipBoundingRect() const;
#ifdef Q_OS_WIN
void setDC(HDC hdc);
@@ -276,6 +240,7 @@ public:
void rasterize(QT_FT_Outline *outline, ProcessSpans callback, QSpanData *spanData, QRasterBuffer *rasterBuffer);
void rasterize(QT_FT_Outline *outline, ProcessSpans callback, void *userData, QRasterBuffer *rasterBuffer);
void updateMatrixData(QSpanData *spanData, const QBrush &brush, const QTransform &brushMatrix);
+ void updateClipping();
void systemStateChanged() override;
@@ -350,7 +315,7 @@ public:
int clipSpanHeight;
struct ClipLine {
int count;
- QSpan *spans;
+ QT_FT_Span *spans;
} *m_clipLines;
void initialize();
@@ -361,7 +326,7 @@ public:
return m_clipLines;
}
- inline QSpan *spans() {
+ inline QT_FT_Span *spans() {
if (!m_spans)
initialize();
return m_spans;
@@ -369,7 +334,7 @@ public:
int allocated;
int count;
- QSpan *m_spans;
+ QT_FT_Span *m_spans;
int xmin, xmax, ymin, ymax;
QRect clipRect;
@@ -380,7 +345,7 @@ public:
uint hasRegionClip : 1;
void appendSpan(int x, int length, int y, int coverage);
- void appendSpans(const QSpan *s, int num);
+ void appendSpans(const QT_FT_Span *s, int num);
// ### Should optimize and actually kill the QSpans if the rect is
// ### a subset of The current region. Thus the "fast" clipspan
@@ -396,7 +361,7 @@ inline void QClipData::appendSpan(int x, int length, int y, int coverage)
if (count == allocated) {
allocated *= 2;
- m_spans = (QSpan *)realloc(m_spans, allocated*sizeof(QSpan));
+ m_spans = (QT_FT_Span *)realloc(m_spans, allocated*sizeof(QT_FT_Span));
}
m_spans[count].x = x;
m_spans[count].len = length;
@@ -405,7 +370,7 @@ inline void QClipData::appendSpan(int x, int length, int y, int coverage)
++count;
}
-inline void QClipData::appendSpans(const QSpan *s, int num)
+inline void QClipData::appendSpans(const QT_FT_Span *s, int num)
{
Q_ASSERT(m_spans);
@@ -413,9 +378,9 @@ inline void QClipData::appendSpans(const QSpan *s, int num)
do {
allocated *= 2;
} while (count + num > allocated);
- m_spans = (QSpan *)realloc(m_spans, allocated*sizeof(QSpan));
+ m_spans = (QT_FT_Span *)realloc(m_spans, allocated*sizeof(QT_FT_Span));
}
- memcpy(m_spans+count, s, num*sizeof(QSpan));
+ memcpy(m_spans+count, s, num*sizeof(QT_FT_Span));
count += num;
}
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 2997d53310..9468876c23 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpaintengineex_p.h"
#include "qpainter_p.h"
@@ -388,7 +352,7 @@ Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal
void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen)
{
#ifdef QT_DEBUG_DRAW
- qDebug() << "QPaintEngineEx::stroke()" << pen;
+ qDebug() << "QPaintEngineEx::stroke()" << inPen;
#endif
Q_D(QPaintEngineEx);
@@ -415,18 +379,18 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &inPen)
clipRect = xf.inverted().mapRect(QRectF(d->exDeviceRect));
}
// Check to avoid generating unwieldy amount of dashes that will not be visible anyway
- QRectF extentRect = cpRect & clipRect;
+ qreal pw = pen.widthF() ? pen.widthF() : 1;
+ QRectF extentRect = cpRect.adjusted(-pw, -pw, pw, pw) & clipRect;
qreal extent = qMax(extentRect.width(), extentRect.height());
qreal patternLength = 0;
const QList<qreal> pattern = pen.dashPattern();
const int patternSize = qMin(pattern.size(), 32);
for (int i = 0; i < patternSize; i++)
patternLength += qMax(pattern.at(i), qreal(0));
- if (pen.widthF())
- patternLength *= pen.widthF();
+ patternLength *= pw;
if (qFuzzyIsNull(patternLength)) {
pen.setStyle(Qt::NoPen);
- } else if (extent / patternLength > 10000) {
+ } else if (extent / patternLength > QDashStroker::repetitionLimit()) {
// approximate stream of tiny dashes with semi-transparent solid line
pen.setStyle(Qt::SolidLine);
QColor color(pen.color());
@@ -938,7 +902,7 @@ void QPaintEngineEx::drawPoints(const QPoint *points, int pointCount)
void QPaintEngineEx::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
{
- Q_ASSUME(pointCount >= 2);
+ Q_ASSERT(pointCount >= 2);
QVectorPath path((const qreal *) points, pointCount, nullptr, QVectorPath::polygonFlags(mode));
if (mode == PolylineMode)
@@ -949,7 +913,7 @@ void QPaintEngineEx::drawPolygon(const QPointF *points, int pointCount, PolygonD
void QPaintEngineEx::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
{
- Q_ASSUME(pointCount >= 2);
+ Q_ASSERT(pointCount >= 2);
int count = pointCount<<1;
QVarLengthArray<qreal> pts(count);
@@ -967,12 +931,12 @@ void QPaintEngineEx::drawPolygon(const QPoint *points, int pointCount, PolygonDr
void QPaintEngineEx::drawPixmap(const QPointF &pos, const QPixmap &pm)
{
- drawPixmap(QRectF(pos, pm.size() / pm.devicePixelRatio()), pm, pm.rect());
+ drawPixmap(QRectF(pos, pm.deviceIndependentSize()), pm, pm.rect());
}
void QPaintEngineEx::drawImage(const QPointF &pos, const QImage &image)
{
- drawImage(QRectF(pos, image.size() / image.devicePixelRatio()), image, image.rect());
+ drawImage(QRectF(pos, image.deviceIndependentSize()), image, image.rect());
}
void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h
index b2f8b64029..d2a5a9ceab 100644
--- a/src/gui/painting/qpaintengineex_p.h
+++ b/src/gui/painting/qpaintengineex_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTENGINEEX_P_H
#define QPAINTENGINEEX_P_H
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 31f8e40381..f4b9741eed 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -1,43 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// QtCore
+#include <memory>
#include <qdebug.h>
#include <qmath.h>
#include <qmutex.h>
@@ -74,9 +39,15 @@
#include <private/qhexstring_p.h>
#include <private/qguiapplication_p.h>
#include <private/qrawfont_p.h>
+#include <private/qfont_p.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+// We changed the type from QScopedPointer to unique_ptr, make sure it's binary compatible:
+static_assert(sizeof(QScopedPointer<QPainterPrivate>) == sizeof(std::unique_ptr<QPainterPrivate>));
+
#define QGradient_StretchToDevice 0x10000000
#define QPaintEngine_OpaqueBackground 0x40000000
@@ -180,6 +151,23 @@ static bool qt_painter_thread_test(int devType, int engineType, const char *what
}
#endif
+static bool needsEmulation(const QBrush &brush)
+{
+ bool res = false;
+
+ const QGradient *bg = brush.gradient();
+ if (bg) {
+ res = (bg->coordinateMode() > QGradient::LogicalMode);
+ } else if (brush.style() == Qt::TexturePattern) {
+ if (qHasPixmapTexture(brush))
+ res = !qFuzzyCompare(brush.texture().devicePixelRatio(), qreal(1.0));
+ else
+ res = !qFuzzyCompare(brush.textureImage().devicePixelRatio(), qreal(1.0));
+ }
+
+ return res;
+}
+
void QPainterPrivate::checkEmulation()
{
Q_ASSERT(extended);
@@ -187,21 +175,12 @@ void QPainterPrivate::checkEmulation()
if (state->bgMode == Qt::OpaqueMode)
doEmulation = true;
- const QGradient *bg = state->brush.gradient();
- if (bg && bg->coordinateMode() > QGradient::LogicalMode)
+ if (needsEmulation(state->brush))
doEmulation = true;
- const QGradient *pg = qpen_brush(state->pen).gradient();
- if (pg && pg->coordinateMode() > QGradient::LogicalMode)
+ if (needsEmulation(qpen_brush(state->pen)))
doEmulation = true;
- if (state->brush.style() == Qt::TexturePattern) {
- if (qHasPixmapTexture(state->brush))
- doEmulation |= !qFuzzyCompare(state->brush.texture().devicePixelRatio(), qreal(1.0));
- else
- doEmulation |= !qFuzzyCompare(state->brush.textureImage().devicePixelRatio(), qreal(1.0));
- }
-
if (doEmulation && extended->flags() & QPaintEngineEx::DoNotEmulate)
return;
@@ -242,7 +221,7 @@ qreal QPainterPrivate::effectiveDevicePixelRatio() const
if (device->devType() == QInternal::Printer)
return qreal(1);
- return qMax(qreal(1), device->devicePixelRatio());
+ return device->devicePixelRatio();
}
QTransform QPainterPrivate::hidpiScaleTransform() const
@@ -268,9 +247,9 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
// the current d_ptr to the shared painter's d_ptr.
sp->save();
++sp->d_ptr->refcount;
- sp->d_ptr->d_ptrs.push_back(q->d_ptr.data());
- q->d_ptr.take();
- q->d_ptr.reset(sp->d_ptr.data());
+ sp->d_ptr->d_ptrs.push_back(q->d_ptr.get());
+ Q_UNUSED(q->d_ptr.release());
+ q->d_ptr.reset(sp->d_ptr.get());
Q_ASSERT(q->d_ptr->state);
@@ -325,7 +304,7 @@ void QPainterPrivate::detachPainterPrivate(QPainter *q)
}
q->restore();
- q->d_ptr.take();
+ Q_UNUSED(q->d_ptr.release());
q->d_ptr.reset(original);
if (emulationEngine) {
@@ -402,7 +381,7 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio
if (q->hasClipping()) {
bool hasPerspectiveTransform = false;
- for (const QPainterClipInfo &info : qAsConst(state->clipInfo)) {
+ for (const QPainterClipInfo &info : std::as_const(state->clipInfo)) {
if (info.matrix.type() == QTransform::TxProject) {
hasPerspectiveTransform = true;
break;
@@ -1146,24 +1125,22 @@ void QPainterPrivate::updateState(QPainterState *newState)
The QPainter class also provides a means of controlling the
rendering quality through its RenderHint enum and the support for
floating point precision: All the functions for drawing primitives
- has a floating point version. These are often used in combination
+ have floating point versions.
+
+ \snippet code/src_gui_painting_qpainter.cpp floatBased
+
+ These are often used in combination
with the \l {RenderHint}{QPainter::Antialiasing} render hint.
+ \snippet code/src_gui_painting_qpainter.cpp renderHint
+
\table 100%
\row
+ \li Comparing concentric circles with int and float, and with or without
+ anti-aliased rendering. Using the floating point precision versions
+ produces evenly spaced rings. Anti-aliased rendering results in
+ smooth circles.
\li \inlineimage qpainter-concentriccircles.png
- \li
- \b {Concentric Circles Example}
-
- The \l {painting/concentriccircles}{Concentric Circles} example
- shows the improved rendering quality that can be obtained using
- floating point precision and anti-aliasing when drawing custom
- widgets.
-
- The application's main window displays several widgets which are
- drawn using the various combinations of precision and
- anti-aliasing.
-
\endtable
The RenderHint enum specifies flags to QPainter that may or may
@@ -1223,7 +1200,7 @@ void QPainterPrivate::updateState(QPainterState *newState)
\li \inlineimage qpainter-affinetransformations.png
\endtable
- All the tranformation operations operate on the transformation
+ All the transformation operations operate on the transformation
worldTransform(). A matrix transforms a point in the plane to another
point. For more information about the transformation matrix, see
the \l {Coordinate System} and QTransform documentation.
@@ -1434,8 +1411,14 @@ void QPainterPrivate::updateState(QPainterState *newState)
JPEG compression.
This value was added in Qt 5.13.
+ \value NonCosmeticBrushPatterns When painting with a brush with one of the predefined pattern
+ styles, transform the pattern too, along with the object being painted. The default is to treat
+ the pattern as cosmetic, so that the pattern pixels will map directly to device pixels,
+ independently of any active transformations.
+ This value was added in Qt 6.4.
+
\sa renderHints(), setRenderHint(), {QPainter#Rendering
- Quality}{Rendering Quality}, {Concentric Circles Example}
+ Quality}{Rendering Quality}
*/
@@ -1631,9 +1614,8 @@ void QPainter::restore()
tmp->clipPath = QPainterPath();
d->engine->updateState(*tmp);
// replay the list of clip states,
- for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) {
+ for (const QPainterClipInfo &info : std::as_const(d->state->clipInfo)) {
tmp->matrix = info.matrix;
- tmp->matrix *= d->state->redirectionMatrix;
tmp->clipOperation = info.operation;
if (info.clipType == QPainterClipInfo::RectClip) {
tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
@@ -1783,9 +1765,12 @@ bool QPainter::begin(QPaintDevice *pd)
qWarning("QPainter::begin: Cannot paint on a null image");
qt_cleanup_painter_state(d);
return false;
- } else if (img->format() == QImage::Format_Indexed8) {
- // Painting on indexed8 images is not supported.
- qWarning("QPainter::begin: Cannot paint on an image with the QImage::Format_Indexed8 format");
+ } else if (img->format() == QImage::Format_Indexed8 ||
+ img->format() == QImage::Format_CMYK8888) {
+ // Painting on these formats is not supported.
+ qWarning() << "QPainter::begin: Cannot paint on an image with the"
+ << img->format()
+ << "format";
qt_cleanup_painter_state(d);
return false;
}
@@ -1840,7 +1825,7 @@ bool QPainter::begin(QPaintDevice *pd)
Q_ASSERT(d->engine->isActive());
- if (!d->state->redirectionMatrix.isIdentity() || d->effectiveDevicePixelRatio() > 1)
+ if (!d->state->redirectionMatrix.isIdentity() || !qFuzzyCompare(d->effectiveDevicePixelRatio(), qreal(1.0)))
d->updateMatrix();
Q_ASSERT(d->engine->isActive());
@@ -2493,7 +2478,7 @@ QRegion QPainter::clipRegion() const
const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
// ### Falcon: Use QPainterPath
- for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) {
+ for (const QPainterClipInfo &info : std::as_const(d->state->clipInfo)) {
switch (info.clipType) {
case QPainterClipInfo::RegionClip: {
@@ -2660,7 +2645,7 @@ QRectF QPainter::clipBoundingRect() const
// fast.
QRectF bounds;
bool first = true;
- for (const QPainterClipInfo &info : qAsConst(d->state->clipInfo)) {
+ for (const QPainterClipInfo &info : std::as_const(d->state->clipInfo)) {
QRectF r;
if (info.clipType == QPainterClipInfo::RectClip)
@@ -3039,7 +3024,8 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
return;
}
- if ((!d->state->clipEnabled && op != Qt::NoClip))
+ bool simplifyClipOp = (paintEngine()->type() != QPaintEngine::Picture);
+ if (simplifyClipOp && (!d->state->clipEnabled && op != Qt::NoClip))
op = Qt::ReplaceClip;
if (d->extended) {
@@ -3052,7 +3038,7 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
return;
}
- if (d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
+ if (simplifyClipOp && d->state->clipOperation == Qt::NoClip && op == Qt::IntersectClip)
op = Qt::ReplaceClip;
d->state->clipPath = path;
@@ -3083,12 +3069,9 @@ void QPainter::strokePath(const QPainterPath &path, const QPen &pen)
if (path.isEmpty())
return;
- if (d->extended) {
- const QGradient *g = qpen_brush(pen).gradient();
- if (!g || g->coordinateMode() == QGradient::LogicalMode) {
- d->extended->stroke(qtVectorPathForPath(path), pen);
- return;
- }
+ if (d->extended && !needsEmulation(pen.brush())) {
+ d->extended->stroke(qtVectorPathForPath(path), pen);
+ return;
}
QBrush oldBrush = d->state->brush;
@@ -3126,12 +3109,9 @@ void QPainter::fillPath(const QPainterPath &path, const QBrush &brush)
if (path.isEmpty())
return;
- if (d->extended) {
- const QGradient *g = brush.gradient();
- if (!g || g->coordinateMode() == QGradient::LogicalMode) {
- d->extended->fill(qtVectorPathForPath(path), brush);
- return;
- }
+ if (d->extended && !needsEmulation(brush)) {
+ d->extended->fill(qtVectorPathForPath(path), brush);
+ return;
}
QBrush oldBrush = d->state->brush;
@@ -3922,8 +3902,10 @@ void QPainter::drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius,
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawRoundedRect: Painter not active");
return;
+ }
if (xRadius <= 0 || yRadius <= 0) { // draw normal rectangle
drawRect(rect);
@@ -3984,8 +3966,10 @@ void QPainter::drawEllipse(const QRectF &r)
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawEllipse: Painter not active");
return;
+ }
QRectF rect(r.normalized());
@@ -4025,8 +4009,10 @@ void QPainter::drawEllipse(const QRect &r)
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawEllipse: Painter not active");
return;
+ }
QRect rect(r.normalized());
@@ -4112,8 +4098,10 @@ void QPainter::drawArc(const QRectF &r, int a, int alen)
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawArc: Painter not active");
return;
+ }
QRectF rect = r.normalized();
@@ -4174,8 +4162,10 @@ void QPainter::drawPie(const QRectF &r, int a, int alen)
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawPie: Painter not active");
return;
+ }
if (a > (360*16)) {
a = a % (360*16);
@@ -4243,8 +4233,10 @@ void QPainter::drawChord(const QRectF &r, int a, int alen)
#endif
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawChord: Painter not active");
return;
+ }
QRectF rect = r.normalized();
@@ -5469,9 +5461,13 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText
QStaticTextPrivate *staticText_d =
const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
- if (font() != staticText_d->font) {
+ QFontPrivate *fp = QFontPrivate::get(font());
+ QFontPrivate *stfp = QFontPrivate::get(staticText_d->font);
+ if (font() != staticText_d->font || fp == nullptr || stfp == nullptr || fp->dpi != stfp->dpi) {
staticText_d->font = font();
staticText_d->needsRelayout = true;
+ } else if (stfp->engineData == nullptr || stfp->engineData->fontCacheId != QFontCache::instance()->id()) {
+ staticText_d->needsRelayout = true;
}
QFontEngine *fe = staticText_d->font.d->engineForScript(QChar::Script_Common);
@@ -5609,7 +5605,7 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
}
engine.itemize();
QScriptLine line;
- line.length = str.length();
+ line.length = str.size();
engine.shapeLine(line);
int nItems = engine.layoutData->items.size();
@@ -5664,7 +5660,7 @@ void QPainter::drawText(const QRect &r, int flags, const QString &str, QRect *br
Q_D(QPainter);
- if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
+ if (!d->engine || str.size() == 0 || pen().style() == Qt::NoPen)
return;
if (!d->extended)
@@ -5751,7 +5747,7 @@ void QPainter::drawText(const QRectF &r, int flags, const QString &str, QRectF *
Q_D(QPainter);
- if (!d->engine || str.length() == 0 || pen().style() == Qt::NoPen)
+ if (!d->engine || str.size() == 0 || pen().style() == Qt::NoPen)
return;
if (!d->extended)
@@ -5870,7 +5866,7 @@ void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption
Q_D(QPainter);
- if (!d->engine || text.length() == 0 || pen().style() == Qt::NoPen)
+ if (!d->engine || text.size() == 0 || pen().style() == Qt::NoPen)
return;
if (!d->extended)
@@ -5910,7 +5906,7 @@ void QPainter::drawText(const QRectF &r, const QString &text, const QTextOption
It ignores the font set on the painter as the text item has one of its own.
The underline and strikeout parameters of the text items font are
- ignored aswell. You'll need to pass in the correct flags to get
+ ignored as well. You'll need to pass in the correct flags to get
underlining and strikeout.
*/
@@ -5918,7 +5914,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen)
{
const qreal radiusBase = qMax(qreal(1), maxRadius);
- QString key = QLatin1String("WaveUnderline-")
+ QString key = "WaveUnderline-"_L1
% pen.color().name()
% HexString<qreal>(radiusBase)
% HexString<qreal>(pen.widthF());
@@ -6361,7 +6357,7 @@ QRectF QPainter::boundingRect(const QRectF &r, const QString &text, const QTextO
{
Q_D(QPainter);
- if (!d->engine || text.length() == 0)
+ if (!d->engine || text.size() == 0)
return QRectF(r.x(),r.y(), 0,0);
QRectF br;
@@ -6526,8 +6522,10 @@ void QPainter::drawPicture(const QPointF &p, const QPicture &picture)
{
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::drawPicture: Painter not active");
return;
+ }
if (!d->extended)
d->updateState(d->state);
@@ -6638,15 +6636,14 @@ void QPainter::fillRect(const QRectF &r, const QBrush &brush)
{
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::fillRect: Painter not active");
return;
+ }
- if (d->extended) {
- const QGradient *g = brush.gradient();
- if (!g || g->coordinateMode() == QGradient::LogicalMode) {
- d->extended->fillRect(r, brush);
- return;
- }
+ if (d->extended && !needsEmulation(brush)) {
+ d->extended->fillRect(r, brush);
+ return;
}
QPen oldPen = pen();
@@ -6676,15 +6673,14 @@ void QPainter::fillRect(const QRect &r, const QBrush &brush)
{
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::fillRect: Painter not active");
return;
+ }
- if (d->extended) {
- const QGradient *g = brush.gradient();
- if (!g || g->coordinateMode() == QGradient::LogicalMode) {
- d->extended->fillRect(r, brush);
- return;
- }
+ if (d->extended && !needsEmulation(brush)) {
+ d->extended->fillRect(r, brush);
+ return;
}
QPen oldPen = pen();
@@ -6717,8 +6713,10 @@ void QPainter::fillRect(const QRect &r, const QColor &color)
{
Q_D(QPainter);
- if (!d->engine)
+ if (!d->engine) {
+ qWarning("QPainter::fillRect: Painter not active");
return;
+ }
if (d->extended) {
d->extended->fillRect(r, color);
@@ -7157,19 +7155,19 @@ start_lengthVariant:
// compatible behaviour to the old implementation. Replace
// tabs by spaces
int old_offset = offset;
- for (; offset < text.length(); offset++) {
+ for (; offset < text.size(); offset++) {
QChar chr = text.at(offset);
- if (chr == QLatin1Char('\r') || (singleline && chr == QLatin1Char('\n'))) {
- text[offset] = QLatin1Char(' ');
- } else if (chr == QLatin1Char('\n')) {
+ if (chr == u'\r' || (singleline && chr == u'\n')) {
+ text[offset] = u' ';
+ } else if (chr == u'\n') {
text[offset] = QChar::LineSeparator;
- } else if (chr == QLatin1Char('&')) {
+ } else if (chr == u'&') {
++maxUnderlines;
- } else if (chr == QLatin1Char('\t')) {
+ } else if (chr == u'\t') {
if (!expandtabs) {
- text[offset] = QLatin1Char(' ');
+ text[offset] = u' ';
} else if (!tabarraylen && !tabstops) {
- tabstops = qRound(fm.horizontalAdvance(QLatin1Char('x'))*8);
+ tabstops = qRound(fm.horizontalAdvance(u'x')*8);
}
} else if (chr == u'\x9c') {
// string with multiple length variants
@@ -7186,13 +7184,13 @@ start_lengthVariant:
QChar *cin = cout;
int l = length;
while (l) {
- if (*cin == QLatin1Char('&')) {
+ if (*cin == u'&') {
++cin;
--length;
--l;
if (!l)
break;
- if (*cin != QLatin1Char('&') && !hidemnmemonic && !(tf & Qt::TextDontPrint)) {
+ if (*cin != u'&' && !hidemnmemonic && !(tf & Qt::TextDontPrint)) {
QTextLayout::FormatRange range;
range.start = cout - cout0;
range.length = 1;
@@ -7200,9 +7198,9 @@ start_lengthVariant:
underlineFormats.append(range);
}
#ifdef Q_OS_MAC
- } else if (hidemnmemonic && *cin == QLatin1Char('(') && l >= 4 &&
- cin[1] == QLatin1Char('&') && cin[2] != QLatin1Char('&') &&
- cin[3] == QLatin1Char(')')) {
+ } else if (hidemnmemonic && *cin == u'(' && l >= 4 &&
+ cin[1] == u'&' && cin[2] != u'&' &&
+ cin[3] == u')') {
int n = 0;
while ((cout - n) > cout0 && (cout - n - 1)->isSpace())
++n;
@@ -8167,3 +8165,5 @@ void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivat
}
QT_END_NAMESPACE
+
+#include "moc_qpainter.cpp"
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index 4c854e0026..7bcacb4bca 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTER_H
#define QPAINTER_H
@@ -48,6 +12,7 @@
#include <QtGui/qpixmap.h>
#include <QtGui/qimage.h>
#include <QtGui/qtextoption.h>
+#include <memory>
#ifndef QT_INCLUDE_COMPAT
#include <QtGui/qpolygon.h>
@@ -89,8 +54,9 @@ public:
SmoothPixmapTransform = 0x04,
VerticalSubpixelPositioning = 0x08,
LosslessImageRendering = 0x40,
+ NonCosmeticBrushPatterns = 0x80
};
- Q_FLAG(RenderHint)
+ Q_ENUM(RenderHint)
Q_DECLARE_FLAGS(RenderHints, RenderHint)
Q_FLAG(RenderHints)
@@ -438,7 +404,7 @@ public:
void setRenderHint(RenderHint hint, bool on = true);
void setRenderHints(RenderHints hints, bool on = true);
RenderHints renderHints() const;
- inline bool testRenderHint(RenderHint hint) const { return renderHints() & hint; }
+ inline bool testRenderHint(RenderHint hint) const { return bool(renderHints() & hint); }
QPaintEngine *paintEngine() const;
@@ -448,7 +414,7 @@ public:
private:
Q_DISABLE_COPY(QPainter)
- QScopedPointer<QPainterPrivate> d_ptr;
+ std::unique_ptr<QPainterPrivate> d_ptr;
friend class QWidget;
friend class QFontEngine;
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 7f5fe1a6c5..0ddd78fb2a 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTER_P_H
#define QPAINTER_P_H
@@ -252,7 +216,7 @@ public:
static QPainterPrivate *get(QPainter *painter)
{
- return painter->d_ptr.data();
+ return painter->d_ptr.get();
}
QTransform viewTransform() const;
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 6042106399..8d23d167b0 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpainterpath.h"
#include "qpainterpath_p.h"
@@ -553,10 +517,8 @@ QPainterPath::QPainterPath(const QPainterPath &other) = default;
*/
QPainterPath::QPainterPath(const QPointF &startPoint)
- : d_ptr(new QPainterPathPrivate)
+ : d_ptr(new QPainterPathPrivate(startPoint))
{
- Element e = { startPoint.x(), startPoint.y(), MoveToElement };
- d_func()->elements << e;
}
void QPainterPath::detach()
@@ -1171,6 +1133,9 @@ void QPainterPath::addEllipse(const QRectF &boundingRect)
that the left end of the text's baseline lies at the specified \a
point.
+ Some fonts may yield overlapping subpaths and will require the
+ \c Qt::WindingFill fill rule for correct rendering.
+
\table 100%
\row
\li \inlineimage qpainterpath-addtext.png
@@ -1179,7 +1144,7 @@ void QPainterPath::addEllipse(const QRectF &boundingRect)
\endtable
\sa QPainter::drawText(), {QPainterPath#Composing a
- QPainterPath}{Composing a QPainterPath}
+ QPainterPath}{Composing a QPainterPath}, setFillRule()
*/
void QPainterPath::addText(const QPointF &point, const QFont &f, const QString &text)
{
@@ -1222,7 +1187,7 @@ void QPainterPath::addText(const QPointF &point, const QFont &f, const QString &
if (si.analysis.flags < QScriptAnalysis::TabOrObject) {
QGlyphLayout glyphs = eng->shapedGlyphs(&si);
- QFontEngine *fe = f.d->engineForScript(si.analysis.script);
+ QFontEngine *fe = eng->fontEngine(si);
Q_ASSERT(fe);
fe->addOutlineToPath(x, y, glyphs, this,
si.analysis.bidiLevel % 2
@@ -1524,7 +1489,7 @@ QRectF QPainterPath::controlPointRect() const
bool QPainterPath::isEmpty() const
{
- return !d_ptr || (d_ptr->elements.size() == 1 && d_ptr->elements.first().type == MoveToElement);
+ return !d_ptr || (d_ptr->elements.size() == 1 && d_ptr->elements.constFirst().type == MoveToElement);
}
/*!
@@ -2126,7 +2091,7 @@ bool QPainterPath::intersects(const QRectF &rect) const
Q_D(QPainterPath);
- // Check if the rectangle surounds any subpath...
+ // Check if the rectangle surrounds any subpath...
for (int i=0; i<d->elements.size(); ++i) {
const Element &e = d->elements.at(i);
if (e.type == QPainterPath::MoveToElement && rect.contains(e))
@@ -2477,14 +2442,14 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
int size;
s >> size;
- if (size == 0)
+ if (size == 0) {
+ p = {};
return s;
+ }
p.ensureData(); // in case if p.d_func() == 0
- if (p.d_func()->elements.size() == 1) {
- Q_ASSERT(p.d_func()->elements.at(0).type == QPainterPath::MoveToElement);
- p.d_func()->elements.clear();
- }
+ p.detach();
+ p.d_func()->elements.clear();
for (int i=0; i<size; ++i) {
int type;
double x, y;
@@ -2507,9 +2472,7 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
s >> fillRule;
Q_ASSERT(fillRule == Qt::OddEvenFill || fillRule == Qt::WindingFill);
p.d_func()->fillRule = Qt::FillRule(fillRule);
- p.d_func()->dirtyBounds = true;
- p.d_func()->dirtyControlBounds = true;
- if (errorDetected)
+ if (errorDetected || p.d_func()->elements.isEmpty())
p = QPainterPath(); // Better than to return path with possibly corrupt datastructure, which would likely cause crash
return s;
}
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index 7dadc4084d..4caf1aa5c0 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTERPATH_H
#define QPAINTERPATH_H
diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h
index 5a07e3dc8d..a07b6cca37 100644
--- a/src/gui/painting/qpainterpath_p.h
+++ b/src/gui/painting/qpainterpath_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTERPATH_P_H
#define QPAINTERPATH_P_H
@@ -155,6 +119,21 @@ public:
{
}
+ QPainterPathPrivate(QPointF startPoint)
+ : QSharedData(),
+ elements{ { startPoint.x(), startPoint.y(), QPainterPath::MoveToElement } },
+ cStart(0),
+ fillRule(Qt::OddEvenFill),
+ bounds(startPoint, QSizeF(0, 0)),
+ controlBounds(startPoint, QSizeF(0, 0)),
+ require_moveTo(false),
+ dirtyBounds(false),
+ dirtyControlBounds(false),
+ convex(false),
+ pathConverter(nullptr)
+ {
+ }
+
QPainterPathPrivate(const QPainterPathPrivate &other) noexcept
: QSharedData(other),
elements(other.elements),
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index b3521f41ac..10a0639b53 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpathclipper_p.h"
@@ -99,6 +63,7 @@ struct QIntersection
QPointF pos;
};
+Q_DECLARE_TYPEINFO(QIntersection, Q_PRIMITIVE_TYPE);
class QIntersectionFinder
{
@@ -685,7 +650,8 @@ int QKdPointTree::build(int begin, int end, int depth)
}
}
- qSwap(m_nodes.at(last), m_nodes.at(begin));
+ if (last != begin)
+ qSwap(m_nodes.at(last), m_nodes.at(begin));
if (last > begin)
m_nodes.at(last).left = &m_nodes.at(build(begin, last, depth + 1));
diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h
index 6f712c396e..f13b96e0ef 100644
--- a/src/gui/painting/qpathclipper_p.h
+++ b/src/gui/painting/qpathclipper_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPATHCLIPPER_P_H
#define QPATHCLIPPER_P_H
@@ -115,6 +79,7 @@ public:
qreal x;
qreal y;
};
+Q_DECLARE_TYPEINFO(QPathVertex, Q_PRIMITIVE_TYPE);
class QPathEdge
{
@@ -156,8 +121,9 @@ public:
int vertex(Direction direction) const;
private:
- int m_next[2][2];
+ int m_next[2][2] = { { -1, -1 }, { -1, -1 } };
};
+Q_DECLARE_TYPEINFO(QPathEdge, Q_PRIMITIVE_TYPE);
class QPathSegments
{
@@ -171,6 +137,7 @@ public:
return t < o.t;
}
};
+ friend class QTypeInfo<Intersection>;
struct Segment {
Segment(int pathId, int vertexA, int vertexB)
@@ -192,6 +159,7 @@ public:
QRectF bounds;
};
+ friend class QTypeInfo<Segment>;
QPathSegments(int reserve);
@@ -223,6 +191,8 @@ private:
int m_pathId;
};
+Q_DECLARE_TYPEINFO(QPathSegments::Intersection, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QPathSegments::Segment, Q_PRIMITIVE_TYPE);
class Q_AUTOTEST_EXPORT QWingedEdge
{
@@ -296,10 +266,6 @@ inline QPathEdge::QPathEdge(int a, int b)
, angle(0)
, invAngle(0)
{
- m_next[0][0] = -1;
- m_next[1][0] = -1;
- m_next[0][0] = -1;
- m_next[1][0] = -1;
}
inline int QPathEdge::next(Traversal traversal, Direction direction) const
diff --git a/src/gui/painting/qpathsimplifier.cpp b/src/gui/painting/qpathsimplifier.cpp
index 74313c9ca2..969308f0bb 100644
--- a/src/gui/painting/qpathsimplifier.cpp
+++ b/src/gui/painting/qpathsimplifier.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpathsimplifier_p.h"
@@ -44,7 +8,9 @@
#include <QtCore/qpoint.h>
#include <QtCore/qalgorithms.h>
-#include <private/qopengl_p.h>
+#if QT_CONFIG(opengl)
+# include <private/qopengl_p.h>
+#endif
#include <private/qrbtree_p.h>
QT_BEGIN_NAMESPACE
@@ -339,6 +305,7 @@ private:
Type type;
Element *element;
};
+ friend class QTypeInfo<Event>;
typedef QRBTree<Element *>::Node RBNode;
typedef BoundingVolumeHierarchy::Node BVHNode;
@@ -377,6 +344,10 @@ private:
uint m_hints;
};
+} // unnamed namespace
+
+Q_DECLARE_TYPEINFO(PathSimplifier::Event, Q_PRIMITIVE_TYPE);
+
inline PathSimplifier::BoundingVolumeHierarchy::BoundingVolumeHierarchy()
: root(nullptr)
, nodeBlock(nullptr)
@@ -1650,9 +1621,6 @@ void PathSimplifier::sortEvents(Event *events, int count)
}
}
-} // end anonymous namespace
-
-
void qSimplifyPath(const QVectorPath &path, QDataBuffer<QPoint> &vertices,
QDataBuffer<quint32> &indices, const QTransform &matrix)
{
@@ -1667,3 +1635,5 @@ void qSimplifyPath(const QPainterPath &path, QDataBuffer<QPoint> &vertices,
QT_END_NAMESPACE
+
+#undef Q_FIXED_POINT_SCALE
diff --git a/src/gui/painting/qpathsimplifier_p.h b/src/gui/painting/qpathsimplifier_p.h
index 6c0062c592..b20b6370b3 100644
--- a/src/gui/painting/qpathsimplifier_p.h
+++ b/src/gui/painting/qpathsimplifier_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPATHSIMPLIFIER_P_H
#define QPATHSIMPLIFIER_P_H
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 55a1aa0242..38f2a9b803 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpdf_p.h"
@@ -43,6 +7,7 @@
#include "qplatformdefs.h"
+#include <private/qcmyk_p.h>
#include <private/qfont_p.h>
#include <private/qmath_p.h>
#include <private/qpainter_p.h>
@@ -78,7 +43,9 @@ static void initResources()
QT_BEGIN_NAMESPACE
-inline QPaintEngine::PaintEngineFeatures qt_pdf_decide_features()
+using namespace Qt::StringLiterals;
+
+constexpr QPaintEngine::PaintEngineFeatures qt_pdf_decide_features()
{
QPaintEngine::PaintEngineFeatures f = QPaintEngine::AllFeatures;
f &= ~(QPaintEngine::PorterDuff
@@ -133,7 +100,7 @@ static void removeTransparencyFromBrush(QBrush &brush)
const char *qt_real_to_string(qreal val, char *buf) {
const char *ret = buf;
- if (qIsNaN(val)) {
+ if (!qIsFinite(val) || std::abs(val) > std::numeric_limits<quint32>::max()) {
*(buf++) = '0';
*(buf++) = ' ';
*buf = 0;
@@ -144,8 +111,8 @@ const char *qt_real_to_string(qreal val, char *buf) {
*(buf++) = '-';
val = -val;
}
- unsigned int ival = (unsigned int) val;
- qreal frac = val - (qreal)ival;
+ qreal frac = std::modf(val, &val);
+ quint32 ival(val);
int ifrac = (int)(frac * 1000000000);
if (ifrac == 1000000000) {
@@ -304,13 +271,6 @@ namespace QPdf {
dev->open(QIODevice::ReadWrite | QIODevice::Truncate);
}
- void ByteStream::constructor_helper(QByteArray *ba)
- {
- delete dev;
- dev = new QBuffer(ba);
- dev->open(QIODevice::ReadWrite);
- }
-
void ByteStream::prepareBuffer()
{
Q_ASSERT(!dev->isSequential());
@@ -319,16 +279,17 @@ namespace QPdf {
&& size > maxMemorySize()) {
// Switch to file backing.
QTemporaryFile *newFile = new QTemporaryFile;
- newFile->open();
- dev->reset();
- while (!dev->atEnd()) {
- QByteArray buf = dev->read(chunkSize());
- newFile->write(buf);
+ if (newFile->open()) {
+ dev->reset();
+ while (!dev->atEnd()) {
+ QByteArray buf = dev->read(chunkSize());
+ newFile->write(buf);
+ }
+ delete dev;
+ dev = newFile;
+ ba.clear();
+ fileBackingActive = true;
}
- delete dev;
- dev = newFile;
- ba.clear();
- fileBackingActive = true;
}
if (dev->pos() != size) {
dev->seek(size);
@@ -856,14 +817,14 @@ void QPdfEngine::drawRects (const QRectF *rects, int rectCount)
if (!d->hasPen && !d->hasBrush)
return;
- if (d->simplePen || !d->hasPen) {
- // draw strokes natively in this case for better output
- if (!d->simplePen && !d->stroker.matrix.isIdentity())
+ if ((d->simplePen && !d->needsTransform) || !d->hasPen) {
+ // draw natively in this case for better output
+ if (!d->hasPen && d->needsTransform) // i.e. this is just a fillrect
*d->currentPage << "q\n" << QPdf::generateMatrix(d->stroker.matrix);
for (int i = 0; i < rectCount; ++i)
*d->currentPage << rects[i].x() << rects[i].y() << rects[i].width() << rects[i].height() << "re\n";
*d->currentPage << (d->hasPen ? (d->hasBrush ? "B\n" : "S\n") : "f\n");
- if (!d->simplePen && !d->stroker.matrix.isIdentity())
+ if (!d->hasPen && d->needsTransform)
*d->currentPage << "Q\n";
} else {
QPainterPath p;
@@ -920,7 +881,8 @@ void QPdfEngine::drawPath (const QPainterPath &p)
if (d->simplePen) {
// draw strokes natively in this case for better output
- *d->currentPage << QPdf::generatePath(p, QTransform(), d->hasBrush ? QPdf::FillAndStrokePath : QPdf::StrokePath);
+ *d->currentPage << QPdf::generatePath(p, d->needsTransform ? d->stroker.matrix : QTransform(),
+ d->hasBrush ? QPdf::FillAndStrokePath : QPdf::StrokePath);
} else {
if (d->hasBrush)
*d->currentPage << QPdf::generatePath(p, d->stroker.matrix, QPdf::FillPath);
@@ -967,7 +929,7 @@ void QPdfEngine::drawPixmap (const QRectF &rectangle, const QPixmap &pixmap, con
*d->currentPage
<< QPdf::generateMatrix(QTransform(rectangle.width() / sr.width(), 0, 0, rectangle.height() / sr.height(),
- rectangle.x(), rectangle.y()) * (d->simplePen ? QTransform() : d->stroker.matrix));
+ rectangle.x(), rectangle.y()) * (!d->needsTransform ? QTransform() : d->stroker.matrix));
if (bitmap) {
// set current pen as d->brush
d->brush = d->pen.brush();
@@ -1007,7 +969,7 @@ void QPdfEngine::drawImage(const QRectF &rectangle, const QImage &image, const Q
*d->currentPage
<< QPdf::generateMatrix(QTransform(rectangle.width() / sr.width(), 0, 0, rectangle.height() / sr.height(),
- rectangle.x(), rectangle.y()) * (d->simplePen ? QTransform() : d->stroker.matrix));
+ rectangle.x(), rectangle.y()) * (!d->needsTransform ? QTransform() : d->stroker.matrix));
setBrush();
d->currentPage->streamImage(im.width(), im.height(), object);
*d->currentPage << "Q\n";
@@ -1056,7 +1018,7 @@ void QPdfEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
}
*d->currentPage << "q\n";
- if (!d->simplePen)
+ if (d->needsTransform)
*d->currentPage << QPdf::generateMatrix(d->stroker.matrix);
bool hp = d->hasPen;
@@ -1114,6 +1076,9 @@ void QPdfEngine::updateState(const QPaintEngineState &state)
QPaintEngine::DirtyFlags flags = state.state();
+ if (flags & DirtyHints)
+ flags |= DirtyBrush;
+
if (flags & DirtyTransform)
d->stroker.matrix = state.transform();
@@ -1135,12 +1100,12 @@ void QPdfEngine::updateState(const QPaintEngineState &state)
d->pen = state.pen();
}
d->hasPen = d->pen.style() != Qt::NoPen;
+ bool oldCosmetic = d->stroker.cosmeticPen;
d->stroker.setPen(d->pen, state.renderHints());
QBrush penBrush = d->pen.brush();
- bool cosmeticPen = d->pen.isCosmetic();
bool oldSimple = d->simplePen;
- d->simplePen = (d->hasPen && !cosmeticPen && (penBrush.style() == Qt::SolidPattern) && penBrush.isOpaque() && d->opacity == 1.0);
- if (oldSimple != d->simplePen)
+ d->simplePen = (d->hasPen && (penBrush.style() == Qt::SolidPattern) && penBrush.isOpaque() && d->opacity == 1.0);
+ if (oldSimple != d->simplePen || oldCosmetic != d->stroker.cosmeticPen)
flags |= DirtyTransform;
} else if (flags & DirtyHints) {
d->stroker.setPen(d->pen, state.renderHints());
@@ -1224,8 +1189,13 @@ void QPdfEngine::setupGraphicsState(QPaintEngine::DirtyFlags flags)
if (flags & DirtyTransform) {
*d->currentPage << "q\n";
- if (d->simplePen && !d->stroker.matrix.isIdentity())
- *d->currentPage << QPdf::generateMatrix(d->stroker.matrix);
+ d->needsTransform = false;
+ if (!d->stroker.matrix.isIdentity()) {
+ if (d->simplePen && !d->stroker.cosmeticPen)
+ *d->currentPage << QPdf::generateMatrix(d->stroker.matrix);
+ else
+ d->needsTransform = true; // I.e. page-wide xf not set, local xf needed
+ }
}
if (flags & DirtyBrush)
setBrush();
@@ -1241,20 +1211,18 @@ void QPdfEngine::updateClipPath(const QPainterPath &p, Qt::ClipOperation op)
QPainterPath path = d->stroker.matrix.map(p);
//qDebug() << "updateClipPath: " << d->stroker.matrix << p.boundingRect() << path.boundingRect() << op;
- if (op == Qt::NoClip) {
+ switch (op) {
+ case Qt::NoClip:
d->clipEnabled = false;
d->clips.clear();
- } else if (op == Qt::ReplaceClip) {
+ break;
+ case Qt::ReplaceClip:
d->clips.clear();
d->clips.append(path);
- } else if (op == Qt::IntersectClip) {
- d->clips.append(path);
- } else { // UniteClip
- // ask the painter for the current clipping path. that's the easiest solution
- path = painter()->clipPath();
- path = d->stroker.matrix.map(path);
- d->clips.clear();
+ break;
+ case Qt::IntersectClip:
d->clips.append(path);
+ break;
}
}
@@ -1266,17 +1234,8 @@ void QPdfEngine::setPen()
QBrush b = d->pen.brush();
Q_ASSERT(b.style() == Qt::SolidPattern && b.isOpaque());
- QColor rgba = b.color();
- if (d->grayscale) {
- qreal gray = qGray(rgba.rgba())/255.;
- *d->currentPage << gray << gray << gray;
- } else {
- *d->currentPage << rgba.redF()
- << rgba.greenF()
- << rgba.blueF();
- }
+ d->writeColor(QPdfEnginePrivate::ColorDomain::Stroking, b.color());
*d->currentPage << "SCN\n";
-
*d->currentPage << d->pen.widthF() << "w ";
int pdfCapStyle = 0;
@@ -1330,18 +1289,9 @@ void QPdfEngine::setBrush()
if (!patternObject && !specifyColor)
return;
- *d->currentPage << (patternObject ? "/PCSp cs " : "/CSp cs ");
- if (specifyColor) {
- QColor rgba = d->brush.color();
- if (d->grayscale) {
- qreal gray = qGray(rgba.rgba())/255.;
- *d->currentPage << gray << gray << gray;
- } else {
- *d->currentPage << rgba.redF()
- << rgba.greenF()
- << rgba.blueF();
- }
- }
+ const auto domain = patternObject ? QPdfEnginePrivate::ColorDomain::NonStrokingPattern
+ : QPdfEnginePrivate::ColorDomain::NonStroking;
+ d->writeColor(domain, specifyColor ? d->brush.color() : QColor());
if (patternObject)
*d->currentPage << "/Pat" << patternObject;
*d->currentPage << "scn\n";
@@ -1480,10 +1430,10 @@ int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const
QPdfEnginePrivate::QPdfEnginePrivate()
: clipEnabled(false), allClipped(false), hasPen(true), hasBrush(false), simplePen(false),
- pdfVersion(QPdfEngine::Version_1_4),
+ needsTransform(false), pdfVersion(QPdfEngine::Version_1_4),
+ colorModel(QPdfEngine::ColorModel::Auto),
outDevice(nullptr), ownsDevice(false),
embedFonts(true),
- grayscale(false),
m_pageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(10, 10, 10, 10))
{
initResources();
@@ -1532,13 +1482,17 @@ bool QPdfEngine::begin(QPaintDevice *pdev)
d->xrefPositions.clear();
d->pageRoot = 0;
- d->embeddedfilesRoot = 0;
d->namesRoot = 0;
+ d->destsRoot = 0;
+ d->attachmentsRoot = 0;
d->catalog = 0;
d->info = 0;
d->graphicsState = 0;
- d->patternColorSpace = 0;
+ d->patternColorSpaceRGB = 0;
+ d->patternColorSpaceGrayscale = 0;
+ d->patternColorSpaceCMYK = 0;
d->simplePen = false;
+ d->needsTransform = false;
d->pages.clear();
d->imageCache.clear();
@@ -1569,6 +1523,7 @@ bool QPdfEngine::end()
d->outDevice = nullptr;
}
+ d->destCache.clear();
d->fileCache.clear();
setActive(false);
@@ -1617,10 +1572,7 @@ void QPdfEnginePrivate::writeHeader()
catalog = addXrefEntry(-1);
pageRoot = requestObject();
- if (!fileCache.isEmpty()) {
- namesRoot = requestObject();
- embeddedfilesRoot = requestObject();
- }
+ namesRoot = requestObject();
// catalog
{
@@ -1628,11 +1580,8 @@ void QPdfEnginePrivate::writeHeader()
QPdf::ByteStream s(&catalog);
s << "<<\n"
<< "/Type /Catalog\n"
- << "/Pages " << pageRoot << "0 R\n";
-
- // Embedded files, if any
- if (!fileCache.isEmpty())
- s << "/Names " << embeddedfilesRoot << "0 R\n";
+ << "/Pages " << pageRoot << "0 R\n"
+ << "/Names " << namesRoot << "0 R\n";
if (pdfVersion == QPdfEngine::Version_A1b || !xmpDocumentMetadata.isEmpty())
s << "/Metadata " << metaDataObj << "0 R\n";
@@ -1646,12 +1595,6 @@ void QPdfEnginePrivate::writeHeader()
write(catalog);
}
- if (!fileCache.isEmpty()) {
- addXrefEntry(embeddedfilesRoot);
- xprintf("<</EmbeddedFiles %d 0 R>>\n"
- "endobj\n", namesRoot);
- }
-
// graphics state
graphicsState = addXrefEntry(-1);
xprintf("<<\n"
@@ -1665,10 +1608,108 @@ void QPdfEnginePrivate::writeHeader()
">>\n"
"endobj\n");
- // color space for pattern
- patternColorSpace = addXrefEntry(-1);
+ // color spaces for pattern
+ patternColorSpaceRGB = addXrefEntry(-1);
xprintf("[/Pattern /DeviceRGB]\n"
"endobj\n");
+ patternColorSpaceGrayscale = addXrefEntry(-1);
+ xprintf("[/Pattern /DeviceGray]\n"
+ "endobj\n");
+ patternColorSpaceCMYK = addXrefEntry(-1);
+ xprintf("[/Pattern /DeviceCMYK]\n"
+ "endobj\n");
+}
+
+QPdfEngine::ColorModel QPdfEnginePrivate::colorModelForColor(const QColor &color) const
+{
+ switch (colorModel) {
+ case QPdfEngine::ColorModel::RGB:
+ case QPdfEngine::ColorModel::Grayscale:
+ case QPdfEngine::ColorModel::CMYK:
+ return colorModel;
+ case QPdfEngine::ColorModel::Auto:
+ switch (color.spec()) {
+ case QColor::Invalid:
+ case QColor::Rgb:
+ case QColor::Hsv:
+ case QColor::Hsl:
+ case QColor::ExtendedRgb:
+ return QPdfEngine::ColorModel::RGB;
+ case QColor::Cmyk:
+ return QPdfEngine::ColorModel::CMYK;
+ }
+
+ break;
+ }
+
+ Q_UNREACHABLE_RETURN(QPdfEngine::ColorModel::RGB);
+}
+
+void QPdfEnginePrivate::writeColor(ColorDomain domain, const QColor &color)
+{
+ // Switch to the right colorspace.
+ // For simplicity: do it even if it redundant (= already in that colorspace)
+ const QPdfEngine::ColorModel actualColorModel = colorModelForColor(color);
+
+ switch (actualColorModel) {
+ case QPdfEngine::ColorModel::RGB:
+ switch (domain) {
+ case ColorDomain::Stroking:
+ *currentPage << "/CSp CS\n"; break;
+ case ColorDomain::NonStroking:
+ *currentPage << "/CSp cs\n"; break;
+ case ColorDomain::NonStrokingPattern:
+ *currentPage << "/PCSp cs\n"; break;
+ }
+ break;
+ case QPdfEngine::ColorModel::Grayscale:
+ switch (domain) {
+ case ColorDomain::Stroking:
+ *currentPage << "/CSpg CS\n"; break;
+ case ColorDomain::NonStroking:
+ *currentPage << "/CSpg cs\n"; break;
+ case ColorDomain::NonStrokingPattern:
+ *currentPage << "/PCSpg cs\n"; break;
+ }
+ break;
+ case QPdfEngine::ColorModel::CMYK:
+ switch (domain) {
+ case ColorDomain::Stroking:
+ *currentPage << "/CSpcmyk CS\n"; break;
+ case ColorDomain::NonStroking:
+ *currentPage << "/CSpcmyk cs\n"; break;
+ case ColorDomain::NonStrokingPattern:
+ *currentPage << "/PCSpcmyk cs\n"; break;
+ }
+ break;
+ case QPdfEngine::ColorModel::Auto:
+ Q_UNREACHABLE_RETURN();
+ }
+
+ // If we also have a color specified, write it out.
+ if (!color.isValid())
+ return;
+
+ switch (actualColorModel) {
+ case QPdfEngine::ColorModel::RGB:
+ *currentPage << color.redF()
+ << color.greenF()
+ << color.blueF();
+ break;
+ case QPdfEngine::ColorModel::Grayscale: {
+ const qreal gray = qGray(color.rgba()) / 255.;
+ *currentPage << gray;
+ break;
+ }
+ case QPdfEngine::ColorModel::CMYK:
+ *currentPage << color.cyanF()
+ << color.magentaF()
+ << color.yellowF()
+ << color.blackF();
+ break;
+ case QPdfEngine::ColorModel::Auto:
+ Q_UNREACHABLE_RETURN();
+ }
}
void QPdfEnginePrivate::writeInfo()
@@ -1728,12 +1769,13 @@ int QPdfEnginePrivate::writeXmpDcumentMetaData()
else if (offset > 0)
tzStr = QString::asprintf("+%02d:%02d", hours , mins);
else
- tzStr = QLatin1String("Z");
+ tzStr = "Z"_L1;
const QString metaDataDate = timeStr + tzStr;
- QFile metaDataFile(QLatin1String(":/qpdf/qpdfa_metadata.xml"));
- metaDataFile.open(QIODevice::ReadOnly);
+ QFile metaDataFile(":/qpdf/qpdfa_metadata.xml"_L1);
+ bool ok = metaDataFile.open(QIODevice::ReadOnly);
+ Q_ASSERT(ok);
metaDataContent = QString::fromUtf8(metaDataFile.readAll()).arg(producer.toHtmlEscaped(),
title.toHtmlEscaped(),
creator.toHtmlEscaped(),
@@ -1758,8 +1800,9 @@ int QPdfEnginePrivate::writeOutputIntent()
{
const int colorProfile = addXrefEntry(-1);
{
- QFile colorProfileFile(QLatin1String(":/qpdf/sRGB2014.icc"));
- colorProfileFile.open(QIODevice::ReadOnly);
+ QFile colorProfileFile(":/qpdf/sRGB2014.icc"_L1);
+ bool ok = colorProfileFile.open(QIODevice::ReadOnly);
+ Q_ASSERT(ok);
const QByteArray colorProfileData = colorProfileFile.readAll();
QByteArray data;
@@ -1819,6 +1862,39 @@ void QPdfEnginePrivate::writePageRoot()
"endobj\n");
}
+void QPdfEnginePrivate::writeDestsRoot()
+{
+ if (destCache.isEmpty())
+ return;
+
+ QHash<QString, int> destObjects;
+ QByteArray xs, ys;
+ for (const DestInfo &destInfo : std::as_const(destCache)) {
+ int destObj = addXrefEntry(-1);
+ xs.setNum(static_cast<double>(destInfo.coords.x()), 'f');
+ ys.setNum(static_cast<double>(destInfo.coords.y()), 'f');
+ xprintf("[%d 0 R /XYZ %s %s 0]\n", destInfo.pageObj, xs.constData(), ys.constData());
+ xprintf("endobj\n");
+ destObjects.insert(destInfo.anchor, destObj);
+ }
+
+ // names
+ destsRoot = addXrefEntry(-1);
+ QStringList anchors = destObjects.keys();
+ anchors.sort();
+ xprintf("<<\n/Limits [");
+ printString(anchors.constFirst());
+ xprintf(" ");
+ printString(anchors.constLast());
+ xprintf("]\n/Names [\n");
+ for (const QString &anchor : std::as_const(anchors)) {
+ printString(anchor);
+ xprintf(" %d 0 R\n", destObjects[anchor]);
+ }
+ xprintf("]\n>>\n"
+ "endobj\n");
+}
+
void QPdfEnginePrivate::writeAttachmentRoot()
{
if (fileCache.isEmpty())
@@ -1853,13 +1929,12 @@ void QPdfEnginePrivate::writeAttachmentRoot()
, attachmentID);
if (!attachment.mimeType.isEmpty())
xprintf("/Subtype/%s\n",
- attachment.mimeType.replace(QLatin1String("/"),
- QLatin1String("#2F")).toLatin1().constData());
+ attachment.mimeType.replace("/"_L1, "#2F"_L1).toLatin1().constData());
xprintf(">>\nendobj\n");
}
// names
- addXrefEntry(namesRoot);
+ attachmentsRoot = addXrefEntry(-1);
xprintf("<</Names[");
for (int i = 0; i < size; ++i) {
auto attachment = fileCache.at(i);
@@ -1870,6 +1945,21 @@ void QPdfEnginePrivate::writeAttachmentRoot()
"endobj\n");
}
+void QPdfEnginePrivate::writeNamesRoot()
+{
+ addXrefEntry(namesRoot);
+ xprintf("<<\n");
+
+ if (attachmentsRoot)
+ xprintf("/EmbeddedFiles %d 0 R\n", attachmentsRoot);
+
+ if (destsRoot)
+ xprintf("/Dests %d 0 R\n", destsRoot);
+
+ xprintf(">>\n");
+ xprintf("endobj\n");
+}
+
void QPdfEnginePrivate::embedFont(QFontSubset *font)
{
//qDebug() << "embedFont" << font->object_id;
@@ -1963,7 +2053,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
addXrefEntry(toUnicode);
QByteArray touc = font->createToUnicodeMap();
xprintf("<< /Length %d >>\n"
- "stream\n", touc.length());
+ "stream\n", touc.size());
write(touc);
write("\nendstream\n"
"endobj\n");
@@ -1986,7 +2076,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
QByteArray cidSetStream(font->nGlyphs() / 8 + 1, 0);
int byteCounter = 0;
int bitCounter = 0;
- for (int i = 0; i < font->nGlyphs(); ++i) {
+ for (qsizetype i = 0; i < font->nGlyphs(); ++i) {
cidSetStream.data()[byteCounter] |= (1 << (7 - bitCounter));
bitCounter++;
@@ -2067,12 +2157,18 @@ void QPdfEnginePrivate::writePage()
xprintf("<<\n"
"/ColorSpace <<\n"
"/PCSp %d 0 R\n"
+ "/PCSpg %d 0 R\n"
+ "/PCSpcmyk %d 0 R\n"
"/CSp /DeviceRGB\n"
"/CSpg /DeviceGray\n"
+ "/CSpcmyk /DeviceCMYK\n"
">>\n"
"/ExtGState <<\n"
"/GSa %d 0 R\n",
- patternColorSpace, graphicsState);
+ patternColorSpaceRGB,
+ patternColorSpaceGrayscale,
+ patternColorSpaceCMYK,
+ graphicsState);
for (int i = 0; i < currentPage->graphicStates.size(); ++i)
xprintf("/GState%d %d 0 R\n", currentPage->graphicStates.at(i), currentPage->graphicStates.at(i));
@@ -2126,7 +2222,9 @@ void QPdfEnginePrivate::writeTail()
writePage();
writeFonts();
writePageRoot();
+ writeDestsRoot();
writeAttachmentRoot();
+ writeNamesRoot();
addXrefEntry(xrefPositions.size(),false);
xprintf("xref\n"
@@ -2175,7 +2273,7 @@ int QPdfEnginePrivate::addXrefEntry(int object, bool printostr)
return object;
}
-void QPdfEnginePrivate::printString(const QString &string)
+void QPdfEnginePrivate::printString(QStringView string)
{
if (string.isEmpty()) {
write("()");
@@ -2186,9 +2284,9 @@ void QPdfEnginePrivate::printString(const QString &string)
// Unicode UTF-16 with a Unicode byte order mark as the first character
// (0xfeff), with the high-order byte first.
QByteArray array("(\xfe\xff");
- const ushort *utf16 = string.utf16();
+ const char16_t *utf16 = string.utf16();
- for (int i=0; i < string.size(); ++i) {
+ for (qsizetype i = 0; i < string.size(); ++i) {
char part[2] = {char((*(utf16 + i)) >> 8), char((*(utf16 + i)) & 0xff)};
for(int j=0; j < 2; ++j) {
if (part[j] == '(' || part[j] == ')' || part[j] == '\\')
@@ -2305,16 +2403,15 @@ int QPdfEnginePrivate::writeCompressed(const char *src, int len)
{
#ifndef QT_NO_COMPRESS
if (do_compress) {
- uLongf destLen = len + len/100 + 13; // zlib requirement
- Bytef* dest = new Bytef[destLen];
- if (Z_OK == ::compress(dest, &destLen, (const Bytef*) src, (uLongf)len)) {
- stream->writeRawData((const char*)dest, destLen);
+ const QByteArray data = qCompress(reinterpret_cast<const uchar *>(src), len);
+ constexpr qsizetype HeaderSize = 4;
+ if (!data.isNull()) {
+ stream->writeRawData(data.data() + HeaderSize, data.size() - HeaderSize);
+ len = data.size() - HeaderSize;
} else {
qWarning("QPdfStream::writeCompressed: Error in compress()");
- destLen = 0;
+ len = 0;
}
- delete [] dest;
- len = destLen;
} else
#endif
{
@@ -2324,7 +2421,7 @@ int QPdfEnginePrivate::writeCompressed(const char *src, int len)
return len;
}
-int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height, int depth,
+int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height, WriteImageOption option,
int maskObject, int softMaskObject, bool dct, bool isMono)
{
int image = addXrefEntry(-1);
@@ -2334,7 +2431,8 @@ int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height,
"/Width %d\n"
"/Height %d\n", width, height);
- if (depth == 1) {
+ switch (option) {
+ case WriteImageOption::Monochrome:
if (!isMono) {
xprintf("/ImageMask true\n"
"/Decode [1 0]\n");
@@ -2342,10 +2440,21 @@ int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height,
xprintf("/BitsPerComponent 1\n"
"/ColorSpace /DeviceGray\n");
}
- } else {
+ break;
+ case WriteImageOption::Grayscale:
+ xprintf("/BitsPerComponent 8\n"
+ "/ColorSpace /DeviceGray\n");
+ break;
+ case WriteImageOption::RGB:
+ xprintf("/BitsPerComponent 8\n"
+ "/ColorSpace /DeviceRGB\n");
+ break;
+ case WriteImageOption::CMYK:
xprintf("/BitsPerComponent 8\n"
- "/ColorSpace %s\n", (depth == 32) ? "/DeviceRGB" : "/DeviceGray");
+ "/ColorSpace /DeviceCMYK\n");
+ break;
}
+
if (maskObject > 0)
xprintf("/Mask %d 0 R\n", maskObject);
if (softMaskObject > 0)
@@ -2360,7 +2469,7 @@ int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height,
//qDebug("DCT");
xprintf("/Filter /DCTDecode\n>>\nstream\n");
write(data);
- len = data.length();
+ len = data.size();
} else {
if (do_compress)
xprintf("/Filter /FlateDecode\n>>\nstream\n");
@@ -2384,7 +2493,23 @@ struct QGradientBound {
};
Q_DECLARE_TYPEINFO(QGradientBound, Q_PRIMITIVE_TYPE);
-int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha)
+void QPdfEnginePrivate::ShadingFunctionResult::writeColorSpace(QPdf::ByteStream *stream) const
+{
+ *stream << "/ColorSpace ";
+ switch (colorModel) {
+ case QPdfEngine::ColorModel::RGB:
+ *stream << "/DeviceRGB\n"; break;
+ case QPdfEngine::ColorModel::Grayscale:
+ *stream << "/DeviceGray\n"; break;
+ case QPdfEngine::ColorModel::CMYK:
+ *stream << "/DeviceCMYK\n"; break;
+ case QPdfEngine::ColorModel::Auto:
+ Q_UNREACHABLE(); break;
+ }
+}
+
+QPdfEnginePrivate::ShadingFunctionResult
+QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha)
{
QGradientStops stops = gradient->stops();
if (stops.isEmpty()) {
@@ -2396,6 +2521,35 @@ int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from
if (stops.at(stops.size() - 1).first < 1)
stops.append(QGradientStop(1, stops.at(stops.size() - 1).second));
+ // Color to use which colorspace to use
+ const QColor referenceColor = stops.constFirst().second;
+
+ switch (colorModel) {
+ case QPdfEngine::ColorModel::RGB:
+ case QPdfEngine::ColorModel::Grayscale:
+ case QPdfEngine::ColorModel::CMYK:
+ break;
+ case QPdfEngine::ColorModel::Auto: {
+ // Make sure that all the stops have the same color spec
+ // (we don't support anything else)
+ const QColor::Spec referenceSpec = referenceColor.spec();
+ bool warned = false;
+ for (QGradientStop &stop : stops) {
+ if (stop.second.spec() != referenceSpec) {
+ if (!warned) {
+ qWarning("QPdfEngine: unable to create a gradient between colors of different spec");
+ warned = true;
+ }
+ stop.second = stop.second.convertTo(referenceSpec);
+ }
+ }
+ break;
+ }
+ }
+
+ ShadingFunctionResult result;
+ result.colorModel = colorModelForColor(referenceColor);
+
QList<int> functions;
const int numStops = stops.size();
functions.reserve(numStops - 1);
@@ -2411,8 +2565,31 @@ int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from
s << "/C0 [" << stops.at(i).second.alphaF() << "]\n"
"/C1 [" << stops.at(i + 1).second.alphaF() << "]\n";
} else {
- s << "/C0 [" << stops.at(i).second.redF() << stops.at(i).second.greenF() << stops.at(i).second.blueF() << "]\n"
- "/C1 [" << stops.at(i + 1).second.redF() << stops.at(i + 1).second.greenF() << stops.at(i + 1).second.blueF() << "]\n";
+ switch (result.colorModel) {
+ case QPdfEngine::ColorModel::RGB:
+ s << "/C0 [" << stops.at(i).second.redF() << stops.at(i).second.greenF() << stops.at(i).second.blueF() << "]\n"
+ "/C1 [" << stops.at(i + 1).second.redF() << stops.at(i + 1).second.greenF() << stops.at(i + 1).second.blueF() << "]\n";
+ break;
+ case QPdfEngine::ColorModel::Grayscale:
+ s << "/C0 [" << (qGray(stops.at(i).second.rgba()) / 255.) << "]\n"
+ "/C1 [" << (qGray(stops.at(i + 1).second.rgba()) / 255.) << "]\n";
+ break;
+ case QPdfEngine::ColorModel::CMYK:
+ s << "/C0 [" << stops.at(i).second.cyanF()
+ << stops.at(i).second.magentaF()
+ << stops.at(i).second.yellowF()
+ << stops.at(i).second.blackF() << "]\n"
+ "/C1 [" << stops.at(i + 1).second.cyanF()
+ << stops.at(i + 1).second.magentaF()
+ << stops.at(i + 1).second.yellowF()
+ << stops.at(i + 1).second.blackF() << "]\n";
+ break;
+
+ case QPdfEngine::ColorModel::Auto:
+ Q_UNREACHABLE();
+ break;
+ }
+
}
s << ">>\n"
"endobj\n";
@@ -2480,7 +2657,8 @@ int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from
} else {
function = functions.at(0);
}
- return function;
+ result.function = function;
+ return result;
}
int QPdfEnginePrivate::generateLinearGradientShader(const QLinearGradient *gradient, const QTransform &matrix, bool alpha)
@@ -2526,17 +2704,22 @@ int QPdfEnginePrivate::generateLinearGradientShader(const QLinearGradient *gradi
}
}
- int function = createShadingFunction(gradient, from, to, reflect, alpha);
+ const auto shadingFunctionResult = createShadingFunction(gradient, from, to, reflect, alpha);
QByteArray shader;
QPdf::ByteStream s(&shader);
s << "<<\n"
- "/ShadingType 2\n"
- "/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
- "/AntiAlias true\n"
+ "/ShadingType 2\n";
+
+ if (alpha)
+ s << "/ColorSpace /DeviceGray\n";
+ else
+ shadingFunctionResult.writeColorSpace(&s);
+
+ s << "/AntiAlias true\n"
"/Coords [" << start.x() << start.y() << stop.x() << stop.y() << "]\n"
"/Extend [true true]\n"
- "/Function " << function << "0 R\n"
+ "/Function " << shadingFunctionResult.function << "0 R\n"
">>\n"
"endobj\n";
int shaderObject = addXrefEntry(-1);
@@ -2594,18 +2777,23 @@ int QPdfEnginePrivate::generateRadialGradientShader(const QRadialGradient *gradi
}
}
- int function = createShadingFunction(gradient, from, to, reflect, alpha);
+ const auto shadingFunctionResult = createShadingFunction(gradient, from, to, reflect, alpha);
QByteArray shader;
QPdf::ByteStream s(&shader);
s << "<<\n"
- "/ShadingType 3\n"
- "/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
- "/AntiAlias true\n"
+ "/ShadingType 3\n";
+
+ if (alpha)
+ s << "/ColorSpace /DeviceGray\n";
+ else
+ shadingFunctionResult.writeColorSpace(&s);
+
+ s << "/AntiAlias true\n"
"/Domain [0 1]\n"
"/Coords [" << p0.x() << p0.y() << r0 << p1.x() << p1.y() << r1 << "]\n"
"/Extend [true true]\n"
- "/Function " << function << "0 R\n"
+ "/Function " << shadingFunctionResult.function << "0 R\n"
">>\n"
"endobj\n";
int shaderObject = addXrefEntry(-1);
@@ -2691,7 +2879,7 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QTransform &matrix,
"/Shading << /Shader" << alphaShaderObject << alphaShaderObject << "0 R >>\n"
">>\n";
- f << "/Length " << content.length() << "\n"
+ f << "/Length " << content.size() << "\n"
">>\n"
"stream\n"
<< content
@@ -2742,17 +2930,23 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
*specifyColor = true;
*gStateObject = 0;
- QTransform matrix = m;
+ const Qt::BrushStyle style = brush.style();
+ const bool isCosmetic = style >= Qt::Dense1Pattern && style <= Qt::DiagCrossPattern
+ && !q->painter()->testRenderHint(QPainter::NonCosmeticBrushPatterns);
+ QTransform matrix;
+ if (!isCosmetic)
+ matrix = m;
matrix.translate(brushOrigin.x(), brushOrigin.y());
matrix = matrix * pageMatrix();
- //qDebug() << brushOrigin << matrix;
- Qt::BrushStyle style = brush.style();
if (style == Qt::LinearGradientPattern || style == Qt::RadialGradientPattern) {// && style <= Qt::ConicalGradientPattern) {
*specifyColor = false;
return gradientBrush(brush, matrix, gStateObject);
}
+ if (!isCosmetic)
+ matrix = brush.transform() * matrix;
+
if ((!brush.isOpaque() && brush.style() < Qt::LinearGradientPattern) || opacity != 1.0)
*gStateObject = addConstantAlphaObject(qRound(brush.color().alpha() * opacity),
qRound(pen.color().alpha() * opacity));
@@ -2803,7 +2997,7 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
s << "/XObject << /Im" << imageObject << ' ' << imageObject << "0 R >> ";
}
s << ">>\n"
- "/Length " << pattern.length() << "\n"
+ "/Length " << pattern.size() << "\n"
">>\n"
"stream\n"
<< pattern
@@ -2838,6 +3032,7 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless,
QImage image = img;
QImage::Format format = image.format();
+ const bool grayscale = (colorModel == QPdfEngine::ColorModel::Grayscale);
if (pdfVersion == QPdfEngine::Version_A1b) {
if (image.hasAlphaChannel()) {
@@ -2861,7 +3056,7 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless,
format = QImage::Format_Mono;
} else {
*bitmap = false;
- if (format != QImage::Format_RGB32 && format != QImage::Format_ARGB32) {
+ if (format != QImage::Format_RGB32 && format != QImage::Format_ARGB32 && format != QImage::Format_CMYK8888) {
image = image.convertToFormat(QImage::Format_ARGB32);
format = QImage::Format_ARGB32;
}
@@ -2869,7 +3064,6 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless,
int w = image.width();
int h = image.height();
- int d = image.depth();
if (format == QImage::Format_Mono) {
int bytesPerLine = (w + 7) >> 3;
@@ -2880,7 +3074,7 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless,
memcpy(rawdata, image.constScanLine(y), bytesPerLine);
rawdata += bytesPerLine;
}
- object = writeImage(data, w, h, d, 0, 0, false, is_monochrome(img.colorTable()));
+ object = writeImage(data, w, h, WriteImageOption::Monochrome, 0, 0, false, is_monochrome(img.colorTable()));
} else {
QByteArray softMaskData;
bool dct = false;
@@ -2892,10 +3086,14 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless,
QBuffer buffer(&imageData);
QImageWriter writer(&buffer, "jpeg");
writer.setQuality(94);
+ if (format == QImage::Format_CMYK8888) {
+ // PDFs require CMYK colors not to be inverted in the JPEG encoding
+ writer.setSubType("CMYK");
+ }
writer.write(image);
dct = true;
- if (format != QImage::Format_RGB32) {
+ if (format != QImage::Format_RGB32 && format != QImage::Format_CMYK8888) {
softMaskData.resize(w * h);
uchar *sdata = (uchar *)softMaskData.data();
for (int y = 0; y < h; ++y) {
@@ -2910,41 +3108,59 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless,
}
}
} else {
- imageData.resize(grayscale ? w * h : 3 * w * h);
- uchar *data = (uchar *)imageData.data();
- softMaskData.resize(w * h);
- uchar *sdata = (uchar *)softMaskData.data();
- for (int y = 0; y < h; ++y) {
- const QRgb *rgb = (const QRgb *)image.constScanLine(y);
+ if (format == QImage::Format_CMYK8888) {
+ imageData.resize(grayscale ? w * h : w * h * 4);
+ uchar *data = (uchar *)imageData.data();
+ const qsizetype bytesPerLine = image.bytesPerLine();
if (grayscale) {
- for (int x = 0; x < w; ++x) {
- *(data++) = qGray(*rgb);
- uchar alpha = qAlpha(*rgb);
- *sdata++ = alpha;
- hasMask |= (alpha < 255);
- hasAlpha |= (alpha != 0 && alpha != 255);
- ++rgb;
+ for (int y = 0; y < h; ++y) {
+ const uint *cmyk = (const uint *)image.constScanLine(y);
+ for (int x = 0; x < w; ++x)
+ *data++ = qGray(QCmyk32::fromCmyk32(*cmyk++).toColor().rgba());
}
} else {
- for (int x = 0; x < w; ++x) {
- *(data++) = qRed(*rgb);
- *(data++) = qGreen(*rgb);
- *(data++) = qBlue(*rgb);
- uchar alpha = qAlpha(*rgb);
- *sdata++ = alpha;
- hasMask |= (alpha < 255);
- hasAlpha |= (alpha != 0 && alpha != 255);
- ++rgb;
+ for (int y = 0; y < h; ++y) {
+ uchar *start = data + y * w * 4;
+ memcpy(start, image.constScanLine(y), bytesPerLine);
+ }
+ }
+ } else {
+ imageData.resize(grayscale ? w * h : 3 * w * h);
+ uchar *data = (uchar *)imageData.data();
+ softMaskData.resize(w * h);
+ uchar *sdata = (uchar *)softMaskData.data();
+ for (int y = 0; y < h; ++y) {
+ const QRgb *rgb = (const QRgb *)image.constScanLine(y);
+ if (grayscale) {
+ for (int x = 0; x < w; ++x) {
+ *(data++) = qGray(*rgb);
+ uchar alpha = qAlpha(*rgb);
+ *sdata++ = alpha;
+ hasMask |= (alpha < 255);
+ hasAlpha |= (alpha != 0 && alpha != 255);
+ ++rgb;
+ }
+ } else {
+ for (int x = 0; x < w; ++x) {
+ *(data++) = qRed(*rgb);
+ *(data++) = qGreen(*rgb);
+ *(data++) = qBlue(*rgb);
+ uchar alpha = qAlpha(*rgb);
+ *sdata++ = alpha;
+ hasMask |= (alpha < 255);
+ hasAlpha |= (alpha != 0 && alpha != 255);
+ ++rgb;
+ }
}
}
}
- if (format == QImage::Format_RGB32)
+ if (format == QImage::Format_RGB32 || format == QImage::Format_CMYK8888)
hasAlpha = hasMask = false;
}
int maskObject = 0;
int softMaskObject = 0;
if (hasAlpha) {
- softMaskObject = writeImage(softMaskData, w, h, 8, 0, 0);
+ softMaskObject = writeImage(softMaskData, w, h, WriteImageOption::Grayscale, 0, 0);
} else if (hasMask) {
// dither the soft mask to 1bit and add it. This also helps PDF viewers
// without transparency support
@@ -2960,9 +3176,18 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless,
}
mdata += bytesPerLine;
}
- maskObject = writeImage(mask, w, h, 1, 0, 0);
+ maskObject = writeImage(mask, w, h, WriteImageOption::Monochrome, 0, 0);
}
- object = writeImage(imageData, w, h, grayscale ? 8 : 32,
+
+ const WriteImageOption option = [&]() {
+ if (grayscale)
+ return WriteImageOption::Grayscale;
+ if (format == QImage::Format_CMYK8888)
+ return WriteImageOption::CMYK;
+ return WriteImageOption::RGB;
+ }();
+
+ object = writeImage(imageData, w, h, option,
maskObject, softMaskObject, dct);
}
imageCache.insert(serial_no, object);
@@ -2973,7 +3198,9 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti)
{
Q_Q(QPdfEngine);
- if (ti.charFormat.isAnchor()) {
+ const bool isLink = ti.charFormat.hasProperty(QTextFormat::AnchorHref);
+ const bool isAnchor = ti.charFormat.hasProperty(QTextFormat::AnchorName);
+ if (isLink || isAnchor) {
qreal size = ti.fontEngine->fontDef.pixelSize;
int synthesized = ti.fontEngine->synthesized();
qreal stretch = synthesized & QFontEngine::SynthesizedStretch ? ti.fontEngine->fontDef.stretch/100. : 1.;
@@ -2993,32 +3220,47 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti)
trans.map(0, 0, &x1, &y1);
trans.map(ti.width.toReal()/size, (ti.ascent.toReal()-ti.descent.toReal())/size, &x2, &y2);
- uint annot = addXrefEntry(-1);
- QByteArray x1s, y1s, x2s, y2s;
- x1s.setNum(static_cast<double>(x1), 'f');
- y1s.setNum(static_cast<double>(y1), 'f');
- x2s.setNum(static_cast<double>(x2), 'f');
- y2s.setNum(static_cast<double>(y2), 'f');
- QByteArray rectData = x1s + ' ' + y1s + ' ' + x2s + ' ' + y2s;
- xprintf("<<\n/Type /Annot\n/Subtype /Link\n");
-
- if (pdfVersion == QPdfEngine::Version_A1b)
- xprintf("/F 4\n"); // enable print flag, disable all other
-
- xprintf("/Rect [");
- xprintf(rectData.constData());
+ if (isLink) {
+ uint annot = addXrefEntry(-1);
+ QByteArray x1s, y1s, x2s, y2s;
+ x1s.setNum(static_cast<double>(x1), 'f');
+ y1s.setNum(static_cast<double>(y1), 'f');
+ x2s.setNum(static_cast<double>(x2), 'f');
+ y2s.setNum(static_cast<double>(y2), 'f');
+ QByteArray rectData = x1s + ' ' + y1s + ' ' + x2s + ' ' + y2s;
+ xprintf("<<\n/Type /Annot\n/Subtype /Link\n");
+
+ if (pdfVersion == QPdfEngine::Version_A1b)
+ xprintf("/F 4\n"); // enable print flag, disable all other
+
+ xprintf("/Rect [");
+ xprintf(rectData.constData());
#ifdef Q_DEBUG_PDF_LINKS
- xprintf("]\n/Border [16 16 1]\n/A <<\n");
+ xprintf("]\n/Border [16 16 1]\n");
#else
- xprintf("]\n/Border [0 0 0]\n/A <<\n");
+ xprintf("]\n/Border [0 0 0]\n");
#endif
- xprintf("/Type /Action\n/S /URI\n/URI (%s)\n",
- ti.charFormat.anchorHref().toLatin1().constData());
- xprintf(">>\n>>\n");
- xprintf("endobj\n");
+ const QString link = ti.charFormat.anchorHref();
+ const bool isInternal = link.startsWith(QLatin1Char('#'));
+ if (!isInternal) {
+ xprintf("/A <<\n");
+ xprintf("/Type /Action\n/S /URI\n/URI (%s)\n", link.toLatin1().constData());
+ xprintf(">>\n");
+ } else {
+ xprintf("/Dest ");
+ printString(link.sliced(1));
+ xprintf("\n");
+ }
+ xprintf(">>\n");
+ xprintf("endobj\n");
- if (!currentPage->annotations.contains(annot)) {
- currentPage->annotations.append(annot);
+ if (!currentPage->annotations.contains(annot)) {
+ currentPage->annotations.append(annot);
+ }
+ } else {
+ const QString anchor = ti.charFormat.anchorNames().constFirst();
+ const uint curPage = pages.last();
+ destCache.append(DestInfo({ anchor, curPage, QPointF(x1, y2) }));
}
}
@@ -3100,7 +3342,7 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti)
x += .3*y;
x /= stretch;
char buf[5];
- int g = font->addGlyph(glyphs[i]);
+ qsizetype g = font->addGlyph(glyphs[i]);
*currentPage << x - last_x << last_y - y << "Td <"
<< QPdf::toHex((ushort)g, buf) << "> Tj\n";
last_x = x;
@@ -3120,7 +3362,7 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti)
x += .3*y;
x /= stretch;
char buf[5];
- int g = font->addGlyph(glyphs[i]);
+ qsizetype g = font->addGlyph(glyphs[i]);
*currentPage << x - last_x << last_y - y << "Td <"
<< QPdf::toHex((ushort)g, buf) << "> Tj\n";
last_x = x;
diff --git a/src/gui/painting/qpdf.qrc b/src/gui/painting/qpdf.qrc
deleted file mode 100644
index 56359c775b..0000000000
--- a/src/gui/painting/qpdf.qrc
+++ /dev/null
@@ -1,7 +0,0 @@
-<!DOCTYPE RCC>
-<RCC version="1.0">
- <qresource prefix="qpdf/">
- <file>qpdfa_metadata.xml</file>
- <file alias="sRGB2014.icc">../../3rdparty/icc/sRGB2014.icc</file>
- </qresource>
-</RCC>
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index 67b189a4db..3c34e0bd7a 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPDF_P_H
#define QPDF_P_H
@@ -96,10 +60,6 @@ namespace QPdf {
static inline int maxMemorySize() { return 100000000; }
static inline int chunkSize() { return 10000000; }
- protected:
- void constructor_helper(QIODevice *dev);
- void constructor_helper(QByteArray *ba);
-
private:
void prepareBuffer();
@@ -178,7 +138,7 @@ public:
};
QPdfEngine();
- QPdfEngine(QPdfEnginePrivate &d);
+ explicit QPdfEngine(QPdfEnginePrivate &d);
~QPdfEngine() {}
void setOutputFilename(const QString &filename);
@@ -193,6 +153,18 @@ public:
void addFileAttachment(const QString &fileName, const QByteArray &data, const QString &mimeType);
+ // keep in sync with QPdfWriter
+ enum class ColorModel
+ {
+ RGB,
+ Grayscale,
+ CMYK,
+ Auto,
+ };
+
+ ColorModel colorModel() const;
+ void setColorModel(ColorModel model);
+
// reimplementations QPaintEngine
bool begin(QPaintDevice *pdev) override;
bool end() override;
@@ -273,8 +245,10 @@ public:
bool hasPen;
bool hasBrush;
bool simplePen;
+ bool needsTransform;
qreal opacity;
QPdfEngine::PdfVersion pdfVersion;
+ QPdfEngine::ColorModel colorModel;
QHash<QFontEngine::FaceId, QFontSubset *> fonts;
@@ -290,7 +264,6 @@ public:
QString creator;
bool embedFonts;
int resolution;
- bool grayscale;
// Page layout: size, orientation and margins
QPageLayout m_pageLayout;
@@ -300,13 +273,29 @@ private:
int generateGradientShader(const QGradient *gradient, const QTransform &matrix, bool alpha = false);
int generateLinearGradientShader(const QLinearGradient *lg, const QTransform &matrix, bool alpha);
int generateRadialGradientShader(const QRadialGradient *gradient, const QTransform &matrix, bool alpha);
- int createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha);
+ struct ShadingFunctionResult
+ {
+ int function;
+ QPdfEngine::ColorModel colorModel;
+ void writeColorSpace(QPdf::ByteStream *stream) const;
+ };
+ ShadingFunctionResult createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha);
+ enum class ColorDomain {
+ Stroking,
+ NonStroking,
+ NonStrokingPattern,
+ };
+
+ QPdfEngine::ColorModel colorModelForColor(const QColor &color) const;
+ void writeColor(ColorDomain domain, const QColor &color);
void writeInfo();
int writeXmpDcumentMetaData();
int writeOutputIntent();
void writePageRoot();
+ void writeDestsRoot();
void writeAttachmentRoot();
+ void writeNamesRoot();
void writeFonts();
void embedFont(QFontSubset *font);
qreal calcUserUnit() const;
@@ -315,12 +304,20 @@ private:
QDataStream* stream;
int streampos;
- int writeImage(const QByteArray &data, int width, int height, int depth,
+ enum class WriteImageOption
+ {
+ Monochrome,
+ Grayscale,
+ RGB,
+ CMYK,
+ };
+
+ int writeImage(const QByteArray &data, int width, int height, WriteImageOption option,
int maskObject, int softMaskObject, bool dct = false, bool isMono = false);
void writePage();
int addXrefEntry(int object, bool printostr = true);
- void printString(const QString &string);
+ void printString(QStringView string);
void xprintf(const char* fmt, ...);
inline void write(const QByteArray &data) {
stream->writeRawData(data.constData(), data.size());
@@ -328,7 +325,7 @@ private:
}
int writeCompressed(const char *src, int len);
- inline int writeCompressed(const QByteArray &data) { return writeCompressed(data.constData(), data.length()); }
+ inline int writeCompressed(const QByteArray &data) { return writeCompressed(data.constData(), data.size()); }
int writeCompressed(QIODevice *dev);
struct AttachmentInfo
@@ -340,11 +337,23 @@ private:
QString mimeType;
};
+ struct DestInfo
+ {
+ QString anchor;
+ uint pageObj;
+ QPointF coords;
+ };
+
// various PDF objects
- int pageRoot, embeddedfilesRoot, namesRoot, catalog, info, graphicsState, patternColorSpace;
+ int pageRoot, namesRoot, destsRoot, attachmentsRoot, catalog, info;
+ int graphicsState;
+ int patternColorSpaceRGB;
+ int patternColorSpaceGrayscale;
+ int patternColorSpaceCMYK;
QList<uint> pages;
QHash<qint64, uint> imageCache;
QHash<QPair<uint, uint>, uint > alphaCache;
+ QList<DestInfo> destCache;
QList<AttachmentInfo> fileCache;
QByteArray xmpDocumentMetadata;
};
diff --git a/src/gui/painting/qpdfwriter.cpp b/src/gui/painting/qpdfwriter.cpp
index 0bb0e81761..bce65927ab 100644
--- a/src/gui/painting/qpdfwriter.cpp
+++ b/src/gui/painting/qpdfwriter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qpdfwriter.h>
@@ -331,6 +295,55 @@ bool QPdfWriter::newPage()
return d->engine->newPage();
}
+/*!
+ \enum QPdfWriter::ColorModel
+ \since 6.8
+
+ This enumeration describes the way in which the PDF engine interprets
+ stroking and filling colors, set as a QPainter's pen or brush (via
+ QPen and QBrush).
+
+ \value RGB All colors are converted to RGB and saved as such in the
+ PDF.
+
+ \value Grayscale All colors are converted to grayscale. For backwards
+ compatibility, they are emitted in the PDF output as RGB colors, with
+ identical quantities of red, green and blue.
+
+ \value CMYK All colors are converted to CMYK and saved as such.
+
+ \value Auto RGB colors are emitted as RGB; CMYK colors are emitted as
+ CMYK. Colors of any other color spec are converted to RGB.
+ This is the default since Qt 6.8.
+
+ \sa QColor, QGradient
+*/
+
+/*!
+ \since 6.8
+
+ Returns the color model used by this PDF writer.
+ The default is QPdfWriter::ColorModel::Auto.
+*/
+QPdfWriter::ColorModel QPdfWriter::colorModel() const
+{
+ Q_D(const QPdfWriter);
+ return static_cast<ColorModel>(d->engine->d_func()->colorModel);
+}
+
+/*!
+ \since 6.8
+
+ Sets the color model used by this PDF writer to \a model.
+*/
+void QPdfWriter::setColorModel(ColorModel model)
+{
+ Q_D(QPdfWriter);
+ d->engine->d_func()->colorModel = static_cast<QPdfEngine::ColorModel>(model);
+}
+
QT_END_NAMESPACE
+#include "moc_qpdfwriter.cpp"
+
#endif // QT_NO_PDF
diff --git a/src/gui/painting/qpdfwriter.h b/src/gui/painting/qpdfwriter.h
index aa068e20e0..1a4b607b66 100644
--- a/src/gui/painting/qpdfwriter.h
+++ b/src/gui/painting/qpdfwriter.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPDFWRITER_H
#define QPDFWRITER_H
@@ -80,6 +44,18 @@ public:
void addFileAttachment(const QString &fileName, const QByteArray &data, const QString &mimeType = QString());
+ enum class ColorModel
+ {
+ RGB,
+ Grayscale,
+ CMYK,
+ Auto,
+ };
+ Q_ENUM(ColorModel)
+
+ ColorModel colorModel() const;
+ void setColorModel(ColorModel model);
+
protected:
QPaintEngine *paintEngine() const override;
int metric(PaintDeviceMetric id) const override;
diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp
index 978c96af96..d37beda6b6 100644
--- a/src/gui/painting/qpen.cpp
+++ b/src/gui/painting/qpen.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpen.h"
#include "qpen_p.h"
#include "qdatastream.h"
@@ -46,8 +10,6 @@
QT_BEGIN_NAMESPACE
-typedef QPenPrivate QPenData;
-
/*!
\class QPen
\inmodule QtGui
@@ -229,7 +191,7 @@ typedef QPenPrivate QPenData;
*/
QPenPrivate::QPenPrivate(const QBrush &_brush, qreal _width, Qt::PenStyle penStyle,
Qt::PenCapStyle _capStyle, Qt::PenJoinStyle _joinStyle)
- : ref(1), dashOffset(0), miterLimit(2),
+ : dashOffset(0), miterLimit(2),
cosmetic(false)
{
width = _width;
@@ -245,17 +207,13 @@ static const Qt::PenJoinStyle qpen_default_join = Qt::BevelJoin;
class QPenDataHolder
{
public:
- QPenData *pen;
+ QPen::DataPtr pen;
QPenDataHolder(const QBrush &brush, qreal width, Qt::PenStyle penStyle,
Qt::PenCapStyle penCapStyle, Qt::PenJoinStyle _joinStyle)
- : pen(new QPenData(brush, width, penStyle, penCapStyle, _joinStyle))
+ : pen(new QPenPrivate(brush, width, penStyle, penCapStyle, _joinStyle))
{ }
- ~QPenDataHolder()
- {
- if (!pen->ref.deref())
- delete pen;
- pen = nullptr;
- }
+ ~QPenDataHolder() = default;
+ Q_DISABLE_COPY_MOVE(QPenDataHolder)
};
Q_GLOBAL_STATIC_WITH_ARGS(QPenDataHolder, defaultPenInstance,
@@ -270,7 +228,6 @@ Q_GLOBAL_STATIC_WITH_ARGS(QPenDataHolder, nullPenInstance,
QPen::QPen()
{
d = defaultPenInstance()->pen;
- d->ref.ref();
}
/*!
@@ -283,9 +240,8 @@ QPen::QPen(Qt::PenStyle style)
{
if (style == Qt::NoPen) {
d = nullPenInstance()->pen;
- d->ref.ref();
} else {
- d = new QPenData(Qt::black, 1, style, qpen_default_cap, qpen_default_join);
+ d = new QPenPrivate(Qt::black, 1, style, qpen_default_cap, qpen_default_join);
}
}
@@ -298,7 +254,7 @@ QPen::QPen(Qt::PenStyle style)
QPen::QPen(const QColor &color)
{
- d = new QPenData(color, 1, Qt::SolidLine, qpen_default_cap, qpen_default_join);
+ d = new QPenPrivate(color, 1, Qt::SolidLine, qpen_default_cap, qpen_default_join);
}
@@ -313,7 +269,7 @@ QPen::QPen(const QColor &color)
QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle s, Qt::PenCapStyle c, Qt::PenJoinStyle j)
{
- d = new QPenData(brush, width, s, c, j);
+ d = new QPenPrivate(brush, width, s, c, j);
}
/*!
@@ -323,10 +279,8 @@ QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle s, Qt::PenCapStyle c,
*/
QPen::QPen(const QPen &p) noexcept
+ : d(p.d)
{
- d = p.d;
- if (d)
- d->ref.ref();
}
@@ -345,11 +299,9 @@ QPen::QPen(const QPen &p) noexcept
Destroys the pen.
*/
-QPen::~QPen()
-{
- if (d && !d->ref.deref())
- delete d;
-}
+QPen::~QPen() = default;
+
+QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QPenPrivate)
/*!
\fn void QPen::detach()
@@ -363,14 +315,7 @@ QPen::~QPen()
void QPen::detach()
{
- if (d->ref.loadRelaxed() == 1)
- return;
-
- QPenData *x = new QPenData(*static_cast<QPenData *>(d));
- if (!d->ref.deref())
- delete d;
- x->ref.storeRelaxed(1);
- d = x;
+ d.detach();
}
@@ -443,9 +388,8 @@ void QPen::setStyle(Qt::PenStyle s)
return;
detach();
d->style = s;
- QPenData *dd = static_cast<QPenData *>(d);
- dd->dashPattern.clear();
- dd->dashOffset = 0;
+ d->dashPattern.clear();
+ d->dashOffset = 0;
}
/*!
@@ -455,36 +399,35 @@ void QPen::setStyle(Qt::PenStyle s)
*/
QList<qreal> QPen::dashPattern() const
{
- QPenData *dd = static_cast<QPenData *>(d);
if (d->style == Qt::SolidLine || d->style == Qt::NoPen) {
return QList<qreal>();
- } else if (dd->dashPattern.isEmpty()) {
+ } else if (d->dashPattern.isEmpty()) {
const qreal space = 2;
const qreal dot = 1;
const qreal dash = 4;
switch (d->style) {
case Qt::DashLine:
- dd->dashPattern.reserve(2);
- dd->dashPattern << dash << space;
+ d->dashPattern.reserve(2);
+ d->dashPattern << dash << space;
break;
case Qt::DotLine:
- dd->dashPattern.reserve(2);
- dd->dashPattern << dot << space;
+ d->dashPattern.reserve(2);
+ d->dashPattern << dot << space;
break;
case Qt::DashDotLine:
- dd->dashPattern.reserve(4);
- dd->dashPattern << dash << space << dot << space;
+ d->dashPattern.reserve(4);
+ d->dashPattern << dash << space << dot << space;
break;
case Qt::DashDotDotLine:
- dd->dashPattern.reserve(6);
- dd->dashPattern << dash << space << dot << space << dot << space;
+ d->dashPattern.reserve(6);
+ d->dashPattern << dash << space << dot << space << dot << space;
break;
default:
break;
}
}
- return dd->dashPattern;
+ return d->dashPattern;
}
/*!
@@ -523,13 +466,12 @@ void QPen::setDashPattern(const QList<qreal> &pattern)
return;
detach();
- QPenData *dd = static_cast<QPenData *>(d);
- dd->dashPattern = pattern;
+ d->dashPattern = pattern;
d->style = Qt::CustomDashLine;
- if ((dd->dashPattern.size() % 2) == 1) {
+ if ((d->dashPattern.size() % 2) == 1) {
qWarning("QPen::setDashPattern: Pattern not of even length");
- dd->dashPattern << 1;
+ d->dashPattern << 1;
}
}
@@ -541,8 +483,7 @@ void QPen::setDashPattern(const QList<qreal> &pattern)
*/
qreal QPen::dashOffset() const
{
- QPenData *dd = static_cast<QPenData *>(d);
- return dd->dashOffset;
+ return d->dashOffset;
}
/*!
Sets the dash offset (the starting point on the dash pattern) for this pen
@@ -564,13 +505,12 @@ qreal QPen::dashOffset() const
*/
void QPen::setDashOffset(qreal offset)
{
- if (qFuzzyCompare(offset, static_cast<QPenData *>(d)->dashOffset))
+ if (qFuzzyCompare(offset, d->dashOffset))
return;
detach();
- QPenData *dd = static_cast<QPenData *>(d);
- dd->dashOffset = offset;
+ d->dashOffset = offset;
if (d->style != Qt::CustomDashLine) {
- dd->dashPattern = dashPattern();
+ d->dashPattern = dashPattern();
d->style = Qt::CustomDashLine;
}
}
@@ -583,8 +523,7 @@ void QPen::setDashOffset(qreal offset)
*/
qreal QPen::miterLimit() const
{
- const QPenData *dd = static_cast<QPenData *>(d);
- return dd->miterLimit;
+ return d->miterLimit;
}
/*!
@@ -606,8 +545,7 @@ qreal QPen::miterLimit() const
void QPen::setMiterLimit(qreal limit)
{
detach();
- QPenData *dd = static_cast<QPenData *>(d);
- dd->miterLimit = limit;
+ d->miterLimit = limit;
}
@@ -818,8 +756,7 @@ bool QPen::isSolid() const
bool QPen::isCosmetic() const
{
- QPenData *dd = static_cast<QPenData *>(d);
- return (dd->cosmetic == true) || d->width == 0;
+ return (d->cosmetic == true) || d->width == 0;
}
@@ -833,8 +770,7 @@ bool QPen::isCosmetic() const
void QPen::setCosmetic(bool cosmetic)
{
detach();
- QPenData *dd = static_cast<QPenData *>(d);
- dd->cosmetic = cosmetic;
+ d->cosmetic = cosmetic;
}
@@ -861,19 +797,17 @@ void QPen::setCosmetic(bool cosmetic)
bool QPen::operator==(const QPen &p) const
{
- QPenData *dd = static_cast<QPenData *>(d);
- QPenData *pdd = static_cast<QPenData *>(p.d);
return (p.d == d)
|| (p.d->style == d->style
&& p.d->capStyle == d->capStyle
&& p.d->joinStyle == d->joinStyle
&& p.d->width == d->width
- && pdd->miterLimit == dd->miterLimit
+ && p.d->miterLimit == d->miterLimit
&& (d->style != Qt::CustomDashLine
- || (qFuzzyCompare(pdd->dashOffset, dd->dashOffset) &&
- pdd->dashPattern == dd->dashPattern))
+ || (qFuzzyCompare(p.d->dashOffset, d->dashOffset) &&
+ p.d->dashPattern == d->dashPattern))
&& p.d->brush == d->brush
- && pdd->cosmetic == dd->cosmetic);
+ && p.d->cosmetic == d->cosmetic);
}
@@ -905,14 +839,13 @@ bool QPen::isDetached()
QDataStream &operator<<(QDataStream &s, const QPen &p)
{
- QPenData *dd = static_cast<QPenData *>(p.d);
if (s.version() < 3) {
s << (quint8)p.style();
} else if (s.version() < QDataStream::Qt_4_3) {
s << (quint8)(uint(p.style()) | uint(p.capStyle()) | uint(p.joinStyle()));
} else {
s << (quint16)(uint(p.style()) | uint(p.capStyle()) | uint(p.joinStyle()));
- s << (bool)(dd->cosmetic);
+ s << (bool)(p.d->cosmetic);
}
if (s.version() < 7) {
@@ -1001,16 +934,15 @@ QDataStream &operator>>(QDataStream &s, QPen &p)
}
p.detach();
- QPenData *dd = static_cast<QPenData *>(p.d);
- dd->width = width;
- dd->brush = brush;
- dd->style = Qt::PenStyle(style & Qt::MPenStyle);
- dd->capStyle = Qt::PenCapStyle(style & Qt::MPenCapStyle);
- dd->joinStyle = Qt::PenJoinStyle(style & Qt::MPenJoinStyle);
- dd->dashPattern = dashPattern;
- dd->miterLimit = miterLimit;
- dd->dashOffset = dashOffset;
- dd->cosmetic = cosmetic;
+ p.d->width = width;
+ p.d->brush = brush;
+ p.d->style = Qt::PenStyle(style & Qt::MPenStyle);
+ p.d->capStyle = Qt::PenCapStyle(style & Qt::MPenCapStyle);
+ p.d->joinStyle = Qt::PenJoinStyle(style & Qt::MPenJoinStyle);
+ p.d->dashPattern = dashPattern;
+ p.d->miterLimit = miterLimit;
+ p.d->dashOffset = dashOffset;
+ p.d->cosmetic = cosmetic;
return s;
}
diff --git a/src/gui/painting/qpen.h b/src/gui/painting/qpen.h
index db280c765b..3367b96c35 100644
--- a/src/gui/painting/qpen.h
+++ b/src/gui/painting/qpen.h
@@ -1,45 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPEN_H
#define QPEN_H
+#include <QtCore/qshareddata.h>
#include <QtGui/qtguiglobal.h>
#include <QtGui/qcolor.h>
#include <QtGui/qbrush.h>
@@ -57,6 +22,8 @@ Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPen &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPen &);
#endif
+QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QPenPrivate, Q_GUI_EXPORT)
+
class Q_GUI_EXPORT QPen
{
public:
@@ -70,10 +37,9 @@ public:
~QPen();
QPen &operator=(const QPen &pen) noexcept;
- QPen(QPen &&other) noexcept
- : d(qExchange(other.d, nullptr)) {}
+ QPen(QPen &&other) noexcept = default;
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QPen)
- void swap(QPen &other) noexcept { qSwap(d, other.d); }
+ void swap(QPen &other) noexcept { d.swap(other.d); }
Qt::PenStyle style() const;
void setStyle(Qt::PenStyle);
@@ -115,15 +81,19 @@ public:
operator QVariant() const;
bool isDetached();
+
private:
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPen &);
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPen &);
+public:
+ using DataPtr = QExplicitlySharedDataPointer<QPenPrivate>;
+
+private:
void detach();
- class QPenPrivate *d;
+ DataPtr d;
public:
- typedef QPenPrivate * DataPtr;
inline DataPtr &data_ptr() { return d; }
};
diff --git a/src/gui/painting/qpen_p.h b/src/gui/painting/qpen_p.h
index e86b72a6e6..a939c5e4f6 100644
--- a/src/gui/painting/qpen_p.h
+++ b/src/gui/painting/qpen_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPEN_P_H
#define QPEN_P_H
@@ -51,15 +15,16 @@
// We mean it.
//
-#include <QtCore/qglobal.h>
+#include <QtCore/private/qglobal_p.h>
+#include <QtCore/qshareddata.h>
QT_BEGIN_NAMESPACE
-class QPenPrivate {
+class QPenPrivate : public QSharedData
+{
public:
QPenPrivate(const QBrush &brush, qreal width, Qt::PenStyle, Qt::PenCapStyle,
Qt::PenJoinStyle _joinStyle);
- QAtomicInt ref;
qreal width;
QBrush brush;
Qt::PenStyle style;
diff --git a/src/gui/painting/qpixellayout.cpp b/src/gui/painting/qpixellayout.cpp
index 99fb229fba..4f2f0ae13a 100644
--- a/src/gui/painting/qpixellayout.cpp
+++ b/src/gui/painting/qpixellayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qglobal.h>
@@ -43,6 +7,7 @@
#include "qpixellayout_p.h"
#include "qrgba64_p.h"
#include <QtCore/private/qsimd_p.h>
+#include <QtGui/private/qcmyk_p.h>
QT_BEGIN_NAMESPACE
@@ -248,8 +213,7 @@ inline void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index,
template <QPixelLayout::BPP bpp> static
inline uint QT_FASTCALL fetchPixel(const uchar *, int)
{
- Q_UNREACHABLE();
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
template <>
@@ -1224,10 +1188,12 @@ static const QRgba64 *QT_FASTCALL fetchRGBA64ToRGBA64PM(QRgba64 *buffer, const u
const QRgba64 *s = reinterpret_cast<const QRgba64 *>(src) + index;
#ifdef __SSE2__
for (int i = 0; i < count; ++i) {
+ const auto a = s[i].alpha();
__m128i vs = _mm_loadl_epi64((const __m128i *)(s + i));
__m128i va = _mm_shufflelo_epi16(vs, _MM_SHUFFLE(3, 3, 3, 3));
vs = multiplyAlpha65535(vs, va);
_mm_storel_epi64((__m128i *)(buffer + i), vs);
+ buffer[i].setAlpha(a);
}
#else
for (int i = 0; i < count; ++i)
@@ -1692,11 +1658,71 @@ static const QRgba64 *QT_FASTCALL fetchRGBA32FPMToRGBA64PM(QRgba64 *buffer, cons
return buffer;
}
+inline const uint *qt_convertCMYK8888ToARGB32PM(uint *buffer, const uint *src, int count)
+{
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint s) {
+ const QColor color = QCmyk32::fromCmyk32(s).toColor();
+ return color.rgba();
+ });
+ return buffer;
+}
+
+static void QT_FASTCALL convertCMYK8888ToARGB32PM(uint *buffer, int count, const QList<QRgb> *)
+{
+ qt_convertCMYK8888ToARGB32PM(buffer, buffer, count);
+}
+
+static const QRgba64 *QT_FASTCALL convertCMYK8888ToToRGBA64PM(QRgba64 *buffer, const uint *src, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QCmyk32::fromCmyk32(src[i]).toColor().rgba64();
+ return buffer;
+}
+
+static const uint *QT_FASTCALL fetchCMYK8888ToARGB32PM(uint *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const uint *s = reinterpret_cast<const uint *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QCmyk32::fromCmyk32(s[i]).toColor().rgba();
+ return buffer;
+}
+
+static const QRgba64 *QT_FASTCALL fetchCMYK8888ToRGBA64PM(QRgba64 *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const uint *s = reinterpret_cast<const uint *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QCmyk32::fromCmyk32(s[i]).toColor().rgba64();
+ return buffer;
+}
+
+static void QT_FASTCALL storeCMYK8888FromARGB32PM(uchar *dest, const uint *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ QColor c = qUnpremultiply(src[i]);
+ d[i] = QCmyk32::fromColor(c).toUint();
+ }
+}
+
+static void QT_FASTCALL storeCMYK8888FromRGB32(uchar *dest, const uint *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ QColor c = src[i];
+ d[i] = QCmyk32::fromColor(c).toUint();
+ }
+}
+
// Note:
// convertToArgb32() assumes that no color channel is less than 4 bits.
// storeRGBFromARGB32PM() assumes that no color channel is more than 8 bits.
// QImage::rgbSwapped() assumes that the red and blue color channels have the same number of bits.
-QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
+QPixelLayout qPixelLayouts[] = {
{ false, false, QPixelLayout::BPPNone, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }, // Format_Invalid
{ false, false, QPixelLayout::BPP1MSB, nullptr,
convertIndexedToARGB32PM, convertIndexedTo<QRgba64>,
@@ -1814,9 +1840,13 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
convertPassThrough, nullptr,
fetchRGB32FToRGB32, fetchRGBA32FPMToRGBA64PM,
storeRGB32FFromRGB32, storeRGB32FFromRGB32 }, // Format_RGBA32FPx4_Premultiplied
+ { false, false, QPixelLayout::BPP32, nullptr,
+ convertCMYK8888ToARGB32PM, convertCMYK8888ToToRGBA64PM,
+ fetchCMYK8888ToARGB32PM, fetchCMYK8888ToRGBA64PM,
+ storeCMYK8888FromARGB32PM, storeCMYK8888FromRGB32 }, // Format_CMYK8888
};
-static_assert(sizeof(qPixelLayouts) / sizeof(*qPixelLayouts) == QImage::NImageFormats);
+static_assert(std::size(qPixelLayouts) == QImage::NImageFormats);
static void QT_FASTCALL convertFromRgb64(uint *dest, const QRgba64 *src, int length)
{
@@ -1951,7 +1981,15 @@ static void QT_FASTCALL storeRGBA32FPMFromRGBA64PM(uchar *dest, const QRgba64 *s
d[i] = qConvertRgb64ToRgbaF32(src[i]);
}
-ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = {
+static void QT_FASTCALL storeCMYKFromRGBA64PM(uchar *dest, const QRgba64 *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ for (int i = 0; i < count; ++i)
+ d[i] = QCmyk32::fromColor(QColor(src[i])).toUint();
+}
+
+ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[] = {
nullptr,
nullptr,
nullptr,
@@ -1988,8 +2026,11 @@ ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = {
storeRGBX32FFromRGBA64PM,
storeRGBA32FFromRGBA64PM,
storeRGBA32FPMFromRGBA64PM,
+ storeCMYKFromRGBA64PM,
};
+static_assert(std::size(qStoreFromRGBA64PM) == QImage::NImageFormats);
+
#if QT_CONFIG(raster_fp)
static void QT_FASTCALL convertToRgbaF32(QRgbaFloat32 *dest, const uint *src, int length)
{
@@ -2035,7 +2076,16 @@ static const QRgbaFloat32 * QT_FASTCALL convertRGB30ToRGBA32F(QRgbaFloat32 *buff
return buffer;
}
-ConvertToFPFunc qConvertToRGBA32F[QImage::NImageFormats] = {
+static const QRgbaFloat32 * QT_FASTCALL convertCMYKToRGBA32F(QRgbaFloat32 *buffer, const uint *src, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgbaFloat32::fromArgb32(QCmyk32::fromCmyk32(src[i]).toColor().rgba());
+
+ return buffer;
+}
+
+ConvertToFPFunc qConvertToRGBA32F[] = {
nullptr,
convertIndexedTo<QRgbaFloat32>,
convertIndexedTo<QRgbaFloat32>,
@@ -2072,8 +2122,11 @@ ConvertToFPFunc qConvertToRGBA32F[QImage::NImageFormats] = {
nullptr,
nullptr,
nullptr,
+ convertCMYKToRGBA32F,
};
+static_assert(std::size(qConvertToRGBA32F) == QImage::NImageFormats);
+
static const QRgbaFloat32 *QT_FASTCALL fetchRGBX64ToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count,
const QList<QRgb> *, QDitherInfo *)
{
@@ -2138,7 +2191,17 @@ static const QRgbaFloat32 *QT_FASTCALL fetchRGBA32F(QRgbaFloat32 *, const uchar
return s;
}
-FetchAndConvertPixelsFuncFP qFetchToRGBA32F[QImage::NImageFormats] = {
+static const QRgbaFloat32 *QT_FASTCALL fetchCMYKToRGBA32F(QRgbaFloat32 *buffer, const uchar *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ const uint *s = reinterpret_cast<const uint *>(src) + index;
+ for (int i = 0; i < count; ++i)
+ buffer[i] = QRgbaFloat32::fromArgb32(QCmyk32::fromCmyk32(s[i]).toColor().rgba());
+
+ return buffer;
+}
+
+FetchAndConvertPixelsFuncFP qFetchToRGBA32F[] = {
nullptr,
fetchIndexedToRGBA32F<QPixelLayout::BPP1MSB>,
fetchIndexedToRGBA32F<QPixelLayout::BPP1LSB>,
@@ -2175,8 +2238,11 @@ FetchAndConvertPixelsFuncFP qFetchToRGBA32F[QImage::NImageFormats] = {
fetchRGBA32F,
fetchRGBA32FToRGBA32F,
fetchRGBA32F,
+ fetchCMYKToRGBA32F,
};
+static_assert(std::size(qFetchToRGBA32F) == QImage::NImageFormats);
+
static void QT_FASTCALL convertFromRgba32f(uint *dest, const QRgbaFloat32 *src, int length)
{
for (int i = 0; i < length; ++i)
@@ -2263,7 +2329,7 @@ static void QT_FASTCALL storeRGBX16FFromRGBA32F(uchar *dest, const QRgbaFloat32
QRgbaFloat16 *d = reinterpret_cast<QRgbaFloat16 *>(dest) + index;
for (int i = 0; i < count; ++i) {
auto s = src[i].unpremultiplied();
- d[i] = QRgbaFloat16{ s.r, s.g, s.b, 1.0f };
+ d[i] = QRgbaFloat16{ qfloat16(s.r), qfloat16(s.g), qfloat16(s.b), qfloat16(1.0f) };
}
}
@@ -2273,7 +2339,7 @@ static void QT_FASTCALL storeRGBA16FFromRGBA32F(uchar *dest, const QRgbaFloat32
QRgbaFloat16 *d = reinterpret_cast<QRgbaFloat16 *>(dest) + index;
for (int i = 0; i < count; ++i) {
auto s = src[i].unpremultiplied();
- d[i] = QRgbaFloat16{ s.r, s.g, s.b, s.a };
+ d[i] = QRgbaFloat16{ qfloat16(s.r), qfloat16(s.g), qfloat16(s.b), qfloat16(s.a) };
}
}
@@ -2313,7 +2379,17 @@ static void QT_FASTCALL storeRGBA32FPMFromRGBA32F(uchar *dest, const QRgbaFloat3
}
}
-ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[QImage::NImageFormats] = {
+static void QT_FASTCALL storeCMYKFromRGBA32F(uchar *dest, const QRgbaFloat32 *src, int index, int count,
+ const QList<QRgb> *, QDitherInfo *)
+{
+ uint *d = reinterpret_cast<uint *>(dest) + index;
+ for (int i = 0; i < count; ++i) {
+ // Yikes, this really needs enablers in QColor and friends
+ d[i] = QCmyk32::fromColor(QColor(src[i].toArgb32())).toUint();
+ }
+}
+
+ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[] = {
nullptr,
nullptr,
nullptr,
@@ -2350,7 +2426,11 @@ ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[QImage::NImageFormats] = {
storeRGBX32FFromRGBA32F,
storeRGBA32FFromRGBA32F,
storeRGBA32FPMFromRGBA32F,
+ storeCMYKFromRGBA32F,
};
+
+static_assert(std::size(qStoreFromRGBA32F) == QImage::NImageFormats);
+
#endif // QT_CONFIG(raster_fp)
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpixellayout_p.h b/src/gui/painting/qpixellayout_p.h
index 519ae19cb1..14f19f4e74 100644
--- a/src/gui/painting/qpixellayout_p.h
+++ b/src/gui/painting/qpixellayout_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXELLAYOUT_P_H
#define QPIXELLAYOUT_P_H
@@ -55,6 +19,7 @@
#include <QtGui/qimage.h>
#include <QtGui/qrgba64.h>
#include <QtGui/qrgbafloat.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -356,12 +321,12 @@ struct QPixelLayout
extern ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats];
#if QT_CONFIG(raster_fp)
-extern ConvertToFPFunc qConvertToRGBA32F[QImage::NImageFormats];
-extern FetchAndConvertPixelsFuncFP qFetchToRGBA32F[QImage::NImageFormats];
-extern ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[QImage::NImageFormats];
+extern ConvertToFPFunc qConvertToRGBA32F[];
+extern FetchAndConvertPixelsFuncFP qFetchToRGBA32F[];
+extern ConvertAndStorePixelsFuncFP qStoreFromRGBA32F[];
#endif
-extern QPixelLayout qPixelLayouts[QImage::NImageFormats];
+extern QPixelLayout qPixelLayouts[];
extern MemRotateFunc qMemRotateFunctions[QPixelLayout::BPPCount][3];
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index bf7dc55644..f7c4df40c8 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -1,45 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformbackingstore.h"
#include <qwindow.h>
#include <qpixmap.h>
+#include <private/qbackingstorerhisupport_p.h>
+#include <private/qbackingstoredefaultcompositor_p.h>
+#include <private/qwindow_p.h>
#include <QtCore/private/qobject_p.h>
@@ -56,25 +23,21 @@ public:
{
}
- ~QPlatformBackingStorePrivate()
- {
-#ifndef QT_NO_OPENGL
- delete openGLSupport;
-#endif
- }
QWindow *window;
QBackingStore *backingStore;
-#ifndef QT_NO_OPENGL
- QPlatformBackingStoreOpenGLSupportBase *openGLSupport = nullptr;
-#endif
-};
-#ifndef QT_NO_OPENGL
+ // The order matters. if it needs to be rearranged in the future, call
+ // reset() explicitly from the dtor in the correct order.
+ // (first the compositor, then the rhiSupport)
+ QBackingStoreRhiSupport rhiSupport;
+ QBackingStoreDefaultCompositor compositor;
+};
struct QBackingstoreTextureInfo
{
void *source; // may be null
- GLuint textureId;
+ QRhiTexture *texture;
+ QRhiTexture *textureExtra;
QRect rect;
QRect clipRect;
QPlatformTextureList::Flags flags;
@@ -106,13 +69,19 @@ QPlatformTextureList::~QPlatformTextureList()
int QPlatformTextureList::count() const
{
Q_D(const QPlatformTextureList);
- return d->textures.count();
+ return d->textures.size();
+}
+
+QRhiTexture *QPlatformTextureList::texture(int index) const
+{
+ Q_D(const QPlatformTextureList);
+ return d->textures.at(index).texture;
}
-GLuint QPlatformTextureList::textureId(int index) const
+QRhiTexture *QPlatformTextureList::textureExtra(int index) const
{
Q_D(const QPlatformTextureList);
- return d->textures.at(index).textureId;
+ return d->textures.at(index).textureExtra;
}
void *QPlatformTextureList::source(int index)
@@ -154,13 +123,29 @@ bool QPlatformTextureList::isLocked() const
return d->locked;
}
-void QPlatformTextureList::appendTexture(void *source, GLuint textureId, const QRect &geometry,
+void QPlatformTextureList::appendTexture(void *source, QRhiTexture *texture, const QRect &geometry,
const QRect &clipRect, Flags flags)
{
Q_D(QPlatformTextureList);
QBackingstoreTextureInfo bi;
bi.source = source;
- bi.textureId = textureId;
+ bi.texture = texture;
+ bi.textureExtra = nullptr;
+ bi.rect = geometry;
+ bi.clipRect = clipRect;
+ bi.flags = flags;
+ d->textures.append(bi);
+}
+
+void QPlatformTextureList::appendTexture(void *source, QRhiTexture *textureLeft, QRhiTexture *textureRight, const QRect &geometry,
+ const QRect &clipRect, Flags flags)
+{
+ Q_D(QPlatformTextureList);
+
+ QBackingstoreTextureInfo bi;
+ bi.source = source;
+ bi.texture = textureLeft;
+ bi.textureExtra = textureRight;
bi.rect = geometry;
bi.clipRect = clipRect;
bi.flags = flags;
@@ -172,7 +157,6 @@ void QPlatformTextureList::clear()
Q_D(QPlatformTextureList);
d->textures.clear();
}
-#endif // QT_NO_OPENGL
/*!
\class QPlatformBackingStore
@@ -185,60 +169,81 @@ void QPlatformTextureList::clear()
windows.
*/
-#ifndef QT_NO_OPENGL
/*!
- Flushes the given \a region from the specified \a window onto the
- screen, and composes it with the specified \a textures.
-
- The default implementation retrieves the contents using toTexture()
- and composes using OpenGL. May be reimplemented in subclasses if there
- is a more efficient native way to do it.
+ Flushes the given \a region from the specified \a window.
\note \a region is relative to the window which may not be top-level in case
\a window corresponds to a native child widget. \a offset is the position of
the native child relative to the top-level window.
+
+ Unlike rhiFlush(), this function's default implementation does nothing. It
+ is expected that subclasses provide a platform-specific (non-QRhi-based)
+ implementation, if applicable on the given platform.
+
+ \sa rhiFlush()
*/
+void QPlatformBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(window);
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+}
+
+/*!
+ Flushes the given \a region from the specified \a window, and compositing
+ it with the specified \a textures list.
+
+ The default implementation retrieves the contents using toTexture() and
+ composes using QRhi with OpenGL, Metal, Vulkan, or Direct 3D underneath.
+ May be reimplemented in subclasses if customization is desired.
+
+ \note \a region is relative to the window which may not be top-level in case
+ \a window corresponds to a native child widget. \a offset is the position of
+ the native child relative to the top-level window.
-void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &region,
- const QPoint &offset,
- QPlatformTextureList *textures,
- bool translucentBackground)
+ \sa flush()
+ */
+QPlatformBackingStore::FlushResult QPlatformBackingStore::rhiFlush(QWindow *window,
+ qreal sourceDevicePixelRatio,
+ const QRegion &region,
+ const QPoint &offset,
+ QPlatformTextureList *textures,
+ bool translucentBackground)
{
- if (auto *c = d_ptr->openGLSupport)
- c->composeAndFlush(window, region, offset, textures, translucentBackground);
- else
- qWarning() << Q_FUNC_INFO << "no opengl support set";
+ return d_ptr->compositor.flush(this, d_ptr->rhiSupport.rhi(), d_ptr->rhiSupport.swapChainForWindow(window),
+ window, sourceDevicePixelRatio, region, offset, textures, translucentBackground);
}
-#endif
/*!
Implemented in subclasses to return the content of the backingstore as a QImage.
- If QPlatformIntegration::RasterGLSurface is supported, either this function or
+ If composition via a 3D graphics API is supported, either this function or
toTexture() must be implemented.
+ The returned image is only valid until the next operation (resize, paint, scroll,
+ or flush) on the backingstore. The caller must not store the return value between
+ calls, but instead call this function before each use, or make an explicit copy.
+
\sa toTexture()
*/
QImage QPlatformBackingStore::toImage() const
{
return QImage();
}
-#ifndef QT_NO_OPENGL
+
/*!
May be reimplemented in subclasses to return the content of the
- backingstore as an OpenGL texture. \a dirtyRegion is the part of the
+ backingstore as an QRhiTexture. \a dirtyRegion is the part of the
backingstore which may have changed since the last call to this function. The
caller of this function must ensure that there is a current context.
- The size of the texture is returned in \a textureSize.
-
The ownership of the texture is not transferred. The caller must not store
the return value between calls, but instead call this function before each use.
- The default implementation returns a cached texture if \a dirtyRegion is empty and
- \a textureSize matches the backingstore size, otherwise it retrieves the content using
- toImage() and performs a texture upload. This works only if the value of \a textureSize
- is preserved between the calls to this function.
+ The default implementation returns a cached texture if \a dirtyRegion is
+ empty and the existing texture's size matches the backingstore size,
+ otherwise it retrieves the content using toImage() and performs a texture
+ upload.
If the red and blue components have to swapped, \a flags will be set to include \c
TextureSwizzle. This allows creating textures from images in formats like
@@ -252,16 +257,12 @@ QImage QPlatformBackingStore::toImage() const
\note \a dirtyRegion is relative to the backingstore so no adjustment is needed.
*/
-GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const
+QRhiTexture *QPlatformBackingStore::toTexture(QRhiResourceUpdateBatch *resourceUpdates,
+ const QRegion &dirtyRegion,
+ TextureFlags *flags) const
{
- if (auto *c = d_ptr->openGLSupport)
- return c->toTexture(dirtyRegion, textureSize, flags);
- else {
- qWarning() << Q_FUNC_INFO << "no opengl support set";
- return 0;
- }
+ return d_ptr->compositor.toTexture(this, d_ptr->rhiSupport.rhi(), resourceUpdates, dirtyRegion, flags);
}
-#endif // QT_NO_OPENGL
/*!
\fn QPaintDevice* QPlatformBackingStore::paintDevice()
@@ -275,12 +276,6 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu
QPlatformBackingStore::QPlatformBackingStore(QWindow *window)
: d_ptr(new QPlatformBackingStorePrivate(window))
{
-#ifndef QT_NO_OPENGL
- if (auto createOpenGLSupport = QPlatformBackingStoreOpenGLSupportBase::factoryFunction()) {
- d_ptr->openGLSupport = createOpenGLSupport();
- d_ptr->openGLSupport->backingStore = this;
- }
-#endif
}
/*!
@@ -317,30 +312,6 @@ QBackingStore *QPlatformBackingStore::backingStore() const
return d_ptr->backingStore;
}
-#ifndef QT_NO_OPENGL
-
-using FactoryFunction = QPlatformBackingStoreOpenGLSupportBase::FactoryFunction;
-
-/*!
- Registers a factory function for OpenGL implementation helper.
-
- The QtOpenGL library automatically registers a default function,
- unless already set by the platform plugin in other ways.
-*/
-void QPlatformBackingStoreOpenGLSupportBase::setFactoryFunction(FactoryFunction function)
-{
- s_factoryFunction = function;
-}
-
-FactoryFunction QPlatformBackingStoreOpenGLSupportBase::factoryFunction()
-{
- return s_factoryFunction;
-}
-
-FactoryFunction QPlatformBackingStoreOpenGLSupportBase::s_factoryFunction = nullptr;
-
-#endif // QT_NO_OPENGL
-
/*!
This function is called before painting onto the surface begins,
with the \a region in which the painting will occur.
@@ -385,4 +356,36 @@ bool QPlatformBackingStore::scroll(const QRegion &area, int dx, int dy)
return false;
}
+void QPlatformBackingStore::setRhiConfig(const QPlatformBackingStoreRhiConfig &config)
+{
+ if (!config.isEnabled())
+ return;
+
+ d_ptr->rhiSupport.setConfig(config);
+ d_ptr->rhiSupport.setWindow(d_ptr->window);
+ d_ptr->rhiSupport.setFormat(d_ptr->window->format());
+ d_ptr->rhiSupport.create();
+}
+
+QRhi *QPlatformBackingStore::rhi() const
+{
+ // Returning null is valid, and means this is not a QRhi-capable backingstore.
+ return d_ptr->rhiSupport.rhi();
+}
+
+void QPlatformBackingStore::graphicsDeviceReportedLost()
+{
+ if (!d_ptr->rhiSupport.rhi())
+ return;
+
+ qWarning("Rhi backingstore: graphics device lost, attempting to reinitialize");
+ d_ptr->compositor.reset();
+ d_ptr->rhiSupport.reset();
+ d_ptr->rhiSupport.create();
+ if (!d_ptr->rhiSupport.rhi())
+ qWarning("Rhi backingstore: failed to reinitialize after losing the device");
+}
+
QT_END_NAMESPACE
+
+#include "moc_qplatformbackingstore.cpp"
diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h
index e0fdca2f21..1d55e9ab6a 100644
--- a/src/gui/painting/qplatformbackingstore.h
+++ b/src/gui/painting/qplatformbackingstore.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMBACKINGSTORE_H
#define QPLATFORMBACKINGSTORE_H
@@ -56,11 +20,10 @@
#include <QtGui/qwindow.h>
#include <QtGui/qregion.h>
-#include <QtGui/qopengl.h>
QT_BEGIN_NAMESPACE
-Q_GUI_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcQpaBackingStore)
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcQpaBackingStore, Q_GUI_EXPORT)
class QRegion;
class QRect;
@@ -70,9 +33,58 @@ class QPlatformBackingStorePrivate;
class QPlatformTextureList;
class QPlatformTextureListPrivate;
class QPlatformGraphicsBuffer;
-class QPlatformBackingStoreOpenGLSupportBase;
+class QRhi;
+class QRhiTexture;
+class QRhiResourceUpdateBatch;
+
+struct Q_GUI_EXPORT QPlatformBackingStoreRhiConfig
+{
+ enum Api {
+ OpenGL,
+ Metal,
+ Vulkan,
+ D3D11,
+ D3D12,
+ Null
+ };
+
+ QPlatformBackingStoreRhiConfig()
+ : m_enable(false)
+ { }
+
+ QPlatformBackingStoreRhiConfig(Api api)
+ : m_enable(true),
+ m_api(api)
+ { }
+
+ bool isEnabled() const { return m_enable; }
+ void setEnabled(bool enable) { m_enable = enable; }
+
+ Api api() const { return m_api; }
+ void setApi(Api api) { m_api = api; }
+
+ bool isDebugLayerEnabled() const { return m_debugLayer; }
+ void setDebugLayer(bool enable) { m_debugLayer = enable; }
+
+private:
+ bool m_enable;
+ Api m_api = Null;
+ bool m_debugLayer = false;
+ friend bool operator==(const QPlatformBackingStoreRhiConfig &a, const QPlatformBackingStoreRhiConfig &b);
+};
+
+inline bool operator==(const QPlatformBackingStoreRhiConfig &a, const QPlatformBackingStoreRhiConfig &b)
+{
+ return a.m_enable == b.m_enable
+ && a.m_api == b.m_api
+ && a.m_debugLayer == b.m_debugLayer;
+}
+
+inline bool operator!=(const QPlatformBackingStoreRhiConfig &a, const QPlatformBackingStoreRhiConfig &b)
+{
+ return !(a == b);
+}
-#ifndef QT_NO_OPENGL
class Q_GUI_EXPORT QPlatformTextureList : public QObject
{
Q_OBJECT
@@ -81,7 +93,8 @@ public:
enum Flag {
StacksOnTop = 0x01,
TextureIsSrgb = 0x02,
- NeedsPremultipliedAlphaBlending = 0x04
+ NeedsPremultipliedAlphaBlending = 0x04,
+ MirrorVertically = 0x08
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -90,7 +103,8 @@ public:
int count() const;
bool isEmpty() const { return count() == 0; }
- GLuint textureId(int index) const;
+ QRhiTexture *texture(int index) const;
+ QRhiTexture *textureExtra(int index) const;
QRect geometry(int index) const;
QRect clipRect(int index) const;
void *source(int index);
@@ -98,7 +112,10 @@ public:
void lock(bool on);
bool isLocked() const;
- void appendTexture(void *source, GLuint textureId, const QRect &geometry,
+ void appendTexture(void *source, QRhiTexture *texture, const QRect &geometry,
+ const QRect &clipRect = QRect(), Flags flags = { });
+
+ void appendTexture(void *source, QRhiTexture *textureLeft, QRhiTexture *textureRight, const QRect &geometry,
const QRect &clipRect = QRect(), Flags flags = { });
void clear();
@@ -106,11 +123,16 @@ public:
void locked(bool);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformTextureList::Flags)
-#endif
class Q_GUI_EXPORT QPlatformBackingStore
{
public:
+ enum FlushResult {
+ FlushSuccess,
+ FlushFailed,
+ FlushFailedDueToLostDevice
+ };
+
explicit QPlatformBackingStore(QWindow *window);
virtual ~QPlatformBackingStore();
@@ -119,22 +141,26 @@ public:
virtual QPaintDevice *paintDevice() = 0;
- virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset) = 0;
-#ifndef QT_NO_OPENGL
- virtual void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
+ virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset);
+
+ virtual FlushResult rhiFlush(QWindow *window,
+ qreal sourceDevicePixelRatio,
+ const QRegion &region,
+ const QPoint &offset,
QPlatformTextureList *textures,
bool translucentBackground);
-#endif
+
virtual QImage toImage() const;
-#ifndef QT_NO_OPENGL
+
enum TextureFlag {
TextureSwizzle = 0x01,
TextureFlip = 0x02,
- TexturePremultiplied = 0x04,
+ TexturePremultiplied = 0x04
};
Q_DECLARE_FLAGS(TextureFlags, TextureFlag)
- virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const;
-#endif
+ virtual QRhiTexture *toTexture(QRhiResourceUpdateBatch *resourceUpdates,
+ const QRegion &dirtyRegion,
+ TextureFlags *flags) const;
virtual QPlatformGraphicsBuffer *graphicsBuffer() const;
@@ -145,6 +171,11 @@ public:
virtual void beginPaint(const QRegion &);
virtual void endPaint();
+ void setRhiConfig(const QPlatformBackingStoreRhiConfig &config);
+ QRhi *rhi() const;
+ void surfaceAboutToBeDestroyed();
+ void graphicsDeviceReportedLost();
+
private:
QPlatformBackingStorePrivate *d_ptr;
@@ -152,31 +183,7 @@ private:
friend class QBackingStore;
};
-#ifndef QT_NO_OPENGL
-class Q_GUI_EXPORT QPlatformBackingStoreOpenGLSupportBase
-{
-public:
- virtual void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
- QPlatformTextureList *textures, bool translucentBackground) = 0;
- virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, QPlatformBackingStore::TextureFlags *flags) const = 0;
- virtual ~QPlatformBackingStoreOpenGLSupportBase() {}
-
- using FactoryFunction = QPlatformBackingStoreOpenGLSupportBase *(*)();
- static void setFactoryFunction(FactoryFunction);
- static FactoryFunction factoryFunction();
-
-protected:
- QPlatformBackingStore *backingStore = nullptr;
- friend class QPlatformBackingStore;
-
-private:
- static FactoryFunction s_factoryFunction;
-};
-#endif // QT_NO_OPENGL
-
-#ifndef QT_NO_OPENGL
Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformBackingStore::TextureFlags)
-#endif
QT_END_NAMESPACE
diff --git a/src/gui/painting/qpolygon.cpp b/src/gui/painting/qpolygon.cpp
index d601dcdb0c..d615245eb4 100644
--- a/src/gui/painting/qpolygon.cpp
+++ b/src/gui/painting/qpolygon.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpolygon.h"
#include "qrect.h"
@@ -263,13 +227,16 @@ void QPolygon::point(int index, int *x, int *y) const
*/
/*!
- \fn void QPolygon::setPoint(int index, int x, int y)
-
Sets the point at the given \a index to the point specified by
(\a{x}, \a{y}).
\sa point(), putPoints(), setPoints(),
*/
+void QPolygon::setPoint(int index, int x, int y)
+{
+ (*this)[index] = QPoint(x, y);
+}
+
/*!
Resizes the polygon to \a nPoints and populates it with the given
@@ -439,15 +406,20 @@ QRect QPolygon::boundingRect() const
return QRect(QPoint(minx,miny), QPoint(maxx,maxy));
}
+/*!
+ \fn QPolygon::toPolygonF() const
+ \since 6.4
+
+ Returns this polygon as a polygon with floating point accuracy.
+
+ \sa QPolygonF::toPolygon()
+*/
+
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QPolygon &a)
{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "QPolygon(";
- for (int i = 0; i < a.count(); ++i)
- dbg.nospace() << a.at(i);
- dbg.nospace() << ')';
- return dbg;
+ return QtPrivate::printSequentialContainer(dbg, "QPolygon", a);
}
#endif
@@ -725,13 +697,7 @@ QDataStream &operator>>(QDataStream &s, QPolygon &a)
QDataStream &operator<<(QDataStream &s, const QPolygonF &a)
{
- quint32 len = a.size();
- uint i;
-
- s << len;
- for (i = 0; i < len; ++i)
- s << a.at(i);
- return s;
+ return s << static_cast<const QList<QPointF> &>(a);
}
/*!
@@ -746,29 +712,14 @@ QDataStream &operator<<(QDataStream &s, const QPolygonF &a)
QDataStream &operator>>(QDataStream &s, QPolygonF &a)
{
- quint32 len;
- uint i;
-
- s >> len;
- a.reserve(a.size() + (int)len);
- QPointF p;
- for (i = 0; i < len; ++i) {
- s >> p;
- a.insert(i, p);
- }
- return s;
+ return s >> static_cast<QList<QPointF> &>(a);
}
#endif //QT_NO_DATASTREAM
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QPolygonF &a)
{
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "QPolygonF(";
- for (int i = 0; i < a.count(); ++i)
- dbg.nospace() << a.at(i);
- dbg.nospace() << ')';
- return dbg;
+ return QtPrivate::printSequentialContainer(dbg, "QPolygonF", a);
}
#endif
diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h
index 32567dcef8..f2f5d48395 100644
--- a/src/gui/painting/qpolygon.h
+++ b/src/gui/painting/qpolygon.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPOLYGON_H
#define QPOLYGON_H
@@ -51,7 +15,9 @@ class QTransform;
class QRect;
class QVariant;
-// We export each out-of-line method invidually to prevent MSVC from
+class QPolygonF;
+
+// We export each out-of-line method individually to prevent MSVC from
// exporting the whole QList class.
class QPolygon : public QList<QPoint>
{
@@ -76,8 +42,8 @@ public:
Q_GUI_EXPORT void point(int i, int *x, int *y) const;
QPoint point(int i) const;
- void setPoint(int index, int x, int y);
- void setPoint(int index, const QPoint &p);
+ Q_GUI_EXPORT void setPoint(int index, int x, int y);
+ inline void setPoint(int index, const QPoint &p);
Q_GUI_EXPORT void setPoints(int nPoints, const int *points);
Q_GUI_EXPORT void setPoints(int nPoints, int firstx, int firsty, ...);
Q_GUI_EXPORT void putPoints(int index, int nPoints, const int *points);
@@ -91,6 +57,8 @@ public:
[[nodiscard]] Q_GUI_EXPORT QPolygon subtracted(const QPolygon &r) const;
Q_GUI_EXPORT bool intersects(const QPolygon &r) const;
+
+ [[nodiscard]] inline QPolygonF toPolygonF() const;
};
Q_DECLARE_SHARED(QPolygon)
@@ -111,10 +79,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QPolygon &polygon);
*****************************************************************************/
inline void QPolygon::setPoint(int index, const QPoint &pt)
-{ (*this)[index] = pt; }
-
-inline void QPolygon::setPoint(int index, int x, int y)
-{ (*this)[index] = QPoint(x, y); }
+{ setPoint(index, pt.x(), pt.y()); }
inline QPoint QPolygon::point(int index) const
{ return at(index); }
@@ -162,6 +127,8 @@ public:
};
Q_DECLARE_SHARED(QPolygonF)
+QPolygonF QPolygon::toPolygonF() const { return QPolygonF(*this); }
+
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QPolygonF &);
#endif
diff --git a/src/gui/painting/qrasterbackingstore.cpp b/src/gui/painting/qrasterbackingstore.cpp
index a3ffe11d19..3b3ef2fd2e 100644
--- a/src/gui/painting/qrasterbackingstore.cpp
+++ b/src/gui/painting/qrasterbackingstore.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qrasterbackingstore_p.h"
@@ -82,7 +46,7 @@ QImage QRasterBackingStore::toImage() const
bool QRasterBackingStore::scroll(const QRegion &region, int dx, int dy)
{
- if (window()->surfaceType() != QSurface::RasterSurface)
+ if (!QPlatformSurface::isRasterSurface(window()))
return false;
extern void qt_scrollRectInImage(QImage &, const QRect &, const QPoint &);
@@ -90,8 +54,8 @@ bool QRasterBackingStore::scroll(const QRegion &region, int dx, int dy)
const qreal devicePixelRatio = m_image.devicePixelRatio();
const QPoint delta(dx * devicePixelRatio, dy * devicePixelRatio);
- for (const QRect &rect : region)
- qt_scrollRectInImage(m_image, QRect(rect.topLeft() * devicePixelRatio, rect.size() * devicePixelRatio), delta);
+ const QRect rect = region.boundingRect();
+ qt_scrollRectInImage(m_image, QRect(rect.topLeft() * devicePixelRatio, rect.size() * devicePixelRatio), delta);
return true;
}
@@ -103,7 +67,7 @@ void QRasterBackingStore::beginPaint(const QRegion &region)
if (m_image.devicePixelRatio() != nativeWindowDevicePixelRatio || m_image.size() != effectiveBufferSize) {
m_image = QImage(effectiveBufferSize, format());
m_image.setDevicePixelRatio(nativeWindowDevicePixelRatio);
- if (m_image.format() == QImage::Format_ARGB32_Premultiplied)
+ if (m_image.hasAlphaChannel())
m_image.fill(Qt::transparent);
}
diff --git a/src/gui/painting/qrasterbackingstore_p.h b/src/gui/painting/qrasterbackingstore_p.h
index 01d75c655b..be8d122655 100644
--- a/src/gui/painting/qrasterbackingstore_p.h
+++ b/src/gui/painting/qrasterbackingstore_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRASTERBACKINGSTORE_P_H
#define QRASTERBACKINGSTORE_P_H
@@ -52,6 +16,7 @@
//
#include <qpa/qplatformbackingstore.h>
+#include <private/qglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/painting/qrasterdefs_p.h b/src/gui/painting/qrasterdefs_p.h
index f1ab64a70e..f6bf3bb0c8 100644
--- a/src/gui/painting/qrasterdefs_p.h
+++ b/src/gui/painting/qrasterdefs_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/***************************************************************************/
/* */
diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp
index 7b26b20db8..cd9d3ba4d0 100644
--- a/src/gui/painting/qrasterizer.cpp
+++ b/src/gui/painting/qrasterizer.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qrasterizer_p.h"
@@ -744,6 +708,63 @@ static inline QScFixed qSafeFloatToQScFixed(qreal x)
return QScFixed(tmp);
}
+// returns true if the whole line gets clipped away
+static inline bool qClipLine(QPointF *pt1, QPointF *pt2, const QRectF &clip)
+{
+ qreal &x1 = pt1->rx();
+ qreal &y1 = pt1->ry();
+ qreal &x2 = pt2->rx();
+ qreal &y2 = pt2->ry();
+
+ if (!qIsFinite(x1) || !qIsFinite(y1) || !qIsFinite(x2) || !qIsFinite(y2))
+ return true;
+
+ const qreal xmin = clip.left();
+ const qreal xmax = clip.right();
+ const qreal ymin = clip.top();
+ const qreal ymax = clip.bottom();
+
+ if (x1 < xmin) {
+ if (x2 <= xmin)
+ return true;
+ y1 += (y2 - y1) / (x2 - x1) * (xmin - x1);
+ x1 = xmin;
+ } else if (x1 > xmax) {
+ if (x2 >= xmax)
+ return true;
+ y1 += (y2 - y1) / (x2 - x1) * (xmax - x1);
+ x1 = xmax;
+ }
+ if (x2 < xmin) {
+ y2 += (y2 - y1) / (x2 - x1) * (xmin - x2);
+ x2 = xmin;
+ } else if (x2 > xmax) {
+ y2 += (y2 - y1) / (x2 - x1) * (xmax - x2);
+ x2 = xmax;
+ }
+
+ if (y1 < ymin) {
+ if (y2 <= ymin)
+ return true;
+ x1 += (x2 - x1) / (y2 - y1) * (ymin - y1);
+ y1 = ymin;
+ } else if (y1 > ymax) {
+ if (y2 >= ymax)
+ return true;
+ x1 += (x2 - x1) / (y2 - y1) * (ymax - y1);
+ y1 = ymax;
+ }
+ if (y2 < ymin) {
+ x2 += (x2 - x1) / (y2 - y1) * (ymin - y2);
+ y2 = ymin;
+ } else if (y2 > ymax) {
+ x2 += (x2 - x1) / (y2 - y1) * (ymax - y2);
+ y2 = ymax;
+ }
+
+ return false;
+}
+
void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, bool squareCap)
{
if (a == b || !(width > 0.0) || d->clipRect.isEmpty())
@@ -760,42 +781,8 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
QPointF offs = QPointF(qAbs(b.y() - a.y()), qAbs(b.x() - a.x())) * width * 0.5;
const QRectF clip(d->clipRect.topLeft() - offs, d->clipRect.bottomRight() + QPoint(1, 1) + offs);
-
- if (!clip.contains(pa) || !clip.contains(pb)) {
- qreal t1 = 0;
- qreal t2 = 1;
-
- const qreal o[2] = { pa.x(), pa.y() };
- const qreal d[2] = { pb.x() - pa.x(), pb.y() - pa.y() };
-
- const qreal low[2] = { clip.left(), clip.top() };
- const qreal high[2] = { clip.right(), clip.bottom() };
-
- for (int i = 0; i < 2; ++i) {
- if (d[i] == 0) {
- if (o[i] <= low[i] || o[i] >= high[i])
- return;
- continue;
- }
- const qreal d_inv = 1 / d[i];
- qreal t_low = (low[i] - o[i]) * d_inv;
- qreal t_high = (high[i] - o[i]) * d_inv;
- if (t_low > t_high)
- qSwap(t_low, t_high);
- if (t1 < t_low)
- t1 = t_low;
- if (t2 > t_high)
- t2 = t_high;
- if (t1 >= t2)
- return;
- }
-
- QPointF npa = pa + (pb - pa) * t1;
- QPointF npb = pa + (pb - pa) * t2;
-
- pa = npa;
- pb = npb;
- }
+ if (qClipLine(&pa, &pb, clip))
+ return;
{
// old delta
@@ -1077,28 +1064,26 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
while (x <= leftMax) {
QScFixed excluded = 0;
- if (yFP <= iLeftFP)
+ if (yFP <= iLeftFP && rowBottomLeft > rowTop)
excluded += intersectPixelFP(x, rowTop, rowBottomLeft,
bottomLeftIntersectAf, topLeftIntersectAf,
topLeftSlopeFP, invTopLeftSlopeFP);
- if (yFP >= iLeftFP)
+ if (yFP >= iLeftFP && rowBottom > rowTopLeft)
excluded += intersectPixelFP(x, rowTopLeft, rowBottom,
topLeftIntersectBf, bottomLeftIntersectBf,
bottomLeftSlopeFP, invBottomLeftSlopeFP);
-
if (x >= rightMin) {
- if (yFP <= iRightFP)
+ if (yFP <= iRightFP && rowBottomRight > rowTop)
excluded += (rowBottomRight - rowTop) - intersectPixelFP(x, rowTop, rowBottomRight,
topRightIntersectAf, bottomRightIntersectAf,
topRightSlopeFP, invTopRightSlopeFP);
- if (yFP >= iRightFP)
+ if (yFP >= iRightFP && rowBottom > rowTopRight)
excluded += (rowBottom - rowTopRight) - intersectPixelFP(x, rowTopRight, rowBottom,
bottomRightIntersectBf, topRightIntersectBf,
bottomRightSlopeFP, invBottomRightSlopeFP);
}
- if (excluded > QScFixedFactor)
- excluded = excluded % QScFixedFactor;
+ Q_ASSERT(excluded >= 0 && excluded <= rowHeight);
QScFixed coverage = rowHeight - excluded;
buffer.addSpan(x, 1, QScFixedToInt(yFP),
QScFixedToInt(255 * coverage));
@@ -1111,17 +1096,16 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
}
while (x <= rightMax) {
QScFixed excluded = 0;
- if (yFP <= iRightFP)
+ if (yFP <= iRightFP && rowBottomRight > rowTop)
excluded += (rowBottomRight - rowTop) - intersectPixelFP(x, rowTop, rowBottomRight,
topRightIntersectAf, bottomRightIntersectAf,
topRightSlopeFP, invTopRightSlopeFP);
- if (yFP >= iRightFP)
+ if (yFP >= iRightFP && rowBottom > rowTopRight)
excluded += (rowBottom - rowTopRight) - intersectPixelFP(x, rowTopRight, rowBottom,
bottomRightIntersectBf, topRightIntersectBf,
bottomRightSlopeFP, invBottomRightSlopeFP);
- if (excluded > QScFixedFactor)
- excluded = excluded % QScFixedFactor;
+ Q_ASSERT(excluded >= 0 && excluded <= rowHeight);
QScFixed coverage = rowHeight - excluded;
buffer.addSpan(x, 1, QScFixedToInt(yFP),
QScFixedToInt(255 * coverage));
diff --git a/src/gui/painting/qrasterizer_p.h b/src/gui/painting/qrasterizer_p.h
index b6f3e83c6c..f12ab1b812 100644
--- a/src/gui/painting/qrasterizer_p.h
+++ b/src/gui/painting/qrasterizer_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRASTERIZER_P_H
#define QRASTERIZER_P_H
diff --git a/src/gui/painting/qrbtree_p.h b/src/gui/painting/qrbtree_p.h
index 42539bf8e9..e42c4081f6 100644
--- a/src/gui/painting/qrbtree_p.h
+++ b/src/gui/painting/qrbtree_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRBTREE_P_H
#define QRBTREE_P_H
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 6ca87cb416..8b712ee46d 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qregion.h"
#include "qpainterpath.h"
@@ -48,6 +12,7 @@
#include "qbitmap.h"
#include "qtransform.h"
+#include <memory>
#include <private/qdebug_p.h>
#ifdef Q_OS_WIN
@@ -86,7 +51,7 @@ QT_BEGIN_NAMESPACE
contains() a QPoint or QRect. The bounding rectangle can be found
with boundingRect().
- Iteration over the region (with begin(), end(), or C++11
+ Iteration over the region (with begin(), end(), or
ranged-for loops) gives a decomposition of the region into
rectangles.
@@ -671,7 +636,7 @@ bool QRegion::intersects(const QRegion &region) const
*/
-#if !defined (Q_OS_UNIX) && !defined (Q_OS_WIN) || defined(Q_CLANG_QDOC)
+#if !defined (Q_OS_UNIX) && !defined (Q_OS_WIN) || defined(Q_QDOC)
/*
\overload
\since 4.4
@@ -3226,8 +3191,7 @@ static void CreateETandAET(int count, const QPoint *pts,
int iSLLBlock = 0;
int dy;
- if (count < 2)
- return;
+ Q_ASSERT(count > 1);
/*
* initialize the Active Edge Table
@@ -3573,7 +3537,7 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
POINTBLOCK *tmpPtBlock;
int numFullPtBlocks = 0;
- Q_ASSUME(Count > 1);
+ Q_ASSERT(Count > 1);
region = new QRegionPrivate;
@@ -3853,7 +3817,7 @@ QRegion::QRegion(const QRect &r, RegionType t)
QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule)
{
- if (a.count() > 2) {
+ if (a.size() > 2) {
QRegionPrivate *qt_rgn = PolygonRegion(a.constData(), a.size(),
fillRule == Qt::WindingFill ? WindingRule : EvenOddRule);
if (qt_rgn) {
@@ -3915,7 +3879,7 @@ QRegion &QRegion::operator=(const QRegion &r)
QRegion QRegion::copy() const
{
QRegion r;
- QScopedPointer<QRegionData> x(new QRegionData);
+ auto x = std::make_unique<QRegionData>();
x->ref.initializeOwned();
if (d->qt_rgn)
x->qt_rgn = new QRegionPrivate(*d->qt_rgn);
@@ -3923,7 +3887,7 @@ QRegion QRegion::copy() const
x->qt_rgn = new QRegionPrivate;
if (!r.d->ref.deref())
cleanUp(r.d);
- r.d = x.take();
+ r.d = x.release();
return r;
}
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index 8f52185ed9..b0051b6067 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QREGION_H
#define QREGION_H
@@ -70,12 +34,12 @@ public:
QRegion(const QPolygon &pa, Qt::FillRule fillRule = Qt::OddEvenFill);
QRegion(const QRegion &region);
QRegion(QRegion &&other) noexcept
- : d(qExchange(other.d, const_cast<QRegionData*>(&shared_empty))) {}
+ : d(std::exchange(other.d, const_cast<QRegionData*>(&shared_empty))) {}
QRegion(const QBitmap &bitmap);
~QRegion();
QRegion &operator=(const QRegion &);
- QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QRegion);
- inline void swap(QRegion &other) noexcept { qSwap(d, other.d); }
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QRegion)
+ void swap(QRegion &other) noexcept { qt_ptr_swap(d, other.d); }
bool isEmpty() const;
bool isNull() const;
diff --git a/src/gui/painting/qrgb.h b/src/gui/painting/qrgb.h
index 5635b69ec4..150d889d33 100644
--- a/src/gui/painting/qrgb.h
+++ b/src/gui/painting/qrgb.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRGB_H
#define QRGB_H
diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h
index 2c644c4cf0..9c0c210320 100644
--- a/src/gui/painting/qrgba64.h
+++ b/src/gui/painting/qrgba64.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRGBA64_H
#define QRGBA64_H
@@ -118,7 +82,6 @@ public:
constexpr quint8 alpha8() const { return div_257(alpha()); }
constexpr uint toArgb32() const
{
-#if defined(__cpp_constexpr) && __cpp_constexpr-0 >= 201304
quint64 br = rgba & Q_UINT64_C(0xffff0000ffff);
quint64 ag = (rgba >> 16) & Q_UINT64_C(0xffff0000ffff);
br += Q_UINT64_C(0x8000000080);
@@ -136,9 +99,6 @@ public:
| (ag & 0xff00)
| ((br >> 32) & 0xff);
#endif
-#else
- return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8());
-#endif
}
constexpr ushort toRgb16() const
{
diff --git a/src/gui/painting/qrgba64.qdoc b/src/gui/painting/qrgba64.qdoc
index 3ee8a355e6..fd78b539a3 100644
--- a/src/gui/painting/qrgba64.qdoc
+++ b/src/gui/painting/qrgba64.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QRgba64
diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h
index aa447b690e..ae8b6fd8cb 100644
--- a/src/gui/painting/qrgba64_p.h
+++ b/src/gui/painting/qrgba64_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRGBA64_P_H
#define QRGBA64_P_H
@@ -117,18 +81,22 @@ static inline QRgba64 multiplyAlpha65535(QRgba64 rgba64, uint alpha65535)
#endif
}
+#if defined(__SSE2__) || defined(__ARM_NEON__)
template<typename T>
static inline T Q_DECL_VECTORCALL multiplyAlpha255(T rgba64, uint alpha255)
{
-#if defined(__SSE2__) || defined(__ARM_NEON__)
return multiplyAlpha65535(rgba64, alpha255 * 257);
+}
#else
+template<typename T>
+static inline T multiplyAlpha255(T rgba64, uint alpha255)
+{
return QRgba64::fromRgba64(qt_div_255(rgba64.red() * alpha255),
qt_div_255(rgba64.green() * alpha255),
qt_div_255(rgba64.blue() * alpha255),
qt_div_255(rgba64.alpha() * alpha255));
-#endif
}
+#endif
#if defined __SSE2__
static inline __m128i Q_DECL_VECTORCALL interpolate255(__m128i x, uint alpha1, __m128i y, uint alpha2)
diff --git a/src/gui/painting/qrgbafloat.h b/src/gui/painting/qrgbafloat.h
index 8d81850b4d..da74328f71 100644
--- a/src/gui/painting/qrgbafloat.h
+++ b/src/gui/painting/qrgbafloat.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRGBAFLOAT_H
#define QRGBAFLOAT_H
@@ -55,7 +19,13 @@ class alignas(sizeof(F) * 4) QRgbaFloat
static_assert(std::is_same<F, qfloat16>::value || std::is_same<F, float>::value);
public:
using Type = F;
+#if defined(__AVX512FP16__) && QFLOAT16_IS_NATIVE
+ // AVX512FP16 has multiplication instructions
+ using FastType = F;
+#else
+ // use FP32 for multiplications
using FastType = float;
+#endif
F r;
F g;
F b;
@@ -64,21 +34,23 @@ public:
static constexpr
QRgbaFloat fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
{
+ constexpr FastType scale = FastType(1.0f / 65535.0f);
return QRgbaFloat{
- red * (1.0f / 65535.0f),
- green * (1.0f / 65535.0f),
- blue * (1.0f / 65535.0f),
- alpha * (1.0f / 65535.0f) };
+ F(red * scale),
+ F(green * scale),
+ F(blue * scale),
+ F(alpha * scale) };
}
static constexpr
QRgbaFloat fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
{
+ constexpr FastType scale = FastType(1.0f / 255.0f);
return QRgbaFloat{
- red * (1.0f / 255.0f),
- green * (1.0f / 255.0f),
- blue * (1.0f / 255.0f),
- alpha * (1.0f / 255.0f) };
+ F(red * scale),
+ F(green * scale),
+ F(blue * scale),
+ F(alpha * scale) };
}
static constexpr
QRgbaFloat fromArgb32(uint rgb)
@@ -86,36 +58,36 @@ public:
return fromRgba(quint8(rgb >> 16), quint8(rgb >> 8), quint8(rgb), quint8(rgb >> 24));
}
- constexpr bool isOpaque() const { return a >= 1.0f; }
- constexpr bool isTransparent() const { return a <= 0.0f; }
-
- constexpr FastType red() const { return r; }
- constexpr FastType green() const { return g; }
- constexpr FastType blue() const { return b; }
- constexpr FastType alpha() const { return a; }
- void setRed(FastType _red) { r = _red; }
- void setGreen(FastType _green) { g = _green; }
- void setBlue(FastType _blue) { b = _blue; }
- void setAlpha(FastType _alpha) { a = _alpha; }
-
- constexpr FastType redNormalized() const { return std::clamp(static_cast<FastType>(r), 0.0f, 1.0f); }
- constexpr FastType greenNormalized() const { return std::clamp(static_cast<FastType>(g), 0.0f, 1.0f); }
- constexpr FastType blueNormalized() const { return std::clamp(static_cast<FastType>(b), 0.0f, 1.0f); }
- constexpr FastType alphaNormalized() const { return std::clamp(static_cast<FastType>(a), 0.0f, 1.0f); }
-
- constexpr quint8 red8() const { return std::lround(redNormalized() * 255.0f); }
- constexpr quint8 green8() const { return std::lround(greenNormalized() * 255.0f); }
- constexpr quint8 blue8() const { return std::lround(blueNormalized() * 255.0f); }
- constexpr quint8 alpha8() const { return std::lround(alphaNormalized() * 255.0f); }
+ constexpr bool isOpaque() const { return a >= FastType(1.0f); }
+ constexpr bool isTransparent() const { return a <= FastType(0.0f); }
+
+ constexpr float red() const { return r; }
+ constexpr float green() const { return g; }
+ constexpr float blue() const { return b; }
+ constexpr float alpha() const { return a; }
+ void setRed(float _red) { r = F(_red); }
+ void setGreen(float _green) { g = F(_green); }
+ void setBlue(float _blue) { b = F(_blue); }
+ void setAlpha(float _alpha) { a = F(_alpha); }
+
+ constexpr float redNormalized() const { return clamp01(r); }
+ constexpr float greenNormalized() const { return clamp01(g); }
+ constexpr float blueNormalized() const { return clamp01(b); }
+ constexpr float alphaNormalized() const { return clamp01(a); }
+
+ constexpr quint8 red8() const { return qRound(redNormalized() * FastType(255.0f)); }
+ constexpr quint8 green8() const { return qRound(greenNormalized() * FastType(255.0f)); }
+ constexpr quint8 blue8() const { return qRound(blueNormalized() * FastType(255.0f)); }
+ constexpr quint8 alpha8() const { return qRound(alphaNormalized() * FastType(255.0f)); }
constexpr uint toArgb32() const
{
return uint((alpha8() << 24) | (red8() << 16) | (green8() << 8) | blue8());
}
- constexpr quint16 red16() const { return std::lround(redNormalized() * 65535.0f); }
- constexpr quint16 green16() const { return std::lround(greenNormalized() * 65535.0f); }
- constexpr quint16 blue16() const { return std::lround(blueNormalized() * 65535.0f); }
- constexpr quint16 alpha16() const { return std::lround(alphaNormalized() * 65535.0f); }
+ constexpr quint16 red16() const { return qRound(redNormalized() * FastType(65535.0f)); }
+ constexpr quint16 green16() const { return qRound(greenNormalized() * FastType(65535.0f)); }
+ constexpr quint16 blue16() const { return qRound(blueNormalized() * FastType(65535.0f)); }
+ constexpr quint16 alpha16() const { return qRound(alphaNormalized() * FastType(65535.0f)); }
constexpr Q_ALWAYS_INLINE QRgbaFloat premultiplied() const
{
@@ -123,12 +95,26 @@ public:
}
constexpr Q_ALWAYS_INLINE QRgbaFloat unpremultiplied() const
{
- if (a <= 0.0f)
- return QRgbaFloat{0.0f, 0.0f, 0.0f, 0.0f};
- if (a >= 1.0f)
+ if (a <= F{0.0f})
+ return QRgbaFloat{}; // default-initialization: zeroes
+ if (a >= F{1.0f})
return *this;
const FastType ia = 1.0f / a;
- return QRgbaFloat{r * ia, g * ia, b * ia, a};
+ return QRgbaFloat{F(r * ia), F(g * ia), F(b * ia), F(a)};
+ }
+ constexpr bool operator==(QRgbaFloat f) const
+ {
+ return r == f.r && g == f.g && b == f.b && a == f.a;
+ }
+ constexpr bool operator!=(QRgbaFloat f) const
+ {
+ return !(*this == f);
+ }
+
+private:
+ constexpr static FastType clamp01(Type f)
+ {
+ return std::clamp(FastType(f), FastType(0.0f), FastType(1.0f));
}
};
diff --git a/src/gui/painting/qrgbafloat.qdoc b/src/gui/painting/qrgbafloat.qdoc
index bcfe355c08..3ec0d209f4 100644
--- a/src/gui/painting/qrgbafloat.qdoc
+++ b/src/gui/painting/qrgbafloat.qdoc
@@ -1,29 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\class QRgbaFloat
@@ -57,7 +33,7 @@
*/
/*!
- \fn template<typename F> QRgbaFloat<F>::fromRgba64(quint16 r, quint16 g, quint16 b, quint16 a)
+ \fn template<typename F> QRgbaFloat QRgbaFloat<F>::fromRgba64(quint16 red, quint16 green, quint16 blue, quint16 alpha)
Constructs a QRgbaFloat value from the four 16-bit integer color channels \a red, \a green, \a blue and \a alpha.
@@ -65,7 +41,7 @@
*/
/*!
- \fn template<typename F> QRgbaFloat<F>::fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
+ \fn template<typename F> QRgbaFloat QRgbaFloat<F>::fromRgba(quint8 red, quint8 green, quint8 blue, quint8 alpha)
Constructs a QRgbaFloat value from the four 8-bit color channels \a red, \a green, \a blue and \a alpha.
@@ -73,7 +49,7 @@
*/
/*!
- \fn template<typename F> QRgbaFloat<F>::fromArgb32(uint rgb)
+ \fn template<typename F> QRgbaFloat QRgbaFloat<F>::fromArgb32(uint rgb)
Constructs a QRgbaFloat value from the 32bit ARGB value \a rgb.
@@ -105,7 +81,7 @@
*/
/*!
- \fn template<typename F> void QRgbaFloat<F>::setRed(QRgbaFloat::FastType red)
+ \fn template<typename F> void QRgbaFloat<F>::setRed(float red)
Sets the red color component of this color to \a red.
@@ -121,7 +97,7 @@
*/
/*!
- \fn template<typename F> void QRgbaFloat<F>::setGreen(QRgbaFloat::FastType green)
+ \fn template<typename F> void QRgbaFloat<F>::setGreen(float green)
Sets the green color component of this color to \a green.
@@ -137,7 +113,7 @@
*/
/*!
- \fn template<typename F> void QRgbaFloat<F>::setBlue(QRgbaFloat::FastType blue)
+ \fn template<typename F> void QRgbaFloat<F>::setBlue(float blue)
Sets the blue color component of this color to \a blue.
@@ -153,7 +129,7 @@
*/
/*!
- \fn template<typename F> void QRgbaFloat<F>::setAlpha(QRgbaFloat::FastType alpha)
+ \fn template<typename F> void QRgbaFloat<F>::setAlpha(float alpha)
Sets the alpha of this color to \a alpha.
diff --git a/src/gui/painting/qrhibackingstore.cpp b/src/gui/painting/qrhibackingstore.cpp
new file mode 100644
index 0000000000..586dfb44a4
--- /dev/null
+++ b/src/gui/painting/qrhibackingstore.cpp
@@ -0,0 +1,68 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhibackingstore_p.h"
+#include <private/qimage_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QRhiBackingStore::QRhiBackingStore(QWindow *window)
+ : QRasterBackingStore(window)
+{
+}
+
+QRhiBackingStore::~QRhiBackingStore()
+{
+}
+
+void QRhiBackingStore::flush(QWindow *flushedWindow, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+
+ if (flushedWindow->surfaceType() != window()->surfaceType()) {
+ qWarning() << "Cannot flush child window" << flushedWindow
+ << "with surface type" << flushedWindow->surfaceType() << ";"
+ << "Must match" << window()->surfaceType() << "of" << window();
+
+ // FIXME: Support different surface types by not tying the
+ // RHI config to the backing store itself (per window config).
+ return;
+ }
+
+ if (!rhi()) {
+ QPlatformBackingStoreRhiConfig rhiConfig;
+ switch (window()->surfaceType()) {
+ case QSurface::OpenGLSurface:
+ rhiConfig.setApi(QPlatformBackingStoreRhiConfig::OpenGL);
+ break;
+ case QSurface::MetalSurface:
+ rhiConfig.setApi(QPlatformBackingStoreRhiConfig::Metal);
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+ rhiConfig.setEnabled(true);
+ setRhiConfig(rhiConfig);
+ }
+
+ static QPlatformTextureList emptyTextureList;
+ bool translucentBackground = m_image.hasAlphaChannel();
+ rhiFlush(flushedWindow, flushedWindow->devicePixelRatio(),
+ region, offset, &emptyTextureList, translucentBackground);
+}
+
+QImage::Format QRhiBackingStore::format() const
+{
+ QImage::Format fmt = QRasterBackingStore::format();
+
+ // With render-to-texture widgets and QRhi-based flushing the backingstore
+ // image must have an alpha channel. Hence upgrading the format. Matches
+ // what other platforms (Windows, xcb) do.
+ if (QImage::toPixelFormat(fmt).alphaUsage() != QPixelFormat::UsesAlpha)
+ fmt = qt_maybeDataCompatibleAlphaVersion(fmt);
+
+ return fmt;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qrhibackingstore_p.h b/src/gui/painting/qrhibackingstore_p.h
new file mode 100644
index 0000000000..f222db860f
--- /dev/null
+++ b/src/gui/painting/qrhibackingstore_p.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHIBACKINGSTORE_H
+#define QRHIBACKINGSTORE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qrasterbackingstore_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QRhiBackingStore : public QRasterBackingStore
+{
+public:
+ QRhiBackingStore(QWindow *window);
+ ~QRhiBackingStore();
+
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
+ QImage::Format format() const override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QRHIBACKINGSTORE_H
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index cd1a49150b..79799ca2ec 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qstroker_p.h"
#include "private/qbezier_p.h"
@@ -295,7 +259,7 @@ void QStrokerOps::strokePath(const QPainterPath &path, void *customData, const Q
/*!
Convenience function for stroking a polygon of the \a pointCount
first points in \a points. If \a implicit_close is set to true a
- line is implictly drawn between the first and last point in the
+ line is implicitly drawn between the first and last point in the
polygon. Typically true for polygons and false for polylines.
The \a matrix is used to transform the points before they enter the
@@ -1133,7 +1097,9 @@ void QDashStroker::processCurrentSubpath()
qreal doffset = m_dashOffset * m_stroke_width;
// make sure doffset is in range [0..sumLength)
- doffset -= qFloor(doffset * invSumLength) * sumLength;
+ doffset = std::fmod(doffset, sumLength);
+ if (doffset < 0)
+ doffset += sumLength;
while (doffset >= dashes[idash]) {
doffset -= dashes[idash];
@@ -1179,32 +1145,42 @@ void QDashStroker::processCurrentSubpath()
bool done = pos >= estop;
- if (clipping) {
- // Check if the entire line can be clipped away.
- if (!lineIntersectsRect(prev, e, clip_tl, clip_br)) {
- // Cut away full dash sequences.
- elen -= qFloor(elen * invSumLength) * sumLength;
- // Update dash offset.
- while (!done) {
- qreal dpos = pos + dashes[idash] - doffset - estart;
-
- Q_ASSERT(dpos >= 0);
-
- if (dpos > elen) { // dash extends this line
- doffset = dashes[idash] - (dpos - elen); // subtract the part already used
- pos = estop; // move pos to next path element
- done = true;
- } else { // Dash is on this line
- pos = dpos + estart;
- done = pos >= estop;
- if (++idash >= dashCount)
- idash = 0;
- doffset = 0; // full segment so no offset on next.
- }
+ // Check if the entire line should be clipped away or simplified
+ bool clipIt = clipping && !lineIntersectsRect(prev, e, clip_tl, clip_br);
+ bool skipDashing = elen * invSumLength > repetitionLimit();
+ int maxDashes = dashCount;
+ if (skipDashing || clipIt) {
+ // Cut away full dash sequences.
+ elen -= std::floor(elen * invSumLength) * sumLength;
+ // Update dash offset.
+ while (!done) {
+ qreal dpos = pos + dashes[idash] - doffset - estart;
+
+ Q_ASSERT(dpos >= 0);
+
+ if (dpos > elen) { // dash extends this line
+ doffset = dashes[idash] - (dpos - elen); // subtract the part already used
+ pos = estop; // move pos to next path element
+ done = true;
+ } else { // Dash is on this line
+ pos = --maxDashes > 0 ? dpos + estart : estop;
+ done = pos >= estop;
+ if (++idash >= dashCount)
+ idash = 0;
+ doffset = 0; // full segment so no offset on next.
}
+ }
+ if (clipIt) {
hasMoveTo = false;
- move_to_pos = e;
+ } else {
+ // skip costly dashing, just draw solid line
+ if (!hasMoveTo) {
+ emitMoveTo(move_to_pos.x, move_to_pos.y);
+ hasMoveTo = true;
+ }
+ emitLineTo(e.x, e.y);
}
+ move_to_pos = e;
}
// Dash away...
diff --git a/src/gui/painting/qstroker_p.h b/src/gui/painting/qstroker_p.h
index eb0e5d7ffa..2519bbadc2 100644
--- a/src/gui/painting/qstroker_p.h
+++ b/src/gui/painting/qstroker_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTROKER_P_H
#define QSTROKER_P_H
@@ -268,6 +232,7 @@ public:
QStroker *stroker() const { return m_stroker; }
static QList<qfixed> patternForStyle(Qt::PenStyle style);
+ static int repetitionLimit() { return 10000; }
void setDashPattern(const QList<qfixed> &dashPattern) { m_dashPattern = dashPattern; }
QList<qfixed> dashPattern() const { return m_dashPattern; }
diff --git a/src/gui/painting/qt_attribution.json b/src/gui/painting/qt_attribution.json
index e2326a56c1..33ed2fd5c7 100644
--- a/src/gui/painting/qt_attribution.json
+++ b/src/gui/painting/qt_attribution.json
@@ -4,13 +4,13 @@
"Name": "Anti-aliasing rasterizer from FreeType 2",
"QDocModule": "qtgui",
"QtUsage": "Used in Qt GUI.",
- "Path": "qgrayraster.c",
+ "Files": "qgrayraster.c",
"Description": "FreeType is a freely available software library to render fonts.",
"Homepage": "http://www.freetype.org",
"License": "Freetype Project License or GNU General Public License v2.0 only",
- "LicenseId": "FTL or GPL-2.0",
- "LicenseFile": "../../3rdparty/freetype/docs/LICENSE.TXT",
+ "LicenseId": "FTL OR GPL-2.0-only",
+ "LicenseFile": "../../3rdparty/freetype/LICENSE.txt",
"Copyright": "Copyright 2000-2016 by David Turner, Robert Wilhelm, and Werner Lemberg."
},
{
@@ -24,9 +24,9 @@
"LicenseId": "BSD-2-Clause AND Imlib2",
"License": "BSD 2-clause \"Simplified\" License and Imlib2 License",
"LicenseFile": "QIMAGETRANSFORM_LICENSE.txt",
- "Copyright": "Copyright (C) 2004, 2005 Daniel M. Duley.
- (C) Carsten Haitzler and various contributors.
- (C) Willem Monsuwe <willem@stack.nl>"
+ "Copyright": ["Copyright (C) 2004, 2005 Daniel M. Duley.",
+ "(C) Carsten Haitzler and various contributors.",
+ "(C) Willem Monsuwe <willem@stack.nl>"]
},
{
"Id": "xserverhelper",
@@ -40,7 +40,7 @@
"License": "X11 License and Historical Permission Notice and Disclaimer",
"LicenseId": "X11 AND HPND",
"LicenseFile": "XCONSORTIUM_LICENSE.txt",
- "Copyright": "Copyright (c) 1987, 1988 X Consortium
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts."
+ "Copyright": ["Copyright (c) 1987, 1988 X Consortium",
+ "Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts."]
}
]
diff --git a/src/gui/painting/qt_mips_asm_dsp_p.h b/src/gui/painting/qt_mips_asm_dsp_p.h
index 172910ea1c..6b33285f32 100644
--- a/src/gui/painting/qt_mips_asm_dsp_p.h
+++ b/src/gui/painting/qt_mips_asm_dsp_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QT_MIPS_ASM_DSP_H
#define QT_MIPS_ASM_DSP_H
@@ -55,7 +19,7 @@
#pragma qt_sync_stop_processing
#endif
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
#define zero $0
#define AT $1
#define v0 $2
@@ -277,7 +241,7 @@ LEAF_MIPS32R2(symbol) \
/*
* Saves set of registers on stack. Maximum number of registers that
- * can be saved on stack is limitted to 14 (a0-a3, v0-v1 and s0-s7).
+ * can be saved on stack is limited to 14 (a0-a3, v0-v1 and s0-s7).
* Stack offset is number of bytes that are added to stack pointer (sp)
* before registers are pushed in order to provide enough space on stack
* (offset must be multiple of 4, and must be big enough, as described by
@@ -352,7 +316,7 @@ LEAF_MIPS32R2(symbol) \
/*
* Restores set of registers from stack. Maximum number of registers that
- * can be restored from stack is limitted to 14 (a0-a3, v0-v1 and s0-s7).
+ * can be restored from stack is limited to 14 (a0-a3, v0-v1 and s0-s7).
* Stack offset is number of bytes that are added to stack pointer (sp)
* after registers are restored (offset must be multiple of 4, and must
* be big enough, as described by CHECK_STACK_OFFSET macro). This macro is
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index dfb937ed84..70d70e342a 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qmath.h>
@@ -93,13 +57,14 @@ int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const
}
bool QTextureGlyphCache::populate(QFontEngine *fontEngine,
- int numGlyphs,
+ qsizetype numGlyphs,
const glyph_t *glyphs,
const QFixedPoint *positions,
- QPainter::RenderHints renderHints)
+ QPainter::RenderHints renderHints,
+ bool includeGlyphCacheScale)
{
#ifdef CACHE_DEBUG
- printf("Populating with %d glyphs\n", numGlyphs);
+ printf("Populating with %lld glyphs\n", static_cast<long long>(numGlyphs));
qDebug() << " -> current transformation: " << m_transform;
#endif
@@ -114,7 +79,7 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine,
if (!supportsSubPixelPositions) {
fontEngine->m_subPixelPositionCount = 1;
} else {
- int i = 0;
+ qsizetype i = 0;
while (fontEngine->m_subPixelPositionCount == 0 && i < numGlyphs)
fontEngine->m_subPixelPositionCount = calculateSubPixelPositionCount(glyphs[i++]);
}
@@ -125,16 +90,23 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine,
m_cy = padding;
}
+ qreal glyphCacheScaleX = transform().m11();
+ qreal glyphCacheScaleY = transform().m22();
+
QHash<GlyphAndSubPixelPosition, Coord> listItemCoordinates;
int rowHeight = 0;
// check each glyph for its metrics and get the required rowHeight.
- for (int i=0; i < numGlyphs; ++i) {
+ for (qsizetype i = 0; i < numGlyphs; ++i) {
const glyph_t glyph = glyphs[i];
QFixedPoint subPixelPosition;
if (supportsSubPixelPositions) {
QFixedPoint pos = positions != nullptr ? positions[i] : QFixedPoint();
+ if (includeGlyphCacheScale) {
+ pos = QFixedPoint(QFixed::fromReal(pos.x.toReal() * glyphCacheScaleX),
+ QFixed::fromReal(pos.y.toReal() * glyphCacheScaleY));
+ }
subPixelPosition = fontEngine->subPixelPositionFor(pos);
if (!verticalSubPixelPositions)
subPixelPosition.y = 0;
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index a401778a63..c0218b3ace 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTUREGLYPHCACHE_P_H
#define QTEXTUREGLYPHCACHE_P_H
@@ -111,10 +75,11 @@ public:
};
bool populate(QFontEngine *fontEngine,
- int numGlyphs,
+ qsizetype numGlyphs,
const glyph_t *glyphs,
const QFixedPoint *positions,
- QPainter::RenderHints renderHints = QPainter::RenderHints());
+ QPainter::RenderHints renderHints = QPainter::RenderHints(),
+ bool includeGlyphCacheScale = false);
bool hasPendingGlyphs() const { return !m_pendingGlyphs.isEmpty(); }
void fillInPendingGlyphs();
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index 7d057732c7..df57d2c190 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtransform.h"
#include "qdatastream.h"
@@ -45,7 +9,7 @@
#include "qpainterpath.h"
#include "qpainterpath_p.h"
#include "qvariant.h"
-#include <qmath.h>
+#include "qmath_p.h"
#include <qnumeric.h>
#include <private/qbezier_p.h>
@@ -90,7 +54,7 @@ static void nanWarning(const char *func)
if (t == TxProject) { \
qreal w = (m_matrix[0][2] * FX_ + m_matrix[1][2] * FY_ + m_matrix[2][2]); \
if (w < qreal(Q_NEAR_CLIP)) w = qreal(Q_NEAR_CLIP); \
- w = 1./w; \
+ w = qreal(1.)/w; \
nx *= w; \
ny *= w; \
} \
@@ -394,7 +358,7 @@ QTransform &QTransform::translate(qreal dx, qreal dy)
if (dx == 0 && dy == 0)
return *this;
#ifndef QT_NO_DEBUG
- if (qIsNaN(dx) | qIsNaN(dy)) {
+ if (qIsNaN(dx) || qIsNaN(dy)) {
nanWarning("translate");
return *this;
}
@@ -437,7 +401,7 @@ QTransform &QTransform::translate(qreal dx, qreal dy)
QTransform QTransform::fromTranslate(qreal dx, qreal dy)
{
#ifndef QT_NO_DEBUG
- if (qIsNaN(dx) | qIsNaN(dy)) {
+ if (qIsNaN(dx) || qIsNaN(dy)) {
nanWarning("fromTranslate");
return QTransform();
}
@@ -462,7 +426,7 @@ QTransform & QTransform::scale(qreal sx, qreal sy)
if (sx == 1 && sy == 1)
return *this;
#ifndef QT_NO_DEBUG
- if (qIsNaN(sx) | qIsNaN(sy)) {
+ if (qIsNaN(sx) || qIsNaN(sy)) {
nanWarning("scale");
return *this;
}
@@ -503,7 +467,7 @@ QTransform & QTransform::scale(qreal sx, qreal sy)
QTransform QTransform::fromScale(qreal sx, qreal sy)
{
#ifndef QT_NO_DEBUG
- if (qIsNaN(sx) | qIsNaN(sy)) {
+ if (qIsNaN(sx) || qIsNaN(sy)) {
nanWarning("fromScale");
return QTransform();
}
@@ -528,7 +492,7 @@ QTransform & QTransform::shear(qreal sh, qreal sv)
if (sh == 0 && sv == 0)
return *this;
#ifndef QT_NO_DEBUG
- if (qIsNaN(sh) | qIsNaN(sv)) {
+ if (qIsNaN(sh) || qIsNaN(sv)) {
nanWarning("shear");
return *this;
}
@@ -569,29 +533,33 @@ QTransform & QTransform::shear(qreal sh, qreal sv)
return *this;
}
-const qreal deg2rad = qreal(0.017453292519943295769); // pi/180
-const qreal inv_dist_to_plane = 1. / 1024.;
-
/*!
- \fn QTransform &QTransform::rotate(qreal angle, Qt::Axis axis)
+ \since 6.5
- Rotates the coordinate system counterclockwise by the given \a angle
- about the specified \a axis and returns a reference to the matrix.
+ Rotates the coordinate system counterclockwise by the given angle \a a
+ about the specified \a axis at distance \a distanceToPlane from the
+ screen and returns a reference to the matrix.
+//! [transform-rotate-note]
Note that if you apply a QTransform to a point defined in widget
coordinates, the direction of the rotation will be clockwise
because the y-axis points downwards.
The angle is specified in degrees.
+//! [transform-rotate-note]
+
+ If \a distanceToPlane is zero, it will be ignored. This is suitable
+ for implementing orthographic projections where the z coordinate should
+ be dropped rather than projected.
\sa setMatrix()
*/
-QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
+QTransform & QTransform::rotate(qreal a, Qt::Axis axis, qreal distanceToPlane)
{
if (a == 0)
return *this;
#ifndef QT_NO_DEBUG
- if (qIsNaN(a)) {
+ if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
nanWarning("rotate");
return *this;
}
@@ -606,7 +574,7 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
else if (a == 180.)
cosa = -1.;
else{
- qreal b = deg2rad*a; // convert to radians
+ qreal b = qDegreesToRadians(a);
sina = qSin(b); // fast and convenient
cosa = qCos(b);
}
@@ -654,13 +622,16 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
if (m_dirty < TxRotate)
m_dirty = TxRotate;
} else {
+ if (!qIsNull(distanceToPlane))
+ sina /= distanceToPlane;
+
QTransform result;
if (axis == Qt::YAxis) {
result.m_matrix[0][0] = cosa;
- result.m_matrix[0][2] = -sina * inv_dist_to_plane;
+ result.m_matrix[0][2] = -sina;
} else {
result.m_matrix[1][1] = cosa;
- result.m_matrix[1][2] = -sina * inv_dist_to_plane;
+ result.m_matrix[1][2] = -sina;
}
result.m_type = TxProject;
*this = result * *this;
@@ -669,24 +640,49 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
return *this;
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+/*!
+ \overload
+
+ Rotates the coordinate system counterclockwise by the given angle \a a
+ about the specified \a axis at distance 1024.0 from the screen and
+ returns a reference to the matrix.
+
+ \include qtransform.cpp transform-rotate-note
+
+ \sa setMatrix
+*/
+QTransform &QTransform::rotate(qreal a, Qt::Axis axis)
+{
+ return rotate(a, axis, 1024.0);
+}
+#endif
+
/*!
- \fn QTransform & QTransform::rotateRadians(qreal angle, Qt::Axis axis)
+ \since 6.5
- Rotates the coordinate system counterclockwise by the given \a angle
- about the specified \a axis and returns a reference to the matrix.
+ Rotates the coordinate system counterclockwise by the given angle \a a
+ about the specified \a axis at distance \a distanceToPlane from the
+ screen and returns a reference to the matrix.
+//! [transform-rotate-radians-note]
Note that if you apply a QTransform to a point defined in widget
coordinates, the direction of the rotation will be clockwise
because the y-axis points downwards.
The angle is specified in radians.
+//! [transform-rotate-radians-note]
+
+ If \a distanceToPlane is zero, it will be ignored. This is suitable
+ for implementing orthographic projections where the z coordinate should
+ be dropped rather than projected.
\sa setMatrix()
*/
-QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
+QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis, qreal distanceToPlane)
{
#ifndef QT_NO_DEBUG
- if (qIsNaN(a)) {
+ if (qIsNaN(a) || qIsNaN(distanceToPlane)) {
nanWarning("rotateRadians");
return *this;
}
@@ -737,13 +733,16 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
if (m_dirty < TxRotate)
m_dirty = TxRotate;
} else {
+ if (!qIsNull(distanceToPlane))
+ sina /= distanceToPlane;
+
QTransform result;
if (axis == Qt::YAxis) {
result.m_matrix[0][0] = cosa;
- result.m_matrix[0][2] = -sina * inv_dist_to_plane;
+ result.m_matrix[0][2] = -sina;
} else {
result.m_matrix[1][1] = cosa;
- result.m_matrix[1][2] = -sina * inv_dist_to_plane;
+ result.m_matrix[1][2] = -sina;
}
result.m_type = TxProject;
*this = result * *this;
@@ -751,6 +750,24 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
return *this;
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+/*!
+ \overload
+
+ Rotates the coordinate system counterclockwise by the given angle \a a
+ about the specified \a axis at distance 1024.0 from the screen and
+ returns a reference to the matrix.
+
+ \include qtransform.cpp transform-rotate-radians-note
+
+ \sa setMatrix()
+*/
+QTransform &QTransform::rotateRadians(qreal a, Qt::Axis axis)
+{
+ return rotateRadians(a, axis, 1024.0);
+}
+#endif
+
/*!
\fn bool QTransform::operator==(const QTransform &matrix) const
Returns \c true if this matrix is equal to the given \a matrix,
@@ -1128,30 +1145,8 @@ QPoint QTransform::map(const QPoint &p) const
qreal x = 0, y = 0;
TransformationType t = inline_type();
- switch(t) {
- case TxNone:
- x = fx;
- y = fy;
- break;
- case TxTranslate:
- x = fx + m_matrix[2][0];
- y = fy + m_matrix[2][1];
- break;
- case TxScale:
- x = m_matrix[0][0] * fx + m_matrix[2][0];
- y = m_matrix[1][1] * fy + m_matrix[2][1];
- break;
- case TxRotate:
- case TxShear:
- case TxProject:
- x = m_matrix[0][0] * fx + m_matrix[1][0] * fy + m_matrix[2][0];
- y = m_matrix[0][1] * fx + m_matrix[1][1] * fy + m_matrix[2][1];
- if (t == TxProject) {
- qreal w = 1./(m_matrix[0][2] * fx + m_matrix[1][2] * fy + m_matrix[2][2]);
- x *= w;
- y *= w;
- }
- }
+ MAP(fx, fy, x, y);
+
return QPoint(qRound(x), qRound(y));
}
@@ -1179,30 +1174,8 @@ QPointF QTransform::map(const QPointF &p) const
qreal x = 0, y = 0;
TransformationType t = inline_type();
- switch(t) {
- case TxNone:
- x = fx;
- y = fy;
- break;
- case TxTranslate:
- x = fx + m_matrix[2][0];
- y = fy + m_matrix[2][1];
- break;
- case TxScale:
- x = m_matrix[0][0] * fx + m_matrix[2][0];
- y = m_matrix[1][1] * fy + m_matrix[2][1];
- break;
- case TxRotate:
- case TxShear:
- case TxProject:
- x = m_matrix[0][0] * fx + m_matrix[1][0] * fy + m_matrix[2][0];
- y = m_matrix[0][1] * fx + m_matrix[1][1] * fy + m_matrix[2][1];
- if (t == TxProject) {
- qreal w = 1./(m_matrix[0][2] * fx + m_matrix[1][2] * fy + m_matrix[2][2]);
- x *= w;
- y *= w;
- }
- }
+ MAP(fx, fy, x, y);
+
return QPointF(x, y);
}
@@ -1250,41 +1223,9 @@ QLine QTransform::map(const QLine &l) const
qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
TransformationType t = inline_type();
- switch(t) {
- case TxNone:
- x1 = fx1;
- y1 = fy1;
- x2 = fx2;
- y2 = fy2;
- break;
- case TxTranslate:
- x1 = fx1 + m_matrix[2][0];
- y1 = fy1 + m_matrix[2][1];
- x2 = fx2 + m_matrix[2][0];
- y2 = fy2 + m_matrix[2][1];
- break;
- case TxScale:
- x1 = m_matrix[0][0] * fx1 + m_matrix[2][0];
- y1 = m_matrix[1][1] * fy1 + m_matrix[2][1];
- x2 = m_matrix[0][0] * fx2 + m_matrix[2][0];
- y2 = m_matrix[1][1] * fy2 + m_matrix[2][1];
- break;
- case TxRotate:
- case TxShear:
- case TxProject:
- x1 = m_matrix[0][0] * fx1 + m_matrix[1][0] * fy1 + m_matrix[2][0];
- y1 = m_matrix[0][1] * fx1 + m_matrix[1][1] * fy1 + m_matrix[2][1];
- x2 = m_matrix[0][0] * fx2 + m_matrix[1][0] * fy2 + m_matrix[2][0];
- y2 = m_matrix[0][1] * fx2 + m_matrix[1][1] * fy2 + m_matrix[2][1];
- if (t == TxProject) {
- qreal w = 1./(m_matrix[0][2] * fx1 + m_matrix[1][2] * fy1 + m_matrix[2][2]);
- x1 *= w;
- y1 *= w;
- w = 1./(m_matrix[0][2] * fx2 + m_matrix[1][2] * fy2 + m_matrix[2][2]);
- x2 *= w;
- y2 *= w;
- }
- }
+ MAP(fx1, fy1, x1, y1);
+ MAP(fx2, fy2, x2, y2);
+
return QLine(qRound(x1), qRound(y1), qRound(x2), qRound(y2));
}
@@ -1309,66 +1250,12 @@ QLineF QTransform::map(const QLineF &l) const
qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
TransformationType t = inline_type();
- switch(t) {
- case TxNone:
- x1 = fx1;
- y1 = fy1;
- x2 = fx2;
- y2 = fy2;
- break;
- case TxTranslate:
- x1 = fx1 + m_matrix[2][0];
- y1 = fy1 + m_matrix[2][1];
- x2 = fx2 + m_matrix[2][0];
- y2 = fy2 + m_matrix[2][1];
- break;
- case TxScale:
- x1 = m_matrix[0][0] * fx1 + m_matrix[2][0];
- y1 = m_matrix[1][1] * fy1 + m_matrix[2][1];
- x2 = m_matrix[0][0] * fx2 + m_matrix[2][0];
- y2 = m_matrix[1][1] * fy2 + m_matrix[2][1];
- break;
- case TxRotate:
- case TxShear:
- case TxProject:
- x1 = m_matrix[0][0] * fx1 + m_matrix[1][0] * fy1 + m_matrix[2][0];
- y1 = m_matrix[0][1] * fx1 + m_matrix[1][1] * fy1 + m_matrix[2][1];
- x2 = m_matrix[0][0] * fx2 + m_matrix[1][0] * fy2 + m_matrix[2][0];
- y2 = m_matrix[0][1] * fx2 + m_matrix[1][1] * fy2 + m_matrix[2][1];
- if (t == TxProject) {
- qreal w = 1./(m_matrix[0][2] * fx1 + m_matrix[1][2] * fy1 + m_matrix[2][2]);
- x1 *= w;
- y1 *= w;
- w = 1./(m_matrix[0][2] * fx2 + m_matrix[1][2] * fy2 + m_matrix[2][2]);
- x2 *= w;
- y2 *= w;
- }
- }
- return QLineF(x1, y1, x2, y2);
-}
+ MAP(fx1, fy1, x1, y1);
+ MAP(fx2, fy2, x2, y2);
-static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &poly)
-{
- if (poly.size() == 0)
- return poly;
-
- if (poly.size() == 1)
- return QPolygonF() << transform.map(poly.at(0));
-
- QPainterPath path;
- path.addPolygon(poly);
-
- path = transform.map(path);
-
- QPolygonF result;
- const int elementCount = path.elementCount();
- result.reserve(elementCount);
- for (int i = 0; i < elementCount; ++i)
- result << path.elementAt(i);
- return result;
+ return QLineF(x1, y1, x2, y2);
}
-
/*!
\fn QPolygonF operator *(const QPolygonF &polygon, const QTransform &matrix)
\since 4.3
@@ -1402,9 +1289,6 @@ QPolygonF QTransform::map(const QPolygonF &a) const
if (t <= TxTranslate)
return a.translated(m_matrix[2][0], m_matrix[2][1]);
- if (t >= QTransform::TxProject)
- return mapProjective(*this, a);
-
int size = a.size();
int i;
QPolygonF p(size);
@@ -1432,9 +1316,6 @@ QPolygon QTransform::map(const QPolygon &a) const
if (t <= TxTranslate)
return a.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1]));
- if (t >= QTransform::TxProject)
- return mapProjective(*this, QPolygonF(a)).toPolygon();
-
int size = a.size();
int i;
QPolygon p(size);
@@ -1487,16 +1368,16 @@ QRegion QTransform::map(const QRegion &r) const
QRegion res;
if (m11() < 0 || m22() < 0) {
for (const QRect &rect : r)
- res += mapRect(QRectF(rect)).toRect();
+ res += qt_mapFillRect(QRectF(rect), *this);
} else {
QVarLengthArray<QRect, 32> rects;
rects.reserve(r.rectCount());
for (const QRect &rect : r) {
- QRect nr = mapRect(QRectF(rect)).toRect();
+ QRect nr = qt_mapFillRect(QRectF(rect), *this);
if (!nr.isEmpty())
rects.append(nr);
}
- res.setRects(rects.constData(), rects.count());
+ res.setRects(rects.constData(), rects.size());
}
return res;
}
@@ -1725,7 +1606,7 @@ QPolygon QTransform::mapToPolygon(const QRect &rect) const
MAP(rect.x(), bottom, x[3], y[3]);
}
- // all coordinates are correctly, tranform to a pointarray
+ // all coordinates are correctly, transform to a pointarray
// (rounding to the next integer)
a.setPoints(4, qRound(x[0]), qRound(y[0]),
qRound(x[1]), qRound(y[1]),
@@ -1743,7 +1624,7 @@ QPolygon QTransform::mapToPolygon(const QRect &rect) const
*/
bool QTransform::squareToQuad(const QPolygonF &quad, QTransform &trans)
{
- if (quad.count() != 4)
+ if (quad.size() != 4)
return false;
qreal dx0 = quad[0].x();
@@ -1865,14 +1746,6 @@ void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
m_dirty = TxProject;
}
-static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform)
-{
- const qreal wx = qMin(transform.m13() * rect.left(), transform.m13() * rect.right());
- const qreal wy = qMin(transform.m23() * rect.top(), transform.m23() * rect.bottom());
-
- return wx + wy + transform.m33() < Q_NEAR_CLIP;
-}
-
QRect QTransform::mapRect(const QRect &rect) const
{
TransformationType t = inline_type();
@@ -1893,8 +1766,7 @@ QRect QTransform::mapRect(const QRect &rect) const
y -= h;
}
return QRect(x, y, w, h);
- } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
- // see mapToPolygon for explanations of the algorithm.
+ } else {
qreal x = 0, y = 0;
MAP(rect.left(), rect.top(), x, y);
qreal xmin = x;
@@ -1916,11 +1788,7 @@ QRect QTransform::mapRect(const QRect &rect) const
ymin = qMin(ymin, y);
xmax = qMax(xmax, x);
ymax = qMax(ymax, y);
- return QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin));
- } else {
- QPainterPath path;
- path.addRect(rect);
- return map(path).boundingRect().toRect();
+ return QRectF(xmin, ymin, xmax-xmin, ymax-ymin).toRect();
}
}
@@ -1963,7 +1831,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const
y -= h;
}
return QRectF(x, y, w, h);
- } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) {
+ } else {
qreal x = 0, y = 0;
MAP(rect.x(), rect.y(), x, y);
qreal xmin = x;
@@ -1986,10 +1854,6 @@ QRectF QTransform::mapRect(const QRectF &rect) const
xmax = qMax(xmax, x);
ymax = qMax(ymax, y);
return QRectF(xmin, ymin, xmax-xmin, ymax - ymin);
- } else {
- QPainterPath path;
- path.addRect(rect);
- return map(path).boundingRect();
}
}
diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h
index a1ec8e9399..e5b245d8c9 100644
--- a/src/gui/painting/qtransform.h
+++ b/src/gui/painting/qtransform.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTRANSFORM_H
#define QTRANSFORM_H
@@ -120,8 +84,17 @@ public:
QTransform &translate(qreal dx, qreal dy);
QTransform &scale(qreal sx, qreal sy);
QTransform &shear(qreal sh, qreal sv);
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ QTransform &rotate(qreal a, Qt::Axis axis, qreal distanceToPlane);
+ // ### Qt7: Remove
QTransform &rotate(qreal a, Qt::Axis axis = Qt::ZAxis);
+ QTransform &rotateRadians(qreal a, Qt::Axis axis, qreal distanceToPlane);
+ // ### Qt7: Remove
QTransform &rotateRadians(qreal a, Qt::Axis axis = Qt::ZAxis);
+#else
+ QTransform &rotate(qreal a, Qt::Axis axis = Qt::ZAxis, qreal distanceToPlane = 1024.0f);
+ QTransform &rotateRadians(qreal a, Qt::Axis axis = Qt::ZAxis, qreal distanceToPlane = 1024.0f);
+#endif
static bool squareToQuad(const QPolygonF &square, QTransform &result);
static bool quadToSquare(const QPolygonF &quad, QTransform &result);
diff --git a/src/gui/painting/qtriangulatingstroker.cpp b/src/gui/painting/qtriangulatingstroker.cpp
index 8687d221cd..c8d2e90397 100644
--- a/src/gui/painting/qtriangulatingstroker.cpp
+++ b/src/gui/painting/qtriangulatingstroker.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtriangulatingstroker_p.h"
#include <qmath.h>
diff --git a/src/gui/painting/qtriangulatingstroker_p.h b/src/gui/painting/qtriangulatingstroker_p.h
index 9537311ec5..cd038b0d45 100644
--- a/src/gui/painting/qtriangulatingstroker_p.h
+++ b/src/gui/painting/qtriangulatingstroker_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTRIANGULATINGSTROKER_P_H
#define QTRIANGULATINGSTROKER_P_H
diff --git a/src/gui/painting/qtriangulator.cpp b/src/gui/painting/qtriangulator.cpp
index d9c1b2c003..029566f1b9 100644
--- a/src/gui/painting/qtriangulator.cpp
+++ b/src/gui/painting/qtriangulator.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtriangulator_p.h"
@@ -2357,3 +2321,5 @@ QPolylineSet qPolyline(const QPainterPath &path,
}
QT_END_NAMESPACE
+
+#undef Q_FIXED_POINT_SCALE
diff --git a/src/gui/painting/qtriangulator_p.h b/src/gui/painting/qtriangulator_p.h
index e07fcae090..09db3f1619 100644
--- a/src/gui/painting/qtriangulator_p.h
+++ b/src/gui/painting/qtriangulator_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTRIANGULATOR_P_H
#define QTRIANGULATOR_P_H
diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h
index df5772d4cc..b99d8fd857 100644
--- a/src/gui/painting/qvectorpath_p.h
+++ b/src/gui/painting/qvectorpath_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVECTORPATH_P_H
#define QVECTORPATH_P_H
diff --git a/src/gui/painting/shaders/backingstorecompose.frag b/src/gui/painting/shaders/backingstorecompose.frag
new file mode 100644
index 0000000000..3b08ade035
--- /dev/null
+++ b/src/gui/painting/shaders/backingstorecompose.frag
@@ -0,0 +1,25 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 vertexTransform;
+ mat3 textureTransform;
+ float opacity;
+ int textureSwizzle;
+};
+
+layout(binding = 1) uniform sampler2D textureSampler;
+
+void main()
+{
+ vec4 tmpFragColor = texture(textureSampler, v_texcoord);
+ tmpFragColor.a *= opacity;
+ if (textureSwizzle == 0)
+ fragColor = tmpFragColor;
+ else if(textureSwizzle == 2)
+ fragColor.argb = tmpFragColor;
+ else
+ fragColor.bgra = tmpFragColor;
+}
diff --git a/src/gui/painting/shaders/backingstorecompose.frag.qsb b/src/gui/painting/shaders/backingstorecompose.frag.qsb
new file mode 100644
index 0000000000..63ba55eed8
--- /dev/null
+++ b/src/gui/painting/shaders/backingstorecompose.frag.qsb
Binary files differ
diff --git a/src/gui/painting/shaders/backingstorecompose.vert b/src/gui/painting/shaders/backingstorecompose.vert
new file mode 100644
index 0000000000..0c72c97419
--- /dev/null
+++ b/src/gui/painting/shaders/backingstorecompose.vert
@@ -0,0 +1,19 @@
+#version 440
+
+layout(location = 0) in vec3 position;
+layout(location = 1) in vec2 texcoord;
+
+layout(location = 0) out vec2 v_texcoord;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 vertexTransform;
+ mat3 textureTransform;
+ float opacity;
+ int textureSwizzle;
+};
+
+void main()
+{
+ v_texcoord = (textureTransform * vec3(texcoord, 1.0)).xy;
+ gl_Position = vertexTransform * vec4(position, 1.0);
+}
diff --git a/src/gui/painting/shaders/backingstorecompose.vert.qsb b/src/gui/painting/shaders/backingstorecompose.vert.qsb
new file mode 100644
index 0000000000..1aa6e661f8
--- /dev/null
+++ b/src/gui/painting/shaders/backingstorecompose.vert.qsb
Binary files differ
diff --git a/src/gui/painting/webgradients.cpp b/src/gui/painting/webgradients.cpp
index 0bd450e00b..fd5031349e 100644
--- a/src/gui/painting/webgradients.cpp
+++ b/src/gui/painting/webgradients.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// This file is auto-generated by gradientgen. DO NOT EDIT!
@@ -382,8 +346,7 @@ static QList<QGradientStop> qt_preset_gradient_stops(QGradient::Preset preset)
case QGradient::NumPresets:
Q_UNREACHABLE();
}
- Q_UNREACHABLE();
- return {};
+ Q_UNREACHABLE_RETURN({});
}
static constexpr QGradient::QGradientData qt_preset_gradient_data[] = {
diff --git a/src/gui/platform/android/qandroidnativeinterface.cpp b/src/gui/platform/android/qandroidnativeinterface.cpp
index 20c378a9e9..c1c4b7149f 100644
--- a/src/gui/platform/android/qandroidnativeinterface.cpp
+++ b/src/gui/platform/android/qandroidnativeinterface.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qpa/qplatformoffscreensurface.h>
#include <qpa/qplatformintegration.h>
@@ -43,6 +7,8 @@
#include <QtGui/qoffscreensurface_platform.h>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformscreen_p.h>
+
QT_BEGIN_NAMESPACE
using namespace QNativeInterface::Private;
@@ -69,4 +35,20 @@ QOffscreenSurface *QNativeInterface::QAndroidOffscreenSurface::fromNative(ANati
&QAndroidOffScreenIntegration::createOffscreenSurface>(nativeSurface);
}
+/*!
+ \class QNativeInterface::QAndroidScreen
+ \since 6.7
+ \brief Native interface to a screen.
+
+ Accessed through QScreen::nativeInterface().
+ \inmodule QtGui
+ \ingroup native-interfaces
+ \ingroup native-interfaces-qscreen
+*/
+/*!
+ \fn int QNativeInterface::QAndroidScreen::displayId() const;
+ \return the id of the underlying Android display.
+*/
+QT_DEFINE_NATIVE_INTERFACE(QAndroidScreen);
+
QT_END_NAMESPACE
diff --git a/src/gui/platform/darwin/qappleiconengine.mm b/src/gui/platform/darwin/qappleiconengine.mm
new file mode 100644
index 0000000000..7e0ed184dc
--- /dev/null
+++ b/src/gui/platform/darwin/qappleiconengine.mm
@@ -0,0 +1,464 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qappleiconengine_p.h"
+
+#if defined(Q_OS_MACOS)
+# include <AppKit/AppKit.h>
+#elif defined(QT_PLATFORM_UIKIT)
+# include <UIKit/UIKit.h>
+#endif
+
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpalette.h>
+#include <QtGui/qstylehints.h>
+
+#include <QtGui/private/qcoregraphics_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+namespace {
+auto *loadImage(const QString &iconName)
+{
+ static constexpr std::pair<QLatin1StringView, NSString *> iconMap[] = {
+ {"address-book-new"_L1, @"book.closed"},
+ {"application-exit"_L1, @"xmark.circle"},
+ {"appointment-new"_L1, @"calendar.badge.plus"},
+ {"call-start"_L1, @"phone.arrow.up.right"},
+ {"call-stop"_L1, @"phone.down"},
+ {"contact-new"_L1, @"person.crop.circle.badge.plus"},
+ {"document-new"_L1, @"doc.badge.plus"},
+ {"document-open"_L1, @"folder"},
+ {"document-open-recent"_L1, @"doc.badge.clock"},
+ {"document-page-setup"_L1, @"doc.badge.gearshape"},
+ {"document-print"_L1, @"printer"},
+ //{"document-print-preview"_L1, @""},
+ {"document-properties"_L1, @"doc.badge.ellipsis"},
+ //{"document-revert"_L1, @""},
+ {"document-save"_L1, @"square.and.arrow.down"},
+ //{"document-save-as"_L1, @""},
+ {"document-send"_L1, @"paperplane"},
+ {"edit-clear"_L1, @"xmark.circle"},
+ {"edit-copy"_L1, @"doc.on.doc"},
+ {"edit-cut"_L1, @"scissors"},
+ {"edit-delete"_L1, @"delete.left"},
+ {"edit-find"_L1, @"magnifyingglass"},
+ //{"edit-find-replace"_L1, @"arrow.up.left.and.down.right.magnifyingglass"},
+ {"edit-paste"_L1, @"clipboard"},
+ {"edit-redo"_L1, @"arrowshape.turn.up.right"},
+ //{"edit-select-all"_L1, @""},
+ {"edit-undo"_L1, @"arrowshape.turn.up.left"},
+ {"folder-new"_L1, @"folder.badge.plus"},
+ {"format-indent-less"_L1, @"decrease.indent"},
+ {"format-indent-more"_L1, @"increase.indent"},
+ {"format-justify-center"_L1, @"text.aligncenter"},
+ {"format-justify-fill"_L1, @"text.justify"},
+ {"format-justify-left"_L1, @"text.justify.left"},
+ {"format-justify-right"_L1, @"text.justify.right"},
+ {"format-text-direction-ltr"_L1, @"text.justify.leading"},
+ {"format-text-direction-rtl"_L1, @"text.justify.trailing"},
+ {"format-text-bold"_L1, @"bold"},
+ {"format-text-italic"_L1, @"italic"},
+ {"format-text-underline"_L1, @"underline"},
+ {"format-text-strikethrough"_L1, @"strikethrough"},
+ //{"go-bottom"_L1, @""},
+ {"go-down"_L1, @"arrowshape.down"},
+ {"go-first"_L1, @"increase.indent"},
+ {"go-home"_L1, @"house"},
+ //{"go-jump"_L1, @""},
+ //{"go-last"_L1, @""},
+ {"go-next"_L1, @"arrowshape.right"},
+ {"go-previous"_L1, @"arrowshape.left"},
+ //{"go-top"_L1, @""},
+ {"go-up"_L1, @"arrowshape.up"},
+ {"help-about"_L1, @"info.circle"},
+ //{"help-contents"_L1, @""},
+ {"help-faq"_L1, @"questionmark.app"},
+ {"insert-image"_L1, @"photo.badge.plus"},
+ {"insert-link"_L1, @"link.badge.plus"},
+ //{"insert-object"_L1, @""},
+ {"insert-text"_L1, @"textformat"},
+ {"list-add"_L1, @"plus.circle"},
+ {"list-remove"_L1, @"minus.circle"},
+ {"mail-forward"_L1, @"arrowshape.turn.up.right"},
+ {"mail-mark-important"_L1, @"star"},
+ {"mail-mark-junk"_L1, @"xmark.bin"},
+ {"mail-mark-notjunk"_L1, @"trash.slash"},
+ {"mail-mark-read"_L1, @"envelope.open"},
+ {"mail-mark-unread"_L1, @"envelope.fill"},
+ {"mail-message-new"_L1, @"square.and.pencil"},
+ {"mail-reply-all"_L1, @"arrowshape.turn.up.left.2"},
+ {"mail-reply-sender"_L1, @"arrowshape.turn.up.left"},
+ {"mail-send"_L1, @"paperplane"},
+ {"mail-send-receive"_L1, @"envelope.arrow.triangle.branch"},
+ {"media-eject"_L1, @"eject"},
+ {"media-playback-pause"_L1, @"pause"},
+ {"media-playback-start"_L1, @"play"},
+ {"media-playback-stop"_L1, @"stop"},
+ {"media-record"_L1, @"record.circle"},
+ {"media-seek-backward"_L1, @"backward"},
+ {"media-seek-forward"_L1, @"forward"},
+ {"media-skip-backward"_L1, @"backward.end.alt"},
+ {"media-skip-forward"_L1, @"forward.end.alt"},
+ {"object-flip-horizontal"_L1, @"rectangle.landscape.rotate"},
+ {"object-flip-vertical"_L1, @"rectangle.portrait.rotate"},
+ {"object-rotate-left"_L1, @"rotate.left"},
+ {"object-rotate-right"_L1, @"rotate.right"},
+ {"process-stop"_L1, @"stop.circle"},
+ {"system-lock-screen"_L1, @"lock.display"},
+ {"system-log-out"_L1, @"door.left.hand.open"},
+ //{"system-run"_L1, @""},
+ {"system-search"_L1, @"magnifyingglass"},
+ //{"system-reboot"_L1, @""},
+ {"system-shutdown"_L1, @"power"},
+ //{"tools-check-spelling"_L1, @""},
+ {"view-fullscreen"_L1, @"arrow.up.left.and.arrow.down.right"},
+ {"view-refresh"_L1, @"arrow.clockwise"},
+ {"view-restore"_L1, @"arrow.down.right.and.arrow.up.left"},
+ //{"view-sort-ascending"_L1, @""},
+ //{"view-sort-descending"_L1, @""},
+ {"window-close"_L1, @"xmark.circle"},
+ {"window-new"_L1, @"macwindow.badge.plus"},
+ {"zoom-fit-best"_L1, @"square.arrowtriangle.4.outward"},
+ {"zoom-in"_L1, @"plus.magnifyingglass"},
+ //{"zoom-original"_L1, @""},
+ {"zoom-out"_L1, @"minus.magnifyingglass"},
+ {"process-working"_L1, @"circle.dotted"},
+ //{"accessories-calculator"_L1, @""},
+ //{"accessories-character-map"_L1, @""},
+ {"accessories-dictionary"_L1, @"character.book.closed"},
+ {"accessories-text-editor"_L1, @"textformat"},
+ {"help-browser"_L1, @"folder.badge.questionmark"},
+ {"multimedia-volume-control"_L1, @"speaker.wave.3"},
+ {"preferences-desktop-accessibility"_L1, @"accessibility"},
+ //{"preferences-desktop-font"_L1, @""},
+ {"preferences-desktop-keyboard"_L1, @"keyboard.badge.ellipsis"},
+ //{"preferences-desktop-locale"_L1, @""},
+ //{"preferences-desktop-multimedia"_L1, @""},
+ //{"preferences-desktop-screensaver"_L1, @""},
+ //{"preferences-desktop-theme"_L1, @""},
+ //{"preferences-desktop-wallpaper"_L1, @""},
+ {"system-file-manager"_L1, @"folder.badge.gearshape"},
+ //{"system-software-install"_L1, @""},
+ //{"system-software-update"_L1, @""}, d
+ //{"utilities-system-monitor"_L1, @""},
+ {"utilities-terminal"_L1, @"apple.terminal"},
+ //{"applications-accessories"_L1, @""},
+ //{"applications-development"_L1, @""},
+ //{"applications-engineering"_L1, @""},
+ {"applications-games"_L1, @"gamecontroller"},
+ //{"applications-graphics"_L1, @""},
+ {"applications-internet"_L1, @"network"},
+ {"applications-multimedia"_L1, @"tv.and.mediabox"},
+ //{"applications-office"_L1, @""},
+ //{"applications-other"_L1, @""},
+ {"applications-science"_L1, @"atom"},
+ //{"applications-system"_L1, @""},
+ //{"applications-utilities"_L1, @""},
+ {"preferences-desktop"_L1, @"menubar.dock.rectangle"},
+ //{"preferences-desktop-peripherals"_L1, @""},
+ //{"preferences-desktop-personal"_L1, @""},
+ //{"preferences-other"_L1, @""},
+ //{"preferences-system"_L1, @""},
+ {"preferences-system-network"_L1, @"network"},
+ {"system-help"_L1, @"questionmark.diamond"},
+ {"audio-card"_L1, @"waveform.circle"},
+ {"audio-input-microphone"_L1, @"mic"},
+ {"battery"_L1, @"battery.100percent"},
+ {"camera-photo"_L1, @"camera"},
+ {"camera-video"_L1, @"video"},
+ {"camera-web"_L1, @"web.camera"},
+ {"computer"_L1, @"desktopcomputer"},
+ {"drive-harddisk"_L1, @"internaldrive"},
+ {"drive-optical"_L1, @"opticaldiscdrive"},
+ {"drive-removable-media"_L1, @"externaldrive"},
+ {"input-gaming"_L1, @"gamecontroller"}, // "games" also using this one
+ {"input-keyboard"_L1, @"keyboard"},
+ {"input-mouse"_L1, @"computermouse"},
+ {"input-tablet"_L1, @"ipad"},
+ {"media-flash"_L1, @"mediastick"},
+ //{"media-floppy"_L1, @""},
+ //{"media-optical"_L1, @""},
+ {"media-tape"_L1, @"recordingtape"},
+ //{"modem"_L1, @""},
+ {"multimedia-player"_L1, @"play.rectangle"},
+ {"network-wired"_L1, @"app.connected.to.app.below.fill"},
+ {"network-wireless"_L1, @"wifi"},
+ //{"pda"_L1, @""},
+ {"phone"_L1, @"iphone"},
+ {"printer"_L1, @"printer"},
+ {"scanner"_L1, @"scanner"},
+ {"video-display"_L1, @"play.display"},
+ //{"emblem-default"_L1, @""},
+ {"emblem-documents"_L1, @"doc.circle"},
+ {"emblem-downloads"_L1, @"arrow.down.circle"},
+ {"emblem-favorite"_L1, @"star"},
+ {"emblem-important"_L1, @"exclamationmark.bubble.circle"},
+ {"emblem-mail"_L1, @"envelope"},
+ {"emblem-photos"_L1, @"photo.stack"},
+ //{"emblem-readonly"_L1, @""},
+ {"emblem-shared"_L1, @"folder.badge.person.crop"},
+ {"emblem-symbolic-link"_L1, @"link.circle"},
+ {"emblem-synchronized"_L1, @"arrow.triangle.2.circlepath.circle"},
+ {"emblem-system"_L1, @"gear"},
+ //{"emblem-unreadable"_L1, @""},
+ {"folder"_L1, @"folder"},
+ //{"folder-remote"_L1, @""},
+ {"network-server"_L1, @"server.rack"},
+ //{"network-workgroup"_L1, @""},
+ //{"start-here"_L1, @""},
+ {"user-bookmarks"_L1, @"bookmark.circle"},
+ {"user-desktop"_L1, @"desktopcomputer"}, //"computer" also using this one
+ {"user-home"_L1, @"house"}, //"go-home" also using this one
+ {"user-trash"_L1, @"trash"},
+ {"appointment-missed"_L1, @"calendar.badge.exclamationmark"},
+ {"appointment-soon"_L1, @"calendar.badge.clock"},
+ {"audio-volume-high"_L1, @"speaker.wave.3"},
+ {"audio-volume-low"_L1, @"speaker.wave.1"},
+ {"audio-volume-medium"_L1, @"speaker.wave.2"},
+ {"audio-volume-muted"_L1, @"speaker.slash"},
+ {"battery-caution"_L1, @"minus.plus.batteryblock.exclamationmark"},
+ {"battery-low"_L1, @"battery.25percent"}, // there are different levels that can be low battery
+ {"dialog-error"_L1, @"exclamationmark.bubble"},
+ {"dialog-information"_L1, @"info.circle"},
+ {"dialog-password"_L1, @"lock"},
+ {"dialog-question"_L1, @"questionmark.circle"},
+ {"dialog-warning"_L1, @"exclamationmark.octagon"},
+ {"folder-drag-accept"_L1, @"plus.rectangle.on.folder"},
+ //{"folder-open"_L1, @""},
+ {"folder-visiting"_L1, @"folder.circle"},
+ {"image-loading"_L1, @"photo.circle"},
+ {"image-missing"_L1, @"photo"},
+ {"mail-attachment"_L1, @"paperclip"},
+ {"mail-unread"_L1, @"envelope.badge"},
+ {"mail-read"_L1, @"envelope.open"},
+ {"mail-replied"_L1, @"arrowshape.turn.up.left"},
+ //{"mail-signed"_L1, @""},
+ //{"mail-signed-verified"_L1, @""},
+ {"media-playlist-repeat"_L1, @"repet"},
+ {"media-playlist-shuffle"_L1, @"shuffle"},
+ //{"network-error"_L1, @""},
+ //{"network-idle"_L1, @""},
+ {"network-offline"_L1, @"network.slash"},
+ //{"network-receive"_L1, @""},
+ //{"network-transmit"_L1, @""},
+ //{"network-transmit-receive"_L1, @""},
+ //{"printer-error"_L1, @""},
+ {"printer-printing"_L1, @"printer.dotmatrix.filled.and.paper"}, // not sure
+ {"security-high"_L1, @"lock.shield"},
+ //{"security-medium"_L1, @""},
+ {"security-low"_L1, @"lock.trianglebadge.exclamationmark"},
+ {"software-update-available"_L1, @"arrowshape.up.circle"},
+ {"software-update-urgent"_L1, @"exclamationmark.transmission"},
+ {"sync-error"_L1, @"exclamationmark.arrow.triangle.2.circlepath"},
+ {"sync-synchronizing"_L1, @"arrow.triangle.2.circlepath"},
+ {"task-due"_L1, @"clock.badge.exclamationmark"},
+ {"task-past-due"_L1, @"clock.badge.xmark"},
+ {"user-available"_L1, @"person.crop.circle.badge.checkmark"},
+ {"user-away"_L1, @"person.crop.circle.badge.clock"},
+ //{"user-idle"_L1, @""},
+ {"user-offline"_L1, @"person.crop.circle.badge.xmark"},
+ //{"user-trash-full"_L1, @""},
+ {"weather-clear"_L1, @"sun.max"},
+ {"weather-clear-night"_L1, @"moon"},
+ {"weather-few-clouds"_L1, @"cloud.sun"},
+ {"weather-few-clouds-night"_L1, @"cloud.moon"},
+ {"weather-fog"_L1, @"cloud.fog"},
+ {"weather-overcast"_L1, @"cloud"},
+ //{"weather-severe-alert"_L1, @""},
+ {"weather-showers"_L1, @"cloud.rain"},
+ //{"weather-showers-scattered"_L1, @""},
+ {"weather-snow"_L1, @"cloud.snow"},
+ {"weather-storm"_L1, @"tropicalstorm"},
+ };
+ const auto it = std::find_if(std::begin(iconMap), std::end(iconMap), [iconName](const auto &c){
+ return c.first == iconName;
+ });
+ NSString *systemIconName = it != std::end(iconMap) ? it->second : iconName.toNSString();
+#if defined(Q_OS_MACOS)
+ return [NSImage imageWithSystemSymbolName:systemIconName accessibilityDescription:nil];
+#elif defined(QT_PLATFORM_UIKIT)
+ return [UIImage systemImageNamed:systemIconName];
+#endif
+}
+}
+
+QAppleIconEngine::QAppleIconEngine(const QString &iconName)
+ : m_iconName(iconName), m_image(loadImage(iconName))
+{
+ if (m_image)
+ [m_image retain];
+}
+
+QAppleIconEngine::~QAppleIconEngine()
+{
+ if (m_image)
+ [m_image release];
+}
+
+QIconEngine *QAppleIconEngine::clone() const
+{
+ return new QAppleIconEngine(m_iconName);
+}
+
+QString QAppleIconEngine::key() const
+{
+ return u"QAppleIconEngine"_s;
+}
+
+QString QAppleIconEngine::iconName()
+{
+ return m_iconName;
+}
+
+bool QAppleIconEngine::isNull()
+{
+ return m_image == nullptr;
+}
+
+QList<QSize> QAppleIconEngine::availableIconSizes(double aspectRatio)
+{
+ const qreal devicePixelRatio = qGuiApp->devicePixelRatio();
+ const QList<QSize> sizes = {
+ {qRound(16 * devicePixelRatio), qRound(16. * devicePixelRatio / aspectRatio)},
+ {qRound(32 * devicePixelRatio), qRound(32. * devicePixelRatio / aspectRatio)},
+ {qRound(64 * devicePixelRatio), qRound(64. * devicePixelRatio / aspectRatio)},
+ {qRound(128 * devicePixelRatio), qRound(128. * devicePixelRatio / aspectRatio)},
+ {qRound(256 * devicePixelRatio), qRound(256. * devicePixelRatio / aspectRatio)},
+ };
+ return sizes;
+}
+
+QList<QSize> QAppleIconEngine::availableSizes(QIcon::Mode, QIcon::State)
+{
+ const double aspectRatio = isNull() ? 1.0 : m_image.size.width / m_image.size.height;
+ return availableIconSizes(aspectRatio);
+}
+
+QSize QAppleIconEngine::actualSize(const QSize &size, QIcon::Mode /*mode*/, QIcon::State /*state*/)
+{
+ const double inputAspectRatio = isNull() ? 1.0 : m_image.size.width / m_image.size.height;
+ const double outputAspectRatio = size.width() / size.height();
+ QSize result = size;
+ if (outputAspectRatio > inputAspectRatio)
+ result.rwidth() = result.height() * inputAspectRatio;
+ else
+ result.rheight() = result.width() / inputAspectRatio;
+ return result;
+}
+
+QPixmap QAppleIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ return scaledPixmap(size, mode, state, 1.0);
+}
+
+namespace {
+#if defined(Q_OS_MACOS)
+auto *configuredImage(const NSImage *image, const QColor &color)
+{
+ auto *config = [NSImageSymbolConfiguration configurationWithPointSize:48
+ weight:NSFontWeightRegular
+ scale:NSImageSymbolScaleLarge];
+ if (@available(macOS 12, *)) {
+ auto *primaryColor = [NSColor colorWithSRGBRed:color.redF()
+ green:color.greenF()
+ blue:color.blueF()
+ alpha:color.alphaF()];
+
+ auto *colorConfig = [NSImageSymbolConfiguration configurationWithHierarchicalColor:primaryColor];
+ config = [config configurationByApplyingConfiguration:colorConfig];
+ }
+
+ return [image imageWithSymbolConfiguration:config];
+}
+#elif defined(QT_PLATFORM_UIKIT)
+auto *configuredImage(const UIImage *image, const QColor &color)
+{
+ auto *config = [UIImageSymbolConfiguration configurationWithPointSize:48
+ weight:UIImageSymbolWeightRegular
+ scale:UIImageSymbolScaleLarge];
+
+ if (@available(iOS 15, *)) {
+ auto *primaryColor = [UIColor colorWithRed:color.redF()
+ green:color.greenF()
+ blue:color.blueF()
+ alpha:color.alphaF()];
+
+ auto *colorConfig = [UIImageSymbolConfiguration configurationWithHierarchicalColor:primaryColor];
+ config = [config configurationByApplyingConfiguration:colorConfig];
+ }
+ return [image imageByApplyingSymbolConfiguration:config];
+}
+#endif
+}
+
+QPixmap QAppleIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
+{
+ const quint64 cacheKey = calculateCacheKey(mode, state);
+ if (cacheKey != m_cacheKey || m_pixmap.size() != size || m_pixmap.devicePixelRatio() != scale) {
+ const QSize paintSize = actualSize(size, mode, state);
+ const QSize paintOffset = paintSize != size
+ ? (QSizeF(size - paintSize) * 0.5).toSize()
+ : QSize();
+
+ m_pixmap = QPixmap(size * scale);
+ m_pixmap.setDevicePixelRatio(scale);
+ m_pixmap.fill(Qt::transparent);
+
+ QPainter painter(&m_pixmap);
+ paint(&painter, QRect(paintOffset.width(), paintOffset.height(),
+ paintSize.width(), paintSize.height()), mode, state);
+
+ m_cacheKey = cacheKey;
+ }
+ return m_pixmap;
+}
+
+void QAppleIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
+{
+ Q_UNUSED(state);
+
+ QColor color;
+ const QPalette palette;
+ switch (mode) {
+ case QIcon::Normal:
+ color = palette.color(QPalette::Inactive, QPalette::Text);
+ break;
+ case QIcon::Disabled:
+ color = palette.color(QPalette::Disabled, QPalette::Text);
+ break;
+ case QIcon::Active:
+ color = palette.color(QPalette::Active, QPalette::Text);
+ break;
+ case QIcon::Selected:
+ color = palette.color(QPalette::Active, QPalette::HighlightedText);
+ break;
+ }
+ const auto *image = configuredImage(m_image, color);
+
+ QMacCGContext ctx(painter);
+
+#if defined(Q_OS_MACOS)
+ NSGraphicsContext *gc = [NSGraphicsContext graphicsContextWithCGContext:ctx flipped:YES];
+ [NSGraphicsContext saveGraphicsState];
+ [NSGraphicsContext setCurrentContext:gc];
+
+ const NSSize pixmapSize = NSMakeSize(rect.width(), rect.height());
+ [image setSize:pixmapSize];
+ const NSRect sourceRect = NSMakeRect(0, 0, pixmapSize.width, pixmapSize.height);
+ const NSRect iconRect = NSMakeRect(rect.x(), rect.y(), pixmapSize.width, pixmapSize.height);
+
+ [image drawInRect:iconRect fromRect:sourceRect operation:NSCompositingOperationSourceOver fraction:1.0 respectFlipped:YES hints:nil];
+ [NSGraphicsContext restoreGraphicsState];
+#elif defined(QT_PLATFORM_UIKIT)
+ UIGraphicsPushContext(ctx);
+ const CGRect cgrect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
+ [image drawInRect:cgrect];
+ UIGraphicsPopContext();
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/platform/darwin/qappleiconengine_p.h b/src/gui/platform/darwin/qappleiconengine_p.h
new file mode 100644
index 0000000000..2a4ff7fc64
--- /dev/null
+++ b/src/gui/platform/darwin/qappleiconengine_p.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QAPPLEICONENGINE_P_H
+#define QAPPLEICONENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/qiconengine.h>
+
+#include <QtCore/private/qcore_mac_p.h>
+
+Q_FORWARD_DECLARE_OBJC_CLASS(UIImage);
+Q_FORWARD_DECLARE_OBJC_CLASS(NSImage);
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QAppleIconEngine : public QIconEngine
+{
+public:
+ QAppleIconEngine(const QString &iconName);
+ ~QAppleIconEngine();
+ QIconEngine *clone() const override;
+ QString key() const override;
+ QString iconName() override;
+ bool isNull() override;
+
+ QList<QSize> availableSizes(QIcon::Mode, QIcon::State) override;
+ QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+ QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
+
+ static QList<QSize> availableIconSizes(double aspectRatio = 1.0);
+
+private:
+ static constexpr quint64 calculateCacheKey(QIcon::Mode mode, QIcon::State state)
+ {
+ return (quint64(mode) << 32) | state;
+ }
+
+ const QString m_iconName;
+#if defined(Q_OS_MACOS)
+ const NSImage *m_image;
+#elif defined(QT_PLATFORM_UIKIT)
+ const UIImage *m_image;
+#endif
+ mutable QPixmap m_pixmap;
+ mutable quint64 m_cacheKey = {};
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QAPPLEICONENGINE_P_H
diff --git a/src/gui/platform/darwin/qapplekeymapper.mm b/src/gui/platform/darwin/qapplekeymapper.mm
index 738fab3863..b8ff5c9d6d 100644
--- a/src/gui/platform/darwin/qapplekeymapper.mm
+++ b/src/gui/platform/darwin/qapplekeymapper.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qglobal.h>
@@ -54,7 +18,6 @@
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcQpaKeyMapper, "qt.qpa.keymapper");
Q_LOGGING_CATEGORY(lcQpaKeyMapperKeys, "qt.qpa.keymapper.keys");
static Qt::KeyboardModifiers swapModifiersIfNeeded(const Qt::KeyboardModifiers modifiers)
@@ -73,36 +36,6 @@ static Qt::KeyboardModifiers swapModifiersIfNeeded(const Qt::KeyboardModifiers m
return swappedModifiers;
}
-Qt::Key QAppleKeyMapper::fromNSString(Qt::KeyboardModifiers qtModifiers, NSString *characters,
- NSString *charactersIgnoringModifiers, QString &text)
-{
- if ([characters isEqualToString:@"\t"]) {
- if (qtModifiers & Qt::ShiftModifier)
- return Qt::Key_Backtab;
- return Qt::Key_Tab;
- } else if ([characters isEqualToString:@"\r"]) {
- if (qtModifiers & Qt::KeypadModifier)
- return Qt::Key_Enter;
- return Qt::Key_Return;
- }
- if ([characters length] != 0 || [charactersIgnoringModifiers length] != 0) {
- QChar ch;
- if (((qtModifiers & Qt::MetaModifier) || (qtModifiers & Qt::AltModifier)) &&
- ([charactersIgnoringModifiers length] != 0)) {
- ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
- } else if ([characters length] != 0) {
- ch = QChar([characters characterAtIndex:0]);
- }
- if (!(qtModifiers & (Qt::ControlModifier | Qt::MetaModifier)) &&
- (ch.unicode() < 0xf700 || ch.unicode() > 0xf8ff)) {
- text = QString::fromNSString(characters);
- }
- if (!ch.isNull())
- return Qt::Key(ch.toUpper().unicode());
- }
- return Qt::Key_unknown;
-}
-
#ifdef Q_OS_MACOS
static constexpr std::tuple<NSEventModifierFlags, Qt::KeyboardModifier> cocoaModifierMap[] = {
{ NSEventModifierFlagShift, Qt::ShiftModifier },
@@ -396,11 +329,11 @@ QChar QAppleKeyMapper::toCocoaKey(Qt::Key key)
{
// Prioritize overloaded keys
if (key == Qt::Key_Return)
- return QChar(NSNewlineCharacter);
+ return QChar(NSCarriageReturnCharacter);
if (key == Qt::Key_Backspace)
return QChar(NSBackspaceCharacter);
- static QHash<Qt::Key, char16_t> reverseCocoaKeys;
+ Q_CONSTINIT static QHash<Qt::Key, char16_t> reverseCocoaKeys;
if (reverseCocoaKeys.isEmpty()) {
reverseCocoaKeys.reserve(cocoaKeys.size());
for (auto it = cocoaKeys.begin(); it != cocoaKeys.end(); ++it)
@@ -420,7 +353,7 @@ Qt::Key QAppleKeyMapper::fromCocoaKey(QChar keyCode)
// ------------------------------------------------
-Qt::KeyboardModifiers QAppleKeyMapper::queryKeyboardModifiers()
+Qt::KeyboardModifiers QAppleKeyMapper::queryKeyboardModifiers() const
{
return fromCocoaModifiers(NSEvent.modifierFlags);
}
@@ -437,7 +370,6 @@ bool QAppleKeyMapper::updateKeyboard()
Q_ASSERT(source);
m_currentInputSource = source;
m_keyboardKind = LMGetKbdType();
- m_deadKeyState = 0;
m_keyMap.clear();
@@ -508,12 +440,15 @@ const QAppleKeyMapper::KeyMap &QAppleKeyMapper::keyMapForKey(VirtualKeyCode virt
auto carbonModifiers = toCarbonModifiers(qtModifiers);
const UInt32 modifierKeyState = (carbonModifiers >> 8) & 0xFF;
+ UInt32 deadKeyState = 0;
static const UniCharCount maxStringLength = 10;
static UniChar unicodeString[maxStringLength];
UniCharCount actualStringLength = 0;
OSStatus err = UCKeyTranslate(m_keyboardLayoutFormat, virtualKey,
- kUCKeyActionDown, modifierKeyState, m_keyboardKind, OptionBits(0),
- &m_deadKeyState, maxStringLength, &actualStringLength, unicodeString);
+ kUCKeyActionDown, modifierKeyState, m_keyboardKind,
+ kUCKeyTranslateNoDeadKeysMask, &deadKeyState,
+ maxStringLength, &actualStringLength,
+ unicodeString);
// Use translated Unicode key if valid
QChar carbonUnicodeKey;
@@ -549,15 +484,32 @@ const QAppleKeyMapper::KeyMap &QAppleKeyMapper::keyMapForKey(VirtualKeyCode virt
qCDebug(lcQpaKeyMapper).verbosity(0) << "\t" << qtModifiers
<< "+" << qUtf8Printable(QString::asprintf("0x%02x", virtualKey))
<< "=" << qUtf8Printable(QString::asprintf("%d / 0x%02x /", qtKey, qtKey))
- << QString::asprintf("%c", qtKey);
+ << QKeySequence(qtKey).toString();
}
return keyMap;
}
-QList<int> QAppleKeyMapper::possibleKeys(const QKeyEvent *event) const
+/*
+ Compute the possible key combinations that can map to the event's
+ virtual key and modifiers, in the current keyboard layout.
+
+ For example, given a normal US keyboard layout, the virtual key
+ 23 combined with the Alt (⌥) and Shift (⇧) modifiers, can map
+ to the following key combinations:
+
+ - Alt+Shift+5
+ - Alt+%
+ - Shift+∞
+ - fi
+
+ The function builds on a key map produced by keyMapForKey(),
+ where each modifier-key combination has been mapped to the
+ key it will produce.
+*/
+QList<QKeyCombination> QAppleKeyMapper::possibleKeyCombinations(const QKeyEvent *event) const
{
- QList<int> ret;
+ QList<QKeyCombination> ret;
const auto nativeVirtualKey = event->nativeVirtualKey();
if (!nativeVirtualKey)
@@ -570,21 +522,93 @@ QList<int> QAppleKeyMapper::possibleKeys(const QKeyEvent *event) const
auto eventModifiers = event->modifiers();
- // The base key, with the complete set of modifiers,
- // is always valid, and the first priority.
- ret << int(unmodifiedKey) + int(eventModifiers);
+ int startingModifierLayer = 0;
+ if (toCocoaModifiers(eventModifiers) & NSEventModifierFlagCommand) {
+ // When the Command key is pressed AppKit seems to do key equivalent
+ // matching using a Latin/Roman interpretation of the current keyboard
+ // layout. For example, for a Greek layout, pressing Option+Command+C
+ // produces a key event with chars="ç" and unmodchars="ψ", but AppKit
+ // still treats this as a match for a key equivalent of Option+Command+C.
+ // We can't do the same by just applying the modifiers to our key map,
+ // as that too contains "ψ" for the Option+Command combination. What we
+ // can do instead is take advantage of the fact that the Command
+ // modifier layer in all/most keyboard layouts contains a Latin
+ // layer. We then combine that with the modifiers of the event
+ // to produce the resulting "Latin" key combination.
+ static constexpr int kCommandLayer = 2;
+ ret << QKeyCombination::fromCombined(
+ int(eventModifiers) + int(keyMap[kCommandLayer]));
+
+ // If the unmodified key is outside of Latin1, we also treat
+ // that as a valid key combination, even if AppKit natively
+ // does not. For example, for a Greek layout, we still want
+ // to support Option+Command+ψ as a key combination, as it's
+ // unlikely to clash with the Latin key combination we added
+ // above.
+
+ // However, if the unmodified key is within Latin1, we skip
+ // it, to avoid these types of conflicts. For example, in
+ // the same Greek layout, pressing the key next to Tab will
+ // produce a Latin ';' symbol, but we've already treated that
+ // as 'q' above, thanks to the Command modifier, so we skip
+ // the potential Command+; key combination. This is also in
+ // line with what AppKit natively does.
+
+ // Skipping Latin1 unmodified keys also handles the case of
+ // a Latin layout, where the unmodified and modified keys
+ // are the same.
+
+ if (unmodifiedKey <= 0xff)
+ startingModifierLayer = 1;
+ }
// FIXME: We only compute the first 8 combinations. Why?
- for (int i = 1; i < 8; ++i) {
+ for (int i = startingModifierLayer; i < 15; ++i) {
auto keyAfterApplyingModifiers = keyMap[i];
- if (keyAfterApplyingModifiers == unmodifiedKey)
- continue;
+ if (!keyAfterApplyingModifiers)
+ continue;
- // Include key if event modifiers includes, or matches
- // perfectly, the current candidate modifiers.
+ // Include key if the event modifiers match exactly,
+ // or are a superset of the current candidate modifiers.
auto candidateModifiers = modifierCombinations[i];
- if ((eventModifiers & candidateModifiers) == candidateModifiers)
- ret << int(keyAfterApplyingModifiers) + int(eventModifiers & ~candidateModifiers);
+ if ((eventModifiers & candidateModifiers) == candidateModifiers) {
+ // If the event includes more modifiers than the candidate they
+ // will need to be included in the resulting key combination.
+ auto additionalModifiers = eventModifiers & ~candidateModifiers;
+
+ auto keyCombination = QKeyCombination::fromCombined(
+ int(additionalModifiers) + int(keyAfterApplyingModifiers));
+
+ // If there's an existing key combination with the same key,
+ // but a different set of modifiers, we want to choose only
+ // one of them, by priority (see below).
+ const auto existingCombination = std::find_if(
+ ret.begin(), ret.end(), [&](auto existingCombination) {
+ return existingCombination.key() == keyAfterApplyingModifiers;
+ });
+
+ if (existingCombination != ret.end()) {
+ // We prioritize the combination with the more specific
+ // modifiers. In the case where the number of modifiers
+ // are the same, we want to prioritize Command over Option
+ // over Control over Shift. Unfortunately the order (and
+ // hence value) of the modifiers in Qt::KeyboardModifier
+ // does not match our preferred order when Control and
+ // Meta is switched, but we can work around that by
+ // explicitly swapping the modifiers and using that
+ // for the comparison. This also works when the
+ // Qt::AA_MacDontSwapCtrlAndMeta application attribute
+ // is set, as the incoming modifiers are then left
+ // as is, and we can still trust the order.
+ auto existingModifiers = swapModifiersIfNeeded(existingCombination->keyboardModifiers());
+ auto replacementModifiers = swapModifiersIfNeeded(additionalModifiers);
+ if (replacementModifiers > existingModifiers)
+ *existingCombination = keyCombination;
+ } else {
+ // All is good, no existing combination has this key
+ ret << keyCombination;
+ }
+ }
}
return ret;
@@ -592,36 +616,65 @@ QList<int> QAppleKeyMapper::possibleKeys(const QKeyEvent *event) const
-#else
-// Keyboard keys (non-modifiers)
-API_AVAILABLE(ios(13.4)) static QHash<NSString *, Qt::Key> uiKitKeys = {
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_13_4)
- { UIKeyInputF1, Qt::Key_F1 },
- { UIKeyInputF2, Qt::Key_F2 },
- { UIKeyInputF3, Qt::Key_F3 },
- { UIKeyInputF4, Qt::Key_F4 },
- { UIKeyInputF5, Qt::Key_F5 },
- { UIKeyInputF6, Qt::Key_F6 },
- { UIKeyInputF7, Qt::Key_F7 },
- { UIKeyInputF8, Qt::Key_F8 },
- { UIKeyInputF9, Qt::Key_F9 },
- { UIKeyInputF10, Qt::Key_F10 },
- { UIKeyInputF11, Qt::Key_F11 },
- { UIKeyInputF12, Qt::Key_F12 },
- { UIKeyInputHome, Qt::Key_Home },
- { UIKeyInputEnd, Qt::Key_End },
- { UIKeyInputPageUp, Qt::Key_PageUp },
- { UIKeyInputPageDown, Qt::Key_PageDown },
-#endif
- { UIKeyInputEscape, Qt::Key_Escape },
- { UIKeyInputUpArrow, Qt::Key_Up },
- { UIKeyInputDownArrow, Qt::Key_Down },
- { UIKeyInputLeftArrow, Qt::Key_Left },
- { UIKeyInputRightArrow, Qt::Key_Right }
-};
+#else // iOS
+Qt::Key QAppleKeyMapper::fromNSString(Qt::KeyboardModifiers qtModifiers, NSString *characters,
+ NSString *charactersIgnoringModifiers, QString &text)
+{
+ if ([characters isEqualToString:@"\t"]) {
+ if (qtModifiers & Qt::ShiftModifier)
+ return Qt::Key_Backtab;
+ return Qt::Key_Tab;
+ } else if ([characters isEqualToString:@"\r"]) {
+ if (qtModifiers & Qt::KeypadModifier)
+ return Qt::Key_Enter;
+ return Qt::Key_Return;
+ }
+ if ([characters length] != 0 || [charactersIgnoringModifiers length] != 0) {
+ QChar ch;
+ if (((qtModifiers & Qt::MetaModifier) || (qtModifiers & Qt::AltModifier)) &&
+ ([charactersIgnoringModifiers length] != 0)) {
+ ch = QChar([charactersIgnoringModifiers characterAtIndex:0]);
+ } else if ([characters length] != 0) {
+ ch = QChar([characters characterAtIndex:0]);
+ }
+ if (!(qtModifiers & (Qt::ControlModifier | Qt::MetaModifier)) &&
+ (ch.unicode() < 0xf700 || ch.unicode() > 0xf8ff)) {
+ text = QString::fromNSString(characters);
+ }
+ if (!ch.isNull())
+ return Qt::Key(ch.toUpper().unicode());
+ }
+ return Qt::Key_unknown;
+}
+
+// Keyboard keys (non-modifiers)
API_AVAILABLE(ios(13.4)) Qt::Key QAppleKeyMapper::fromUIKitKey(NSString *keyCode)
{
+ static QHash<NSString *, Qt::Key> uiKitKeys = {
+ { UIKeyInputF1, Qt::Key_F1 },
+ { UIKeyInputF2, Qt::Key_F2 },
+ { UIKeyInputF3, Qt::Key_F3 },
+ { UIKeyInputF4, Qt::Key_F4 },
+ { UIKeyInputF5, Qt::Key_F5 },
+ { UIKeyInputF6, Qt::Key_F6 },
+ { UIKeyInputF7, Qt::Key_F7 },
+ { UIKeyInputF8, Qt::Key_F8 },
+ { UIKeyInputF9, Qt::Key_F9 },
+ { UIKeyInputF10, Qt::Key_F10 },
+ { UIKeyInputF11, Qt::Key_F11 },
+ { UIKeyInputF12, Qt::Key_F12 },
+ { UIKeyInputHome, Qt::Key_Home },
+ { UIKeyInputEnd, Qt::Key_End },
+ { UIKeyInputPageUp, Qt::Key_PageUp },
+ { UIKeyInputPageDown, Qt::Key_PageDown },
+ { UIKeyInputEscape, Qt::Key_Escape },
+ { UIKeyInputUpArrow, Qt::Key_Up },
+ { UIKeyInputDownArrow, Qt::Key_Down },
+ { UIKeyInputLeftArrow, Qt::Key_Left },
+ { UIKeyInputRightArrow, Qt::Key_Right }
+ };
+
if (auto key = uiKitKeys.value(keyCode))
return key;
diff --git a/src/gui/platform/darwin/qapplekeymapper_p.h b/src/gui/platform/darwin/qapplekeymapper_p.h
index 78e71ac37d..1f3494d16f 100644
--- a/src/gui/platform/darwin/qapplekeymapper_p.h
+++ b/src/gui/platform/darwin/qapplekeymapper_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QAPPLEKEYMAPPER_H
#define QAPPLEKEYMAPPER_H
@@ -55,20 +19,22 @@
#include <Carbon/Carbon.h>
#endif
+#include <qpa/qplatformkeymapper.h>
+
#include <QtCore/QList>
+#include <QtCore/QHash>
#include <QtGui/QKeyEvent>
#include <QtCore/private/qcore_mac_p.h>
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QAppleKeyMapper
+class Q_GUI_EXPORT QAppleKeyMapper : public QPlatformKeyMapper
{
public:
- static Qt::KeyboardModifiers queryKeyboardModifiers();
- QList<int> possibleKeys(const QKeyEvent *event) const;
- static Qt::Key fromNSString(Qt::KeyboardModifiers qtMods, NSString *characters,
- NSString *charactersIgnoringModifiers, QString &text);
+ Qt::KeyboardModifiers queryKeyboardModifiers() const override;
+ QList<QKeyCombination> possibleKeyCombinations(const QKeyEvent *event) const override;
+
#ifdef Q_OS_MACOS
static Qt::KeyboardModifiers fromCocoaModifiers(NSEventModifierFlags cocoaModifiers);
static NSEventModifierFlags toCocoaModifiers(Qt::KeyboardModifiers);
@@ -76,6 +42,9 @@ public:
static QChar toCocoaKey(Qt::Key key);
static Qt::Key fromCocoaKey(QChar keyCode);
#else
+ static Qt::Key fromNSString(Qt::KeyboardModifiers qtMods, NSString *characters,
+ NSString *charactersIgnoringModifiers, QString &text);
+
static Qt::Key fromUIKitKey(NSString *keyCode);
static Qt::KeyboardModifiers fromUIKitModifiers(ulong uikitModifiers);
static ulong toUIKitModifiers(Qt::KeyboardModifiers);
@@ -102,7 +71,6 @@ private:
enum { NullMode, UnicodeMode, OtherMode } m_keyboardMode = NullMode;
const UCKeyboardLayout *m_keyboardLayoutFormat = nullptr;
KeyboardLayoutKind m_keyboardKind = kKLKCHRuchrKind;
- mutable UInt32 m_deadKeyState = 0; // Maintains dead key state beween calls to UCKeyTranslate
mutable QHash<VirtualKeyCode, KeyMap> m_keyMap;
#endif
diff --git a/src/gui/platform/darwin/qmacmime.mm b/src/gui/platform/darwin/qmacmime.mm
deleted file mode 100644
index a248f8fb15..0000000000
--- a/src/gui/platform/darwin/qmacmime.mm
+++ /dev/null
@@ -1,1048 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <ImageIO/ImageIO.h>
-
-#include <QtCore/qsystemdetection.h>
-#include <QtCore/qurl.h>
-#include <QtGui/qimage.h>
-#include <QtCore/qmimedata.h>
-#include <QtCore/qstringconverter.h>
-
-#if defined(Q_OS_MACOS)
-#import <AppKit/AppKit.h>
-#else
-#include <MobileCoreServices/MobileCoreServices.h>
-#endif
-
-#if defined(QT_PLATFORM_UIKIT)
-#import <UIKit/UIKit.h>
-#endif
-
-#include "qmacmime_p.h"
-#include "qguiapplication.h"
-#include "private/qcore_mac_p.h"
-
-QT_BEGIN_NAMESPACE
-
-typedef QList<QMacInternalPasteboardMime*> MimeList;
-Q_GLOBAL_STATIC(MimeList, globalMimeList)
-Q_GLOBAL_STATIC(QStringList, globalDraggedTypesList)
-
-void qt_mac_addToGlobalMimeList(QMacInternalPasteboardMime *macMime)
-{
- // globalMimeList is in decreasing priority order. Recently added
- // converters take prioity over previously added converters: prepend
- // to the list.
- globalMimeList()->prepend(macMime);
-}
-
-void qt_mac_removeFromGlobalMimeList(QMacInternalPasteboardMime *macMime)
-{
- if (!QGuiApplication::closingDown())
- globalMimeList()->removeAll(macMime);
-}
-
-/*!
- \fn void qRegisterDraggedTypes(const QStringList &types)
- \relates QMacPasteboardMime
-
- Registers the given \a types as custom pasteboard types.
-
- This function should be called to enable the Drag and Drop events
- for custom pasteboard types on Cocoa implementations. This is required
- in addition to a QMacPasteboardMime subclass implementation. By default
- drag and drop is enabled for all standard pasteboard types.
-
- \sa QMacPasteboardMime
-*/
-void qt_mac_registerDraggedTypes(const QStringList &types)
-{
- (*globalDraggedTypesList()) += types;
-}
-
-const QStringList& qt_mac_enabledDraggedTypes()
-{
- return (*globalDraggedTypesList());
-}
-
-/*****************************************************************************
- QDnD debug facilities
- *****************************************************************************/
-//#define DEBUG_MIME_MAPS
-
-/*!
- \class QMacInternalPasteboardMime
- \internal
- \brief The QMacPasteboardMime class converts between a MIME type and a
- \l{http://developer.apple.com/macosx/uniformtypeidentifiers.html}{Uniform
- Type Identifier (UTI)} format.
- \since 4.2
-
- \ingroup draganddrop
- \inmodule QtWidgets
-
- Qt's drag and drop and clipboard facilities use the MIME
- standard. On X11, this maps trivially to the Xdnd protocol. On
- Mac, although some applications use MIME to describe clipboard
- contents, it is more common to use Apple's UTI format.
-
- QMacPasteboardMime's role is to bridge the gap between MIME and UTI;
- By subclasses this class, one can extend Qt's drag and drop
- and clipboard handling to convert to and from unsupported, or proprietary, UTI formats.
-
- A subclass of QMacPasteboardMime will automatically be registered, and active, upon instantiation.
-
- Qt has predefined support for the following UTIs:
- \list
- \li public.utf8-plain-text - converts to "text/plain"
- \li public.utf16-plain-text - converts to "text/plain"
- \li public.text - converts to "text/plain"
- \li public.html - converts to "text/html"
- \li public.url - converts to "text/uri-list"
- \li public.file-url - converts to "text/uri-list"
- \li public.tiff - converts to "application/x-qt-image"
- \li public.vcard - converts to "text/plain"
- \li com.apple.traditional-mac-plain-text - converts to "text/plain"
- \li com.apple.pict - converts to "application/x-qt-image"
- \endlist
-
- When working with MIME data, Qt will interate through all instances of QMacPasteboardMime to
- find an instance that can convert to, or from, a specific MIME type. It will do this by calling
- canConvert() on each instance, starting with (and choosing) the last created instance first.
- The actual conversions will be done by using convertToMime() and convertFromMime().
-
- \note The API uses the term "flavor" in some cases. This is for backwards
- compatibility reasons, and should now be understood as UTIs.
-*/
-
-/*
- \enum QMacPasteboardMime::QMacPasteboardMimeType
- \internal
-*/
-
-/*
- Constructs a new conversion object of type \a t, adding it to the
- globally accessed list of available convertors.
-*/
-QMacInternalPasteboardMime::QMacInternalPasteboardMime(char t) : type(t)
-{
- qt_mac_addToGlobalMimeList(this);
-}
-
-/*
- Destroys a conversion object, removing it from the global
- list of available convertors.
-*/
-QMacInternalPasteboardMime::~QMacInternalPasteboardMime()
-{
- qt_mac_removeFromGlobalMimeList(this);
-}
-
-/*
- Returns the item count for the given \a mimeData
-*/
-int QMacInternalPasteboardMime::count(QMimeData *mimeData)
-{
- Q_UNUSED(mimeData);
- return 1;
-}
-
-class QMacPasteboardMimeAny : public QMacInternalPasteboardMime {
-private:
-
-public:
- QMacPasteboardMimeAny() : QMacInternalPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
- }
- ~QMacPasteboardMimeAny() {
- }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
-};
-
-QString QMacPasteboardMimeAny::convertorName()
-{
- return QLatin1String("Any-Mime");
-}
-
-QString QMacPasteboardMimeAny::flavorFor(const QString &mime)
-{
- // do not handle the mime type name in the drag pasteboard
- if (mime == QLatin1String("application/x-qt-mime-type-name"))
- return QString();
- QString ret = QLatin1String("com.trolltech.anymime.") + mime;
- return ret.replace(QLatin1Char('/'), QLatin1String("--"));
-}
-
-QString QMacPasteboardMimeAny::mimeFor(QString flav)
-{
- const QString any_prefix = QLatin1String("com.trolltech.anymime.");
- if (flav.size() > any_prefix.length() && flav.startsWith(any_prefix))
- return flav.mid(any_prefix.length()).replace(QLatin1String("--"), QLatin1String("/"));
- return QString();
-}
-
-bool QMacPasteboardMimeAny::canConvert(const QString &mime, QString flav)
-{
- return mimeFor(flav) == mime;
-}
-
-QVariant QMacPasteboardMimeAny::convertToMime(const QString &mime, QList<QByteArray> data, QString)
-{
- if (data.count() > 1)
- qWarning("QMacPasteboardMimeAny: Cannot handle multiple member data");
- QVariant ret;
- if (mime == QLatin1String("text/plain"))
- ret = QString::fromUtf8(data.first());
- else
- ret = data.first();
- return ret;
-}
-
-QList<QByteArray> QMacPasteboardMimeAny::convertFromMime(const QString &mime, QVariant data, QString)
-{
- QList<QByteArray> ret;
- if (mime == QLatin1String("text/plain"))
- ret.append(data.toString().toUtf8());
- else
- ret.append(data.toByteArray());
- return ret;
-}
-
-class QMacPasteboardMimeTypeName : public QMacInternalPasteboardMime {
-private:
-
-public:
- QMacPasteboardMimeTypeName() : QMacInternalPasteboardMime(MIME_QT_CONVERTOR|MIME_ALL) {
- }
- ~QMacPasteboardMimeTypeName() {
- }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
-};
-
-QString QMacPasteboardMimeTypeName::convertorName()
-{
- return QLatin1String("Qt-Mime-Type");
-}
-
-QString QMacPasteboardMimeTypeName::flavorFor(const QString &mime)
-{
- if (mime == QLatin1String("application/x-qt-mime-type-name"))
- return QLatin1String("com.trolltech.qt.MimeTypeName");
- return QString();
-}
-
-QString QMacPasteboardMimeTypeName::mimeFor(QString)
-{
- return QString();
-}
-
-bool QMacPasteboardMimeTypeName::canConvert(const QString &, QString)
-{
- return false;
-}
-
-QVariant QMacPasteboardMimeTypeName::convertToMime(const QString &, QList<QByteArray>, QString)
-{
- QVariant ret;
- return ret;
-}
-
-QList<QByteArray> QMacPasteboardMimeTypeName::convertFromMime(const QString &, QVariant, QString)
-{
- QList<QByteArray> ret;
- ret.append(QString(QLatin1String("x-qt-mime-type-name")).toUtf8());
- return ret;
-}
-
-class QMacPasteboardMimePlainTextFallback : public QMacInternalPasteboardMime {
-public:
- QMacPasteboardMimePlainTextFallback() : QMacInternalPasteboardMime(MIME_ALL) { }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
-};
-
-QString QMacPasteboardMimePlainTextFallback::convertorName()
-{
- return QLatin1String("PlainText (public.text)");
-}
-
-QString QMacPasteboardMimePlainTextFallback::flavorFor(const QString &mime)
-{
- if (mime == QLatin1String("text/plain"))
- return QLatin1String("public.text");
- return QString();
-}
-
-QString QMacPasteboardMimePlainTextFallback::mimeFor(QString flav)
-{
- if (flav == QLatin1String("public.text"))
- return QLatin1String("text/plain");
- return QString();
-}
-
-bool QMacPasteboardMimePlainTextFallback::canConvert(const QString &mime, QString flav)
-{
- return mime == mimeFor(flav);
-}
-
-QVariant QMacPasteboardMimePlainTextFallback::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
-{
- if (data.count() > 1)
- qWarning("QMacPasteboardMimePlainTextFallback: Cannot handle multiple member data");
-
- if (flavor == QLatin1String("public.text")) {
- // Note that public.text is documented by Apple to have an undefined encoding. From
- // testing it seems that utf8 is normally used, at least by Safari on iOS.
- const QByteArray &firstData = data.first();
- return QString(QCFString(CFStringCreateWithBytes(kCFAllocatorDefault,
- reinterpret_cast<const UInt8 *>(firstData.constData()),
- firstData.size(), kCFStringEncodingUTF8, false)));
- } else {
- qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
- }
- return QVariant();
-}
-
-QList<QByteArray> QMacPasteboardMimePlainTextFallback::convertFromMime(const QString &, QVariant data, QString flavor)
-{
- QList<QByteArray> ret;
- QString string = data.toString();
- if (flavor == QLatin1String("public.text"))
- ret.append(string.toUtf8());
- return ret;
-}
-
-class QMacPasteboardMimeUnicodeText : public QMacInternalPasteboardMime {
-public:
- QMacPasteboardMimeUnicodeText() : QMacInternalPasteboardMime(MIME_ALL) { }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
-};
-
-QString QMacPasteboardMimeUnicodeText::convertorName()
-{
- return QLatin1String("UnicodeText");
-}
-
-QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime)
-{
- if (mime == QLatin1String("text/plain"))
- return QLatin1String("public.utf16-plain-text");
- int i = mime.indexOf(QLatin1String("charset="));
- if (i >= 0) {
- QString cs(mime.mid(i+8).toLower());
- i = cs.indexOf(QLatin1Char(';'));
- if (i>=0)
- cs = cs.left(i);
- if (cs == QLatin1String("system"))
- return QLatin1String("public.utf8-plain-text");
- else if (cs == QLatin1String("iso-10646-ucs-2")
- || cs == QLatin1String("utf16"))
- return QLatin1String("public.utf16-plain-text");
- }
- return QString();
-}
-
-QString QMacPasteboardMimeUnicodeText::mimeFor(QString flav)
-{
- if (flav == QLatin1String("public.utf16-plain-text") || flav == QLatin1String("public.utf8-plain-text"))
- return QLatin1String("text/plain");
- return QString();
-}
-
-bool QMacPasteboardMimeUnicodeText::canConvert(const QString &mime, QString flav)
-{
- return (mime == QLatin1String("text/plain")
- && (flav == QLatin1String("public.utf8-plain-text") || (flav == QLatin1String("public.utf16-plain-text"))));
-}
-
-QVariant QMacPasteboardMimeUnicodeText::convertToMime(const QString &mimetype, QList<QByteArray> data, QString flavor)
-{
- if (data.count() > 1)
- qWarning("QMacPasteboardMimeUnicodeText: Cannot handle multiple member data");
- const QByteArray &firstData = data.first();
- // I can only handle two types (system and unicode) so deal with them that way
- QVariant ret;
- if (flavor == QLatin1String("public.utf8-plain-text")) {
- ret = QString::fromUtf8(firstData);
- } else if (flavor == QLatin1String("public.utf16-plain-text")) {
- QString str = QStringDecoder(QStringDecoder::Utf16)(firstData);
- ret = str;
- } else {
- qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
- }
- return ret;
-}
-
-QList<QByteArray> QMacPasteboardMimeUnicodeText::convertFromMime(const QString &, QVariant data, QString flavor)
-{
- QList<QByteArray> ret;
- QString string = data.toString();
- if (flavor == QLatin1String("public.utf8-plain-text"))
- ret.append(string.toUtf8());
- else if (flavor == QLatin1String("public.utf16-plain-text")) {
- QStringEncoder::Flags f;
-#if defined(Q_OS_MACOS)
- // Some applications such as Microsoft Excel, don't deal well with
- // a BOM present, so we follow the traditional approach of Qt on
- // macOS to not generate public.utf16-plain-text with a BOM.
- f = QStringEncoder::Flag::Default;
-#else
- // Whereas iOS applications will fail to paste if we do _not_
- // include a BOM in the public.utf16-plain-text content, most
- // likely due to converting the data using NSUTF16StringEncoding
- // which assumes big-endian byte order if there is no BOM.
- f = QStringEncoder::Flag::WriteBom;
-#endif
- QStringEncoder encoder(QStringEncoder::Utf16, f);
- ret.append(encoder(string));
- }
- return ret;
-}
-
-class QMacPasteboardMimeHTMLText : public QMacInternalPasteboardMime {
-public:
- QMacPasteboardMimeHTMLText() : QMacInternalPasteboardMime(MIME_ALL) { }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
-};
-
-QString QMacPasteboardMimeHTMLText::convertorName()
-{
- return QLatin1String("HTML");
-}
-
-QString QMacPasteboardMimeHTMLText::flavorFor(const QString &mime)
-{
- if (mime == QLatin1String("text/html"))
- return QLatin1String("public.html");
- return QString();
-}
-
-QString QMacPasteboardMimeHTMLText::mimeFor(QString flav)
-{
- if (flav == QLatin1String("public.html"))
- return QLatin1String("text/html");
- return QString();
-}
-
-bool QMacPasteboardMimeHTMLText::canConvert(const QString &mime, QString flav)
-{
- return flavorFor(mime) == flav;
-}
-
-QVariant QMacPasteboardMimeHTMLText::convertToMime(const QString &mimeType, QList<QByteArray> data, QString flavor)
-{
- if (!canConvert(mimeType, flavor))
- return QVariant();
- if (data.count() > 1)
- qWarning("QMacPasteboardMimeHTMLText: Cannot handle multiple member data");
- return data.first();
-}
-
-QList<QByteArray> QMacPasteboardMimeHTMLText::convertFromMime(const QString &mime, QVariant data, QString flavor)
-{
- QList<QByteArray> ret;
- if (!canConvert(mime, flavor))
- return ret;
- ret.append(data.toByteArray());
- return ret;
-}
-
-class QMacPasteboardMimeRtfText : public QMacInternalPasteboardMime {
-public:
- QMacPasteboardMimeRtfText() : QMacInternalPasteboardMime(MIME_ALL) { }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
-};
-
-QString QMacPasteboardMimeRtfText::convertorName()
-{
- return QLatin1String("Rtf");
-}
-
-QString QMacPasteboardMimeRtfText::flavorFor(const QString &mime)
-{
- if (mime == QLatin1String("text/html"))
- return QLatin1String("public.rtf");
- return QString();
-}
-
-QString QMacPasteboardMimeRtfText::mimeFor(QString flav)
-{
- if (flav == QLatin1String("public.rtf"))
- return QLatin1String("text/html");
- return QString();
-}
-
-bool QMacPasteboardMimeRtfText::canConvert(const QString &mime, QString flav)
-{
- return mime == mimeFor(flav);
-}
-
-QVariant QMacPasteboardMimeRtfText::convertToMime(const QString &mimeType, QList<QByteArray> data, QString flavor)
-{
- if (!canConvert(mimeType, flavor))
- return QVariant();
- if (data.count() > 1)
- qWarning("QMacPasteboardMimeHTMLText: Cannot handle multiple member data");
-
- // Read RTF into to NSAttributedString, then convert the string to HTML
- NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.at(0).toNSData()
- options:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}
- documentAttributes:nil
- error:nil];
-
- NSError *error;
- NSRange range = NSMakeRange(0, [string length]);
- NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
- NSData *htmlData = [string dataFromRange:range documentAttributes:dict error:&error];
- return QByteArray::fromNSData(htmlData);
-}
-
-QList<QByteArray> QMacPasteboardMimeRtfText::convertFromMime(const QString &mime, QVariant data, QString flavor)
-{
- QList<QByteArray> ret;
- if (!canConvert(mime, flavor))
- return ret;
-
- NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.toByteArray().toNSData()
- options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}
- documentAttributes:nil
- error:nil];
-
- NSError *error;
- NSRange range = NSMakeRange(0, [string length]);
- NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType};
- NSData *rtfData = [string dataFromRange:range documentAttributes:dict error:&error];
- ret << QByteArray::fromNSData(rtfData);
- return ret;
-}
-
-class QMacPasteboardMimeFileUri : public QMacInternalPasteboardMime {
-public:
- QMacPasteboardMimeFileUri() : QMacInternalPasteboardMime(MIME_ALL) { }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
- int count(QMimeData *mimeData);
-};
-
-QString QMacPasteboardMimeFileUri::convertorName()
-{
- return QLatin1String("FileURL");
-}
-
-QString QMacPasteboardMimeFileUri::flavorFor(const QString &mime)
-{
- if (mime == QLatin1String("text/uri-list"))
- return QLatin1String("public.file-url");
- return QString();
-}
-
-QString QMacPasteboardMimeFileUri::mimeFor(QString flav)
-{
- if (flav == QLatin1String("public.file-url"))
- return QLatin1String("text/uri-list");
- return QString();
-}
-
-bool QMacPasteboardMimeFileUri::canConvert(const QString &mime, QString flav)
-{
- return mime == QLatin1String("text/uri-list") && flav == QLatin1String("public.file-url");
-}
-
-QVariant QMacPasteboardMimeFileUri::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
-{
- if (!canConvert(mime, flav))
- return QVariant();
- QList<QVariant> ret;
- for (int i = 0; i < data.size(); ++i) {
- const QByteArray &a = data.at(i);
- NSString *urlString = [[[NSString alloc] initWithBytesNoCopy:(void *)a.data() length:a.size()
- encoding:NSUTF8StringEncoding freeWhenDone:NO] autorelease];
- NSURL *nsurl = [NSURL URLWithString:urlString];
- QUrl url;
- // OS X 10.10 sends file references instead of file paths
- if ([nsurl isFileReferenceURL]) {
- url = QUrl::fromNSURL([nsurl filePathURL]);
- } else {
- url = QUrl::fromNSURL(nsurl);
- }
-
- if (url.host().toLower() == QLatin1String("localhost"))
- url.setHost(QString());
-
- url.setPath(url.path().normalized(QString::NormalizationForm_C));
- ret.append(url);
- }
- return QVariant(ret);
-}
-
-QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime, QVariant data, QString flav)
-{
- QList<QByteArray> ret;
- if (!canConvert(mime, flav))
- return ret;
- QList<QVariant> urls = data.toList();
- for (int i = 0; i < urls.size(); ++i) {
- QUrl url = urls.at(i).toUrl();
- if (url.scheme().isEmpty())
- url.setScheme(QLatin1String("file"));
- if (url.scheme() == QLatin1String("file")) {
- if (url.host().isEmpty())
- url.setHost(QLatin1String("localhost"));
- url.setPath(url.path().normalized(QString::NormalizationForm_D));
- }
- if (url.isLocalFile())
- ret.append(url.toEncoded());
- }
- return ret;
-}
-
-int QMacPasteboardMimeFileUri::count(QMimeData *mimeData)
-{
- return mimeData->urls().count();
-}
-
-class QMacPasteboardMimeUrl : public QMacInternalPasteboardMime {
-public:
- QMacPasteboardMimeUrl() : QMacInternalPasteboardMime(MIME_ALL) { }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
-};
-
-QString QMacPasteboardMimeUrl::convertorName()
-{
- return QLatin1String("URL");
-}
-
-QString QMacPasteboardMimeUrl::flavorFor(const QString &mime)
-{
- if (mime.startsWith(QLatin1String("text/uri-list")))
- return QLatin1String("public.url");
- return QString();
-}
-
-QString QMacPasteboardMimeUrl::mimeFor(QString flav)
-{
- if (flav == QLatin1String("public.url"))
- return QLatin1String("text/uri-list");
- return QString();
-}
-
-bool QMacPasteboardMimeUrl::canConvert(const QString &mime, QString flav)
-{
- return flav == QLatin1String("public.url")
- && mime == QLatin1String("text/uri-list");
-}
-
-QVariant QMacPasteboardMimeUrl::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
-{
- if (!canConvert(mime, flav))
- return QVariant();
-
- QList<QVariant> ret;
- for (int i=0; i<data.size(); ++i) {
- QUrl url = QUrl::fromEncoded(data.at(i));
- if (url.host().toLower() == QLatin1String("localhost"))
- url.setHost(QString());
- url.setPath(url.path().normalized(QString::NormalizationForm_C));
- ret.append(url);
- }
- return QVariant(ret);
-}
-
-QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QVariant data, QString flav)
-{
- QList<QByteArray> ret;
- if (!canConvert(mime, flav))
- return ret;
-
- QList<QVariant> urls = data.toList();
- for (int i=0; i<urls.size(); ++i) {
- QUrl url = urls.at(i).toUrl();
- if (url.scheme().isEmpty())
- url.setScheme(QLatin1String("file"));
- if (url.scheme() == QLatin1String("file")) {
- if (url.host().isEmpty())
- url.setHost(QLatin1String("localhost"));
- url.setPath(url.path().normalized(QString::NormalizationForm_D));
- }
- ret.append(url.toEncoded());
- }
- return ret;
-}
-
-class QMacPasteboardMimeVCard : public QMacInternalPasteboardMime
-{
-public:
- QMacPasteboardMimeVCard() : QMacInternalPasteboardMime(MIME_ALL){ }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
-};
-
-QString QMacPasteboardMimeVCard::convertorName()
-{
- return QLatin1String("VCard");
-}
-
-bool QMacPasteboardMimeVCard::canConvert(const QString &mime, QString flav)
-{
- return mimeFor(flav) == mime;
-}
-
-QString QMacPasteboardMimeVCard::flavorFor(const QString &mime)
-{
- if (mime.startsWith(QLatin1String("text/vcard")))
- return QLatin1String("public.vcard");
- return QString();
-}
-
-QString QMacPasteboardMimeVCard::mimeFor(QString flav)
-{
- if (flav == QLatin1String("public.vcard"))
- return QLatin1String("text/vcard");
- return QString();
-}
-
-QVariant QMacPasteboardMimeVCard::convertToMime(const QString &mime, QList<QByteArray> data, QString)
-{
- QByteArray cards;
- if (mime == QLatin1String("text/vcard")) {
- for (int i=0; i<data.size(); ++i)
- cards += data[i];
- }
- return QVariant(cards);
-}
-
-QList<QByteArray> QMacPasteboardMimeVCard::convertFromMime(const QString &mime, QVariant data, QString)
-{
- QList<QByteArray> ret;
- if (mime == QLatin1String("text/vcard"))
- ret.append(data.toString().toUtf8());
- return ret;
-}
-
-extern QImage qt_mac_toQImage(CGImageRef image);
-extern CGImageRef qt_mac_toCGImage(const QImage &qImage);
-
-class QMacPasteboardMimeTiff : public QMacInternalPasteboardMime {
-public:
- QMacPasteboardMimeTiff() : QMacInternalPasteboardMime(MIME_ALL) { }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
-};
-
-QString QMacPasteboardMimeTiff::convertorName()
-{
- return QLatin1String("Tiff");
-}
-
-QString QMacPasteboardMimeTiff::flavorFor(const QString &mime)
-{
- if (mime.startsWith(QLatin1String("application/x-qt-image")))
- return QLatin1String("public.tiff");
- return QString();
-}
-
-QString QMacPasteboardMimeTiff::mimeFor(QString flav)
-{
- if (flav == QLatin1String("public.tiff"))
- return QLatin1String("application/x-qt-image");
- return QString();
-}
-
-bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav)
-{
- return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image");
-}
-
-QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
-{
- if (data.count() > 1)
- qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data");
-
- if (!canConvert(mime, flav))
- return QVariant();
-
- QCFType<CFDataRef> tiffData = data.first().toRawCFData();
- QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
-
- if (QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0))
- return QVariant(qt_mac_toQImage(image));
-
- return QVariant();
-}
-
-QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav)
-{
- if (!canConvert(mime, flav))
- return QList<QByteArray>();
-
- QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
- QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0);
-
- if (!imageDestination)
- return QList<QByteArray>();
-
- QImage img = qvariant_cast<QImage>(variant);
- NSDictionary *props = @{
- static_cast<NSString *>(kCGImagePropertyPixelWidth): @(img.width()),
- static_cast<NSString *>(kCGImagePropertyPixelHeight): @(img.height())
- };
-
- CGImageDestinationAddImage(imageDestination, qt_mac_toCGImage(img), static_cast<CFDictionaryRef>(props));
- CGImageDestinationFinalize(imageDestination);
-
- return QList<QByteArray>() << QByteArray::fromCFData(data);
-}
-
-/*!
- \internal
-
- This is an internal function.
-*/
-void QMacInternalPasteboardMime::initializeMimeTypes()
-{
- if (globalMimeList()->isEmpty()) {
- // Create QMacPasteboardMimeAny first to put it at the end of globalMimeList
- // with lowest priority. (the constructor prepends to the list)
- new QMacPasteboardMimeAny;
-
- //standard types that we wrap
- new QMacPasteboardMimeTiff;
- new QMacPasteboardMimePlainTextFallback;
- new QMacPasteboardMimeUnicodeText;
- new QMacPasteboardMimeRtfText;
- new QMacPasteboardMimeHTMLText;
- new QMacPasteboardMimeFileUri;
- new QMacPasteboardMimeUrl;
- new QMacPasteboardMimeTypeName;
- new QMacPasteboardMimeVCard;
- }
-}
-
-/*!
- \internal
-*/
-void QMacInternalPasteboardMime::destroyMimeTypes()
-{
- MimeList *mimes = globalMimeList();
- while (!mimes->isEmpty())
- delete mimes->takeFirst();
-}
-
-/*
- Returns the most-recently created QMacPasteboardMime of type \a t that can convert
- between the \a mime and \a flav formats. Returns 0 if no such convertor
- exists.
-*/
-QMacInternalPasteboardMime*
-QMacInternalPasteboardMime::convertor(uchar t, const QString &mime, QString flav)
-{
- MimeList *mimes = globalMimeList();
- for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
-#ifdef DEBUG_MIME_MAPS
- qDebug("QMacPasteboardMime::convertor: seeing if %s (%d) can convert %s to %d[%c%c%c%c] [%d]",
- (*it)->convertorName().toLatin1().constData(),
- (*it)->type & t, mime.toLatin1().constData(),
- flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
- (*it)->canConvert(mime,flav));
- for (int i = 0; i < (*it)->countFlavors(); ++i) {
- int f = (*it)->flavor(i);
- qDebug(" %d) %d[%c%c%c%c] [%s]", i, f,
- (f >> 24) & 0xFF, (f >> 16) & 0xFF, (f >> 8) & 0xFF, (f) & 0xFF,
- (*it)->convertorName().toLatin1().constData());
- }
-#endif
- if (((*it)->type & t) && (*it)->canConvert(mime, flav))
- return (*it);
- }
- return 0;
-}
-/*
- Returns a MIME type of type \a t for \a flav, or 0 if none exists.
-*/
-QString QMacInternalPasteboardMime::flavorToMime(uchar t, QString flav)
-{
- MimeList *mimes = globalMimeList();
- for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
-#ifdef DEBUG_MIME_MAPS
- qDebug("QMacMIme::flavorToMime: attempting %s (%d) for flavor %d[%c%c%c%c] [%s]",
- (*it)->convertorName().toLatin1().constData(),
- (*it)->type & t, flav, (flav >> 24) & 0xFF, (flav >> 16) & 0xFF, (flav >> 8) & 0xFF, (flav) & 0xFF,
- (*it)->mimeFor(flav).toLatin1().constData());
-
-#endif
- if ((*it)->type & t) {
- QString mimeType = (*it)->mimeFor(flav);
- if (!mimeType.isNull())
- return mimeType;
- }
- }
- return QString();
-}
-
-/*
- Returns a list of all currently defined QMacPasteboardMime objects of type \a t.
-*/
-QList<QMacInternalPasteboardMime*> QMacInternalPasteboardMime::all(uchar t)
-{
- MimeList ret;
- MimeList *mimes = globalMimeList();
- for (MimeList::const_iterator it = mimes->constBegin(); it != mimes->constEnd(); ++it) {
- if ((*it)->type & t)
- ret.append((*it));
- }
- return ret;
-}
-
-
-/*
- \fn QString QMacPasteboardMime::convertorName()
-
- Returns a name for the convertor.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-/*
- \fn bool QMacPasteboardMime::canConvert(const QString &mime, QString flav)
-
- Returns \c true if the convertor can convert (both ways) between
- \a mime and \a flav; otherwise returns \c false.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-/*
- \fn QString QMacPasteboardMime::mimeFor(QString flav)
-
- Returns the MIME UTI used for Mac flavor \a flav, or 0 if this
- convertor does not support \a flav.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-/*
- \fn QString QMacPasteboardMime::flavorFor(const QString &mime)
-
- Returns the Mac UTI used for MIME type \a mime, or 0 if this
- convertor does not support \a mime.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-/*
- \fn QVariant QMacPasteboardMime::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
-
- Returns \a data converted from Mac UTI \a flav to MIME type \a
- mime.
-
- Note that Mac flavors must all be self-terminating. The input \a
- data may contain trailing data.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-/*
- \fn QList<QByteArray> QMacPasteboardMime::convertFromMime(const QString &mime, QVariant data, QString flav)
-
- Returns \a data converted from MIME type \a mime
- to Mac UTI \a flav.
-
- Note that Mac flavors must all be self-terminating. The return
- value may contain trailing data.
-
- All subclasses must reimplement this pure virtual function.
-*/
-
-QT_END_NAMESPACE
diff --git a/src/gui/platform/darwin/qmacmime_p.h b/src/gui/platform/darwin/qmacmime_p.h
deleted file mode 100644
index 3082683834..0000000000
--- a/src/gui/platform/darwin/qmacmime_p.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QMACMIME_H
-#define QMACMIME_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-
-QT_BEGIN_NAMESPACE
-
-// Duplicate of QMacPasteboardMime in QtMacExtras. Keep in sync!
-class Q_GUI_EXPORT QMacInternalPasteboardMime {
- char type;
-public:
- enum QMacPasteboardMimeType { MIME_DND=0x01,
- MIME_CLIP=0x02,
- MIME_QT_CONVERTOR=0x04,
- MIME_QT3_CONVERTOR=0x08,
- MIME_ALL=MIME_DND|MIME_CLIP
- };
- explicit QMacInternalPasteboardMime(char);
- virtual ~QMacInternalPasteboardMime();
-
- static void initializeMimeTypes();
- static void destroyMimeTypes();
-
- static QList<QMacInternalPasteboardMime*> all(uchar);
- static QMacInternalPasteboardMime *convertor(uchar, const QString &mime, QString flav);
- static QString flavorToMime(uchar, QString flav);
-
- virtual QString convertorName() = 0;
-
- virtual bool canConvert(const QString &mime, QString flav) = 0;
- virtual QString mimeFor(QString flav) = 0;
- virtual QString flavorFor(const QString &mime) = 0;
- virtual QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav) = 0;
- virtual QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav) = 0;
- virtual int count(QMimeData *mimeData);
-};
-
-Q_GUI_EXPORT void qt_mac_addToGlobalMimeList(QMacInternalPasteboardMime *macMime);
-Q_GUI_EXPORT void qt_mac_removeFromGlobalMimeList(QMacInternalPasteboardMime *macMime);
-Q_GUI_EXPORT void qt_mac_registerDraggedTypes(const QStringList &types);
-Q_GUI_EXPORT const QStringList& qt_mac_enabledDraggedTypes();
-
-QT_END_NAMESPACE
-
-#endif
-
diff --git a/src/gui/platform/darwin/qmacmimeregistry.mm b/src/gui/platform/darwin/qmacmimeregistry.mm
new file mode 100644
index 0000000000..6710a0656f
--- /dev/null
+++ b/src/gui/platform/darwin/qmacmimeregistry.mm
@@ -0,0 +1,118 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtCore/qmimedata.h>
+
+#include "qutimimeconverter.h"
+#include "qmacmimeregistry_p.h"
+#include "qguiapplication.h"
+#include "private/qcore_mac_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+namespace QMacMimeRegistry {
+
+typedef QList<QUtiMimeConverter*> MimeList;
+Q_GLOBAL_STATIC(MimeList, globalMimeList)
+Q_GLOBAL_STATIC(QStringList, globalDraggedTypesList)
+
+// implemented in qutimimeconverter.mm
+void registerBuiltInTypes();
+
+void registerDraggedTypes(const QStringList &types)
+{
+ (*globalDraggedTypesList()) += types;
+}
+
+const QStringList& enabledDraggedTypes()
+{
+ return (*globalDraggedTypesList());
+}
+
+/*****************************************************************************
+ QDnD debug facilities
+ *****************************************************************************/
+//#define DEBUG_MIME_MAPS
+
+/*!
+ \class QMacMimeRegistry
+ \internal
+ \ingroup draganddrop
+*/
+
+/*!
+ \internal
+
+ This is an internal function.
+*/
+void initializeMimeTypes()
+{
+ if (globalMimeList()->isEmpty())
+ registerBuiltInTypes();
+}
+
+/*!
+ \internal
+*/
+void destroyMimeTypes()
+{
+ MimeList *mimes = globalMimeList();
+ while (!mimes->isEmpty())
+ delete mimes->takeFirst();
+}
+
+/*
+ Returns a MIME type of for scope \a scope for \a uti, or \nullptr if none exists.
+*/
+QString flavorToMime(QUtiMimeConverter::HandlerScope scope, const QString &uti)
+{
+ const MimeList &mimes = *globalMimeList();
+ for (const auto &mime : mimes) {
+ const bool relevantScope = mime->scope() & scope;
+#ifdef DEBUG_MIME_MAPS
+ qDebug("QMacMimeRegistry::flavorToMime: attempting (%d) for uti %s [%s]",
+ relevantScope, qPrintable(uti), qPrintable((*it)->mimeForUti(uti)));
+#endif
+ if (relevantScope) {
+ const QString mimeType = mime->mimeForUti(uti);
+ if (!mimeType.isNull())
+ return mimeType;
+ }
+ }
+ return QString();
+}
+
+void registerMimeConverter(QUtiMimeConverter *macMime)
+{
+ // globalMimeList is in decreasing priority order. Recently added
+ // converters take prioity over previously added converters: prepend
+ // to the list.
+ globalMimeList()->prepend(macMime);
+}
+
+void unregisterMimeConverter(QUtiMimeConverter *macMime)
+{
+ if (!QGuiApplication::closingDown())
+ globalMimeList()->removeAll(macMime);
+}
+
+
+/*
+ Returns a list of all currently defined QUtiMimeConverter objects for scope \a scope.
+*/
+QList<QUtiMimeConverter *> all(QUtiMimeConverter::HandlerScope scope)
+{
+ MimeList ret;
+ const MimeList &mimes = *globalMimeList();
+ for (const auto &mime : mimes) {
+ if (mime->scope() & scope)
+ ret.append(mime);
+ }
+ return ret;
+}
+
+} // namespace QMacMimeRegistry
+
+QT_END_NAMESPACE
diff --git a/src/gui/platform/darwin/qmacmimeregistry_p.h b/src/gui/platform/darwin/qmacmimeregistry_p.h
new file mode 100644
index 0000000000..5928b81959
--- /dev/null
+++ b/src/gui/platform/darwin/qmacmimeregistry_p.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QMACMIMEREGISTRY_H
+#define QMACMIMEREGISTRY_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include <QtGui/qutimimeconverter.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QMacMimeRegistry {
+ Q_GUI_EXPORT void initializeMimeTypes();
+ Q_GUI_EXPORT void destroyMimeTypes();
+
+ Q_GUI_EXPORT void registerMimeConverter(QUtiMimeConverter *);
+ Q_GUI_EXPORT void unregisterMimeConverter(QUtiMimeConverter *);
+
+ Q_GUI_EXPORT QList<QUtiMimeConverter *> all(QUtiMimeConverter::HandlerScope scope);
+ Q_GUI_EXPORT QString flavorToMime(QUtiMimeConverter::HandlerScope scope, const QString &flav);
+
+ Q_GUI_EXPORT void registerDraggedTypes(const QStringList &types);
+ Q_GUI_EXPORT const QStringList& enabledDraggedTypes();
+};
+
+QT_END_NAMESPACE
+
+#endif // QMACMIMEREGISTRY_H
diff --git a/src/gui/platform/darwin/qutimimeconverter.h b/src/gui/platform/darwin/qutimimeconverter.h
new file mode 100644
index 0000000000..e9297b5fa0
--- /dev/null
+++ b/src/gui/platform/darwin/qutimimeconverter.h
@@ -0,0 +1,62 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QUTIMIMECONVERTER_H
+#define QUTIMIMECONVERTER_H
+
+#include <QtGui/qtguiglobal.h>
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QByteArray;
+class QString;
+class QVariant;
+class QMimeData;
+
+class Q_GUI_EXPORT QUtiMimeConverter
+{
+ Q_DISABLE_COPY(QUtiMimeConverter)
+public:
+ enum class HandlerScopeFlag : uint8_t
+ {
+ DnD = 0x01,
+ Clipboard = 0x02,
+ Qt_compatible = 0x04,
+ Qt3_compatible = 0x08,
+ All = DnD|Clipboard,
+ AllCompatible = All|Qt_compatible
+ };
+ Q_DECLARE_FLAGS(HandlerScope, HandlerScopeFlag)
+
+ QUtiMimeConverter();
+ virtual ~QUtiMimeConverter();
+
+ HandlerScope scope() const { return m_scope; }
+ bool canConvert(const QString &mime, const QString &uti) const { return mimeForUti(uti) == mime; }
+
+ // for converting from Qt
+ virtual QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const = 0;
+ virtual QString utiForMime(const QString &mime) const = 0;
+
+ // for converting to Qt
+ virtual QString mimeForUti(const QString &uti) const = 0;
+ virtual QVariant convertToMime(const QString &mime, const QList<QByteArray> &data, const QString &uti) const = 0;
+ virtual int count(const QMimeData *mimeData) const;
+
+private:
+ friend class QMacMimeTypeName;
+ friend class QMacMimeAny;
+
+ explicit QUtiMimeConverter(HandlerScope scope);
+
+ const HandlerScope m_scope;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QUtiMimeConverter::HandlerScope)
+
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/gui/platform/darwin/qutimimeconverter.mm b/src/gui/platform/darwin/qutimimeconverter.mm
new file mode 100644
index 0000000000..ee643fd0c6
--- /dev/null
+++ b/src/gui/platform/darwin/qutimimeconverter.mm
@@ -0,0 +1,823 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <ImageIO/ImageIO.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <UniformTypeIdentifiers/UTCoreTypes.h>
+
+#include <QtCore/qsystemdetection.h>
+#include <QtCore/qurl.h>
+#include <QtGui/qimage.h>
+#include <QtCore/qmimedata.h>
+#include <QtCore/qstringconverter.h>
+
+#if defined(Q_OS_MACOS)
+#import <AppKit/AppKit.h>
+#else
+#include <MobileCoreServices/MobileCoreServices.h>
+#endif
+
+#if defined(QT_PLATFORM_UIKIT)
+#import <UIKit/UIKit.h>
+#endif
+
+#include "qutimimeconverter.h"
+#include "qmacmimeregistry_p.h"
+#include "qguiapplication.h"
+#include "private/qcore_mac_p.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace Qt::StringLiterals;
+
+/*****************************************************************************
+ QDnD debug facilities
+ *****************************************************************************/
+//#define DEBUG_MIME_MAPS
+
+/*!
+ \class QUtiMimeConverter
+ \brief The QUtiMimeConverter class converts between a MIME type and a
+ \l{https://developer.apple.com/documentation/uniformtypeidentifiers}
+ {Uniform Type Identifier (UTI)} format.
+ \since 6.5
+
+ \ingroup draganddrop
+ \inmodule QtGui
+
+ Qt's drag and drop and clipboard facilities use the MIME
+ standard. On X11, this maps trivially to the Xdnd protocol. On
+ Mac, although some applications use MIME to describe clipboard
+ contents, it is more common to use Apple's UTI format.
+
+ QUtiMimeConverter's role is to bridge the gap between MIME and UTI;
+ By subclasses this class, one can extend Qt's drag and drop
+ and clipboard handling to convert to and from unsupported, or proprietary, UTI formats.
+
+ Construct an instance of your converter implementation after instantiating
+ QGuiApplication:
+
+ \code
+ int main(int argc, char **argv)
+ {
+ QGuiApplication app(argc, argv);
+ JsonMimeConverter jsonConverter;
+ }
+ \endcode
+
+ Destroying the instance will unregister the converter and remove support
+ for the conversion. It is also valid to heap-allocate the converter
+ instance; Qt takes ownership and will delete the converter object during
+ QGuiApplication shut-down.
+
+ Qt has predefined support for the following UTIs:
+ \list
+ \li public.utf8-plain-text - converts to "text/plain"
+ \li public.utf16-plain-text - converts to "text/plain"
+ \li public.text - converts to "text/plain"
+ \li public.html - converts to "text/html"
+ \li public.url - converts to "text/uri-list"
+ \li public.file-url - converts to "text/uri-list"
+ \li public.tiff - converts to "application/x-qt-image"
+ \li public.vcard - converts to "text/plain"
+ \li com.apple.traditional-mac-plain-text - converts to "text/plain"
+ \li com.apple.pict - converts to "application/x-qt-image"
+ \endlist
+
+ When working with MIME data, Qt will iterate through all instances of QUtiMimeConverter to find
+ find an instance that can convert to, or from, a specific MIME type. It will do this by calling
+ mimeForUti() or utiForMime() on each instance, starting with (and choosing) the last created
+ instance first. The actual conversions will be done by using convertToMime() and convertFromMime().
+*/
+
+/*!
+ \enum QUtiMimeConverter::HandlerScope
+ \internal
+*/
+
+/*!
+ \internal
+ Constructs a new conversion object of type \a scope, adding it to the
+ globally accessed list of available converters.
+*/
+QUtiMimeConverter::QUtiMimeConverter(HandlerScope scope)
+ : m_scope(scope)
+{
+ QMacMimeRegistry::registerMimeConverter(this);
+}
+
+/*!
+ Constructs a new conversion object and adds it to the
+ globally accessed list of available converters.
+
+ Call this constructor after QGuiApplication has been created.
+*/
+QUtiMimeConverter::QUtiMimeConverter()
+ : QUtiMimeConverter(HandlerScopeFlag::All)
+{
+}
+
+/*!
+ Destroys a conversion object, removing it from the global
+ list of available converters.
+*/
+QUtiMimeConverter::~QUtiMimeConverter()
+{
+ QMacMimeRegistry::unregisterMimeConverter(this);
+}
+
+/*!
+ Returns the item count for the given \a mimeData
+*/
+int QUtiMimeConverter::count(const QMimeData *mimeData) const
+{
+ Q_UNUSED(mimeData);
+ return 1;
+}
+
+/*!
+ \fn bool QUtiMimeConverter::canConvert(const QString &mime, const QString &uti) const
+
+ Returns \c true if the converter can convert (both ways) between
+ \a mime and \a uti; otherwise returns \c false.
+*/
+
+/*!
+ \fn QString QUtiMimeConverter::mimeForUti(const QString &uti) const
+
+ Returns the MIME type used for Mac UTI \a uti, or an empty string if
+ this converter does not support converting from \a uti.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QString QUtiMimeConverter::utiForMime(const QString &mime) const
+
+ Returns the Mac UTI used for MIME type \a mime, or an empty string if
+ this converter does not support converting from \a mime.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QVariant QUtiMimeConverter::convertToMime(const QString &mime,
+ const QList<QByteArray> &data, const QString &uti) const
+
+ Returns \a data converted from Mac UTI \a uti to MIME type \a mime.
+
+ Note that Mac UTIs must all be self-terminating. The input \a data
+ may contain trailing data.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QList<QByteArray> QUtiMimeConverter::convertFromMime(const QString &mime,
+ const QVariant &data, const QString & uti) const
+
+ Returns \a data converted from MIME type \a mime to Mac UTI \a uti.
+
+ Note that Mac UTIs must all be self-terminating. The return
+ value may contain trailing data.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+
+class QMacMimeAny : public QUtiMimeConverter {
+public:
+ QMacMimeAny() : QUtiMimeConverter(HandlerScopeFlag::AllCompatible) {}
+
+ QString utiForMime(const QString &mime) const override;
+ QString mimeForUti(const QString &uti) const override;
+ QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
+ const QString &uti) const override;
+ QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
+ const QString &uti) const override;
+};
+
+QString QMacMimeAny::utiForMime(const QString &mime) const
+{
+ // do not handle the mime type name in the drag pasteboard
+ if (mime == "application/x-qt-mime-type-name"_L1)
+ return QString();
+ QString ret = "com.trolltech.anymime."_L1 + mime;
+ return ret.replace(u'/', "--"_L1);
+}
+
+QString QMacMimeAny::mimeForUti(const QString &uti) const
+{
+ const QString any_prefix = "com.trolltech.anymime."_L1;
+ if (uti.size() > any_prefix.length() && uti.startsWith(any_prefix))
+ return uti.mid(any_prefix.length()).replace("--"_L1, "/"_L1);
+ return QString();
+}
+
+QVariant QMacMimeAny::convertToMime(const QString &mime, const QList<QByteArray> &data,
+ const QString &) const
+{
+ if (data.count() > 1)
+ qWarning("QMacMimeAny: Cannot handle multiple member data");
+ QVariant ret;
+ if (mime == "text/plain"_L1)
+ ret = QString::fromUtf8(data.first());
+ else
+ ret = data.first();
+ return ret;
+}
+
+QList<QByteArray> QMacMimeAny::convertFromMime(const QString &mime, const QVariant &data,
+ const QString &) const
+{
+ QList<QByteArray> ret;
+ if (mime == "text/plain"_L1)
+ ret.append(data.toString().toUtf8());
+ else
+ ret.append(data.toByteArray());
+ return ret;
+}
+
+class QMacMimeTypeName : public QUtiMimeConverter {
+private:
+
+public:
+ QMacMimeTypeName(): QUtiMimeConverter(HandlerScopeFlag::AllCompatible) {}
+
+ QString utiForMime(const QString &mime) const override;
+ QString mimeForUti(const QString &uti) const override;
+ QVariant convertToMime(const QString &mime, const QList<QByteArray> &data, const QString &uti) const override;
+ QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data, const QString &uti) const override;
+};
+
+QString QMacMimeTypeName::utiForMime(const QString &mime) const
+{
+ if (mime == "application/x-qt-mime-type-name"_L1)
+ return u"com.trolltech.qt.MimeTypeName"_s;
+ return QString();
+}
+
+QString QMacMimeTypeName::mimeForUti(const QString &) const
+{
+ return QString();
+}
+
+QVariant QMacMimeTypeName::convertToMime(const QString &, const QList<QByteArray> &, const QString &) const
+{
+ QVariant ret;
+ return ret;
+}
+
+QList<QByteArray> QMacMimeTypeName::convertFromMime(const QString &, const QVariant &, const QString &) const
+{
+ QList<QByteArray> ret;
+ ret.append(QString("x-qt-mime-type-name"_L1).toUtf8());
+ return ret;
+}
+
+class QMacMimePlainTextFallback : public QUtiMimeConverter
+{
+public:
+ QString utiForMime(const QString &mime) const override;
+ QString mimeForUti(const QString &uti) const override;
+ QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
+ const QString &uti) const override;
+ QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
+ const QString &uti) const override;
+};
+
+QString QMacMimePlainTextFallback::utiForMime(const QString &mime) const
+{
+ if (mime == "text/plain"_L1)
+ return "public.text"_L1;
+ return QString();
+}
+
+QString QMacMimePlainTextFallback::mimeForUti(const QString &uti) const
+{
+ if (uti == "public.text"_L1)
+ return "text/plain"_L1;
+ return QString();
+}
+
+QVariant
+QMacMimePlainTextFallback::convertToMime(const QString &mimetype,
+ const QList<QByteArray> &data, const QString &uti) const
+{
+ if (data.count() > 1)
+ qWarning("QMacMimePlainTextFallback: Cannot handle multiple member data");
+
+ if (uti == "public.text"_L1) {
+ // Note that public.text is documented by Apple to have an undefined encoding. From
+ // testing it seems that utf8 is normally used, at least by Safari on iOS.
+ const QByteArray &firstData = data.first();
+ return QString(QCFString(CFStringCreateWithBytes(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8 *>(firstData.constData()),
+ firstData.size(), kCFStringEncodingUTF8, false)));
+ } else {
+ qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
+ }
+ return QVariant();
+}
+
+QList<QByteArray>
+QMacMimePlainTextFallback::convertFromMime(const QString &, const QVariant &data,
+ const QString &uti) const
+{
+ QList<QByteArray> ret;
+ QString string = data.toString();
+ if (uti == "public.text"_L1)
+ ret.append(string.toUtf8());
+ return ret;
+}
+
+class QMacMimeUnicodeText : public QUtiMimeConverter
+{
+public:
+ QString utiForMime(const QString &mime) const override;
+ QString mimeForUti(const QString &uti) const override;
+ QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
+ const QString &uti) const override;
+ QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
+ const QString &uti) const override;
+};
+
+QString QMacMimeUnicodeText::utiForMime(const QString &mime) const
+{
+ if (mime == "text/plain"_L1)
+ return "public.utf16-plain-text"_L1;
+ if (qsizetype i = mime.indexOf("charset="_L1); i >= 0) {
+ QString cs(mime.mid(i + 8).toLower());
+ i = cs.indexOf(u';');
+ if (i >= 0)
+ cs = cs.left(i);
+ if (cs == "system"_L1)
+ return "public.utf8-plain-text"_L1;
+ else if (cs == "iso-10646-ucs-2"_L1 || cs == "utf16"_L1)
+ return "public.utf16-plain-text"_L1;
+ }
+ return QString();
+}
+
+QString QMacMimeUnicodeText::mimeForUti(const QString &uti) const
+{
+ if (uti == "public.utf16-plain-text"_L1 || uti == "public.utf8-plain-text"_L1)
+ return "text/plain"_L1;
+ return QString();
+}
+
+QVariant
+QMacMimeUnicodeText::convertToMime(const QString &mimetype,
+ const QList<QByteArray> &data, const QString &uti) const
+{
+ if (data.count() > 1)
+ qWarning("QMacMimeUnicodeText: Cannot handle multiple member data");
+ const QByteArray &firstData = data.first();
+ // I can only handle two types (system and unicode) so deal with them that way
+ QVariant ret;
+ if (uti == "public.utf8-plain-text"_L1) {
+ ret = QString::fromUtf8(firstData);
+ } else if (uti == "public.utf16-plain-text"_L1) {
+ QString str = QStringDecoder(QStringDecoder::Utf16)(firstData);
+ ret = str;
+ } else {
+ qWarning("QMime::convertToMime: unhandled mimetype: %s", qPrintable(mimetype));
+ }
+ return ret;
+}
+
+QList<QByteArray>
+QMacMimeUnicodeText::convertFromMime(const QString &, const QVariant &data,
+ const QString &uti) const
+{
+ QList<QByteArray> ret;
+ QString string = data.toString();
+ if (uti == "public.utf8-plain-text"_L1)
+ ret.append(string.toUtf8());
+ else if (uti == "public.utf16-plain-text"_L1) {
+ QStringEncoder::Flags f;
+#if defined(Q_OS_MACOS)
+ // Some applications such as Microsoft Excel, don't deal well with
+ // a BOM present, so we follow the traditional approach of Qt on
+ // macOS to not generate public.utf16-plain-text with a BOM.
+ f = QStringEncoder::Flag::Default;
+#else
+ // Whereas iOS applications will fail to paste if we do _not_
+ // include a BOM in the public.utf16-plain-text content, most
+ // likely due to converting the data using NSUTF16StringEncoding
+ // which assumes big-endian byte order if there is no BOM.
+ f = QStringEncoder::Flag::WriteBom;
+#endif
+ QStringEncoder encoder(QStringEncoder::Utf16, f);
+ ret.append(encoder(string));
+ }
+ return ret;
+}
+
+class QMacMimeHTMLText : public QUtiMimeConverter
+{
+public:
+ QString utiForMime(const QString &mime) const override;
+ QString mimeForUti(const QString &uti) const override;
+ QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
+ const QString &uti) const override;
+ QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
+ const QString &uti) const override;
+};
+
+QString QMacMimeHTMLText::utiForMime(const QString &mime) const
+{
+ if (mime == "text/html"_L1)
+ return "public.html"_L1;
+ return QString();
+}
+
+QString QMacMimeHTMLText::mimeForUti(const QString &uti) const
+{
+ if (uti == "public.html"_L1)
+ return "text/html"_L1;
+ return QString();
+}
+
+QVariant
+QMacMimeHTMLText::convertToMime(const QString &mimeType,
+ const QList<QByteArray> &data, const QString &uti) const
+{
+ if (!canConvert(mimeType, uti))
+ return QVariant();
+ if (data.count() > 1)
+ qWarning("QMacMimeHTMLText: Cannot handle multiple member data");
+ return data.first();
+}
+
+QList<QByteArray>
+QMacMimeHTMLText::convertFromMime(const QString &mime,
+ const QVariant &data, const QString &uti) const
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, uti))
+ return ret;
+ ret.append(data.toByteArray());
+ return ret;
+}
+
+class QMacMimeRtfText : public QUtiMimeConverter
+{
+public:
+ QString utiForMime(const QString &mime) const override;
+ QString mimeForUti(const QString &uti) const override;
+ QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
+ const QString &uti) const override;
+ QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
+ const QString &uti) const override;
+};
+
+QString QMacMimeRtfText::utiForMime(const QString &mime) const
+{
+ if (mime == "text/html"_L1)
+ return "public.rtf"_L1;
+ return QString();
+}
+
+QString QMacMimeRtfText::mimeForUti(const QString &uti) const
+{
+ if (uti == "public.rtf"_L1)
+ return "text/html"_L1;
+ return QString();
+}
+
+QVariant
+QMacMimeRtfText::convertToMime(const QString &mimeType,
+ const QList<QByteArray> &data, const QString &uti) const
+{
+ if (!canConvert(mimeType, uti))
+ return QVariant();
+ if (data.count() > 1)
+ qWarning("QMacMimeHTMLText: Cannot handle multiple member data");
+
+ // Read RTF into to NSAttributedString, then convert the string to HTML
+ NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.at(0).toNSData()
+ options:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}
+ documentAttributes:nil
+ error:nil];
+
+ NSError *error;
+ NSRange range = NSMakeRange(0, [string length]);
+ NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};
+ NSData *htmlData = [string dataFromRange:range documentAttributes:dict error:&error];
+ return QByteArray::fromNSData(htmlData);
+}
+
+QList<QByteArray>
+QMacMimeRtfText::convertFromMime(const QString &mime,
+ const QVariant &data, const QString &uti) const
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, uti))
+ return ret;
+
+ NSAttributedString *string = [[NSAttributedString alloc] initWithData:data.toByteArray().toNSData()
+ options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType}
+ documentAttributes:nil
+ error:nil];
+
+ NSError *error;
+ NSRange range = NSMakeRange(0, [string length]);
+ NSDictionary *dict = @{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType};
+ NSData *rtfData = [string dataFromRange:range documentAttributes:dict error:&error];
+ ret << QByteArray::fromNSData(rtfData);
+ return ret;
+}
+
+class QMacMimeFileUri : public QUtiMimeConverter
+{
+public:
+ QString utiForMime(const QString &mime) const override;
+ QString mimeForUti(const QString &uti) const override;
+ QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
+ const QString &uti) const override;
+ QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
+ const QString &uti) const override;
+ int count(const QMimeData *mimeData) const override;
+};
+
+QString QMacMimeFileUri::utiForMime(const QString &mime) const
+{
+ if (mime == "text/uri-list"_L1)
+ return "public.file-url"_L1;
+ return QString();
+}
+
+QString QMacMimeFileUri::mimeForUti(const QString &uti) const
+{
+ if (uti == "public.file-url"_L1)
+ return "text/uri-list"_L1;
+ return QString();
+}
+
+QVariant
+QMacMimeFileUri::convertToMime(const QString &mime,
+ const QList<QByteArray> &data, const QString &uti) const
+{
+ if (!canConvert(mime, uti))
+ return QVariant();
+ QList<QVariant> ret;
+ for (int i = 0; i < data.size(); ++i) {
+ const QByteArray &a = data.at(i);
+ NSString *urlString = [[[NSString alloc] initWithBytesNoCopy:(void *)a.data() length:a.size()
+ encoding:NSUTF8StringEncoding freeWhenDone:NO] autorelease];
+ NSURL *nsurl = [NSURL URLWithString:urlString];
+ QUrl url;
+ // OS X 10.10 sends file references instead of file paths
+ if ([nsurl isFileReferenceURL]) {
+ url = QUrl::fromNSURL([nsurl filePathURL]);
+ } else {
+ url = QUrl::fromNSURL(nsurl);
+ }
+
+ if (url.host().toLower() == "localhost"_L1)
+ url.setHost(QString());
+
+ url.setPath(url.path().normalized(QString::NormalizationForm_C));
+ ret.append(url);
+ }
+ return QVariant(ret);
+}
+
+QList<QByteArray>
+QMacMimeFileUri::convertFromMime(const QString &mime,
+ const QVariant &data, const QString &uti) const
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, uti))
+ return ret;
+ QList<QVariant> urls = data.toList();
+ for (int i = 0; i < urls.size(); ++i) {
+ QUrl url = urls.at(i).toUrl();
+ if (url.scheme().isEmpty())
+ url.setScheme("file"_L1);
+ if (url.scheme() == "file"_L1) {
+ if (url.host().isEmpty())
+ url.setHost("localhost"_L1);
+ url.setPath(url.path().normalized(QString::NormalizationForm_D));
+ }
+ if (url.isLocalFile())
+ ret.append(url.toEncoded());
+ }
+ return ret;
+}
+
+int QMacMimeFileUri::count(const QMimeData *mimeData) const
+{
+ return mimeData->urls().count();
+}
+
+class QMacMimeUrl : public QUtiMimeConverter
+{
+public:
+ QString utiForMime(const QString &mime) const override;
+ QString mimeForUti(const QString &uti) const override;
+ QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
+ const QString &uti) const override;
+ QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
+ const QString &uti) const override;
+};
+
+QString QMacMimeUrl::utiForMime(const QString &mime) const
+{
+ if (mime.startsWith("text/uri-list"_L1))
+ return "public.url"_L1;
+ return QString();
+}
+
+QString QMacMimeUrl::mimeForUti(const QString &uti) const
+{
+ if (uti == "public.url"_L1)
+ return "text/uri-list"_L1;
+ return QString();
+}
+
+QVariant QMacMimeUrl::convertToMime(const QString &mime,
+ const QList<QByteArray> &data, const QString &uti) const
+{
+ if (!canConvert(mime, uti))
+ return QVariant();
+
+ QList<QVariant> ret;
+ for (int i=0; i<data.size(); ++i) {
+ QUrl url = QUrl::fromEncoded(data.at(i));
+ if (url.host().toLower() == "localhost"_L1)
+ url.setHost(QString());
+ url.setPath(url.path().normalized(QString::NormalizationForm_C));
+ ret.append(url);
+ }
+ return QVariant(ret);
+}
+
+QList<QByteArray> QMacMimeUrl::convertFromMime(const QString &mime,
+ const QVariant &data, const QString &uti) const
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, uti))
+ return ret;
+
+ QList<QVariant> urls = data.toList();
+ for (int i=0; i<urls.size(); ++i) {
+ QUrl url = urls.at(i).toUrl();
+ if (url.scheme().isEmpty())
+ url.setScheme("file"_L1);
+ if (url.scheme() == "file"_L1) {
+ if (url.host().isEmpty())
+ url.setHost("localhost"_L1);
+ url.setPath(url.path().normalized(QString::NormalizationForm_D));
+ }
+ ret.append(url.toEncoded());
+ }
+ return ret;
+}
+
+class QMacMimeVCard : public QUtiMimeConverter
+{
+public:
+ QString utiForMime(const QString &mime) const override;
+ QString mimeForUti(const QString &uti) const override;
+ QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
+ const QString &uti) const override;
+ QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
+ const QString &uti) const override;
+};
+
+QString QMacMimeVCard::utiForMime(const QString &mime) const
+{
+ if (mime.startsWith("text/vcard"_L1))
+ return "public.vcard"_L1;
+ return QString();
+}
+
+QString QMacMimeVCard::mimeForUti(const QString &uti) const
+{
+ if (uti == "public.vcard"_L1)
+ return "text/vcard"_L1;
+ return QString();
+}
+
+QVariant QMacMimeVCard::convertToMime(const QString &mime,
+ const QList<QByteArray> &data, const QString &uti) const
+{
+ if (!canConvert(mime, uti))
+ return QVariant();
+ QByteArray cards;
+ if (uti == "public.vcard"_L1) {
+ for (int i=0; i<data.size(); ++i)
+ cards += data[i];
+ }
+ return QVariant(cards);
+}
+
+QList<QByteArray> QMacMimeVCard::convertFromMime(const QString &mime,
+ const QVariant &data, const QString &uti) const
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, uti))
+ return ret;
+
+ if (mime == "text/vcard"_L1)
+ ret.append(data.toString().toUtf8());
+ return ret;
+}
+
+extern QImage qt_mac_toQImage(CGImageRef image);
+extern CGImageRef qt_mac_toCGImage(const QImage &qImage);
+
+class QMacMimeTiff : public QUtiMimeConverter
+{
+public:
+ QString utiForMime(const QString &mime) const override;
+ QString mimeForUti(const QString &uti) const override;
+ QVariant convertToMime(const QString &mime, const QList<QByteArray> &data,
+ const QString &uti) const override;
+ QList<QByteArray> convertFromMime(const QString &mime, const QVariant &data,
+ const QString &uti) const override;
+};
+
+QString QMacMimeTiff::utiForMime(const QString &mime) const
+{
+ if (mime.startsWith("application/x-qt-image"_L1))
+ return "public.tiff"_L1;
+ return QString();
+}
+
+QString QMacMimeTiff::mimeForUti(const QString &uti) const
+{
+ if (uti == "public.tiff"_L1)
+ return "application/x-qt-image"_L1;
+ return QString();
+}
+
+QVariant QMacMimeTiff::convertToMime(const QString &mime,
+ const QList<QByteArray> &data, const QString &uti) const
+{
+ if (data.count() > 1)
+ qWarning("QMacMimeTiff: Cannot handle multiple member data");
+
+ if (!canConvert(mime, uti))
+ return QVariant();
+
+ QCFType<CFDataRef> tiffData = data.first().toRawCFData();
+ QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
+
+ if (QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0))
+ return QVariant(qt_mac_toQImage(image));
+
+ return QVariant();
+}
+
+QList<QByteArray> QMacMimeTiff::convertFromMime(const QString &mime,
+ const QVariant &variant, const QString &uti) const
+{
+ if (!canConvert(mime, uti))
+ return QList<QByteArray>();
+
+ QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
+ QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data,
+ (CFStringRef)UTTypeTIFF.identifier, 1, 0);
+
+ if (!imageDestination)
+ return QList<QByteArray>();
+
+ QImage img = qvariant_cast<QImage>(variant);
+ NSDictionary *props = @{
+ static_cast<NSString *>(kCGImagePropertyPixelWidth): @(img.width()),
+ static_cast<NSString *>(kCGImagePropertyPixelHeight): @(img.height())
+ };
+
+ CGImageDestinationAddImage(imageDestination, qt_mac_toCGImage(img),
+ static_cast<CFDictionaryRef>(props));
+ CGImageDestinationFinalize(imageDestination);
+
+ return QList<QByteArray>() << QByteArray::fromCFData(data);
+}
+
+namespace QMacMimeRegistry {
+
+void registerBuiltInTypes()
+{
+ // Create QMacMimeAny first to put it at the end of globalMimeList
+ // with lowest priority. (the constructor prepends to the list)
+ new QMacMimeAny;
+
+ //standard types that we wrap
+ new QMacMimeTiff;
+ new QMacMimePlainTextFallback;
+ new QMacMimeUnicodeText;
+ new QMacMimeRtfText;
+ new QMacMimeHTMLText;
+ new QMacMimeFileUri;
+ new QMacMimeUrl;
+ new QMacMimeTypeName;
+ new QMacMimeVCard;
+}
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/platform/ios/PrivacyInfo.xcprivacy b/src/gui/platform/ios/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000000..bde2b167c7
--- /dev/null
+++ b/src/gui/platform/ios/PrivacyInfo.xcprivacy
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSPrivacyTracking</key>
+ <false/>
+ <key>NSPrivacyCollectedDataTypes</key>
+ <array/>
+ <key>NSPrivacyTrackingDomains</key>
+ <array/>
+ <key>NSPrivacyAccessedAPITypes</key>
+ <array>
+ <dict>
+ <key>NSPrivacyAccessedAPIType</key>
+ <string>NSPrivacyAccessedAPICategorySystemBootTime</string>
+ <key>NSPrivacyAccessedAPITypeReasons</key>
+ <array>
+ <string>35F9.1</string> <!-- QUIView event handling -->
+ </array>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/src/gui/platform/macos/qcocoanativeinterface.mm b/src/gui/platform/macos/qcocoanativeinterface.mm
index e1f3c73e5e..cb6acb4496 100644
--- a/src/gui/platform/macos/qcocoanativeinterface.mm
+++ b/src/gui/platform/macos/qcocoanativeinterface.mm
@@ -1,43 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtGui/private/qopenglcontext_p.h>
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtGui/qtgui-config.h>
+#ifndef QT_NO_OPENGL
+# include <QtGui/private/qopenglcontext_p.h>
+#endif
+
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformopenglcontext.h>
#include <qpa/qplatformintegration.h>
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenuadaptor.cpp b/src/gui/platform/unix/dbusmenu/qdbusmenuadaptor.cpp
index a9e508c666..a3b7b6db00 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenuadaptor.cpp
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenuadaptor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
This file was originally created by qdbusxml2cpp version 0.8
@@ -59,6 +23,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
QDBusMenuAdaptor::QDBusMenuAdaptor(QDBusPlatformMenu *topLevelMenu)
: QDBusAbstractAdaptor(topLevelMenu)
, m_topLevelMenu(topLevelMenu)
@@ -73,12 +39,12 @@ QDBusMenuAdaptor::~QDBusMenuAdaptor()
QString QDBusMenuAdaptor::status() const
{
qCDebug(qLcMenu);
- return QLatin1String("normal");
+ return "normal"_L1;
}
QString QDBusMenuAdaptor::textDirection() const
{
- return QLocale().textDirection() == Qt::RightToLeft ? QLatin1String("rtl") : QLatin1String("ltr");
+ return QLocale().textDirection() == Qt::RightToLeft ? "rtl"_L1 : "ltr"_L1;
}
uint QDBusMenuAdaptor::version() const
@@ -117,12 +83,12 @@ void QDBusMenuAdaptor::Event(int id, const QString &eventId, const QDBusVariant
Q_UNUSED(data);
Q_UNUSED(timestamp);
QDBusPlatformMenuItem *item = QDBusPlatformMenuItem::byId(id);
- qCDebug(qLcMenu) << id << (item ? item->text() : QLatin1String("")) << eventId;
- if (item && eventId == QLatin1String("clicked"))
+ qCDebug(qLcMenu) << id << (item ? item->text() : ""_L1) << eventId;
+ if (item && eventId == "clicked"_L1)
item->trigger();
- if (item && eventId == QLatin1String("hovered"))
+ if (item && eventId == "hovered"_L1)
emit item->hovered();
- if (eventId == QLatin1String("closed")) {
+ if (eventId == "closed"_L1) {
// There is no explicit AboutToHide method, so map closed event to aboutToHide method
const QDBusPlatformMenu *menu = nullptr;
if (item)
@@ -163,3 +129,5 @@ QDBusVariant QDBusMenuAdaptor::GetProperty(int id, const QString &name)
}
QT_END_NAMESPACE
+
+#include "moc_qdbusmenuadaptor_p.cpp"
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenuadaptor_p.h b/src/gui/platform/unix/dbusmenu/qdbusmenuadaptor_p.h
index 396f9d220f..b6f538f6b3 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenuadaptor_p.h
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenuadaptor_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtDBus module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
This file was originally created by qdbusxml2cpp version 0.8
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenubar.cpp b/src/gui/platform/unix/dbusmenu/qdbusmenubar.cpp
index b13c875854..2c006366cb 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenubar.cpp
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenubar.cpp
@@ -1,52 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdbusmenubar_p.h"
#include "qdbusmenuregistrarproxy_p.h"
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/* note: do not change these to QStringLiteral;
we are unloaded before QtDBus is done using the strings.
*/
-#define REGISTRAR_SERVICE QLatin1String("com.canonical.AppMenu.Registrar")
-#define REGISTRAR_PATH QLatin1String("/com/canonical/AppMenu/Registrar")
+#define REGISTRAR_SERVICE "com.canonical.AppMenu.Registrar"_L1
+#define REGISTRAR_PATH "/com/canonical/AppMenu/Registrar"_L1
QDBusMenuBar::QDBusMenuBar()
: QPlatformMenuBar()
@@ -177,3 +143,5 @@ void QDBusMenuBar::unregisterMenuBar()
}
QT_END_NAMESPACE
+
+#include "moc_qdbusmenubar_p.cpp"
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenubar_p.h b/src/gui/platform/unix/dbusmenu/qdbusmenubar_p.h
index 364e7da4b6..3028df7215 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenubar_p.h
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenubar_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDBUSMENUBAR_P_H
#define QDBUSMENUBAR_P_H
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenuconnection.cpp b/src/gui/platform/unix/dbusmenu/qdbusmenuconnection.cpp
index ce95ee96b4..1023b16662 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenuconnection.cpp
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenuconnection.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qtgui-config.h>
@@ -55,12 +19,14 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_DECLARE_LOGGING_CATEGORY(qLcMenu)
-const QString StatusNotifierWatcherService = QLatin1String("org.kde.StatusNotifierWatcher");
-const QString StatusNotifierWatcherPath = QLatin1String("/StatusNotifierWatcher");
-const QString StatusNotifierItemPath = QLatin1String("/StatusNotifierItem");
-const QString MenuBarPath = QLatin1String("/MenuBar");
+const QString StatusNotifierWatcherService = "org.kde.StatusNotifierWatcher"_L1;
+const QString StatusNotifierWatcherPath = "/StatusNotifierWatcher"_L1;
+const QString StatusNotifierItemPath = "/StatusNotifierItem"_L1;
+const QString MenuBarPath = "/MenuBar"_L1;
/*!
\class QDBusMenuConnection
@@ -74,14 +40,14 @@ QDBusMenuConnection::QDBusMenuConnection(QObject *parent, const QString &service
, m_connection(serviceName.isNull() ? QDBusConnection::sessionBus()
: QDBusConnection::connectToBus(QDBusConnection::SessionBus, serviceName))
, m_dbusWatcher(new QDBusServiceWatcher(StatusNotifierWatcherService, m_connection, QDBusServiceWatcher::WatchForRegistration, this))
- , m_statusNotifierHostRegistered(false)
+ , m_watcherRegistered(false)
{
#ifndef QT_NO_SYSTEMTRAYICON
- QDBusInterface systrayHost(StatusNotifierWatcherService, StatusNotifierWatcherPath, StatusNotifierWatcherService, m_connection);
- if (systrayHost.isValid() && systrayHost.property("IsStatusNotifierHostRegistered").toBool())
- m_statusNotifierHostRegistered = true;
+ // Start monitoring if any known tray-related services are registered.
+ if (m_connection.interface()->isServiceRegistered(StatusNotifierWatcherService))
+ m_watcherRegistered = true;
else
- qCDebug(qLcMenu) << "StatusNotifierHost is not registered";
+ qCDebug(qLcMenu) << "failed to find service" << StatusNotifierWatcherService;
#endif
}
@@ -131,7 +97,7 @@ bool QDBusMenuConnection::registerTrayIconWithWatcher(QDBusTrayIcon *item)
Q_UNUSED(item);
QDBusMessage registerMethod = QDBusMessage::createMethodCall(
StatusNotifierWatcherService, StatusNotifierWatcherPath, StatusNotifierWatcherService,
- QLatin1String("RegisterStatusNotifierItem"));
+ "RegisterStatusNotifierItem"_L1);
registerMethod.setArguments(QVariantList() << m_connection.baseService());
return m_connection.callWithCallback(registerMethod, this, SIGNAL(trayIconRegistered()), SLOT(dbusError(QDBusError)));
}
@@ -144,3 +110,5 @@ void QDBusMenuConnection::unregisterTrayIcon(QDBusTrayIcon *item)
#endif // QT_NO_SYSTEMTRAYICON
QT_END_NAMESPACE
+
+#include "moc_qdbusmenuconnection_p.cpp"
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenuconnection_p.h b/src/gui/platform/unix/dbusmenu/qdbusmenuconnection_p.h
index 012f83fe0e..37033e2fa3 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenuconnection_p.h
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenuconnection_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDBUSMENUCONNECTION_H
#define QDBUSMENUCONNECTION_H
@@ -56,6 +20,7 @@
#include <QtDBus/QDBusVariant>
#include <QtGui/qtgui-config.h>
+#include <QtCore/private/qglobal_p.h>
Q_MOC_INCLUDE(<QtDBus/QDBusError>)
QT_BEGIN_NAMESPACE
@@ -74,7 +39,7 @@ public:
~QDBusMenuConnection();
QDBusConnection connection() const { return m_connection; }
QDBusServiceWatcher *dbusWatcher() const { return m_dbusWatcher; }
- bool isStatusNotifierHostRegistered() const { return m_statusNotifierHostRegistered; }
+ bool isWatcherRegistered() const { return m_watcherRegistered; }
#ifndef QT_NO_SYSTEMTRAYICON
bool registerTrayIconMenu(QDBusTrayIcon *item);
void unregisterTrayIconMenu(QDBusTrayIcon *item);
@@ -95,7 +60,7 @@ private:
QString m_serviceName;
QDBusConnection m_connection;
QDBusServiceWatcher *m_dbusWatcher;
- bool m_statusNotifierHostRegistered;
+ bool m_watcherRegistered;
};
QT_END_NAMESPACE
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenuregistrarproxy.cpp b/src/gui/platform/unix/dbusmenu/qdbusmenuregistrarproxy.cpp
index c59b5a675e..089bf5de47 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenuregistrarproxy.cpp
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenuregistrarproxy.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
* This file was originally created by qdbusxml2cpp version 0.8
@@ -62,3 +26,5 @@ QDBusMenuRegistrarInterface::~QDBusMenuRegistrarInterface()
}
QT_END_NAMESPACE
+
+#include "moc_qdbusmenuregistrarproxy_p.cpp"
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenuregistrarproxy_p.h b/src/gui/platform/unix/dbusmenu/qdbusmenuregistrarproxy_p.h
index cffc080f87..8041f3af0a 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenuregistrarproxy_p.h
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenuregistrarproxy_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Dmitry Shachnev <mitya57@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
* This file was originally created by qdbusxml2cpp version 0.8
@@ -66,6 +30,7 @@
#include <QtDBus/QDBusAbstractInterface>
#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusReply>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -98,7 +63,7 @@ public Q_SLOTS: // METHODS
{
QDBusMessage reply = call(QDBus::Block, QStringLiteral("GetMenuForWindow"), windowId);
QList<QVariant> arguments = reply.arguments();
- if (reply.type() == QDBusMessage::ReplyMessage && arguments.count() == 2)
+ if (reply.type() == QDBusMessage::ReplyMessage && arguments.size() == 2)
menuObjectPath = qdbus_cast<QDBusObjectPath>(arguments.at(1));
return reply;
}
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenutypes.cpp b/src/gui/platform/unix/dbusmenu/qdbusmenutypes.cpp
index c5bc4a1889..b7fd035883 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenutypes.cpp
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenutypes.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdbusmenutypes_p.h"
@@ -56,6 +20,18 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+QT_IMPL_METATYPE_EXTERN(QDBusMenuItem)
+QT_IMPL_METATYPE_EXTERN(QDBusMenuItemList)
+QT_IMPL_METATYPE_EXTERN(QDBusMenuItemKeys)
+QT_IMPL_METATYPE_EXTERN(QDBusMenuItemKeysList)
+QT_IMPL_METATYPE_EXTERN(QDBusMenuLayoutItem)
+QT_IMPL_METATYPE_EXTERN(QDBusMenuLayoutItemList)
+QT_IMPL_METATYPE_EXTERN(QDBusMenuEvent)
+QT_IMPL_METATYPE_EXTERN(QDBusMenuEventList)
+QT_IMPL_METATYPE_EXTERN(QDBusMenuShortcut)
+
const QDBusArgument &operator<<(QDBusArgument &arg, const QDBusMenuItem &item)
{
arg.beginStructure();
@@ -93,7 +69,7 @@ uint QDBusMenuLayoutItem::populate(int id, int depth, const QStringList &propert
qCDebug(qLcMenu) << id << "depth" << depth << propertyNames;
m_id = id;
if (id == 0) {
- m_properties.insert(QLatin1String("children-display"), QLatin1String("submenu"));
+ m_properties.insert("children-display"_L1, "submenu"_L1);
if (topLevelMenu)
populate(topLevelMenu, depth, propertyNames);
return 1; // revision
@@ -182,34 +158,34 @@ QDBusMenuItem::QDBusMenuItem(const QDBusPlatformMenuItem *item)
: m_id(item->dbusID())
{
if (item->isSeparator()) {
- m_properties.insert(QLatin1String("type"), QLatin1String("separator"));
+ m_properties.insert("type"_L1, "separator"_L1);
} else {
- m_properties.insert(QLatin1String("label"), convertMnemonic(item->text()));
+ m_properties.insert("label"_L1, convertMnemonic(item->text()));
if (item->menu())
- m_properties.insert(QLatin1String("children-display"), QLatin1String("submenu"));
- m_properties.insert(QLatin1String("enabled"), item->isEnabled());
+ m_properties.insert("children-display"_L1, "submenu"_L1);
+ m_properties.insert("enabled"_L1, item->isEnabled());
if (item->isCheckable()) {
- QString toggleType = item->hasExclusiveGroup() ? QLatin1String("radio") : QLatin1String("checkmark");
- m_properties.insert(QLatin1String("toggle-type"), toggleType);
- m_properties.insert(QLatin1String("toggle-state"), item->isChecked() ? 1 : 0);
+ QString toggleType = item->hasExclusiveGroup() ? "radio"_L1 : "checkmark"_L1;
+ m_properties.insert("toggle-type"_L1, toggleType);
+ m_properties.insert("toggle-state"_L1, item->isChecked() ? 1 : 0);
}
#ifndef QT_NO_SHORTCUT
const QKeySequence &scut = item->shortcut();
if (!scut.isEmpty()) {
QDBusMenuShortcut shortcut = convertKeySequence(scut);
- m_properties.insert(QLatin1String("shortcut"), QVariant::fromValue(shortcut));
+ m_properties.insert("shortcut"_L1, QVariant::fromValue(shortcut));
}
#endif
const QIcon &icon = item->icon();
if (!icon.name().isEmpty()) {
- m_properties.insert(QLatin1String("icon-name"), icon.name());
+ m_properties.insert("icon-name"_L1, icon.name());
} else if (!icon.isNull()) {
QBuffer buf;
icon.pixmap(16).save(&buf, "PNG");
- m_properties.insert(QLatin1String("icon-data"), buf.data());
+ m_properties.insert("icon-data"_L1, buf.data());
}
}
- m_properties.insert(QLatin1String("visible"), item->isVisible());
+ m_properties.insert("visible"_L1, item->isVisible());
}
QDBusMenuItemList QDBusMenuItem::items(const QList<int> &ids, const QStringList &propertyNames)
@@ -227,11 +203,11 @@ QString QDBusMenuItem::convertMnemonic(const QString &label)
{
// convert only the first occurrence of ampersand which is not at the end
// dbusmenu uses underscore instead of ampersand
- int idx = label.indexOf(QLatin1Char('&'));
- if (idx < 0 || idx == label.length() - 1)
+ int idx = label.indexOf(u'&');
+ if (idx < 0 || idx == label.size() - 1)
return label;
QString ret(label);
- ret[idx] = QLatin1Char('_');
+ ret[idx] = u'_';
return ret;
}
@@ -241,22 +217,22 @@ QDBusMenuShortcut QDBusMenuItem::convertKeySequence(const QKeySequence &sequence
QDBusMenuShortcut shortcut;
for (int i = 0; i < sequence.count(); ++i) {
QStringList tokens;
- int key = sequence[i].toCombined();
- if (key & Qt::MetaModifier)
+ auto modifiers = sequence[i].keyboardModifiers();
+ if (modifiers & Qt::MetaModifier)
tokens << QStringLiteral("Super");
- if (key & Qt::ControlModifier)
+ if (modifiers & Qt::ControlModifier)
tokens << QStringLiteral("Control");
- if (key & Qt::AltModifier)
+ if (modifiers & Qt::AltModifier)
tokens << QStringLiteral("Alt");
- if (key & Qt::ShiftModifier)
+ if (modifiers & Qt::ShiftModifier)
tokens << QStringLiteral("Shift");
- if (key & Qt::KeypadModifier)
+ if (modifiers & Qt::KeypadModifier)
tokens << QStringLiteral("Num");
- QString keyName = QKeySequencePrivate::keyName(key, QKeySequence::PortableText);
- if (keyName == QLatin1String("+"))
+ QString keyName = QKeySequencePrivate::keyName(sequence[i].key(), QKeySequence::PortableText);
+ if (keyName == "+"_L1)
tokens << QStringLiteral("plus");
- else if (keyName == QLatin1String("-"))
+ else if (keyName == "-"_L1)
tokens << QStringLiteral("minus");
else
tokens << keyName;
@@ -295,7 +271,7 @@ QDebug operator<<(QDebug d, const QDBusMenuLayoutItem &item)
{
QDebugStateSaver saver(d);
d.nospace();
- d << "QDBusMenuLayoutItem(id=" << item.m_id << ", properties=" << item.m_properties << ", " << item.m_children.count() << " children)";
+ d << "QDBusMenuLayoutItem(id=" << item.m_id << ", properties=" << item.m_properties << ", " << item.m_children.size() << " children)";
return d;
}
#endif
diff --git a/src/gui/platform/unix/dbusmenu/qdbusmenutypes_p.h b/src/gui/platform/unix/dbusmenu/qdbusmenutypes_p.h
index 092798d9e3..4775c0094d 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusmenutypes_p.h
+++ b/src/gui/platform/unix/dbusmenu/qdbusmenutypes_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDBUSMENUTYPES_H
#define QDBUSMENUTYPES_H
@@ -57,6 +21,7 @@
#include <QDBusConnection>
#include <QDBusObjectPath>
#include <QPixmap>
+#include <private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -142,14 +107,14 @@ QDebug operator<<(QDebug d, const QDBusMenuLayoutItem &item);
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QDBusMenuItem)
-Q_DECLARE_METATYPE(QDBusMenuItemList)
-Q_DECLARE_METATYPE(QDBusMenuItemKeys)
-Q_DECLARE_METATYPE(QDBusMenuItemKeysList)
-Q_DECLARE_METATYPE(QDBusMenuLayoutItem)
-Q_DECLARE_METATYPE(QDBusMenuLayoutItemList)
-Q_DECLARE_METATYPE(QDBusMenuEvent)
-Q_DECLARE_METATYPE(QDBusMenuEventList)
-Q_DECLARE_METATYPE(QDBusMenuShortcut)
+QT_DECL_METATYPE_EXTERN(QDBusMenuItem, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QDBusMenuItemList, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QDBusMenuItemKeys, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QDBusMenuItemKeysList, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QDBusMenuLayoutItem, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QDBusMenuLayoutItemList, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QDBusMenuEvent, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QDBusMenuEventList, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QDBusMenuShortcut, Q_GUI_EXPORT)
#endif
diff --git a/src/gui/platform/unix/dbusmenu/qdbusplatformmenu.cpp b/src/gui/platform/unix/dbusmenu/qdbusplatformmenu.cpp
index fc1b37f2f2..f25fb0831b 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusplatformmenu.cpp
+++ b/src/gui/platform/unix/dbusmenu/qdbusplatformmenu.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdbusplatformmenu_p.h"
@@ -306,3 +270,5 @@ QPlatformMenu *QDBusPlatformMenu::createSubMenu() const
}
QT_END_NAMESPACE
+
+#include "moc_qdbusplatformmenu_p.cpp"
diff --git a/src/gui/platform/unix/dbusmenu/qdbusplatformmenu_p.h b/src/gui/platform/unix/dbusmenu/qdbusplatformmenu_p.h
index aa0f303416..cb672fee48 100644
--- a/src/gui/platform/unix/dbusmenu/qdbusplatformmenu_p.h
+++ b/src/gui/platform/unix/dbusmenu/qdbusplatformmenu_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDBUSPLATFORMMENU_H
#define QDBUSPLATFORMMENU_H
diff --git a/src/gui/platform/unix/dbustray/qdbustrayicon.cpp b/src/gui/platform/unix/dbustray/qdbustrayicon.cpp
index 892a99d726..0dff9b598e 100644
--- a/src/gui/platform/unix/dbustray/qdbustrayicon.cpp
+++ b/src/gui/platform/unix/dbustray/qdbustrayicon.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdbustrayicon_p.h"
@@ -46,6 +10,7 @@
#include <QRect>
#include <QLoggingCategory>
#include <QStandardPaths>
+#include <QFileInfo>
#include <QDir>
#include <QMetaObject>
#include <QMetaEnum>
@@ -71,13 +36,19 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(qLcTray, "qt.qpa.tray")
static QString iconTempPath()
{
QString tempPath = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
- if (!tempPath.isEmpty())
+ if (!tempPath.isEmpty()) {
+ QString flatpakId = qEnvironmentVariable("FLATPAK_ID");
+ if (!flatpakId.isEmpty() && QFileInfo::exists("/.flatpak-info"_L1))
+ tempPath += "/app/"_L1 + flatpakId;
return tempPath;
+ }
tempPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation);
@@ -105,7 +76,7 @@ static int instanceCount = 0;
static inline QString tempFileTemplate()
{
- static const QString TempFileTemplate = iconTempPath() + QLatin1String("/qt-trayicon-XXXXXX.png");
+ static const QString TempFileTemplate = iconTempPath() + "/qt-trayicon-XXXXXX.png"_L1;
return TempFileTemplate;
}
@@ -207,7 +178,7 @@ QTemporaryFile *QDBusTrayIcon::tempIcon(const QIcon &icon)
QDBusConnection session = QDBusConnection::sessionBus();
uint pid = session.interface()->servicePid(KDEWatcherService).value();
QString processName = QLockFilePrivate::processNameByPid(pid);
- necessary = processName.endsWith(QLatin1String("indicator-application-service"));
+ necessary = processName.endsWith("indicator-application-service"_L1);
if (!necessary) {
necessary = session.interface()->isServiceRegistered(
QStringLiteral("com.canonical.indicator.application"));
@@ -227,7 +198,10 @@ QTemporaryFile *QDBusTrayIcon::tempIcon(const QIcon &icon)
if (!necessary)
return nullptr;
QTemporaryFile *ret = new QTemporaryFile(tempFileTemplate(), this);
- ret->open();
+ if (!ret->open()) {
+ delete ret;
+ return nullptr;
+ }
icon.pixmap(QSize(22, 22)).save(ret);
ret->close();
return ret;
@@ -341,7 +315,7 @@ void QDBusTrayIcon::showMessage(const QString &title, const QString &msg, const
int urgency = static_cast<int>(iconType) - 1;
if (urgency < 0) // no icon
urgency = 0;
- hints.insert(QLatin1String("urgency"), QVariant(urgency));
+ hints.insert("urgency"_L1, QVariant(urgency));
m_notifier->notify(QCoreApplication::applicationName(), 0,
m_attentionIconName, title, msg, notificationActions, hints, msecs);
}
@@ -360,9 +334,14 @@ void QDBusTrayIcon::notificationClosed(uint id, uint reason)
bool QDBusTrayIcon::isSystemTrayAvailable() const
{
QDBusMenuConnection * conn = const_cast<QDBusTrayIcon *>(this)->dBusConnection();
- qCDebug(qLcTray) << conn->isStatusNotifierHostRegistered();
- return conn->isStatusNotifierHostRegistered();
+
+ // If the KDE watcher service is registered, we must be on a desktop
+ // where a StatusNotifier-conforming system tray exists.
+ qCDebug(qLcTray) << conn->isWatcherRegistered();
+ return conn->isWatcherRegistered();
}
QT_END_NAMESPACE
+
+#include "moc_qdbustrayicon_p.cpp"
#endif //QT_NO_SYSTEMTRAYICON
diff --git a/src/gui/platform/unix/dbustray/qdbustrayicon_p.h b/src/gui/platform/unix/dbustray/qdbustrayicon_p.h
index 04eefe3154..3041e132fd 100644
--- a/src/gui/platform/unix/dbustray/qdbustrayicon_p.h
+++ b/src/gui/platform/unix/dbustray/qdbustrayicon_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDBUSTRAYICON_H
diff --git a/src/gui/platform/unix/dbustray/qdbustraytypes.cpp b/src/gui/platform/unix/dbustray/qdbustraytypes.cpp
index 4408bfae5a..accbd87e7e 100644
--- a/src/gui/platform/unix/dbustray/qdbustraytypes.cpp
+++ b/src/gui/platform/unix/dbustray/qdbustraytypes.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Marco Martin <notmart@gmail.com>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2009 Marco Martin <notmart@gmail.com>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QT_NO_SYSTEMTRAYICON
@@ -59,6 +23,10 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QXdgDBusImageStruct)
+QT_IMPL_METATYPE_EXTERN(QXdgDBusImageVector)
+QT_IMPL_METATYPE_EXTERN(QXdgDBusToolTipStruct)
+
static const int IconSizeLimit = 64;
static const int IconNormalSmallSize = 22;
static const int IconNormalMediumSize = 64;
@@ -77,7 +45,7 @@ QXdgDBusImageVector iconToQXdgDBusImageVector(const QIcon &icon)
bool hasSmallIcon = false;
bool hasMediumIcon = false;
QList<QSize> toRemove;
- for (const QSize &size : qAsConst(sizes)) {
+ for (const QSize &size : std::as_const(sizes)) {
int maxSize = qMax(size.width(), size.height());
if (maxSize <= IconNormalSmallSize)
hasSmallIcon = true;
@@ -86,7 +54,7 @@ QXdgDBusImageVector iconToQXdgDBusImageVector(const QIcon &icon)
else if (maxSize > IconSizeLimit)
toRemove << size;
}
- for (const QSize &size : qAsConst(toRemove))
+ for (const QSize &size : std::as_const(toRemove))
sizes.removeOne(size);
if (!hasSmallIcon)
sizes.append(QSize(IconNormalSmallSize, IconNormalSmallSize));
@@ -94,7 +62,7 @@ QXdgDBusImageVector iconToQXdgDBusImageVector(const QIcon &icon)
sizes.append(QSize(IconNormalMediumSize, IconNormalMediumSize));
ret.reserve(sizes.size());
- for (const QSize &size : qAsConst(sizes)) {
+ for (const QSize &size : std::as_const(sizes)) {
// Protocol specifies ARGB32 format in network byte order
QImage im = engine->pixmap(size, QIcon::Normal, QIcon::Off).toImage().convertToFormat(QImage::Format_ARGB32);
// letterbox if necessary to make it square
diff --git a/src/gui/platform/unix/dbustray/qdbustraytypes_p.h b/src/gui/platform/unix/dbustray/qdbustraytypes_p.h
index 5a48a9110a..08294d486c 100644
--- a/src/gui/platform/unix/dbustray/qdbustraytypes_p.h
+++ b/src/gui/platform/unix/dbustray/qdbustraytypes_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Marco Martin <notmart@gmail.com>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2009 Marco Martin <notmart@gmail.com>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDBUSTRAYTYPES_P_H
#define QDBUSTRAYTYPES_P_H
@@ -102,8 +66,8 @@ const QDBusArgument &operator>>(const QDBusArgument &argument, QXdgDBusToolTipSt
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QXdgDBusImageStruct)
-Q_DECLARE_METATYPE(QXdgDBusImageVector)
-Q_DECLARE_METATYPE(QXdgDBusToolTipStruct)
+QT_DECL_METATYPE_EXTERN(QXdgDBusImageStruct, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QXdgDBusImageVector, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(QXdgDBusToolTipStruct, Q_GUI_EXPORT)
#endif // QDBUSTRAYTYPES_P_H
diff --git a/src/gui/platform/unix/dbustray/qstatusnotifieritemadaptor.cpp b/src/gui/platform/unix/dbustray/qstatusnotifieritemadaptor.cpp
index ef2d330959..2f6c13b6cf 100644
--- a/src/gui/platform/unix/dbustray/qstatusnotifieritemadaptor.cpp
+++ b/src/gui/platform/unix/dbustray/qstatusnotifieritemadaptor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
This file was originally created by qdbusxml2cpp version 0.8
@@ -172,6 +136,12 @@ void QStatusNotifierItemAdaptor::ContextMenu(int x, int y)
emit m_trayIcon->activated(QPlatformSystemTrayIcon::Context);
}
+void QStatusNotifierItemAdaptor::ProvideXdgActivationToken(const QString &token)
+{
+ qCDebug(qLcTray) << token;
+ qputenv("XDG_ACTIVATION_TOKEN", token.toUtf8());
+}
+
void QStatusNotifierItemAdaptor::Scroll(int w, const QString &s)
{
qCDebug(qLcTray) << w << s;
@@ -186,4 +156,6 @@ void QStatusNotifierItemAdaptor::SecondaryActivate(int x, int y)
QT_END_NAMESPACE
+#include "moc_qstatusnotifieritemadaptor_p.cpp"
+
#endif // QT_NO_SYSTEMTRAYICON
diff --git a/src/gui/platform/unix/dbustray/qstatusnotifieritemadaptor_p.h b/src/gui/platform/unix/dbustray/qstatusnotifieritemadaptor_p.h
index 01722348bb..103fc974dd 100644
--- a/src/gui/platform/unix/dbustray/qstatusnotifieritemadaptor_p.h
+++ b/src/gui/platform/unix/dbustray/qstatusnotifieritemadaptor_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
This file was originally created by qdbusxml2cpp version 0.8
@@ -109,6 +73,9 @@ class QStatusNotifierItemAdaptor: public QDBusAbstractAdaptor
" <property access=\"read\" type=\"(sa(iiay)ss)\" name=\"ToolTip\">\n"
" <annotation value=\"QXdgDBusToolTipStruct\" name=\"org.qtproject.QtDBus.QtTypeName\"/>\n"
" </property>\n"
+" <method name=\"ProvideXdgActivationToken\">\n"
+" <arg name=\"token\" type=\"s\" direction=\"in\"/>\n"
+" </method>\n"
" <method name=\"ContextMenu\">\n"
" <arg direction=\"in\" type=\"i\" name=\"x\"/>\n"
" <arg direction=\"in\" type=\"i\" name=\"y\"/>\n"
@@ -186,6 +153,7 @@ public: // PROPERTIES
public Q_SLOTS: // METHODS
void Activate(int x, int y);
void ContextMenu(int x, int y);
+ void ProvideXdgActivationToken(const QString &token);
void Scroll(int delta, const QString &orientation);
void SecondaryActivate(int x, int y);
Q_SIGNALS: // SIGNALS
diff --git a/src/gui/platform/unix/dbustray/qxdgnotificationproxy.cpp b/src/gui/platform/unix/dbustray/qxdgnotificationproxy.cpp
index ef2aa799c8..97b6697e6d 100644
--- a/src/gui/platform/unix/dbustray/qxdgnotificationproxy.cpp
+++ b/src/gui/platform/unix/dbustray/qxdgnotificationproxy.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qxdgnotificationproxy_p.h"
@@ -51,3 +15,5 @@ QXdgNotificationInterface::~QXdgNotificationInterface()
}
QT_END_NAMESPACE
+
+#include "moc_qxdgnotificationproxy_p.cpp"
diff --git a/src/gui/platform/unix/dbustray/qxdgnotificationproxy_p.h b/src/gui/platform/unix/dbustray/qxdgnotificationproxy_p.h
index eb916e7512..dfbc64f33b 100644
--- a/src/gui/platform/unix/dbustray/qxdgnotificationproxy_p.h
+++ b/src/gui/platform/unix/dbustray/qxdgnotificationproxy_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
This file was originally created by qdbusxml2cpp version 0.8
@@ -73,6 +37,7 @@
#include <QDBusAbstractInterface>
#include <QDBusPendingReply>
#include <QDBusReply>
+#include <private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -112,7 +77,7 @@ public Q_SLOTS: // METHODS
inline QDBusReply<QString> getServerInformation(QString &vendor, QString &version, QString &specVersion)
{
QDBusMessage reply = call(QDBus::Block, QStringLiteral("GetServerInformation"));
- if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 4) {
+ if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().size() == 4) {
vendor = qdbus_cast<QString>(reply.arguments().at(1));
version = qdbus_cast<QString>(reply.arguments().at(2));
specVersion = qdbus_cast<QString>(reply.arguments().at(3));
diff --git a/src/gui/platform/unix/qeventdispatcher_glib.cpp b/src/gui/platform/unix/qeventdispatcher_glib.cpp
index bf9e31990e..368006f302 100644
--- a/src/gui/platform/unix/qeventdispatcher_glib.cpp
+++ b/src/gui/platform/unix/qeventdispatcher_glib.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qeventdispatcher_glib_p.h"
@@ -124,3 +88,5 @@ bool QPAEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
}
QT_END_NAMESPACE
+
+#include "moc_qeventdispatcher_glib_p.cpp"
diff --git a/src/gui/platform/unix/qeventdispatcher_glib_p.h b/src/gui/platform/unix/qeventdispatcher_glib_p.h
index 91be66a81f..95fac16237 100644
--- a/src/gui/platform/unix/qeventdispatcher_glib_p.h
+++ b/src/gui/platform/unix/qeventdispatcher_glib_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEVENTDISPATCHER_GLIB_QPA_P_H
#define QEVENTDISPATCHER_GLIB_QPA_P_H
diff --git a/src/gui/platform/unix/qgenericunixeventdispatcher.cpp b/src/gui/platform/unix/qgenericunixeventdispatcher.cpp
index 2e1d81a181..b551aefe99 100644
--- a/src/gui/platform/unix/qgenericunixeventdispatcher.cpp
+++ b/src/gui/platform/unix/qgenericunixeventdispatcher.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgenericunixeventdispatcher_p.h"
#include "qunixeventdispatcher_qpa_p.h"
-#include "qeventdispatcher_glib_p.h"
-
+#if QT_CONFIG(glib)
+# include "qeventdispatcher_glib_p.h"
+#endif
QT_BEGIN_NAMESPACE
class QAbstractEventDispatcher *QtGenericUnixDispatcher::createUnixEventDispatcher()
diff --git a/src/gui/platform/unix/qgenericunixeventdispatcher_p.h b/src/gui/platform/unix/qgenericunixeventdispatcher_p.h
index c567463772..82dc35da0b 100644
--- a/src/gui/platform/unix/qgenericunixeventdispatcher_p.h
+++ b/src/gui/platform/unix/qgenericunixeventdispatcher_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//
// W A R N I N G
@@ -52,6 +16,7 @@
#define QGENERICUNIXEVENTDISPATCHER_P_H
#include <QtGui/qtguiglobal.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/platform/unix/qgenericunixservices.cpp b/src/gui/platform/unix/qgenericunixservices.cpp
index e7b9ae3368..bfd2556b1e 100644
--- a/src/gui/platform/unix/qgenericunixservices.cpp
+++ b/src/gui/platform/unix/qgenericunixservices.cpp
@@ -1,44 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgenericunixservices_p.h"
#include <QtGui/private/qtguiglobal_p.h>
+#include "qguiapplication.h"
+#include "qwindow.h"
+#include <QtGui/qpa/qplatformwindow_p.h>
+#include <QtGui/qpa/qplatformwindow.h>
+#include <QtGui/qpa/qplatformnativeinterface.h>
#include <QtCore/QDebug>
#include <QtCore/QFile>
@@ -73,6 +42,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#if QT_CONFIG(multiprocess)
enum { debug = 0 };
@@ -142,9 +113,11 @@ static inline bool detectWebBrowser(const QByteArray &desktop,
}
if (desktop == QByteArray("KDE")) {
+ if (checkExecutable(QStringLiteral("kde-open5"), browser))
+ return true;
// Konqueror launcher
if (checkExecutable(QStringLiteral("kfmclient"), browser)) {
- browser->append(QLatin1String(" exec"));
+ browser->append(" exec"_L1);
return true;
}
} else if (desktop == QByteArray("GNOME")) {
@@ -153,18 +126,23 @@ static inline bool detectWebBrowser(const QByteArray &desktop,
}
for (size_t i = 0; i < sizeof(browsers)/sizeof(char *); ++i)
- if (checkExecutable(QLatin1String(browsers[i]), browser))
+ if (checkExecutable(QLatin1StringView(browsers[i]), browser))
return true;
return false;
}
-static inline bool launch(const QString &launcher, const QUrl &url)
+static inline bool launch(const QString &launcher, const QUrl &url,
+ const QString &xdgActivationToken)
{
- const QString command = launcher + QLatin1Char(' ') + QLatin1String(url.toEncoded());
+ if (!xdgActivationToken.isEmpty()) {
+ qputenv("XDG_ACTIVATION_TOKEN", xdgActivationToken.toUtf8());
+ }
+
+ const QString command = launcher + u' ' + QLatin1StringView(url.toEncoded());
if (debug)
qDebug("Launching %s", qPrintable(command));
#if !QT_CONFIG(process)
- const bool ok = ::system(qPrintable(command + QLatin1String(" &")));
+ const bool ok = ::system(qPrintable(command + " &"_L1));
#else
QStringList args = QProcess::splitCommand(command);
bool ok = false;
@@ -175,24 +153,20 @@ static inline bool launch(const QString &launcher, const QUrl &url)
#endif
if (!ok)
qWarning("Launch failed (%s)", qPrintable(command));
+
+ qunsetenv("XDG_ACTIVATION_TOKEN");
+
return ok;
}
#if QT_CONFIG(dbus)
static inline bool checkNeedPortalSupport()
{
- return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty() || qEnvironmentVariableIsSet("SNAP");
-}
-
-static inline bool isPortalReturnPermanent(const QDBusError &error)
-{
- // A service unknown error isn't permanent, it just indicates that we
- // should fall back to the regular way. This check includes
- // QDBusError::NoError.
- return error.type() != QDBusError::ServiceUnknown && error.type() != QDBusError::AccessDenied;
+ return QFileInfo::exists("/.flatpak-info"_L1) || qEnvironmentVariableIsSet("SNAP");
}
-static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url)
+static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url, const QString &parentWindow,
+ const QString &xdgActivationToken)
{
// DBus signature:
// OpenFile (IN s parent_window,
@@ -203,32 +177,32 @@ static inline QDBusMessage xdgDesktopPortalOpenFile(const QUrl &url)
// handle_token (s) - A string that will be used as the last element of the @handle.
// writable (b) - Whether to allow the chosen application to write to the file.
-#ifdef O_PATH
- const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_PATH);
+ const int fd = qt_safe_open(QFile::encodeName(url.toLocalFile()), O_RDONLY);
if (fd != -1) {
- QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
- QLatin1String("/org/freedesktop/portal/desktop"),
- QLatin1String("org.freedesktop.portal.OpenURI"),
- QLatin1String("OpenFile"));
+ QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
+ "/org/freedesktop/portal/desktop"_L1,
+ "org.freedesktop.portal.OpenURI"_L1,
+ "OpenFile"_L1);
QDBusUnixFileDescriptor descriptor;
descriptor.giveFileDescriptor(fd);
- const QVariantMap options = {{QLatin1String("writable"), true}};
+ QVariantMap options = {};
- // FIXME parent_window_id
- message << QString() << QVariant::fromValue(descriptor) << options;
+ if (!xdgActivationToken.isEmpty()) {
+ options.insert("activation_token"_L1, xdgActivationToken);
+ }
+
+ message << parentWindow << QVariant::fromValue(descriptor) << options;
return QDBusConnection::sessionBus().call(message);
}
-#else
- Q_UNUSED(url);
-#endif
return QDBusMessage::createError(QDBusError::InternalError, qt_error_string());
}
-static inline QDBusMessage xdgDesktopPortalOpenUrl(const QUrl &url)
+static inline QDBusMessage xdgDesktopPortalOpenUrl(const QUrl &url, const QString &parentWindow,
+ const QString &xdgActivationToken)
{
// DBus signature:
// OpenURI (IN s parent_window,
@@ -241,17 +215,24 @@ static inline QDBusMessage xdgDesktopPortalOpenUrl(const QUrl &url)
// This key only takes effect the uri points to a local file that is exported in the document portal,
// and the chosen application is sandboxed itself.
- QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
- QLatin1String("/org/freedesktop/portal/desktop"),
- QLatin1String("org.freedesktop.portal.OpenURI"),
- QLatin1String("OpenURI"));
+ QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
+ "/org/freedesktop/portal/desktop"_L1,
+ "org.freedesktop.portal.OpenURI"_L1,
+ "OpenURI"_L1);
// FIXME parent_window_id and handle writable option
- message << QString() << url.toString() << QVariantMap();
+ QVariantMap options;
+
+ if (!xdgActivationToken.isEmpty()) {
+ options.insert("activation_token"_L1, xdgActivationToken);
+ }
+
+ message << parentWindow << url.toString() << options;
return QDBusConnection::sessionBus().call(message);
}
-static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url)
+static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url, const QString &parentWindow,
+ const QString &xdgActivationToken)
{
// DBus signature:
// ComposeEmail (IN s parent_window,
@@ -265,14 +246,14 @@ static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url)
QUrlQuery urlQuery(url);
QVariantMap options;
- options.insert(QLatin1String("address"), url.path());
- options.insert(QLatin1String("subject"), urlQuery.queryItemValue(QLatin1String("subject")));
- options.insert(QLatin1String("body"), urlQuery.queryItemValue(QLatin1String("body")));
+ options.insert("address"_L1, url.path());
+ options.insert("subject"_L1, urlQuery.queryItemValue("subject"_L1));
+ options.insert("body"_L1, urlQuery.queryItemValue("body"_L1));
// O_PATH seems to be present since Linux 2.6.39, which is not case of RHEL 6
#ifdef O_PATH
QList<QDBusUnixFileDescriptor> attachments;
- const QStringList attachmentUris = urlQuery.allQueryItemValues(QLatin1String("attachment"));
+ const QStringList attachmentUris = urlQuery.allQueryItemValues("attachment"_L1);
for (const QString &attachmentUri : attachmentUris) {
const int fd = qt_safe_open(QFile::encodeName(attachmentUri), O_PATH);
@@ -283,75 +264,277 @@ static inline QDBusMessage xdgDesktopPortalSendEmail(const QUrl &url)
}
}
- options.insert(QLatin1String("attachment_fds"), QVariant::fromValue(attachments));
+ options.insert("attachment_fds"_L1, QVariant::fromValue(attachments));
#endif
- QDBusMessage message = QDBusMessage::createMethodCall(QLatin1String("org.freedesktop.portal.Desktop"),
- QLatin1String("/org/freedesktop/portal/desktop"),
- QLatin1String("org.freedesktop.portal.Email"),
- QLatin1String("ComposeEmail"));
+ if (!xdgActivationToken.isEmpty()) {
+ options.insert("activation_token"_L1, xdgActivationToken);
+ }
+
+ QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop"_L1,
+ "/org/freedesktop/portal/desktop"_L1,
+ "org.freedesktop.portal.Email"_L1,
+ "ComposeEmail"_L1);
- // FIXME parent_window_id
- message << QString() << options;
+ message << parentWindow << options;
return QDBusConnection::sessionBus().call(message);
}
+
+namespace {
+struct XDGDesktopColor
+{
+ double r = 0;
+ double g = 0;
+ double b = 0;
+
+ QColor toQColor() const
+ {
+ constexpr auto rgbMax = 255;
+ return { static_cast<int>(r * rgbMax), static_cast<int>(g * rgbMax),
+ static_cast<int>(b * rgbMax) };
+ }
+};
+
+const QDBusArgument &operator>>(const QDBusArgument &argument, XDGDesktopColor &myStruct)
+{
+ argument.beginStructure();
+ argument >> myStruct.r >> myStruct.g >> myStruct.b;
+ argument.endStructure();
+ return argument;
+}
+
+class XdgDesktopPortalColorPicker : public QPlatformServiceColorPicker
+{
+ Q_OBJECT
+public:
+ XdgDesktopPortalColorPicker(const QString &parentWindowId, QWindow *parent)
+ : QPlatformServiceColorPicker(parent), m_parentWindowId(parentWindowId)
+ {
+ }
+
+ void pickColor() override
+ {
+ // DBus signature:
+ // PickColor (IN s parent_window,
+ // IN a{sv} options
+ // OUT o handle)
+ // Options:
+ // handle_token (s) - A string that will be used as the last element of the @handle.
+
+ QDBusMessage message = QDBusMessage::createMethodCall(
+ "org.freedesktop.portal.Desktop"_L1, "/org/freedesktop/portal/desktop"_L1,
+ "org.freedesktop.portal.Screenshot"_L1, "PickColor"_L1);
+ message << m_parentWindowId << QVariantMap();
+
+ QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
+ auto watcher = new QDBusPendingCallWatcher(pendingCall, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this,
+ [this](QDBusPendingCallWatcher *watcher) {
+ watcher->deleteLater();
+ QDBusPendingReply<QDBusObjectPath> reply = *watcher;
+ if (reply.isError()) {
+ qWarning("DBus call to pick color failed: %s",
+ qPrintable(reply.error().message()));
+ Q_EMIT colorPicked({});
+ } else {
+ QDBusConnection::sessionBus().connect(
+ "org.freedesktop.portal.Desktop"_L1, reply.value().path(),
+ "org.freedesktop.portal.Request"_L1, "Response"_L1, this,
+ // clang-format off
+ SLOT(gotColorResponse(uint,QVariantMap))
+ // clang-format on
+ );
+ }
+ });
+ }
+
+private Q_SLOTS:
+ void gotColorResponse(uint result, const QVariantMap &map)
+ {
+ if (result != 0)
+ return;
+ if (map.contains(u"color"_s)) {
+ XDGDesktopColor color{};
+ map.value(u"color"_s).value<QDBusArgument>() >> color;
+ Q_EMIT colorPicked(color.toQColor());
+ } else {
+ Q_EMIT colorPicked({});
+ }
+ deleteLater();
+ }
+
+private:
+ const QString m_parentWindowId;
+};
+} // namespace
+
#endif // QT_CONFIG(dbus)
+QGenericUnixServices::QGenericUnixServices()
+{
+#if QT_CONFIG(dbus)
+ if (qEnvironmentVariableIntValue("QT_NO_XDG_DESKTOP_PORTAL") > 0) {
+ return;
+ }
+ QDBusMessage message = QDBusMessage::createMethodCall(
+ "org.freedesktop.portal.Desktop"_L1, "/org/freedesktop/portal/desktop"_L1,
+ "org.freedesktop.DBus.Properties"_L1, "Get"_L1);
+ message << "org.freedesktop.portal.Screenshot"_L1
+ << "version"_L1;
+
+ QDBusPendingCall pendingCall = QDBusConnection::sessionBus().asyncCall(message);
+ auto watcher = new QDBusPendingCallWatcher(pendingCall);
+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, watcher,
+ [this](QDBusPendingCallWatcher *watcher) {
+ watcher->deleteLater();
+ QDBusPendingReply<QVariant> reply = *watcher;
+ if (!reply.isError() && reply.value().toUInt() >= 2)
+ m_hasScreenshotPortalWithColorPicking = true;
+ });
+
+#endif
+}
+
+QPlatformServiceColorPicker *QGenericUnixServices::colorPicker(QWindow *parent)
+{
+#if QT_CONFIG(dbus)
+ // Make double sure that we are in a wayland environment. In particular check
+ // WAYLAND_DISPLAY so also XWayland apps benefit from portal-based color picking.
+ // Outside wayland we'll rather rely on other means than the XDG desktop portal.
+ if (!qEnvironmentVariableIsEmpty("WAYLAND_DISPLAY")
+ || QGuiApplication::platformName().startsWith("wayland"_L1)) {
+ return new XdgDesktopPortalColorPicker(portalWindowIdentifier(parent), parent);
+ }
+ return nullptr;
+#else
+ Q_UNUSED(parent);
+ return nullptr;
+#endif
+}
+
QByteArray QGenericUnixServices::desktopEnvironment() const
{
static const QByteArray result = detectDesktopEnvironment();
return result;
}
-bool QGenericUnixServices::openUrl(const QUrl &url)
+template<typename F>
+void runWithXdgActivationToken(F &&functionToCall)
{
- if (url.scheme() == QLatin1String("mailto")) {
-#if QT_CONFIG(dbus)
- if (checkNeedPortalSupport()) {
- QDBusError error = xdgDesktopPortalSendEmail(url);
- if (isPortalReturnPermanent(error))
- return !error.isValid();
+#if QT_CONFIG(wayland)
+ QWindow *window = qGuiApp->focusWindow();
- // service not running, fall back
- }
-#endif
- return openDocument(url);
+ if (!window) {
+ functionToCall({});
+ return;
}
-#if QT_CONFIG(dbus)
- if (checkNeedPortalSupport()) {
- QDBusError error = xdgDesktopPortalOpenUrl(url);
- if (isPortalReturnPermanent(error))
- return !error.isValid();
+ auto waylandApp = dynamic_cast<QNativeInterface::QWaylandApplication *>(
+ qGuiApp->platformNativeInterface());
+ auto waylandWindow =
+ dynamic_cast<QNativeInterface::Private::QWaylandWindow *>(window->handle());
+
+ if (!waylandWindow || !waylandApp) {
+ functionToCall({});
+ return;
}
+
+ QObject::connect(waylandWindow,
+ &QNativeInterface::Private::QWaylandWindow::xdgActivationTokenCreated,
+ waylandWindow, functionToCall, Qt::SingleShotConnection);
+ waylandWindow->requestXdgActivationToken(waylandApp->lastInputSerial());
+#else
+ functionToCall({});
#endif
+}
+
+bool QGenericUnixServices::openUrl(const QUrl &url)
+{
+ auto openUrlInternal = [this](const QUrl &url, const QString &xdgActivationToken) {
+ if (url.scheme() == "mailto"_L1) {
+# if QT_CONFIG(dbus)
+ if (checkNeedPortalSupport()) {
+ const QString parentWindow = QGuiApplication::focusWindow()
+ ? portalWindowIdentifier(QGuiApplication::focusWindow())
+ : QString();
+ QDBusError error = xdgDesktopPortalSendEmail(url, parentWindow, xdgActivationToken);
+ if (!error.isValid())
+ return true;
+
+ // service not running, fall back
+ }
+# endif
+ return openDocument(url);
+ }
+
+# if QT_CONFIG(dbus)
+ if (checkNeedPortalSupport()) {
+ const QString parentWindow = QGuiApplication::focusWindow()
+ ? portalWindowIdentifier(QGuiApplication::focusWindow())
+ : QString();
+ QDBusError error = xdgDesktopPortalOpenUrl(url, parentWindow, xdgActivationToken);
+ if (!error.isValid())
+ return true;
+ }
+# endif
+
+ if (m_webBrowser.isEmpty()
+ && !detectWebBrowser(desktopEnvironment(), true, &m_webBrowser)) {
+ qWarning("Unable to detect a web browser to launch '%s'", qPrintable(url.toString()));
+ return false;
+ }
+ return launch(m_webBrowser, url, xdgActivationToken);
+ };
+
+ if (QGuiApplication::platformName().startsWith("wayland"_L1)) {
+ runWithXdgActivationToken(
+ [openUrlInternal, url](const QString &token) { openUrlInternal(url, token); });
+
+ return true;
- if (m_webBrowser.isEmpty() && !detectWebBrowser(desktopEnvironment(), true, &m_webBrowser)) {
- qWarning("Unable to detect a web browser to launch '%s'", qPrintable(url.toString()));
- return false;
+ } else {
+ return openUrlInternal(url, QString());
}
- return launch(m_webBrowser, url);
}
bool QGenericUnixServices::openDocument(const QUrl &url)
{
-#if QT_CONFIG(dbus)
- if (checkNeedPortalSupport()) {
- QDBusError error = xdgDesktopPortalOpenFile(url);
- if (isPortalReturnPermanent(error))
- return !error.isValid();
- }
-#endif
+ auto openDocumentInternal = [this](const QUrl &url, const QString &xdgActivationToken) {
- if (m_documentLauncher.isEmpty() && !detectWebBrowser(desktopEnvironment(), false, &m_documentLauncher)) {
- qWarning("Unable to detect a launcher for '%s'", qPrintable(url.toString()));
- return false;
+# if QT_CONFIG(dbus)
+ if (checkNeedPortalSupport()) {
+ const QString parentWindow = QGuiApplication::focusWindow()
+ ? portalWindowIdentifier(QGuiApplication::focusWindow())
+ : QString();
+ QDBusError error = xdgDesktopPortalOpenFile(url, parentWindow, xdgActivationToken);
+ if (!error.isValid())
+ return true;
+ }
+# endif
+
+ if (m_documentLauncher.isEmpty()
+ && !detectWebBrowser(desktopEnvironment(), false, &m_documentLauncher)) {
+ qWarning("Unable to detect a launcher for '%s'", qPrintable(url.toString()));
+ return false;
+ }
+ return launch(m_documentLauncher, url, xdgActivationToken);
+ };
+
+ if (QGuiApplication::platformName().startsWith("wayland"_L1)) {
+ runWithXdgActivationToken([openDocumentInternal, url](const QString &token) {
+ openDocumentInternal(url, token);
+ });
+
+ return true;
+ } else {
+ return openDocumentInternal(url, QString());
}
- return launch(m_documentLauncher, url);
}
#else
+QGenericUnixServices::QGenericUnixServices() = default;
+
QByteArray QGenericUnixServices::desktopEnvironment() const
{
return QByteArrayLiteral("UNKNOWN");
@@ -371,6 +554,60 @@ bool QGenericUnixServices::openDocument(const QUrl &url)
return false;
}
+QPlatformServiceColorPicker *QGenericUnixServices::colorPicker(QWindow *parent)
+{
+ Q_UNUSED(parent);
+ return nullptr;
+}
+
#endif // QT_NO_MULTIPROCESS
+QString QGenericUnixServices::portalWindowIdentifier(QWindow *window)
+{
+ Q_UNUSED(window);
+ return QString();
+}
+
+bool QGenericUnixServices::hasCapability(Capability capability) const
+{
+ switch (capability) {
+ case Capability::ColorPicking:
+ return m_hasScreenshotPortalWithColorPicking;
+ }
+ return false;
+}
+
+void QGenericUnixServices::setApplicationBadge(qint64 number)
+{
+#if QT_CONFIG(dbus)
+ if (qGuiApp->desktopFileName().isEmpty()) {
+ qWarning("QGuiApplication::desktopFileName() is empty");
+ return;
+ }
+
+
+ const QString launcherUrl = QStringLiteral("application://") + qGuiApp->desktopFileName() + QStringLiteral(".desktop");
+ const qint64 count = qBound(0, number, 9999);
+ QVariantMap dbusUnityProperties;
+
+ if (count > 0) {
+ dbusUnityProperties[QStringLiteral("count")] = count;
+ dbusUnityProperties[QStringLiteral("count-visible")] = true;
+ } else {
+ dbusUnityProperties[QStringLiteral("count-visible")] = false;
+ }
+
+ auto signal = QDBusMessage::createSignal(QStringLiteral("/com/canonical/unity/launcherentry/")
+ + qGuiApp->applicationName(), QStringLiteral("com.canonical.Unity.LauncherEntry"), QStringLiteral("Update"));
+
+ signal.setArguments({launcherUrl, dbusUnityProperties});
+
+ QDBusConnection::sessionBus().send(signal);
+#else
+ Q_UNUSED(number)
+#endif
+}
+
QT_END_NAMESPACE
+
+#include "qgenericunixservices.moc"
diff --git a/src/gui/platform/unix/qgenericunixservices_p.h b/src/gui/platform/unix/qgenericunixservices_p.h
index 0634360c41..56e15103f7 100644
--- a/src/gui/platform/unix/qgenericunixservices_p.h
+++ b/src/gui/platform/unix/qgenericunixservices_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGENERICUNIXDESKTOPSERVICES_H
#define QGENERICUNIXDESKTOPSERVICES_H
@@ -53,22 +17,31 @@
#include <qpa/qplatformservices.h>
#include <QtCore/QString>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
+class QWindow;
+
class Q_GUI_EXPORT QGenericUnixServices : public QPlatformServices
{
public:
- QGenericUnixServices() {}
+ QGenericUnixServices();
QByteArray desktopEnvironment() const override;
+ bool hasCapability(Capability capability) const override;
bool openUrl(const QUrl &url) override;
bool openDocument(const QUrl &url) override;
+ QPlatformServiceColorPicker *colorPicker(QWindow *parent = nullptr) override;
+
+ void setApplicationBadge(qint64 number);
+ virtual QString portalWindowIdentifier(QWindow *window);
private:
QString m_webBrowser;
QString m_documentLauncher;
+ bool m_hasScreenshotPortalWithColorPicking = false;
};
QT_END_NAMESPACE
diff --git a/src/gui/platform/unix/qgenericunixthemes.cpp b/src/gui/platform/unix/qgenericunixthemes.cpp
index 86f2a266ea..fc4b2296d2 100644
--- a/src/gui/platform/unix/qgenericunixthemes.cpp
+++ b/src/gui/platform/unix/qgenericunixthemes.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgenericunixthemes_p.h"
@@ -69,6 +33,12 @@
#include <QDBusConnectionInterface>
#include <private/qdbusplatformmenu_p.h>
#include <private/qdbusmenubar_p.h>
+#include <private/qflatmap_p.h>
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QJsonObject>
+#include <QJsonValue>
+#include <QJsonParseError>
#endif
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
#include <private/qdbustrayicon_p.h>
@@ -77,6 +47,11 @@
#include <algorithm>
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_DBUS
+Q_LOGGING_CATEGORY(lcQpaThemeDBus, "qt.qpa.theme.dbus")
+#endif
+
+using namespace Qt::StringLiterals;
Q_DECLARE_LOGGING_CATEGORY(qLcTray)
@@ -108,7 +83,7 @@ static bool isDBusTrayAvailable() {
static bool dbusTrayAvailableKnown = false;
if (!dbusTrayAvailableKnown) {
QDBusMenuConnection conn;
- if (conn.isStatusNotifierHostRegistered())
+ if (conn.isWatcherRegistered())
dbusTrayAvailable = true;
dbusTrayAvailableKnown = true;
qCDebug(qLcTray) << "D-Bus tray available:" << dbusTrayAvailable;
@@ -117,6 +92,20 @@ static bool isDBusTrayAvailable() {
}
#endif
+static QString mouseCursorTheme()
+{
+ static QString themeName = qEnvironmentVariable("XCURSOR_THEME");
+ return themeName;
+}
+
+static QSize mouseCursorSize()
+{
+ constexpr int defaultCursorSize = 24;
+ static const int xCursorSize = qEnvironmentVariableIntValue("XCURSOR_SIZE");
+ static const int s = xCursorSize > 0 ? xCursorSize : defaultCursorSize;
+ return QSize(s, s);
+}
+
#ifndef QT_NO_DBUS
static bool checkDBusGlobalMenuAvailable()
{
@@ -132,15 +121,296 @@ static bool isDBusGlobalMenuAvailable()
static bool dbusGlobalMenuAvailable = checkDBusGlobalMenuAvailable();
return dbusGlobalMenuAvailable;
}
+
+/*!
+ * \internal
+ * The QGenericUnixThemeDBusListener class listens to the SettingChanged DBus signal
+ * and translates it into combinations of the enums \c Provider and \c Setting.
+ * Upon construction, it logs success/failure of the DBus connection.
+ *
+ * The signal settingChanged delivers the normalized setting type and the new value as a string.
+ * It is emitted on known setting types only.
+ */
+
+class QGenericUnixThemeDBusListener : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ enum class Provider {
+ Kde,
+ Gtk,
+ Gnome,
+ };
+ Q_ENUM(Provider)
+
+ enum class Setting {
+ Theme,
+ ApplicationStyle,
+ ColorScheme,
+ };
+ Q_ENUM(Setting)
+
+ QGenericUnixThemeDBusListener();
+ QGenericUnixThemeDBusListener(const QString &service, const QString &path,
+ const QString &interface, const QString &signal);
+
+private Q_SLOTS:
+ void onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value);
+
+Q_SIGNALS:
+ void settingChanged(QGenericUnixThemeDBusListener::Provider provider,
+ QGenericUnixThemeDBusListener::Setting setting,
+ const QString &value);
+
+private:
+ struct DBusKey
+ {
+ QString location;
+ QString key;
+ DBusKey(const QString &loc, const QString &k) : location(loc), key(k) {};
+ bool operator<(const DBusKey &other) const
+ {
+ return location + key < other.location + other.key;
+ }
+ };
+
+ struct ChangeSignal
+ {
+ Provider provider;
+ Setting setting;
+ ChangeSignal(Provider p, Setting s) : provider(p), setting(s) {}
+ ChangeSignal() {}
+ };
+
+ // Json keys
+ static constexpr QLatin1StringView s_dbusLocation = QLatin1StringView("DBusLocation");
+ static constexpr QLatin1StringView s_dbusKey = QLatin1StringView("DBusKey");
+ static constexpr QLatin1StringView s_provider = QLatin1StringView("Provider");
+ static constexpr QLatin1StringView s_setting = QLatin1StringView("Setting");
+ static constexpr QLatin1StringView s_signals = QLatin1StringView("DbusSignals");
+ static constexpr QLatin1StringView s_root = QLatin1StringView("Qt.qpa.DBusSignals");
+
+ QFlatMap <DBusKey, ChangeSignal> m_signalMap;
+
+ void init(const QString &service, const QString &path,
+ const QString &interface, const QString &signal);
+
+ std::optional<ChangeSignal> findSignal(const QString &location, const QString &key) const;
+ void populateSignalMap();
+ void loadJson(const QString &fileName);
+ void saveJson(const QString &fileName) const;
+};
+
+QGenericUnixThemeDBusListener::QGenericUnixThemeDBusListener(const QString &service,
+ const QString &path, const QString &interface, const QString &signal)
+{
+ init (service, path, interface, signal);
+}
+
+QGenericUnixThemeDBusListener::QGenericUnixThemeDBusListener()
+{
+ static constexpr QLatin1StringView service("");
+ static constexpr QLatin1StringView path("/org/freedesktop/portal/desktop");
+ static constexpr QLatin1StringView interface("org.freedesktop.portal.Settings");
+ static constexpr QLatin1StringView signal("SettingChanged");
+
+ init (service, path, interface, signal);
+}
+
+void QGenericUnixThemeDBusListener::init(const QString &service, const QString &path,
+ const QString &interface, const QString &signal)
+{
+ QDBusConnection dbus = QDBusConnection::sessionBus();
+ const bool dBusRunning = dbus.isConnected();
+ bool dBusSignalConnected = false;
+#define LOG service << path << interface << signal;
+
+ if (dBusRunning) {
+ populateSignalMap();
+ qRegisterMetaType<QDBusVariant>();
+ dBusSignalConnected = dbus.connect(service, path, interface, signal, this,
+ SLOT(onSettingChanged(QString,QString,QDBusVariant)));
+ }
+
+ if (dBusSignalConnected) {
+ // Connection successful
+ qCDebug(lcQpaThemeDBus) << LOG;
+ } else {
+ if (dBusRunning) {
+ // DBus running, but connection failed
+ qCWarning(lcQpaThemeDBus) << "DBus connection failed:" << LOG;
+ } else {
+ // DBus not running
+ qCWarning(lcQpaThemeDBus) << "Session DBus not running.";
+ }
+ qCWarning(lcQpaThemeDBus) << "Application will not react to setting changes.\n"
+ << "Check your DBus installation.";
+ }
+#undef LOG
+}
+
+void QGenericUnixThemeDBusListener::loadJson(const QString &fileName)
+{
+ Q_ASSERT(!fileName.isEmpty());
+#define CHECK(cond, warning)\
+ if (!cond) {\
+ qCWarning(lcQpaThemeDBus) << fileName << warning << "Falling back to default.";\
+ return;\
+ }
+
+#define PARSE(var, enumeration, string)\
+ enumeration var;\
+ {\
+ bool success;\
+ const int val = QMetaEnum::fromType<enumeration>().keyToValue(string.toLatin1(), &success);\
+ CHECK(success, "Parse Error: Invalid value" << string << "for" << #var);\
+ var = static_cast<enumeration>(val);\
+ }
+
+ QFile file(fileName);
+ CHECK(file.exists(), fileName << "doesn't exist.");
+ CHECK(file.open(QIODevice::ReadOnly), "could not be opened for reading.");
+
+ QJsonParseError error;
+ QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
+ CHECK((error.error == QJsonParseError::NoError), error.errorString());
+ CHECK(doc.isObject(), "Parse Error: Expected root object" << s_root);
+
+ const QJsonObject &root = doc.object();
+ CHECK(root.contains(s_root), "Parse Error: Expected root object" << s_root);
+ CHECK(root[s_root][s_signals].isArray(), "Parse Error: Expected array" << s_signals);
+
+ const QJsonArray &sigs = root[s_root][s_signals].toArray();
+ CHECK((sigs.count() > 0), "Parse Error: Found empty array" << s_signals);
+
+ for (auto sig = sigs.constBegin(); sig != sigs.constEnd(); ++sig) {
+ CHECK(sig->isObject(), "Parse Error: Expected object array" << s_signals);
+ const QJsonObject &obj = sig->toObject();
+ CHECK(obj.contains(s_dbusLocation), "Parse Error: Expected key" << s_dbusLocation);
+ CHECK(obj.contains(s_dbusKey), "Parse Error: Expected key" << s_dbusKey);
+ CHECK(obj.contains(s_provider), "Parse Error: Expected key" << s_provider);
+ CHECK(obj.contains(s_setting), "Parse Error: Expected key" << s_setting);
+ const QString &location = obj[s_dbusLocation].toString();
+ const QString &key = obj[s_dbusKey].toString();
+ const QString &providerString = obj[s_provider].toString();
+ const QString &settingString = obj[s_setting].toString();
+ PARSE(provider, Provider, providerString);
+ PARSE(setting, Setting, settingString);
+ const DBusKey dkey(location, key);
+ CHECK (!m_signalMap.contains(dkey), "Duplicate key" << location << key);
+ m_signalMap.insert(dkey, ChangeSignal(provider, setting));
+ }
+#undef PARSE
+#undef CHECK
+
+ if (m_signalMap.count() > 0)
+ qCInfo(lcQpaThemeDBus) << "Successfully imported" << fileName;
+ else
+ qCWarning(lcQpaThemeDBus) << "No data imported from" << fileName << "falling back to default.";
+
+#ifdef QT_DEBUG
+ const int count = m_signalMap.count();
+ if (count == 0)
+ return;
+
+ qCDebug(lcQpaThemeDBus) << "Listening to" << count << "signals:";
+ for (auto it = m_signalMap.constBegin(); it != m_signalMap.constEnd(); ++it) {
+ qDebug() << it.key().key << it.key().location << "mapped to"
+ << it.value().provider << it.value().setting;
+ }
+
#endif
+}
+
+void QGenericUnixThemeDBusListener::saveJson(const QString &fileName) const
+{
+ Q_ASSERT(!m_signalMap.isEmpty());
+ Q_ASSERT(!fileName.isEmpty());
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly)) {
+ qCWarning(lcQpaThemeDBus) << fileName << "could not be opened for writing.";
+ return;
+ }
+
+ QJsonArray sigs;
+ for (auto sig = m_signalMap.constBegin(); sig != m_signalMap.constEnd(); ++sig) {
+ const DBusKey &dkey = sig.key();
+ const ChangeSignal &csig = sig.value();
+ QJsonObject obj;
+ obj[s_dbusLocation] = dkey.location;
+ obj[s_dbusKey] = dkey.key;
+ obj[s_provider] = QLatin1StringView(QMetaEnum::fromType<Provider>()
+ .valueToKey(static_cast<int>(csig.provider)));
+ obj[s_setting] = QLatin1StringView(QMetaEnum::fromType<Setting>()
+ .valueToKey(static_cast<int>(csig.setting)));
+ sigs.append(obj);
+ }
+ QJsonObject obj;
+ obj[s_signals] = sigs;
+ QJsonObject root;
+ root[s_root] = obj;
+ QJsonDocument doc(root);
+ file.write(doc.toJson());
+ file.close();
+}
+
+void QGenericUnixThemeDBusListener::populateSignalMap()
+{
+ m_signalMap.clear();
+ const QString &loadJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS");
+ if (!loadJsonFile.isEmpty())
+ loadJson(loadJsonFile);
+ if (!m_signalMap.isEmpty())
+ return;
+
+ m_signalMap.insert(DBusKey("org.kde.kdeglobals.KDE"_L1, "widgetStyle"_L1),
+ ChangeSignal(Provider::Kde, Setting::ApplicationStyle));
+
+ m_signalMap.insert(DBusKey("org.kde.kdeglobals.General"_L1, "ColorScheme"_L1),
+ ChangeSignal(Provider::Kde, Setting::Theme));
+
+ m_signalMap.insert(DBusKey("org.gnome.desktop.interface"_L1, "gtk-theme"_L1),
+ ChangeSignal(Provider::Gtk, Setting::Theme));
+
+ m_signalMap.insert(DBusKey("org.freedesktop.appearance"_L1, "color-scheme"_L1),
+ ChangeSignal(Provider::Gnome, Setting::ColorScheme));
+
+ const QString &saveJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS_SAVE");
+ if (!saveJsonFile.isEmpty())
+ saveJson(saveJsonFile);
+}
+
+std::optional<QGenericUnixThemeDBusListener::ChangeSignal>
+ QGenericUnixThemeDBusListener::findSignal(const QString &location, const QString &key) const
+{
+ const DBusKey dkey(location, key);
+ std::optional<QGenericUnixThemeDBusListener::ChangeSignal> ret;
+ if (m_signalMap.contains(dkey))
+ ret.emplace(m_signalMap.value(dkey));
+
+ return ret;
+}
+
+void QGenericUnixThemeDBusListener::onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value)
+{
+ auto sig = findSignal(location, key);
+ if (!sig.has_value())
+ return;
+
+ emit settingChanged(sig.value().provider, sig.value().setting, value.variant().toString());
+}
+
+#endif //QT_NO_DBUS
class QGenericUnixThemePrivate : public QPlatformThemePrivate
{
public:
QGenericUnixThemePrivate()
: QPlatformThemePrivate()
- , systemFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize)
- , fixedFont(QLatin1String(defaultFixedFontNameC), systemFont.pointSize())
+ , systemFont(QLatin1StringView(defaultSystemFontNameC), defaultSystemFontSize)
+ , fixedFont(QLatin1StringView(defaultFixedFontNameC), systemFont.pointSize())
{
fixedFont.setStyleHint(QFont::TypeWriter);
qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont;
@@ -173,7 +443,7 @@ QStringList QGenericUnixTheme::xdgIconThemePaths()
{
QStringList paths;
// Add home directory first in search path
- const QFileInfo homeIconDir(QDir::homePath() + QLatin1String("/.icons"));
+ const QFileInfo homeIconDir(QDir::homePath() + "/.icons"_L1);
if (homeIconDir.isDir())
paths.prepend(homeIconDir.absoluteFilePath());
@@ -232,6 +502,10 @@ QVariant QGenericUnixTheme::themeHint(ThemeHint hint) const
return QVariant(int(X11KeyboardScheme));
case QPlatformTheme::UiEffects:
return QVariant(int(HoverEffect));
+ case QPlatformTheme::MouseCursorTheme:
+ return QVariant(mouseCursorTheme());
+ case QPlatformTheme::MouseCursorSize:
+ return QVariant(mouseCursorSize());
default:
break;
}
@@ -265,17 +539,15 @@ static QIcon xdgFileIcon(const QFileInfo &fileInfo)
#if QT_CONFIG(settings)
class QKdeThemePrivate : public QPlatformThemePrivate
{
+
public:
- QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion)
- : kdeDirs(kdeDirs)
- , kdeVersion(kdeVersion)
- { }
+ QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion);
static QString kdeGlobals(const QString &kdeDir, int kdeVersion)
{
if (kdeVersion > 4)
- return kdeDir + QLatin1String("/kdeglobals");
- return kdeDir + QLatin1String("/share/config/kdeglobals");
+ return kdeDir + "/kdeglobals"_L1;
+ return kdeDir + "/share/config/kdeglobals"_L1;
}
void refresh();
@@ -300,8 +572,66 @@ public:
int startDragDist = 10;
int startDragTime = 500;
int cursorBlinkRate = 1000;
+ Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;
+ void updateColorScheme(const QString &themeName);
+
+#ifndef QT_NO_DBUS
+private:
+ std::unique_ptr<QGenericUnixThemeDBusListener> dbus;
+ bool initDbus();
+ void settingChangedHandler(QGenericUnixThemeDBusListener::Provider provider,
+ QGenericUnixThemeDBusListener::Setting setting,
+ const QString &value);
+#endif // QT_NO_DBUS
};
+#ifndef QT_NO_DBUS
+void QKdeThemePrivate::settingChangedHandler(QGenericUnixThemeDBusListener::Provider provider,
+ QGenericUnixThemeDBusListener::Setting setting,
+ const QString &value)
+{
+ if (provider != QGenericUnixThemeDBusListener::Provider::Kde)
+ return;
+
+ switch (setting) {
+ case QGenericUnixThemeDBusListener::Setting::ColorScheme:
+ qCDebug(lcQpaThemeDBus) << "KDE color theme changed to:" << value;
+ break;
+ case QGenericUnixThemeDBusListener::Setting::Theme:
+ qCDebug(lcQpaThemeDBus) << "KDE global theme changed to:" << value;
+ break;
+ case QGenericUnixThemeDBusListener::Setting::ApplicationStyle:
+ qCDebug(lcQpaThemeDBus) << "KDE application style changed to:" << value;
+ break;
+ }
+
+ refresh();
+}
+
+bool QKdeThemePrivate::initDbus()
+{
+ dbus.reset(new QGenericUnixThemeDBusListener());
+ Q_ASSERT(dbus);
+
+ // Wrap slot in a lambda to avoid inheriting QKdeThemePrivate from QObject
+ auto wrapper = [this](QGenericUnixThemeDBusListener::Provider provider,
+ QGenericUnixThemeDBusListener::Setting setting,
+ const QString &value) {
+ settingChangedHandler(provider, setting, value);
+ };
+
+ return QObject::connect(dbus.get(), &QGenericUnixThemeDBusListener::settingChanged, dbus.get(), wrapper);
+}
+#endif // QT_NO_DBUS
+
+QKdeThemePrivate::QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion)
+ : kdeDirs(kdeDirs), kdeVersion(kdeVersion)
+{
+#ifndef QT_NO_DBUS
+ initDbus();
+#endif // QT_NO_DBUS
+}
+
void QKdeThemePrivate::refresh()
{
resources.clear();
@@ -331,6 +661,14 @@ void QKdeThemePrivate::refresh()
styleNames.push_front(style);
}
+ const QVariant colorScheme = readKdeSetting(QStringLiteral("ColorScheme"), kdeDirs,
+ kdeVersion, kdeSettings);
+
+ if (colorScheme.isValid())
+ updateColorScheme(colorScheme.toString());
+ else
+ m_colorScheme = Qt::ColorScheme::Unknown;
+
const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeVersion, kdeSettings);
if (singleClickValue.isValid())
singleClick = singleClickValue.toBool();
@@ -350,11 +688,11 @@ void QKdeThemePrivate::refresh()
const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle"), kdeDirs, kdeVersion, kdeSettings);
if (toolbarStyleValue.isValid()) {
const QString toolBarStyle = toolbarStyleValue.toString();
- if (toolBarStyle == QLatin1String("TextBesideIcon"))
+ if (toolBarStyle == "TextBesideIcon"_L1)
toolButtonStyle = Qt::ToolButtonTextBesideIcon;
- else if (toolBarStyle == QLatin1String("TextOnly"))
+ else if (toolBarStyle == "TextOnly"_L1)
toolButtonStyle = Qt::ToolButtonTextOnly;
- else if (toolBarStyle == QLatin1String("TextUnderIcon"))
+ else if (toolBarStyle == "TextUnderIcon"_L1)
toolButtonStyle = Qt::ToolButtonTextUnderIcon;
}
@@ -384,12 +722,12 @@ void QKdeThemePrivate::refresh()
if (QFont *systemFont = kdeFont(readKdeSetting(QStringLiteral("font"), kdeDirs, kdeVersion, kdeSettings)))
resources.fonts[QPlatformTheme::SystemFont] = systemFont;
else
- resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1String(defaultSystemFontNameC), defaultSystemFontSize);
+ resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1StringView(defaultSystemFontNameC), defaultSystemFontSize);
if (QFont *fixedFont = kdeFont(readKdeSetting(QStringLiteral("fixed"), kdeDirs, kdeVersion, kdeSettings))) {
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
} else {
- fixedFont = new QFont(QLatin1String(defaultFixedFontNameC), defaultSystemFontSize);
+ fixedFont = new QFont(QLatin1StringView(defaultFixedFontNameC), defaultSystemFontSize);
fixedFont->setStyleHint(QFont::TypeWriter);
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
}
@@ -402,6 +740,8 @@ void QKdeThemePrivate::refresh()
if (QFont *toolBarFont = kdeFont(readKdeSetting(QStringLiteral("toolBarFont"), kdeDirs, kdeVersion, kdeSettings)))
resources.fonts[QPlatformTheme::ToolButtonFont] = toolBarFont;
+ QWindowSystemInterface::handleThemeChange();
+
qCDebug(lcQpaFonts) << "default fonts: system" << resources.fonts[QPlatformTheme::SystemFont]
<< "fixed" << resources.fonts[QPlatformTheme::FixedFont];
qDeleteAll(kdeSettings);
@@ -523,7 +863,7 @@ QFont *QKdeThemePrivate::kdeFont(const QVariant &fontValue)
const QStringList list = fontValue.toStringList();
if (!list.isEmpty()) {
fontFamily = list.first();
- fontDescription = list.join(QLatin1Char(','));
+ fontDescription = list.join(u',');
}
} else {
fontDescription = fontFamily = fontValue.toString();
@@ -590,6 +930,10 @@ QVariant QKdeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
return QVariant(d->cursorBlinkRate);
case QPlatformTheme::UiEffects:
return QVariant(int(HoverEffect));
+ case QPlatformTheme::MouseCursorTheme:
+ return QVariant(mouseCursorTheme());
+ case QPlatformTheme::MouseCursorSize:
+ return QVariant(mouseCursorSize());
default:
break;
}
@@ -606,6 +950,48 @@ QIcon QKdeTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions
#endif
}
+Qt::ColorScheme QKdeTheme::colorScheme() const
+{
+ return d_func()->m_colorScheme;
+}
+
+/*!
+ \internal
+ \brief QKdeTheme::updateColorScheme - guess and set appearance for unix themes.
+ KDE themes do not have an appearance property.
+ The key words "dark" or "light" should be part of the theme name.
+ This is, however, not a mandatory convention.
+
+ If \param themeName contains a key word, the respective appearance is set.
+ If it doesn't, the appearance is heuristically determined by comparing text and base color
+ of the system palette.
+ */
+void QKdeThemePrivate::updateColorScheme(const QString &themeName)
+{
+ if (themeName.contains(QLatin1StringView("light"), Qt::CaseInsensitive)) {
+ m_colorScheme = Qt::ColorScheme::Light;
+ return;
+ }
+ if (themeName.contains(QLatin1StringView("dark"), Qt::CaseInsensitive)) {
+ m_colorScheme = Qt::ColorScheme::Dark;
+ return;
+ }
+
+ if (systemPalette) {
+ if (systemPalette->text().color().lightness() < systemPalette->base().color().lightness()) {
+ m_colorScheme = Qt::ColorScheme::Light;
+ return;
+ }
+ if (systemPalette->text().color().lightness() > systemPalette->base().color().lightness()) {
+ m_colorScheme = Qt::ColorScheme::Dark;
+ return;
+ }
+ }
+
+ m_colorScheme = Qt::ColorScheme::Unknown;
+}
+
+
const QPalette *QKdeTheme::palette(Palette type) const
{
Q_D(const QKdeTheme);
@@ -643,24 +1029,24 @@ QPlatformTheme *QKdeTheme::createKdeTheme()
const QString kdeDirsVar = QFile::decodeName(qgetenv("KDEDIRS"));
if (!kdeDirsVar.isEmpty())
- kdeDirs += kdeDirsVar.split(QLatin1Char(':'), Qt::SkipEmptyParts);
+ kdeDirs += kdeDirsVar.split(u':', Qt::SkipEmptyParts);
- const QString kdeVersionHomePath = QDir::homePath() + QLatin1String("/.kde") + QLatin1String(kdeVersionBA);
+ const QString kdeVersionHomePath = QDir::homePath() + "/.kde"_L1 + QLatin1StringView(kdeVersionBA);
if (QFileInfo(kdeVersionHomePath).isDir())
kdeDirs += kdeVersionHomePath;
- const QString kdeHomePath = QDir::homePath() + QLatin1String("/.kde");
+ const QString kdeHomePath = QDir::homePath() + "/.kde"_L1;
if (QFileInfo(kdeHomePath).isDir())
kdeDirs += kdeHomePath;
- const QString kdeRcPath = QLatin1String("/etc/kde") + QLatin1String(kdeVersionBA) + QLatin1String("rc");
+ const QString kdeRcPath = "/etc/kde"_L1 + QLatin1StringView(kdeVersionBA) + "rc"_L1;
if (QFileInfo(kdeRcPath).isReadable()) {
QSettings kdeSettings(kdeRcPath, QSettings::IniFormat);
kdeSettings.beginGroup(QStringLiteral("Directories-default"));
kdeDirs += kdeSettings.value(QStringLiteral("prefixes")).toStringList();
}
- const QString kdeVersionPrefix = QLatin1String("/etc/kde") + QLatin1String(kdeVersionBA);
+ const QString kdeVersionPrefix = "/etc/kde"_L1 + QLatin1StringView(kdeVersionBA);
if (QFileInfo(kdeVersionPrefix).isDir())
kdeDirs += kdeVersionPrefix;
@@ -706,8 +1092,8 @@ const char *QGnomeTheme::name = "gnome";
class QGnomeThemePrivate : public QPlatformThemePrivate
{
public:
- QGnomeThemePrivate() : systemFont(nullptr), fixedFont(nullptr) {}
- ~QGnomeThemePrivate() { delete systemFont; delete fixedFont; }
+ QGnomeThemePrivate();
+ ~QGnomeThemePrivate();
void configureFonts(const QString &gtkFontName) const
{
@@ -717,15 +1103,75 @@ public:
QString fontName = gtkFontName.left(split);
systemFont = new QFont(fontName, size);
- fixedFont = new QFont(QLatin1String(defaultFixedFontNameC), systemFont->pointSize());
+ fixedFont = new QFont(QLatin1StringView(defaultFixedFontNameC), systemFont->pointSize());
fixedFont->setStyleHint(QFont::TypeWriter);
qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont;
}
- mutable QFont *systemFont;
- mutable QFont *fixedFont;
+ mutable QFont *systemFont = nullptr;
+ mutable QFont *fixedFont = nullptr;
+
+#ifndef QT_NO_DBUS
+ Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;
+private:
+ std::unique_ptr<QGenericUnixThemeDBusListener> dbus;
+ bool initDbus();
+ void updateColorScheme(const QString &themeName);
+#endif // QT_NO_DBUS
};
+QGnomeThemePrivate::QGnomeThemePrivate()
+{
+#ifndef QT_NO_DBUS
+ initDbus();
+#endif // QT_NO_DBUS
+}
+QGnomeThemePrivate::~QGnomeThemePrivate()
+{
+ if (systemFont)
+ delete systemFont;
+ if (fixedFont)
+ delete fixedFont;
+}
+
+#ifndef QT_NO_DBUS
+bool QGnomeThemePrivate::initDbus()
+{
+ dbus.reset(new QGenericUnixThemeDBusListener());
+ Q_ASSERT(dbus);
+
+ // Wrap slot in a lambda to avoid inheriting QGnomeThemePrivate from QObject
+ auto wrapper = [this](QGenericUnixThemeDBusListener::Provider provider,
+ QGenericUnixThemeDBusListener::Setting setting,
+ const QString &value) {
+ if (provider != QGenericUnixThemeDBusListener::Provider::Gnome
+ && provider != QGenericUnixThemeDBusListener::Provider::Gtk) {
+ return;
+ }
+
+ if (setting == QGenericUnixThemeDBusListener::Setting::Theme)
+ updateColorScheme(value);
+ };
+
+ return QObject::connect(dbus.get(), &QGenericUnixThemeDBusListener::settingChanged, dbus.get(), wrapper);
+}
+
+void QGnomeThemePrivate::updateColorScheme(const QString &themeName)
+{
+ const auto oldColorScheme = m_colorScheme;
+ if (themeName.contains(QLatin1StringView("light"), Qt::CaseInsensitive)) {
+ m_colorScheme = Qt::ColorScheme::Light;
+ } else if (themeName.contains(QLatin1StringView("dark"), Qt::CaseInsensitive)) {
+ m_colorScheme = Qt::ColorScheme::Dark;
+ } else {
+ m_colorScheme = Qt::ColorScheme::Unknown;
+ }
+
+ if (oldColorScheme != m_colorScheme)
+ QWindowSystemInterface::handleThemeChange();
+}
+#endif // QT_NO_DBUS
+
QGnomeTheme::QGnomeTheme()
: QPlatformTheme(new QGnomeThemePrivate())
{
@@ -757,6 +1203,15 @@ QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
return QVariant(QChar(0x2022));
case QPlatformTheme::UiEffects:
return QVariant(int(HoverEffect));
+ case QPlatformTheme::ButtonPressKeys:
+ return QVariant::fromValue(
+ QList<Qt::Key>({ Qt::Key_Space, Qt::Key_Return, Qt::Key_Enter, Qt::Key_Select }));
+ case QPlatformTheme::PreselectFirstFileInDirectory:
+ return true;
+ case QPlatformTheme::MouseCursorTheme:
+ return QVariant(mouseCursorTheme());
+ case QPlatformTheme::MouseCursorSize:
+ return QVariant(mouseCursorSize());
default:
break;
}
@@ -790,7 +1245,7 @@ const QFont *QGnomeTheme::font(Font type) const
QString QGnomeTheme::gtkFontName() const
{
- return QStringLiteral("%1 %2").arg(QLatin1String(defaultSystemFontNameC)).arg(defaultSystemFontSize);
+ return QStringLiteral("%1 %2").arg(QLatin1StringView(defaultSystemFontNameC)).arg(defaultSystemFontSize);
}
#ifndef QT_NO_DBUS
@@ -800,6 +1255,12 @@ QPlatformMenuBar *QGnomeTheme::createPlatformMenuBar() const
return new QDBusMenuBar();
return nullptr;
}
+
+Qt::ColorScheme QGnomeTheme::colorScheme() const
+{
+ return d_func()->m_colorScheme;
+}
+
#endif
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
@@ -836,14 +1297,14 @@ QString QGnomeTheme::standardButtonText(int button) const
QPlatformTheme *QGenericUnixTheme::createUnixTheme(const QString &name)
{
- if (name == QLatin1String(QGenericUnixTheme::name))
+ if (name == QLatin1StringView(QGenericUnixTheme::name))
return new QGenericUnixTheme;
#if QT_CONFIG(settings)
- if (name == QLatin1String(QKdeTheme::name))
+ if (name == QLatin1StringView(QKdeTheme::name))
if (QPlatformTheme *kdeTheme = QKdeTheme::createKdeTheme())
return kdeTheme;
#endif
- if (name == QLatin1String(QGnomeTheme::name))
+ if (name == QLatin1StringView(QGnomeTheme::name))
return new QGnomeTheme;
return nullptr;
}
@@ -864,23 +1325,27 @@ QStringList QGenericUnixTheme::themeNames()
for (const QByteArray &desktopName : desktopNames) {
if (desktopEnvironment == "KDE") {
#if QT_CONFIG(settings)
- result.push_back(QLatin1String(QKdeTheme::name));
+ result.push_back(QLatin1StringView(QKdeTheme::name));
#endif
} else if (gtkBasedEnvironments.contains(desktopName)) {
// prefer the GTK3 theme implementation with native dialogs etc.
result.push_back(QStringLiteral("gtk3"));
// fallback to the generic Gnome theme if loading the GTK3 theme fails
- result.push_back(QLatin1String(QGnomeTheme::name));
+ result.push_back(QLatin1StringView(QGnomeTheme::name));
} else {
// unknown, but lowercase the name (our standard practice) and
// remove any "x-" prefix
QString s = QString::fromLatin1(desktopName.toLower());
- result.push_back(s.startsWith(QLatin1String("x-")) ? s.mid(2) : s);
+ result.push_back(s.startsWith("x-"_L1) ? s.mid(2) : s);
}
}
} // desktopSettingsAware
- result.append(QLatin1String(QGenericUnixTheme::name));
+ result.append(QLatin1StringView(QGenericUnixTheme::name));
return result;
}
QT_END_NAMESPACE
+
+#ifndef QT_NO_DBUS
+#include "qgenericunixthemes.moc"
+#endif // QT_NO_DBUS
diff --git a/src/gui/platform/unix/qgenericunixthemes_p.h b/src/gui/platform/unix/qgenericunixthemes_p.h
index 0870275888..63b20651e6 100644
--- a/src/gui/platform/unix/qgenericunixthemes_p.h
+++ b/src/gui/platform/unix/qgenericunixthemes_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGENERICUNIXTHEMES_H
#define QGENERICUNIXTHEMES_H
@@ -55,6 +19,7 @@
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtGui/QFont>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -112,6 +77,7 @@ public:
QPlatformTheme::IconOptions iconOptions = { }) const override;
const QPalette *palette(Palette type = SystemPalette) const override;
+ Qt::ColorScheme colorScheme() const override;
const QFont *font(Font type) const override;
#ifndef QT_NO_DBUS
@@ -141,6 +107,7 @@ public:
virtual QString gtkFontName() const;
#ifndef QT_NO_DBUS
QPlatformMenuBar *createPlatformMenuBar() const override;
+ Qt::ColorScheme colorScheme() const override;
#endif
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
diff --git a/src/gui/platform/unix/qtx11extras.cpp b/src/gui/platform/unix/qtx11extras.cpp
index 09bcb81bae..ef37518d95 100644
--- a/src/gui/platform/unix/qtx11extras.cpp
+++ b/src/gui/platform/unix/qtx11extras.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Copyright (C) 2016 Richard Moore <rich@kde.org>
-** Copyright (C) 2016 David Faure <david.faure@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Richard Moore <rich@kde.org>
+// Copyright (C) 2016 David Faure <david.faure@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtx11extras_p.h"
@@ -53,6 +17,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static QScreen *findScreenForVirtualDesktop(int virtualDesktopNumber)
{
const auto screens = QGuiApplication::screens();
@@ -78,7 +44,7 @@ static QScreen *findScreenForVirtualDesktop(int virtualDesktopNumber)
application.
\warning This class is only available on X11. For querying
- per-screen information in a portable way, use QDesktopWidget.
+ per-screen information in a portable way, use QScreen.
*/
/*!
@@ -95,7 +61,7 @@ QX11Info::QX11Info()
*/
bool QX11Info::isPlatformX11()
{
- return QGuiApplication::platformName() == QLatin1String("xcb");
+ return QGuiApplication::platformName() == "xcb"_L1;
}
/*!
@@ -104,7 +70,7 @@ bool QX11Info::isPlatformX11()
The \a screen argument is an X screen number. Be aware that if
the user's system uses Xinerama (as opposed to traditional X11
- multiscreen), there is only one X screen. Use QDesktopWidget to
+ multiscreen), there is only one X screen. Use QScreen to
query for information about Xinerama screens.
\sa appDpiY()
@@ -131,7 +97,7 @@ int QX11Info::appDpiX(int screen)
The \a screen argument is an X screen number. Be aware that if
the user's system uses Xinerama (as opposed to traditional X11
- multiscreen), there is only one X screen. Use QDesktopWidget to
+ multiscreen), there is only one X screen. Use QScreen to
query for information about Xinerama screens.
\sa appDpiX()
@@ -157,7 +123,7 @@ int QX11Info::appDpiY(int screen)
The \a screen argument is an X screen number. Be aware that if
the user's system uses Xinerama (as opposed to traditional X11
- multiscreen), there is only one X screen. Use QDesktopWidget to
+ multiscreen), there is only one X screen. Use QScreen to
query for information about Xinerama screens.
*/
quint32 QX11Info::appRootWindow(int screen)
@@ -186,7 +152,7 @@ quint32 QX11Info::appRootWindow(int screen)
are combined in one X11 screen. This means this method returns the
same number for each of the physical monitors. In such a setup you
are interested in the monitor information as provided by the X11
- RandR extension. This is available through QDesktopWidget and QScreen.
+ RandR extension. This is available through QScreen.
\sa display()
*/
@@ -394,7 +360,7 @@ bool QX11Info::isCompositingManagerRunning(int screen)
}
/*!
- Returns a new peeker id or -1 if some interal error has occurred.
+ Returns a new peeker id or -1 if some internal error has occurred.
Each peeker id is associated with an index in the buffered native
event queue.
@@ -425,7 +391,7 @@ qint32 QX11Info::generatePeekerId()
Removes \a peekerId, which was earlier obtained via generatePeekerId().
Returns \c true on success or \c false if unknown peeker id was
- provided or some interal error has occurred.
+ provided or some internal error has occurred.
\sa generatePeekerId()
*/
diff --git a/src/gui/platform/unix/qtx11extras_p.h b/src/gui/platform/unix/qtx11extras_p.h
index aed46a82b4..253162f83a 100644
--- a/src/gui/platform/unix/qtx11extras_p.h
+++ b/src/gui/platform/unix/qtx11extras_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTX11EXTRAS_P_H
#define QTX11EXTRAS_P_H
@@ -52,6 +16,7 @@
//
#include <QtGui/qtguiglobal.h>
+#include <QtCore/private/qglobal_p.h>
#include <xcb/xcb.h>
diff --git a/src/gui/platform/unix/qunixeventdispatcher.cpp b/src/gui/platform/unix/qunixeventdispatcher.cpp
index 9262ee7b2f..0178b7544e 100644
--- a/src/gui/platform/unix/qunixeventdispatcher.cpp
+++ b/src/gui/platform/unix/qunixeventdispatcher.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformdefs.h"
#include "qcoreapplication.h"
diff --git a/src/gui/platform/unix/qunixeventdispatcher_qpa_p.h b/src/gui/platform/unix/qunixeventdispatcher_qpa_p.h
index d1ff7298ee..bcae9b5a1c 100644
--- a/src/gui/platform/unix/qunixeventdispatcher_qpa_p.h
+++ b/src/gui/platform/unix/qunixeventdispatcher_qpa_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QUNIXEVENTDISPATCHER_QPA_H
#define QUNIXEVENTDISPATCHER_QPA_H
diff --git a/src/gui/platform/unix/qunixnativeinterface.cpp b/src/gui/platform/unix/qunixnativeinterface.cpp
index 4febe69d91..09561d9ada 100644
--- a/src/gui/platform/unix/qunixnativeinterface.cpp
+++ b/src/gui/platform/unix/qunixnativeinterface.cpp
@@ -1,45 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/private/qtguiglobal_p.h>
-#include <QtGui/private/qopenglcontext_p.h>
+#if QT_CONFIG(opengl)
+# include <QtGui/private/qopenglcontext_p.h>
+#endif
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformopenglcontext.h>
@@ -65,6 +31,7 @@ using namespace QNativeInterface::Private;
Accessed through QOpenGLContext::nativeInterface().
\inmodule QtGui
+ \inheaderfile QOpenGLContext
\ingroup native-interfaces
\ingroup native-interfaces-qopenglcontext
*/
@@ -122,6 +89,7 @@ QOpenGLContext *QNativeInterface::QGLXContext::fromNative(GLXContext visualBased
Accessed through QOpenGLContext::nativeInterface().
\inmodule QtGui
+ \inheaderfile QOpenGLContext
\ingroup native-interfaces
\ingroup native-interfaces-qopenglcontext
*/
@@ -143,6 +111,34 @@ QOpenGLContext *QNativeInterface::QGLXContext::fromNative(GLXContext visualBased
\return the underlying EGLContext.
*/
+/*!
+ \fn EGLConfig QNativeInterface::QEGLContext::config() const
+ \since 6.3
+ \return the EGLConfig associated with the underlying EGLContext.
+*/
+
+/*!
+ \fn EGLDisplay QNativeInterface::QEGLContext::display() const
+ \since 6.3
+ \return the EGLDisplay associated with the underlying EGLContext.
+*/
+
+
+/*!
+ \fn void QNativeInterface::QEGLContext::invalidateContext()
+ \since 6.5
+ \brief Marks the context as invalid
+
+ If this context is used by the Qt Quick scenegraph, this will trigger the
+ SceneGraph to destroy this context and create a new one.
+
+ Similarly to QPlatformWindow::invalidateSurface(),
+ this function can only be expected to have an effect on certain platforms,
+ such as eglfs.
+
+ \sa QOpenGLContext::isValid(), QPlatformWindow::invalidateSurface()
+*/
+
QT_DEFINE_NATIVE_INTERFACE(QEGLContext);
QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QEGLIntegration);
@@ -179,6 +175,37 @@ QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QXcbScreen);
QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QXcbWindow);
+/*!
+ \class QNativeInterface::QX11Application
+ \since 6.2
+ \brief Native interface to an X11 application.
+
+ Accessed through QGuiApplication::nativeInterface().
+
+ \inmodule QtGui
+ \inheaderfile QGuiApplication
+ \ingroup native-interfaces
+ \ingroup native-interfaces-qguiapplication
+*/
+
+/*!
+ \fn Display *QNativeInterface::QX11Application::display() const
+
+ \return the X display of the application, for use with Xlib.
+
+ \sa connection()
+*/
+
+/*!
+ \fn xcb_connection_t *QNativeInterface::QX11Application::connection() const
+
+ \return the X connection of the application, for use with XCB.
+
+ \sa display()
+*/
+
+QT_DEFINE_NATIVE_INTERFACE(QX11Application);
+
#endif // QT_CONFIG(xcb)
#if QT_CONFIG(vsp2)
@@ -204,4 +231,81 @@ QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QEvdevKeyMapper);
#endif // QT_CONFIG(evdev)
+#if QT_CONFIG(wayland)
+
+/*!
+ \class QNativeInterface::QWaylandApplication
+ \inheaderfile QGuiApplication
+ \since 6.5
+ \brief Native interface to a Wayland application.
+
+ Accessed through QGuiApplication::nativeInterface().
+ \inmodule QtGui
+ \ingroup native-interfaces
+ \ingroup native-interfaces-qguiapplication
+*/
+/*!
+ \fn wl_display *QNativeInterface::QWaylandApplication::display() const
+ \return the wl_display that the application is using.
+*/
+/*!
+ \fn wl_compositor *QNativeInterface::QWaylandApplication::compositor() const
+ \return the wl_compositor that the application is using.
+*/
+/*!
+ \fn wl_keyboard *QNativeInterface::QWaylandApplication::keyboard() const
+ \return the wl_keyboard belonging to seat() if available.
+*/
+/*!
+ \fn wl_pointer *QNativeInterface::QWaylandApplication::pointer() const
+ \return the wl_pointer belonging to seat() if available.
+*/
+/*!
+ \fn wl_touch *QNativeInterface::QWaylandApplication::touch() const
+ \return the wl_touch belonging to seat() if available.
+*/
+/*!
+ \fn uint *QNativeInterface::QWaylandApplication::lastInputSerial() const
+ \return the serial of the last input event on any seat.
+*/
+/*!
+ \fn wl_seat *QNativeInterface::QWaylandApplication::lastInputSeat() const
+ \return the seat on which the last input event happened.
+*/
+/*!
+ \fn wl_seat *QNativeInterface::QWaylandApplication::seat() const
+ \return the seat associated with the default input device.
+*/
+
+QT_DEFINE_NATIVE_INTERFACE(QWaylandApplication);
+
+/*!
+ \class QNativeInterface::QWaylandScreen
+ \since 6.7
+ \brief Native interface to a screen on Wayland.
+
+ Accessed through QScreen::nativeInterface().
+ \inmodule QtGui
+ \ingroup native-interfaces
+ \ingroup native-interfaces-qscreen
+*/
+/*!
+ \fn wl_output *QNativeInterface::QWaylandScreen::output() const
+ \return the underlying wl_output of this QScreen.
+*/
+QT_DEFINE_NATIVE_INTERFACE(QWaylandScreen);
+
+/*!
+ \class QNativeInterface::QWaylandWindow
+ \since 6.5
+ \internal
+ \brief Native interface to a Wayland window.
+ \inmodule QtGui
+ \ingroup native-interfaces
+*/
+
+QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QWaylandWindow);
+
+#endif // QT_CONFIG(wayland)
+
QT_END_NAMESPACE
diff --git a/src/gui/platform/unix/qxkbcommon.cpp b/src/gui/platform/unix/qxkbcommon.cpp
index e4d93ceb55..ed29db3005 100644
--- a/src/gui/platform/unix/qxkbcommon.cpp
+++ b/src/gui/platform/unix/qxkbcommon.cpp
@@ -1,47 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qxkbcommon_p.h"
#include <private/qmakearray_p.h>
+#include <QtCore/private/qstringiterator_p.h>
+#include <QtCore/qvarlengtharray.h>
#include <QtCore/QMetaMethod>
+
#include <QtGui/QKeyEvent>
#include <QtGui/private/qguiapplication_p.h>
@@ -50,8 +17,6 @@
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcXkbcommon, "qt.xkbcommon")
-
static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
xkb_state *state, xkb_keycode_t code,
bool superAsMeta, bool hyperAsMeta);
@@ -272,10 +237,14 @@ static constexpr const auto KeyTbl = qMakeArray(
Xkb2Qt<XKB_KEY_dead_small_schwa, Qt::Key_Dead_Small_Schwa>,
Xkb2Qt<XKB_KEY_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa>,
Xkb2Qt<XKB_KEY_dead_greek, Qt::Key_Dead_Greek>,
+/* The following four XKB_KEY_dead keys got removed in libxkbcommon 1.6.0
+ The define check is kind of version check here. */
+#ifdef XKB_KEY_dead_lowline
Xkb2Qt<XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline>,
Xkb2Qt<XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline>,
Xkb2Qt<XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline>,
Xkb2Qt<XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay>,
+#endif
// Special keys from X.org - This include multimedia keys,
// wireless/bluetooth/uwb keys, special launcher keys, etc.
@@ -331,6 +300,7 @@ static constexpr const auto KeyTbl = qMakeArray(
Xkb2Qt<XKB_KEY_XF86Book, Qt::Key_Book>,
Xkb2Qt<XKB_KEY_XF86CD, Qt::Key_CD>,
Xkb2Qt<XKB_KEY_XF86Calculater, Qt::Key_Calculator>,
+ Xkb2Qt<XKB_KEY_XF86Calculator, Qt::Key_Calculator>,
Xkb2Qt<XKB_KEY_XF86Clear, Qt::Key_Clear>,
Xkb2Qt<XKB_KEY_XF86ClearGrab, Qt::Key_ClearGrab>,
Xkb2Qt<XKB_KEY_XF86Close, Qt::Key_Close>,
@@ -494,7 +464,7 @@ QList<xkb_keysym_t> QXkbCommon::toKeysym(QKeyEvent *event)
// From libxkbcommon keysym-utf.c:
// "We allow to represent any UCS character in the range U-00000000 to
// U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff."
- for (uint utf32 : qAsConst(ucs4))
+ for (uint utf32 : std::as_const(ucs4))
keysyms.append(utf32 | 0x01000000);
return keysyms;
@@ -545,13 +515,13 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod
// numeric keypad keys
qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0);
} else if (QXkbCommon::isLatin1(keysym)) {
- // Upper-case first, since Qt::Keys are defined in terms of their
- // upper-case versions.
+ // Most Qt::Key values are determined by their upper-case version,
+ // where this is in the Latin-1 repertoire. So start with that:
qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym);
- // Upper-casing a Latin1 character might move it out of Latin1 range,
- // for example U+00B5 MICRO SIGN, which upper-case equivalent is
- // U+039C GREEK CAPITAL LETTER MU. If that's the case, then map the
- // original lower-case character.
+ // However, Key_mu and Key_ydiaeresis are U+00B5 MICRO SIGN and
+ // U+00FF LATIN SMALL LETTER Y WITH DIAERESIS, both lower-case,
+ // with upper-case forms outside Latin-1, so use them as they are
+ // since they're the Qt::Key values.
if (!QXkbCommon::isLatin1(qtKey))
qtKey = keysym;
} else {
@@ -588,14 +558,16 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod
// e.g CTRL + ۲ (arabic two), is mapped to CTRL + Qt::Key_2.
qtKey = Qt::Key_0 + text.unicode()->digitValue();
} else {
- qtKey = text.unicode()->toUpper().unicode();
+ text = text.toUpper();
+ QStringIterator i(text);
+ qtKey = i.next(0);
}
}
return qtKey;
}
-Qt::KeyboardModifiers QXkbCommon::modifiers(struct xkb_state *state)
+Qt::KeyboardModifiers QXkbCommon::modifiers(struct xkb_state *state, xkb_keysym_t keysym)
{
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
@@ -608,6 +580,9 @@ Qt::KeyboardModifiers QXkbCommon::modifiers(struct xkb_state *state)
if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO, XKB_STATE_MODS_EFFECTIVE) > 0)
modifiers |= Qt::MetaModifier;
+ if (isKeypad(keysym))
+ modifiers |= Qt::KeypadModifier;
+
return modifiers;
}
@@ -624,10 +599,24 @@ static const Qt::KeyboardModifiers ModsTbl[] = {
Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts
};
+/*
+ Compatibility until all sub modules have transitioned to new API below
+*/
QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event,
bool superAsMeta, bool hyperAsMeta)
{
QList<int> result;
+ auto keyCombinations = possibleKeyCombinations(state, event, superAsMeta, hyperAsMeta);
+ for (auto keyCombination : keyCombinations)
+ result << keyCombination.toCombined();
+
+ return result;
+}
+
+QList<QKeyCombination> QXkbCommon::possibleKeyCombinations(xkb_state *state, const QKeyEvent *event,
+ bool superAsMeta, bool hyperAsMeta)
+{
+ QList<QKeyCombination> result;
quint32 keycode = event->nativeScanCode();
if (!keycode)
return result;
@@ -641,7 +630,7 @@ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event,
ScopedXKBState scopedXkbQueryState(xkb_state_new(keymap));
xkb_state *queryState = scopedXkbQueryState.get();
if (!queryState) {
- qCWarning(lcXkbcommon) << Q_FUNC_INFO << "failed to compile xkb keymap";
+ qCWarning(lcQpaKeyMapper) << Q_FUNC_INFO << "failed to compile xkb keymap";
return result;
}
// get kb state from the master state and update the temporary state
@@ -667,7 +656,7 @@ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event,
int baseQtKey = keysymToQtKey_internal(sym, modifiers, queryState, keycode, superAsMeta, hyperAsMeta);
if (baseQtKey)
- result += (baseQtKey + int(modifiers));
+ result += QKeyCombination::fromCombined(baseQtKey + int(modifiers));
xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(keymap, "Shift");
xkb_mod_index_t altMod = xkb_keymap_mod_get_index(keymap, "Alt");
@@ -713,8 +702,9 @@ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event,
// catch only more specific shortcuts, i.e. Ctrl+Shift+= also generates Ctrl++ and +,
// but Ctrl++ is more specific than +, so we should skip the last one
bool ambiguous = false;
- for (int shortcut : qAsConst(result)) {
- if (int(shortcut & ~Qt::KeyboardModifierMask) == qtKey && (shortcut & mods) == mods) {
+ for (auto keyCombination : std::as_const(result)) {
+ if (keyCombination.key() == qtKey
+ && (keyCombination.keyboardModifiers() & mods) == mods) {
ambiguous = true;
break;
}
@@ -722,7 +712,7 @@ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event,
if (ambiguous)
continue;
- result += (qtKey + int(mods));
+ result += QKeyCombination::fromCombined(qtKey + int(mods));
}
}
@@ -749,18 +739,20 @@ void QXkbCommon::verifyHasLatinLayout(xkb_keymap *keymap)
// This means that lookupLatinKeysym() will not find anything and latin
// key shortcuts might not work. This is a bug in the affected desktop
// environment. Usually can be solved via system settings by adding e.g. 'us'
- // layout to the list of seleced layouts, or by using command line, "setxkbmap
+ // layout to the list of selected layouts, or by using command line, "setxkbmap
// -layout rus,en". The position of latin key based layout in the list of the
// selected layouts is irrelevant. Properly functioning desktop environments
// handle this behind the scenes, even if no latin key based layout has been
// explicitly listed in the selected layouts.
- qCDebug(lcXkbcommon, "no keyboard layouts with latin keys present");
+ qCDebug(lcQpaKeyMapper, "no keyboard layouts with latin keys present");
}
xkb_keysym_t QXkbCommon::lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode)
{
xkb_layout_index_t layout;
xkb_keysym_t sym = XKB_KEY_NoSymbol;
+ if (!state)
+ return sym;
xkb_keymap *keymap = xkb_state_get_keymap(state);
const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(keymap, keycode);
const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(state, keycode);
@@ -818,7 +810,7 @@ void QXkbCommon::setXkbContext(QPlatformInputContext *inputContext, struct xkb_c
const char *const inputContextClassName = "QComposeInputContext";
const char *const normalizedSignature = "setXkbContext(xkb_context*)";
- if (inputContext->objectName() != QLatin1String(inputContextClassName))
+ if (inputContext->objectName() != QLatin1StringView(inputContextClassName))
return;
static const QMetaMethod setXkbContext = [&]() {
@@ -826,7 +818,7 @@ void QXkbCommon::setXkbContext(QPlatformInputContext *inputContext, struct xkb_c
QMetaMethod method = inputContext->metaObject()->method(methodIndex);
Q_ASSERT(method.isValid());
if (!method.isValid())
- qCWarning(lcXkbcommon) << normalizedSignature << "not found on" << inputContextClassName;
+ qCWarning(lcQpaKeyMapper) << normalizedSignature << "not found on" << inputContextClassName;
return method;
}();
diff --git a/src/gui/platform/unix/qxkbcommon_3rdparty.cpp b/src/gui/platform/unix/qxkbcommon_3rdparty.cpp
index c5062cc8d9..207c103235 100644
--- a/src/gui/platform/unix/qxkbcommon_3rdparty.cpp
+++ b/src/gui/platform/unix/qxkbcommon_3rdparty.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/* Copyright 1985, 1987, 1990, 1998 The Open Group
diff --git a/src/gui/platform/unix/qxkbcommon_p.h b/src/gui/platform/unix/qxkbcommon_p.h
index 197268dbc1..a40d794451 100644
--- a/src/gui/platform/unix/qxkbcommon_p.h
+++ b/src/gui/platform/unix/qxkbcommon_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXKBCOMMON_P_H
#define QXKBCOMMON_P_H
@@ -55,15 +19,16 @@
#include <QtCore/qstring.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/qlist.h>
+#include <QtCore/private/qglobal_p.h>
#include <xkbcommon/xkbcommon.h>
+#include <qpa/qplatformkeymapper.h>
+
#include <memory>
QT_BEGIN_NAMESPACE
-Q_DECLARE_LOGGING_CATEGORY(lcXkbcommon)
-
class QEvent;
class QKeyEvent;
class QPlatformInputContext;
@@ -79,26 +44,67 @@ public:
static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers);
static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
xkb_state *state, xkb_keycode_t code,
- bool superAsMeta = false, bool hyperAsMeta = false);
+ bool superAsMeta = true, bool hyperAsMeta = true);
// xkbcommon_* API is part of libxkbcommon internals, with modifications as
- // desribed in the header of the implementation file.
+ // described in the header of the implementation file.
static void xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper);
static xkb_keysym_t qxkbcommon_xkb_keysym_to_upper(xkb_keysym_t ks);
- static Qt::KeyboardModifiers modifiers(struct xkb_state *state);
+ static Qt::KeyboardModifiers modifiers(struct xkb_state *state, xkb_keysym_t keysym = XKB_KEY_VoidSymbol);
- static QList<int> possibleKeys(xkb_state *state, const QKeyEvent *event,
- bool superAsMeta = false, bool hyperAsMeta = false);
+ static QList<int> possibleKeys(xkb_state *state,
+ const QKeyEvent *event, bool superAsMeta = false, bool hyperAsMeta = false);
+ static QList<QKeyCombination> possibleKeyCombinations(xkb_state *state,
+ const QKeyEvent *event, bool superAsMeta = false, bool hyperAsMeta = false);
static void verifyHasLatinLayout(xkb_keymap *keymap);
static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode);
static bool isLatin1(xkb_keysym_t sym) {
- return sym <= 0xff;
+ return sym >= 0x20 && sym <= 0xff;
}
static bool isKeypad(xkb_keysym_t sym) {
- return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9;
+ switch (sym) {
+ case XKB_KEY_KP_Space:
+ case XKB_KEY_KP_Tab:
+ case XKB_KEY_KP_Enter:
+ case XKB_KEY_KP_F1:
+ case XKB_KEY_KP_F2:
+ case XKB_KEY_KP_F3:
+ case XKB_KEY_KP_F4:
+ case XKB_KEY_KP_Home:
+ case XKB_KEY_KP_Left:
+ case XKB_KEY_KP_Up:
+ case XKB_KEY_KP_Right:
+ case XKB_KEY_KP_Down:
+ case XKB_KEY_KP_Prior:
+ case XKB_KEY_KP_Next:
+ case XKB_KEY_KP_End:
+ case XKB_KEY_KP_Begin:
+ case XKB_KEY_KP_Insert:
+ case XKB_KEY_KP_Delete:
+ case XKB_KEY_KP_Equal:
+ case XKB_KEY_KP_Multiply:
+ case XKB_KEY_KP_Add:
+ case XKB_KEY_KP_Separator:
+ case XKB_KEY_KP_Subtract:
+ case XKB_KEY_KP_Decimal:
+ case XKB_KEY_KP_Divide:
+ case XKB_KEY_KP_0:
+ case XKB_KEY_KP_1:
+ case XKB_KEY_KP_2:
+ case XKB_KEY_KP_3:
+ case XKB_KEY_KP_4:
+ case XKB_KEY_KP_5:
+ case XKB_KEY_KP_6:
+ case XKB_KEY_KP_7:
+ case XKB_KEY_KP_8:
+ case XKB_KEY_KP_9:
+ return true;
+ default:
+ return false;
+ }
}
static void setXkbContext(QPlatformInputContext *inputContext, struct xkb_context *context);
diff --git a/src/gui/platform/wasm/qlocalfileapi.cpp b/src/gui/platform/wasm/qlocalfileapi.cpp
new file mode 100644
index 0000000000..76b99361c4
--- /dev/null
+++ b/src/gui/platform/wasm/qlocalfileapi.cpp
@@ -0,0 +1,211 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qlocalfileapi_p.h"
+#include <private/qstdweb_p.h>
+#include <QtCore/QRegularExpression>
+
+QT_BEGIN_NAMESPACE
+namespace LocalFileApi {
+namespace {
+std::string qtFilterListToFileInputAccept(const QStringList &filterList)
+{
+ QStringList transformed;
+ for (const auto &filter : filterList) {
+ const auto type = Type::fromQt(filter);
+ if (type && type->accept()) {
+ const auto &extensions = type->accept()->mimeType().extensions();
+ std::transform(extensions.begin(), extensions.end(), std::back_inserter(transformed),
+ [](const Type::Accept::MimeType::Extension &extension) {
+ return extension.value().toString();
+ });
+ }
+ }
+ return transformed.join(QStringLiteral(",")).toStdString();
+}
+
+std::optional<emscripten::val> qtFilterListToTypes(const QStringList &filterList)
+{
+ using namespace qstdweb;
+ using namespace emscripten;
+ auto types = emscripten::val::array();
+
+ for (const auto &fileFilter : filterList) {
+ auto type = Type::fromQt(fileFilter);
+ if (type) {
+ auto jsType = emscripten::val::object();
+ jsType.set("description", type->description().toString().toStdString());
+ if (type->accept()) {
+ jsType.set("accept", ([&mimeType = type->accept()->mimeType()]() {
+ val acceptDict = val::object();
+
+ QList<emscripten::val> extensions;
+ extensions.reserve(mimeType.extensions().size());
+ std::transform(
+ mimeType.extensions().begin(), mimeType.extensions().end(),
+ std::back_inserter(extensions),
+ [](const Type::Accept::MimeType::Extension &extension) {
+ return val(extension.value().toString().toStdString());
+ });
+ acceptDict.set("application/octet-stream",
+ emscripten::val::array(extensions.begin(),
+ extensions.end()));
+ return acceptDict;
+ })());
+ }
+ types.call<void>("push", std::move(jsType));
+ }
+ }
+
+ return types["length"].as<int>() == 0 ? std::optional<emscripten::val>() : types;
+}
+} // namespace
+
+Type::Type(QStringView description, std::optional<Accept> accept)
+ : m_description(description.trimmed()), m_accept(std::move(accept))
+{
+}
+
+Type::~Type() = default;
+
+std::optional<Type> Type::fromQt(QStringView type)
+{
+ using namespace emscripten;
+
+ // Accepts either a string in format:
+ // GROUP3
+ // or in this format:
+ // GROUP1 (GROUP2)
+ // Group 1 is treated as the description, whereas group 2 or 3 are treated as the filter list.
+ static QRegularExpression regex(
+ QString(QStringLiteral("(?:(?:([^(]*)\\(([^()]+)\\)[^)]*)|([^()]+))")));
+ const auto match = regex.matchView(type);
+
+ if (!match.hasMatch())
+ return std::nullopt;
+
+ constexpr size_t DescriptionIndex = 1;
+ constexpr size_t FilterListFromParensIndex = 2;
+ constexpr size_t PlainFilterListIndex = 3;
+
+ const auto description = match.hasCaptured(DescriptionIndex)
+ ? match.capturedView(DescriptionIndex)
+ : QStringView();
+ const auto filterList = match.capturedView(match.hasCaptured(FilterListFromParensIndex)
+ ? FilterListFromParensIndex
+ : PlainFilterListIndex);
+
+ auto accept = Type::Accept::fromQt(filterList);
+ if (!accept)
+ return std::nullopt;
+
+ return Type(description, std::move(*accept));
+}
+
+Type::Accept::Accept() = default;
+
+Type::Accept::~Accept() = default;
+
+std::optional<Type::Accept> Type::Accept::fromQt(QStringView qtRepresentation)
+{
+ Accept accept;
+
+ // Used for accepting multiple extension specifications on a filter list.
+ // The next group of non-empty characters.
+ static QRegularExpression internalRegex(QString(QStringLiteral("([^\\s]+)\\s*")));
+ int offset = 0;
+ auto internalMatch = internalRegex.matchView(qtRepresentation, offset);
+ MimeType mimeType;
+
+ while (internalMatch.hasMatch()) {
+ auto webExtension = MimeType::Extension::fromQt(internalMatch.capturedView(1));
+
+ if (!webExtension)
+ return std::nullopt;
+
+ mimeType.addExtension(*webExtension);
+
+ internalMatch = internalRegex.matchView(qtRepresentation, internalMatch.capturedEnd());
+ }
+
+ accept.setMimeType(mimeType);
+ return accept;
+}
+
+void Type::Accept::setMimeType(MimeType mimeType)
+{
+ m_mimeType = std::move(mimeType);
+}
+
+Type::Accept::MimeType::MimeType() = default;
+
+Type::Accept::MimeType::~MimeType() = default;
+
+void Type::Accept::MimeType::addExtension(Extension extension)
+{
+ m_extensions.push_back(std::move(extension));
+}
+
+Type::Accept::MimeType::Extension::Extension(QStringView extension) : m_value(extension) { }
+
+Type::Accept::MimeType::Extension::~Extension() = default;
+
+std::optional<Type::Accept::MimeType::Extension>
+Type::Accept::MimeType::Extension::fromQt(QStringView qtRepresentation)
+{
+ // Checks for a filter that matches everything:
+ // Any number of asterisks or any number of asterisks with a '.' between them.
+ // The web filter does not support wildcards.
+ static QRegularExpression qtAcceptAllRegex(
+ QRegularExpression::anchoredPattern(QString(QStringLiteral("[*]+|[*]+\\.[*]+"))));
+ if (qtAcceptAllRegex.matchView(qtRepresentation).hasMatch())
+ return std::nullopt;
+
+ // Checks for correctness. The web filter only allows filename extensions and does not filter
+ // the actual filenames, therefore we check whether the filter provided only filters for the
+ // extension.
+ static QRegularExpression qtFilenameMatcherRegex(
+ QRegularExpression::anchoredPattern(QString(QStringLiteral("(\\*?)(\\.[^*]+)"))));
+
+ auto extensionMatch = qtFilenameMatcherRegex.matchView(qtRepresentation);
+ if (extensionMatch.hasMatch())
+ return Extension(extensionMatch.capturedView(2));
+
+ // Mapping impossible.
+ return std::nullopt;
+}
+
+emscripten::val makeOpenFileOptions(const QStringList &filterList, bool acceptMultiple)
+{
+ auto options = emscripten::val::object();
+ if (auto typeList = qtFilterListToTypes(filterList); typeList) {
+ options.set("types", std::move(*typeList));
+ options.set("excludeAcceptAllOption", true);
+ }
+
+ options.set("multiple", acceptMultiple);
+
+ return options;
+}
+
+emscripten::val makeSaveFileOptions(const QStringList &filterList, const std::string& suggestedName)
+{
+ auto options = emscripten::val::object();
+
+ if (!suggestedName.empty())
+ options.set("suggestedName", emscripten::val(suggestedName));
+
+ if (auto typeList = qtFilterListToTypes(filterList))
+ options.set("types", emscripten::val(std::move(*typeList)));
+
+ return options;
+}
+
+std::string makeFileInputAccept(const QStringList &filterList)
+{
+ return qtFilterListToFileInputAccept(filterList);
+}
+
+} // namespace LocalFileApi
+
+QT_END_NAMESPACE
diff --git a/src/gui/platform/wasm/qlocalfileapi_p.h b/src/gui/platform/wasm/qlocalfileapi_p.h
new file mode 100644
index 0000000000..1398d674d8
--- /dev/null
+++ b/src/gui/platform/wasm/qlocalfileapi_p.h
@@ -0,0 +1,94 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QLOCALFILEAPI_P_H
+#define QLOCALFILEAPI_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qglobal_p.h>
+#include <qstringview.h>
+#include <emscripten/val.h>
+#include <cstdint>
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+namespace LocalFileApi {
+class Q_AUTOTEST_EXPORT Type
+{
+public:
+ class Accept {
+ public:
+ class MimeType {
+ public:
+ class Extension {
+ public:
+ static std::optional<Extension> fromQt(QStringView extension);
+
+ ~Extension();
+
+ const QStringView &value() const { return m_value; }
+
+ private:
+ explicit Extension(QStringView extension);
+
+ QStringView m_value;
+ };
+
+ MimeType();
+ ~MimeType();
+
+ void addExtension(Extension type);
+
+ const std::vector<Extension> &extensions() const { return m_extensions; }
+
+ private:
+ std::vector<Extension> m_extensions;
+ };
+
+ static std::optional<Accept> fromQt(QStringView type);
+
+ ~Accept();
+
+ void setMimeType(MimeType mimeType);
+
+ const MimeType &mimeType() const { return m_mimeType; }
+
+ private:
+ Accept();
+ MimeType m_mimeType;
+ };
+
+ Type(QStringView description, std::optional<Accept> accept);
+ ~Type();
+
+ static std::optional<Type> fromQt(QStringView type);
+ const QStringView &description() const { return m_description; }
+ const std::optional<Accept> &accept() const { return m_accept; }
+
+private:
+ QStringView m_description;
+ std::optional<Accept> m_accept;
+};
+
+Q_AUTOTEST_EXPORT emscripten::val makeOpenFileOptions(const QStringList &filterList,
+ bool acceptMultiple);
+Q_AUTOTEST_EXPORT emscripten::val makeSaveFileOptions(const QStringList &filterList,
+ const std::string &suggestedName);
+
+Q_AUTOTEST_EXPORT std::string makeFileInputAccept(const QStringList &filterList);
+
+} // namespace LocalFileApi
+QT_END_NAMESPACE
+
+#endif // QLOCALFILEAPI_P_H
diff --git a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
index 85c894a74a..a946cda043 100644
--- a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
+++ b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
@@ -1,94 +1,111 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwasmlocalfileaccess_p.h"
+#include "qlocalfileapi_p.h"
#include <private/qstdweb_p.h>
#include <emscripten.h>
#include <emscripten/bind.h>
#include <emscripten/html5.h>
#include <emscripten/val.h>
+#include <QtCore/qregularexpression.h>
+
QT_BEGIN_NAMESPACE
namespace QWasmLocalFileAccess {
+namespace FileDialog {
+namespace {
+bool hasLocalFilesApi()
+{
+ return !qstdweb::window()["showOpenFilePicker"].isUndefined();
+}
-void streamFile(const qstdweb::File &file, uint32_t offset, uint32_t length, char *buffer, const std::function<void ()> &completed)
+void showOpenViaHTMLPolyfill(const QStringList &accept, FileSelectMode fileSelectMode,
+ qstdweb::PromiseCallbacks onFilesSelected)
{
- // Read file in chunks in order to avoid holding two copies in memory at the same time
- const uint32_t chunkSize = 256 * 1024;
- const uint32_t end = offset + length;
- // assert end < file.size
- auto fileReader = std::make_shared<qstdweb::FileReader>();
-
- auto chunkCompleted = std::make_shared<std::function<void (uint32_t, char *buffer)>>();
- *chunkCompleted = [=](uint32_t chunkBegin, char *chunkBuffer) mutable {
-
- // Copy current chunk from JS memory to Wasm memory
- qstdweb::ArrayBuffer result = fileReader->result();
- qstdweb::Uint8Array(result).copyTo(chunkBuffer);
-
- // Read next chunk if not at buffer end
- uint32_t nextChunkBegin = std::min(chunkBegin + result.byteLength(), end);
- uint32_t nextChunkEnd = std::min(nextChunkBegin + chunkSize, end);
- if (nextChunkBegin == end) {
- completed();
- chunkCompleted.reset();
- return;
- }
- char *nextChunkBuffer = chunkBuffer + result.byteLength();
- fileReader->onLoad([=]() { (*chunkCompleted)(nextChunkBegin, nextChunkBuffer); });
- qstdweb::Blob blob = file.slice(nextChunkBegin, nextChunkEnd);
- fileReader->readAsArrayBuffer(blob);
- };
+ // Create file input html element which will display a native file dialog
+ // and call back to our onchange handler once the user has selected
+ // one or more files.
+ emscripten::val document = emscripten::val::global("document");
+ emscripten::val input = document.call<emscripten::val>("createElement", std::string("input"));
+ input.set("type", "file");
+ input.set("style", "display:none");
+ input.set("accept", LocalFileApi::makeFileInputAccept(accept));
+ Q_UNUSED(accept);
+ input.set("multiple", emscripten::val(fileSelectMode == FileSelectMode::MultipleFiles));
+
+ // Note: there is no event in case the user cancels the file dialog.
+ static std::unique_ptr<qstdweb::EventCallback> changeEvent;
+ auto callback = [=](emscripten::val) { onFilesSelected.thenFunc(input["files"]); };
+ changeEvent = std::make_unique<qstdweb::EventCallback>(input, "change", callback);
+
+ // Activate file input
+ emscripten::val body = document["body"];
+ body.call<void>("appendChild", input);
+ input.call<void>("click");
+ body.call<void>("removeChild", input);
+}
+
+void showOpenViaLocalFileApi(const QStringList &accept, FileSelectMode fileSelectMode,
+ qstdweb::PromiseCallbacks callbacks)
+{
+ using namespace qstdweb;
+
+ auto options = LocalFileApi::makeOpenFileOptions(accept, fileSelectMode == FileSelectMode::MultipleFiles);
+
+ Promise::make(
+ window(), QStringLiteral("showOpenFilePicker"),
+ {
+ .thenFunc = [=](emscripten::val fileHandles) mutable {
+ std::vector<emscripten::val> filePromises;
+ filePromises.reserve(fileHandles["length"].as<int>());
+ for (int i = 0; i < fileHandles["length"].as<int>(); ++i)
+ filePromises.push_back(fileHandles[i].call<emscripten::val>("getFile"));
+ Promise::all(std::move(filePromises), callbacks);
+ },
+ .catchFunc = callbacks.catchFunc,
+ .finallyFunc = callbacks.finallyFunc,
+ }, std::move(options));
+}
+
+void showSaveViaLocalFileApi(const std::string &fileNameHint, qstdweb::PromiseCallbacks callbacks)
+{
+ using namespace qstdweb;
+ using namespace emscripten;
+
+ auto options = LocalFileApi::makeSaveFileOptions(QStringList(), fileNameHint);
+
+ Promise::make(
+ window(), QStringLiteral("showSaveFilePicker"),
+ std::move(callbacks), std::move(options));
+}
+} // namespace
- // Read first chunk. First iteration is a dummy iteration with no available data.
- (*chunkCompleted)(offset, buffer);
+void showOpen(const QStringList &accept, FileSelectMode fileSelectMode,
+ qstdweb::PromiseCallbacks callbacks)
+{
+ hasLocalFilesApi() ?
+ showOpenViaLocalFileApi(accept, fileSelectMode, std::move(callbacks)) :
+ showOpenViaHTMLPolyfill(accept, fileSelectMode, std::move(callbacks));
+}
+
+bool canShowSave()
+{
+ return hasLocalFilesApi();
}
-void streamFile(const qstdweb::File &file, char *buffer, const std::function<void ()> &completed)
+void showSave(const std::string &fileNameHint, qstdweb::PromiseCallbacks callbacks)
{
- streamFile(file, 0, file.size(), buffer, completed);
+ Q_ASSERT(canShowSave());
+ showSaveViaLocalFileApi(fileNameHint, std::move(callbacks));
}
+} // namespace FileDialog
+namespace {
void readFiles(const qstdweb::FileList &fileList,
- const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
- const std::function<void ()> &fileDataReady)
+ const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
+ const std::function<void ()> &fileDataReady)
{
auto readFile = std::make_shared<std::function<void(int)>>();
@@ -99,7 +116,7 @@ void readFiles(const qstdweb::FileList &fileList,
return;
}
- const qstdweb::File file = fileList[fileIndex];
+ const qstdweb::File file = qstdweb::File(fileList[fileIndex]);
// Ask caller if the file should be accepted
char *buffer = acceptFile(file.size(), file.name());
@@ -109,7 +126,7 @@ void readFiles(const qstdweb::FileList &fileList,
}
// Read file data into caller-provided buffer
- streamFile(file, buffer, [=]() {
+ file.stream(buffer, [readFile = readFile.get(), fileIndex, fileDataReady]() {
fileDataReady();
(*readFile)(fileIndex + 1);
});
@@ -118,87 +135,153 @@ void readFiles(const qstdweb::FileList &fileList,
(*readFile)(0);
}
-typedef std::function<void (const qstdweb::FileList &fileList)> OpenFileDialogCallback;
-void openFileDialog(const std::string &accept, FileSelectMode fileSelectMode,
- const OpenFileDialogCallback &filesSelected)
+QStringList makeFilterList(const std::string &qtAcceptList)
{
- // Create file input html element which will display a native file dialog
- // and call back to our onchange handler once the user has selected
- // one or more files.
- emscripten::val document = emscripten::val::global("document");
- emscripten::val input = document.call<emscripten::val>("createElement", std::string("input"));
- input.set("type", "file");
- input.set("style", "display:none");
- input.set("accept", emscripten::val(accept));
- input.set("multiple", emscripten::val(fileSelectMode == MultipleFiles));
+ // copy of qt_make_filter_list() from qfiledialog.cpp
+ auto filter = QString::fromStdString(qtAcceptList);
+ if (filter.isEmpty())
+ return QStringList();
+ QString sep(";;");
+ if (!filter.contains(sep) && filter.contains(u'\n'))
+ sep = u'\n';
- // Note: there is no event in case the user cancels the file dialog.
- static std::unique_ptr<qstdweb::EventCallback> changeEvent;
- auto callback = [=]() { filesSelected(qstdweb::FileList(input["files"])); };
- changeEvent.reset(new qstdweb::EventCallback(input, "change", callback));
+ return filter.split(sep);
+}
+}
+
+void downloadDataAsFile(const char *content, size_t size, const std::string &fileNameHint)
+{
+ // Save a file by creating programmatically clicking a download
+ // link to an object url to a Blob containing a copy of the file
+ // content. The copy is made so that the passed in content buffer
+ // can be released as soon as this function returns.
+ qstdweb::Blob contentBlob = qstdweb::Blob::copyFrom(content, size);
+ emscripten::val document = emscripten::val::global("document");
+ emscripten::val window = qstdweb::window();
+ emscripten::val contentUrl = window["URL"].call<emscripten::val>("createObjectURL", contentBlob.val());
+ emscripten::val contentLink = document.call<emscripten::val>("createElement", std::string("a"));
+ contentLink.set("href", contentUrl);
+ contentLink.set("download", fileNameHint);
+ contentLink.set("style", "display:none");
- // Activate file input
emscripten::val body = document["body"];
- body.call<void>("appendChild", input);
- input.call<void>("click");
- body.call<void>("removeChild", input);
+ body.call<void>("appendChild", contentLink);
+ contentLink.call<void>("click");
+ body.call<void>("removeChild", contentLink);
+
+ window["URL"].call<emscripten::val>("revokeObjectURL", contentUrl);
}
void openFiles(const std::string &accept, FileSelectMode fileSelectMode,
const std::function<void (int fileCount)> &fileDialogClosed,
- const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
+ const std::function<char *(uint64_t size, const std::string& name)> &acceptFile,
const std::function<void()> &fileDataReady)
{
- openFileDialog(accept, fileSelectMode, [=](const qstdweb::FileList &files) {
- fileDialogClosed(files.length());
- readFiles(files, acceptFile, fileDataReady);
+ FileDialog::showOpen(makeFilterList(accept), fileSelectMode, {
+ .thenFunc = [=](emscripten::val result) {
+ auto files = qstdweb::FileList(result);
+ fileDialogClosed(files.length());
+ readFiles(files, acceptFile, fileDataReady);
+ },
+ .catchFunc = [=](emscripten::val) {
+ fileDialogClosed(0);
+ }
});
}
void openFile(const std::string &accept,
const std::function<void (bool fileSelected)> &fileDialogClosed,
- const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
+ const std::function<char *(uint64_t size, const std::string& name)> &acceptFile,
const std::function<void()> &fileDataReady)
{
auto fileDialogClosedWithInt = [=](int fileCount) { fileDialogClosed(fileCount != 0); };
openFiles(accept, FileSelectMode::SingleFile, fileDialogClosedWithInt, acceptFile, fileDataReady);
}
-void saveFile(const char *content, size_t size, const std::string &fileNameHint)
+void saveDataToFileInChunks(emscripten::val fileHandle, const QByteArray &data)
{
- // Save a file by creating programatically clicking a download
- // link to an object url to a Blob containing the file content.
- // File content is copied once, so that the passed in content
- // buffer can be released as soon as this function returns - we
- // don't know for how long the browser will retain the TypedArray
- // view used to create the Blob.
+ using namespace emscripten;
+ using namespace qstdweb;
- emscripten::val document = emscripten::val::global("document");
- emscripten::val window = emscripten::val::global("window");
+ Promise::make(fileHandle, QStringLiteral("createWritable"), {
+ .thenFunc = [=](val writable) {
+ struct State {
+ size_t written;
+ std::function<void(val result)> continuation;
+ };
- emscripten::val fileContentView = emscripten::val(emscripten::typed_memory_view(size, content));
- emscripten::val fileContentCopy = emscripten::val::global("ArrayBuffer").new_(size);
- emscripten::val fileContentCopyView = emscripten::val::global("Uint8Array").new_(fileContentCopy);
- fileContentCopyView.call<void>("set", fileContentView);
+ static constexpr size_t desiredChunkSize = 1024u;
+#if defined(__EMSCRIPTEN_SHARED_MEMORY__)
+ qstdweb::Uint8Array chunkArray(desiredChunkSize);
+#endif
- emscripten::val contentArray = emscripten::val::array();
- contentArray.call<void>("push", fileContentCopyView);
- emscripten::val type = emscripten::val::object();
- type.set("type","application/octet-stream");
- emscripten::val contentBlob = emscripten::val::global("Blob").new_(contentArray, type);
+ auto state = std::make_shared<State>();
+ state->written = 0u;
+ state->continuation = [=](val) mutable {
+ const size_t remaining = data.size() - state->written;
+ if (remaining == 0) {
+ Promise::make(writable, QStringLiteral("close"), { .thenFunc = [=](val) {} });
+ state.reset();
+ return;
+ }
- emscripten::val contentUrl = window["URL"].call<emscripten::val>("createObjectURL", contentBlob);
- emscripten::val contentLink = document.call<emscripten::val>("createElement", std::string("a"));
- contentLink.set("href", contentUrl);
- contentLink.set("download", fileNameHint);
- contentLink.set("style", "display:none");
+ const auto currentChunkSize = std::min(remaining, desiredChunkSize);
- emscripten::val body = document["body"];
- body.call<void>("appendChild", contentLink);
- contentLink.call<void>("click");
- body.call<void>("removeChild", contentLink);
+#if defined(__EMSCRIPTEN_SHARED_MEMORY__)
+ // If shared memory is used, WebAssembly.Memory is instantiated with the 'shared'
+ // option on. Passing a typed_memory_view to SharedArrayBuffer to
+ // FileSystemWritableFileStream.write is disallowed by security policies, so we
+ // need to make a copy of the data to a chunk array buffer.
+ Promise::make(
+ writable, QStringLiteral("write"),
+ {
+ .thenFunc = state->continuation,
+ },
+ chunkArray.copyFrom(data.constData() + state->written, currentChunkSize)
+ .val()
+ .call<emscripten::val>("subarray", emscripten::val(0),
+ emscripten::val(currentChunkSize)));
+#else
+ Promise::make(writable, QStringLiteral("write"),
+ {
+ .thenFunc = state->continuation,
+ },
+ val(typed_memory_view(currentChunkSize, data.constData() + state->written)));
+#endif
+ state->written += currentChunkSize;
+ };
- window["URL"].call<emscripten::val>("revokeObjectURL", contentUrl);
+ state->continuation(val::undefined());
+ },
+ });
+}
+
+void saveFile(const QByteArray &data, const std::string &fileNameHint)
+{
+ if (!FileDialog::canShowSave()) {
+ downloadDataAsFile(data.constData(), data.size(), fileNameHint);
+ return;
+ }
+
+ FileDialog::showSave(fileNameHint, {
+ .thenFunc = [=](emscripten::val result) {
+ saveDataToFileInChunks(result, data);
+ },
+ });
+}
+
+void saveFile(const char *content, size_t size, const std::string &fileNameHint)
+{
+ if (!FileDialog::canShowSave()) {
+ downloadDataAsFile(content, size, fileNameHint);
+ return;
+ }
+
+ FileDialog::showSave(fileNameHint, {
+ .thenFunc = [=](emscripten::val result) {
+ saveDataToFileInChunks(result, QByteArray(content, size));
+ },
+ });
}
} // namespace QWasmLocalFileAccess
diff --git a/src/gui/platform/wasm/qwasmlocalfileaccess_p.h b/src/gui/platform/wasm/qwasmlocalfileaccess_p.h
index ccd88570c8..77b14577f7 100644
--- a/src/gui/platform/wasm/qwasmlocalfileaccess_p.h
+++ b/src/gui/platform/wasm/qwasmlocalfileaccess_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWASMLOCALFILEACCESS_P_H
#define QWASMLOCALFILEACCESS_P_H
@@ -51,7 +15,7 @@
// We mean it.
//
-#include <qglobal.h>
+#include <private/qglobal_p.h>
#include <cstdint>
#include <functional>
@@ -59,19 +23,20 @@ QT_BEGIN_NAMESPACE
namespace QWasmLocalFileAccess {
-enum FileSelectMode { SingleFile, MultipleFiles };
+enum class FileSelectMode { SingleFile, MultipleFiles };
-void openFiles(const std::string &accept, FileSelectMode fileSelectMode,
+Q_CORE_EXPORT void openFiles(const std::string &accept, FileSelectMode fileSelectMode,
const std::function<void (int fileCount)> &fileDialogClosed,
- const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
+ const std::function<char *(uint64_t size, const std::string& name)> &acceptFile,
const std::function<void()> &fileDataReady);
-void openFile(const std::string &accept,
+Q_CORE_EXPORT void openFile(const std::string &accept,
const std::function<void (bool fileSelected)> &fileDialogClosed,
- const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
+ const std::function<char *(uint64_t size, const std::string& name)> &acceptFile,
const std::function<void()> &fileDataReady);
-void saveFile(const char *content, size_t size, const std::string &fileNameHint);
+Q_CORE_EXPORT void saveFile(const QByteArray &data, const std::string &fileNameHint);
+Q_CORE_EXPORT void saveFile(const char *content, size_t size, const std::string &fileNameHint);
} // namespace QWasmLocalFileAccess
diff --git a/src/gui/platform/wasm/qwasmnativeinterface.cpp b/src/gui/platform/wasm/qwasmnativeinterface.cpp
new file mode 100644
index 0000000000..7313629a8d
--- /dev/null
+++ b/src/gui/platform/wasm/qwasmnativeinterface.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+
+
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformwindow_p.h>
+
+
+QT_BEGIN_NAMESPACE
+
+using namespace QNativeInterface::Private;
+
+QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QWasmWindow);
+
+QT_END_NAMESPACE
diff --git a/src/gui/platform/windows/qwindowsguieventdispatcher.cpp b/src/gui/platform/windows/qwindowsguieventdispatcher.cpp
index 999e119681..c2f0efe96e 100644
--- a/src/gui/platform/windows/qwindowsguieventdispatcher.cpp
+++ b/src/gui/platform/windows/qwindowsguieventdispatcher.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsguieventdispatcher_p.h"
@@ -209,6 +173,12 @@ messageDebugEntries[] = {
{WM_POINTERROUTEDAWAY, "WM_POINTERROUTEDAWAY", true},
{WM_POINTERROUTEDRELEASED, "WM_POINTERROUTEDRELEASED", true},
#endif // WM_POINTERROUTEDTO
+#ifdef WM_GETDPISCALEDSIZE
+ {WM_GETDPISCALEDSIZE, "WM_GETDPISCALEDSIZE", true},
+#endif
+#ifdef WM_DPICHANGED
+ {WM_DPICHANGED, "WM_DPICHANGED", true},
+#endif
};
static inline const MessageDebugEntry *messageDebugEntry(UINT msg)
@@ -227,3 +197,5 @@ const char *QWindowsGuiEventDispatcher::windowsMessageName(UINT msg)
}
QT_END_NAMESPACE
+
+#include "moc_qwindowsguieventdispatcher_p.cpp"
diff --git a/src/gui/platform/windows/qwindowsguieventdispatcher_p.h b/src/gui/platform/windows/qwindowsguieventdispatcher_p.h
index 804c7e936d..7d326c0780 100644
--- a/src/gui/platform/windows/qwindowsguieventdispatcher_p.h
+++ b/src/gui/platform/windows/qwindowsguieventdispatcher_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSGUIEVENTDISPATCHER_H
#define QWINDOWSGUIEVENTDISPATCHER_H
diff --git a/src/gui/platform/windows/qwindowsmime_p.h b/src/gui/platform/windows/qwindowsmime_p.h
deleted file mode 100644
index 71b1c8a87f..0000000000
--- a/src/gui/platform/windows/qwindowsmime_p.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QWINDOWSMIME_P_H
-#define QWINDOWSMIME_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qt_windows.h>
-#include <QtCore/qvariant.h>
-
-#include <QtGui/qtguiglobal.h>
-
-QT_BEGIN_NAMESPACE
-
-class QMimeData;
-
-namespace QNativeInterface::Private {
-
-class Q_GUI_EXPORT QWindowsMime
-{
-public:
- virtual ~QWindowsMime() = default;
-
- // for converting from Qt
- virtual bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const = 0;
- virtual bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const = 0;
- virtual QList<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const = 0;
-
- // for converting to Qt
- virtual bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const = 0;
- virtual QVariant convertToMime(const QString &mimeType, IDataObject *pDataObj, QMetaType preferredType) const = 0;
- virtual QString mimeForFormat(const FORMATETC &formatetc) const = 0;
-};
-
-} // QNativeInterface::Private
-
-QT_END_NAMESPACE
-
-#endif // QWINDOWSMIME_P_H
diff --git a/src/gui/platform/windows/qwindowsmimeconverter.cpp b/src/gui/platform/windows/qwindowsmimeconverter.cpp
new file mode 100644
index 0000000000..49d524cb99
--- /dev/null
+++ b/src/gui/platform/windows/qwindowsmimeconverter.cpp
@@ -0,0 +1,170 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwindowsmimeconverter.h"
+
+#include <QtCore/qt_windows.h>
+
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWindowsMimeConverter
+ \brief The QWindowsMimeConverter class maps open-standard MIME to Window Clipboard formats.
+ \inmodule QtGui
+
+ Qt's drag-and-drop and clipboard facilities use the MIME standard.
+ On X11, this maps trivially to the Xdnd protocol, but on Windows
+ although some applications use MIME types to describe clipboard
+ formats, others use arbitrary non-standardized naming conventions,
+ or unnamed built-in formats of Windows.
+
+ By instantiating subclasses of QWindowsMimeConverter that provide
+ conversions between Windows Clipboard and MIME formats, you can convert
+ proprietary clipboard formats to MIME formats.
+
+ Construct an instance of your converter implementation after instantiating
+ QGuiApplication:
+
+ \code
+ int main(int argc, char **argv)
+ {
+ QGuiApplication app(argc, argv);
+ JsonMimeConverter jsonConverter;
+ }
+ \endcode
+
+ Destroying the instance will unregister the converter and remove support
+ for the conversion. It is also valid to heap-allocate the converter
+ instance; Qt takes ownership and will delete the converter object during
+ QGuiApplication shut-down.
+
+ Qt has predefined support for the following Windows Clipboard formats:
+
+ \table
+ \header \li Windows Format \li Equivalent MIME type
+ \row \li \c CF_UNICODETEXT \li \c text/plain
+ \row \li \c CF_TEXT \li \c text/plain
+ \row \li \c CF_DIB \li \c{image/xyz}, where \c xyz is
+ a \l{QImageWriter::supportedImageFormats()}{Qt image format}
+ \row \li \c CF_HDROP \li \c text/uri-list
+ \row \li \c CF_INETURL \li \c text/uri-list
+ \row \li \c CF_HTML \li \c text/html
+ \endtable
+
+ An example use of this class would be to map the Windows Metafile
+ clipboard format (\c CF_METAFILEPICT) to and from the MIME type
+ \c{image/x-wmf}. This conversion might simply be adding or removing
+ a header, or even just passing on the data. See \l{Drag and Drop}
+ for more information on choosing and definition MIME types.
+
+ You can check if a MIME type is convertible using canConvertFromMime() and
+ can perform conversions with convertToMime() and convertFromMime().
+*/
+
+
+/*!
+ \fn bool QWindowsMimeConverter::canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const
+
+ Returns \c true if the converter can convert from the \a mimeData to
+ the format specified in \a formatetc.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn bool QWindowsMimeConverter::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const
+
+ Returns \c true if the converter can convert to the \a mimeType from
+ the available formats in \a pDataObj.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QString QWindowsMimeConverter::mimeForFormat(const FORMATETC &formatetc) const
+
+ Returns the mime type that will be created form the format specified
+ in \a formatetc, or an empty string if this converter does not support
+ \a formatetc.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QList<FORMATETC> QWindowsMimeConverter::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const
+
+ Returns a QList of FORMATETC structures representing the different windows clipboard
+ formats that can be provided for the \a mimeType from the \a mimeData.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn QVariant QWindowsMimeConverter::convertToMime(const QString &mimeType, IDataObject *pDataObj,
+ QMetaType preferredType) const
+
+ Returns a QVariant containing the converted data for \a mimeType from \a pDataObj.
+ If possible the QVariant should be of the \a preferredType to avoid needless conversions.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ \fn bool QWindowsMimeConverter::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
+
+ Convert the \a mimeData to the format specified in \a formatetc.
+ The converted data should then be placed in \a pmedium structure.
+
+ Return true if the conversion was successful.
+
+ All subclasses must reimplement this pure virtual function.
+*/
+
+/*!
+ Constructs a QWindowsMimeConverter instance.
+
+ The instance is automatically registered, and will be called to convert data during
+ clipboard or drag'n'drop operations.
+
+ Call this constructor after QGuiApplication has been created.
+*/
+QWindowsMimeConverter::QWindowsMimeConverter()
+{
+ using QWindowsApplication = QNativeInterface::Private::QWindowsApplication;
+ auto nativeWindowsApp = dynamic_cast<QWindowsApplication *>(QGuiApplicationPrivate::platformIntegration());
+ Q_ASSERT(nativeWindowsApp);
+ nativeWindowsApp->registerMime(this);
+}
+
+/*!
+ Constructs a QWindowsMimeConverter instance.
+
+ The instance is automatically unregistered.
+*/
+QWindowsMimeConverter::~QWindowsMimeConverter()
+{
+ using QWindowsApplication = QNativeInterface::Private::QWindowsApplication;
+ auto nativeWindowsApp = dynamic_cast<QWindowsApplication *>(QGuiApplicationPrivate::platformIntegration());
+ Q_ASSERT(nativeWindowsApp);
+ nativeWindowsApp->unregisterMime(this);
+}
+
+/*!
+ Registers the MIME type \a mimeType, and returns an ID number
+ identifying the format on Windows.
+
+ A mime type \c {application/x-qt-windows-mime;value="WindowsType"} will be
+ registered as the clipboard format for \c WindowsType.
+*/
+int QWindowsMimeConverter::registerMimeType(const QString &mimeType)
+{
+ using QWindowsApplication = QNativeInterface::Private::QWindowsApplication;
+ auto nativeWindowsApp = dynamic_cast<QWindowsApplication *>(QGuiApplicationPrivate::platformIntegration());
+ Q_ASSERT(nativeWindowsApp);
+ return nativeWindowsApp->registerMimeType(mimeType);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/platform/windows/qwindowsmimeconverter.h b/src/gui/platform/windows/qwindowsmimeconverter.h
new file mode 100644
index 0000000000..145355fe15
--- /dev/null
+++ b/src/gui/platform/windows/qwindowsmimeconverter.h
@@ -0,0 +1,43 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWINDOWSMIMECONVERTER_P_H
+#define QWINDOWSMIMECONVERTER_P_H
+
+#include <QtGui/qtguiglobal.h>
+
+struct tagFORMATETC;
+using FORMATETC = tagFORMATETC;
+struct tagSTGMEDIUM;
+using STGMEDIUM = tagSTGMEDIUM;
+struct IDataObject;
+
+QT_BEGIN_NAMESPACE
+
+class QMetaType;
+class QMimeData;
+class QVariant;
+
+class Q_GUI_EXPORT QWindowsMimeConverter
+{
+ Q_DISABLE_COPY(QWindowsMimeConverter)
+public:
+ QWindowsMimeConverter();
+ virtual ~QWindowsMimeConverter();
+
+ static int registerMimeType(const QString &mimeType);
+
+ // for converting from Qt
+ virtual bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const = 0;
+ virtual bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const = 0;
+ virtual QList<FORMATETC> formatsForMime(const QString &mimeType, const QMimeData *mimeData) const = 0;
+
+ // for converting to Qt
+ virtual bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const = 0;
+ virtual QVariant convertToMime(const QString &mimeType, IDataObject *pDataObj, QMetaType preferredType) const = 0;
+ virtual QString mimeForFormat(const FORMATETC &formatetc) const = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSMIMECONVERTER_H
diff --git a/src/gui/platform/windows/qwindowsnativeinterface.cpp b/src/gui/platform/windows/qwindowsnativeinterface.cpp
index 4a7d0fd2c9..7ebddb5b9d 100644
--- a/src/gui/platform/windows/qwindowsnativeinterface.cpp
+++ b/src/gui/platform/windows/qwindowsnativeinterface.cpp
@@ -1,49 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/qopenglcontext.h>
#include <QtGui/private/qguiapplication_p.h>
-#include <QtGui/private/qwindowsmime_p.h>
#include <qpa/qplatformopenglcontext.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformwindow.h>
#include <qpa/qplatformwindow_p.h>
+#include <qpa/qplatformscreen_p.h>
QT_BEGIN_NAMESPACE
@@ -60,6 +24,7 @@ using namespace QNativeInterface::Private;
Accessed through QOpenGLContext::nativeInterface().
\inmodule QtGui
+ \inheaderfile QOpenGLContext
\ingroup native-interfaces
\ingroup native-interfaces-qopenglcontext
*/
@@ -124,6 +89,21 @@ QOpenGLContext *QNativeInterface::QWGLContext::fromNative(HGLRC context, HWND wi
QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QWindowsApplication);
/*!
+ \class QNativeInterface::QWindowsScreen
+ \since 6.7
+ \brief Native interface to a screen.
+
+ Accessed through QScreen::nativeInterface().
+ \inmodule QtGui
+ \ingroup native-interfaces
+ \ingroup native-interfaces-qscreen
+*/
+/*!
+ * \fn HWMONITOR QNativeInterface::QWindowsScreen::handle() const;
+ * \return The underlying HWMONITOR of the screen.
+ */
+QT_DEFINE_NATIVE_INTERFACE(QWindowsScreen);
+/*!
\enum QNativeInterface::Private::QWindowsApplication::TouchWindowTouchType
This enum represents the supported TouchWindow touch flags for registerTouchWindow().
@@ -243,21 +223,21 @@ QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QWindowsApplication);
*/
/*!
- \fn bool QNativeInterface::Private::QWindowsApplication::registerMime(QWindowsMime *mime)
+ \fn bool QNativeInterface::Private::QWindowsApplication::registerMime(QWindowsMimeConverter *mime)
\internal
Registers the converter \a mime to the system.
- \sa QNativeInterface::Private::QWindowsMime, unregisterMime()
+ \sa QWindowsMimeConverter, unregisterMime()
*/
/*!
- \fn void QNativeInterface::Private::QWindowsApplication::unregisterMime(QWindowsMime *mime)
+ \fn void QNativeInterface::Private::QWindowsApplication::unregisterMime(QWindowsMimeConverter *mime)
\internal
Unregisters the converter \a mime from the system.
- \sa QNativeInterface::Private::QWindowsMime, registerMime()
+ \sa QWindowsMimeConverter, registerMime()
*/
/*!
diff --git a/src/gui/platform/windows/qwindowsthemecache.cpp b/src/gui/platform/windows/qwindowsthemecache.cpp
new file mode 100644
index 0000000000..3bb92e67ca
--- /dev/null
+++ b/src/gui/platform/windows/qwindowsthemecache.cpp
@@ -0,0 +1,79 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwindowsthemecache_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_NAMESPACE
+
+// Theme names matching the QWindowsVistaStylePrivate::Theme enumeration.
+constexpr const wchar_t *themeNames[] = {
+ L"BUTTON", L"COMBOBOX", L"EDIT", L"HEADER", L"LISTVIEW",
+ L"MENU", L"PROGRESS", L"REBAR", L"SCROLLBAR", L"SPIN",
+ L"TAB", L"TASKDIALOG", L"TOOLBAR", L"TOOLTIP", L"TRACKBAR",
+ L"WINDOW", L"STATUS", L"TREEVIEW"
+};
+
+typedef std::array<HTHEME, std::size(themeNames)> ThemeArray;
+typedef QHash<HWND, ThemeArray> ThemesCache;
+Q_GLOBAL_STATIC(ThemesCache, themesCache);
+
+QString QWindowsThemeCache::themeName(int theme)
+{
+ return theme >= 0 && theme < int(std::size(themeNames))
+ ? QString::fromWCharArray(themeNames[theme]) : QString();
+}
+
+HTHEME QWindowsThemeCache::createTheme(int theme, HWND hwnd)
+{
+ if (Q_UNLIKELY(theme < 0 || theme >= int(std::size(themeNames)) || !hwnd)) {
+ qWarning("Invalid parameters #%d, %p", theme, hwnd);
+ return nullptr;
+ }
+
+ // Get or create themes array for this window.
+ ThemesCache *cache = themesCache();
+ auto it = cache->find(hwnd);
+ if (it == cache->end())
+ it = cache->insert(hwnd, ThemeArray {});
+
+ // Get or create theme data
+ ThemeArray &themes = *it;
+ if (!themes[theme]) {
+ const wchar_t *name = themeNames[theme];
+ themes[theme] = OpenThemeData(hwnd, name);
+ if (Q_UNLIKELY(!themes[theme]))
+ qErrnoWarning("OpenThemeData() failed for theme %d (%s).",
+ theme, qPrintable(themeName(theme)));
+ }
+ return themes[theme];
+}
+
+static void clearThemes(ThemeArray &themes)
+{
+ for (auto &theme : themes) {
+ if (theme) {
+ CloseThemeData(theme);
+ theme = nullptr;
+ }
+ }
+}
+
+void QWindowsThemeCache::clearThemeCache(HWND hwnd)
+{
+ ThemesCache *cache = themesCache();
+ auto it = cache->find(hwnd);
+ if (it == cache->end())
+ return;
+ clearThemes(*it);
+}
+
+void QWindowsThemeCache::clearAllThemeCaches()
+{
+ ThemesCache *cache = themesCache();
+ for (auto &themeArray : *cache)
+ clearThemes(themeArray);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/platform/windows/qwindowsthemecache_p.h b/src/gui/platform/windows/qwindowsthemecache_p.h
new file mode 100644
index 0000000000..beb724dc5c
--- /dev/null
+++ b/src/gui/platform/windows/qwindowsthemecache_p.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWINDOWSTHEME_CACHE_P_H
+#define QWINDOWSTHEME_CACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/private/qtguiglobal_p.h"
+
+#include <QtCore/qt_windows.h>
+#include <uxtheme.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QWindowsThemeCache
+{
+ Q_GUI_EXPORT QString themeName(int theme);
+ Q_GUI_EXPORT HTHEME createTheme(int theme, HWND hwnd);
+ Q_GUI_EXPORT void clearThemeCache(HWND hwnd);
+ Q_GUI_EXPORT void clearAllThemeCaches();
+}
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSTHEME_CACHE_P_H
diff --git a/src/gui/qt_cmdline.cmake b/src/gui/qt_cmdline.cmake
index 3663a24a46..379cc417e7 100644
--- a/src/gui/qt_cmdline.cmake
+++ b/src/gui/qt_cmdline.cmake
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
qt_commandline_option(accessibility TYPE boolean)
qt_commandline_option(direct2d TYPE boolean)
qt_commandline_option(directfb TYPE boolean)
diff --git a/src/gui/qtgui.tracepoints b/src/gui/qtgui.tracepoints
deleted file mode 100644
index adf13d8f84..0000000000
--- a/src/gui/qtgui.tracepoints
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-QT_BEGIN_NAMESPACE
-class QImageReader;
-QT_END_NAMESPACE
-}
-
-QGuiApplicationPrivate_init_entry()
-QGuiApplicationPrivate_init_exit()
-
-QGuiApplicationPrivate_processWindowSystemEvent_entry(int type)
-QGuiApplicationPrivate_processWindowSystemEvent_exit()
-
-QFontDatabase_addApplicationFont(const QString &filename)
-QFontDatabase_load(const QStringList &family, int pointSize)
-QFontDatabase_loadEngine(const QStringList &families, int pointSize)
-QFontDatabasePrivate_addAppFont(const QString &fileName)
-
-QImageData_create_entry(const QSize &size, QImage::Format format)
-QImageData_create_exit()
-QImage_copy_entry(const QRect& r)
-QImage_copy_exit()
-QImage_scaled_entry(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode)
-QImage_scaled_exit()
-QImage_scaledToWidth_entry(int w, Qt::TransformationMode mode)
-QImage_scaledToWidth_exit()
-QImage_scaledToHeight_entry(int h, Qt::TransformationMode mode)
-QImage_scaledToHeight_exit()
-QImage_rgbSwapped_helper_entry()
-QImage_rgbSwapped_helper_exit()
-QImage_transformed_entry(const QTransform &matrix, Qt::TransformationMode mode)
-QImage_transformed_exit()
-
-QPixmap_scaled_entry(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode)
-QPixmap_scaled_exit()
-QPixmap_scaledToWidth_entry(int w, Qt::TransformationMode mode)
-QPixmap_scaledToWidth_exit()
-QPixmap_scaledToHeight_entry(int h, Qt::TransformationMode mode)
-QPixmap_scaledToHeight_exit()
-
-QImageReader_read_before_reading(QImageReader *reader, const QString &filename)
-QImageReader_read_after_reading(QImageReader *reader, bool result)
diff --git a/src/gui/rhi/MiniEngine_LICENSE.txt b/src/gui/rhi/MiniEngine_LICENSE.txt
new file mode 100644
index 0000000000..b8b569d774
--- /dev/null
+++ b/src/gui/rhi/MiniEngine_LICENSE.txt
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Microsoft
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/src/gui/rhi/cs_mipmap_p.h b/src/gui/rhi/cs_mipmap_p.h
new file mode 100644
index 0000000000..317cbe7b2e
--- /dev/null
+++ b/src/gui/rhi/cs_mipmap_p.h
@@ -0,0 +1,939 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef CS_MIPMAP_P_H
+#define CS_MIPMAP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+
+#ifdef Q_OS_WIN
+
+#include <qt_windows.h>
+
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer CB0
+// {
+//
+// uint SrcMipLevel; // Offset: 0 Size: 4
+// uint NumMipLevels; // Offset: 4 Size: 4
+// float2 TexelSize; // Offset: 8 Size: 8
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// BilinearClamp sampler NA NA s0 1
+// SrcMip texture float4 2d t0 1
+// OutMip1 UAV float4 2d u0 1
+// OutMip2 UAV float4 2d u1 1
+// OutMip3 UAV float4 2d u2 1
+// OutMip4 UAV float4 2d u3 1
+// CB0 cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// no Input
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// no Output
+cs_5_0
+dcl_globalFlags refactoringAllowed
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_uav_typed_texture2d (float,float,float,float) u0
+dcl_uav_typed_texture2d (float,float,float,float) u1
+dcl_uav_typed_texture2d (float,float,float,float) u2
+dcl_uav_typed_texture2d (float,float,float,float) u3
+dcl_input vThreadIDInGroupFlattened
+dcl_input vThreadID.xy
+dcl_temps 6
+dcl_tgsm_structured g0, 4, 64
+dcl_tgsm_structured g1, 4, 64
+dcl_tgsm_structured g2, 4, 64
+dcl_tgsm_structured g3, 4, 64
+dcl_thread_group 8, 8, 1
+utof r0.xy, vThreadID.xyxx
+add r0.xy, r0.xyxx, l(0.250000, 0.250000, 0.000000, 0.000000)
+mul r0.zw, r0.xxxy, cb0[0].zzzw
+utof r1.x, cb0[0].x
+sample_l_indexable(texture2d)(float,float,float,float) r2.xyzw, r0.zwzz, t0.xyzw, s0, r1.x
+mul r3.xyz, cb0[0].zwzz, l(0.500000, 0.500000, 0.500000, 0.000000)
+mov r3.w, l(0)
+mad r3.xyzw, cb0[0].zwzw, r0.xyxy, r3.zwxy
+sample_l_indexable(texture2d)(float,float,float,float) r4.xyzw, r3.xyxx, t0.xyzw, s0, r1.x
+add r2.xyzw, r2.xyzw, r4.xyzw
+mov r3.x, l(0)
+mul r3.y, cb0[0].w, l(0.500000)
+mad r0.xy, cb0[0].zwzz, r0.xyxx, r3.xyxx
+sample_l_indexable(texture2d)(float,float,float,float) r0.xyzw, r0.xyxx, t0.xyzw, s0, r1.x
+add r0.xyzw, r0.xyzw, r2.xyzw
+sample_l_indexable(texture2d)(float,float,float,float) r1.xyzw, r3.zwzz, t0.xyzw, s0, r1.x
+add r0.xyzw, r0.xyzw, r1.xyzw
+mul r1.xyzw, r0.xyzw, l(0.250000, 0.250000, 0.250000, 0.250000)
+store_uav_typed u0.xyzw, vThreadID.xyyy, r1.xyzw
+ieq r2.x, cb0[0].y, l(1)
+if_nz r2.x
+ ret
+endif
+store_structured g0.x, vThreadIDInGroupFlattened.x, l(0), r1.x
+store_structured g1.x, vThreadIDInGroupFlattened.x, l(0), r1.y
+store_structured g2.x, vThreadIDInGroupFlattened.x, l(0), r1.z
+store_structured g3.x, vThreadIDInGroupFlattened.x, l(0), r1.w
+sync_g_t
+and r2.x, vThreadIDInGroupFlattened.x, l(9)
+if_z r2.x
+ iadd r2.xyz, vThreadIDInGroupFlattened.xxxx, l(1, 8, 9, 0)
+ ld_structured r3.x, r2.x, l(0), g0.xxxx
+ ld_structured r3.y, r2.x, l(0), g1.xxxx
+ ld_structured r3.z, r2.x, l(0), g2.xxxx
+ ld_structured r3.w, r2.x, l(0), g3.xxxx
+ ld_structured r4.x, r2.y, l(0), g0.xxxx
+ ld_structured r4.y, r2.y, l(0), g1.xxxx
+ ld_structured r4.z, r2.y, l(0), g2.xxxx
+ ld_structured r4.w, r2.y, l(0), g3.xxxx
+ ld_structured r5.x, r2.z, l(0), g0.xxxx
+ ld_structured r5.y, r2.z, l(0), g1.xxxx
+ ld_structured r5.z, r2.z, l(0), g2.xxxx
+ ld_structured r5.w, r2.z, l(0), g3.xxxx
+ mad r0.xyzw, r0.xyzw, l(0.250000, 0.250000, 0.250000, 0.250000), r3.xyzw
+ add r0.xyzw, r4.xyzw, r0.xyzw
+ add r0.xyzw, r5.xyzw, r0.xyzw
+ mul r1.xyzw, r0.xyzw, l(0.250000, 0.250000, 0.250000, 0.250000)
+ ushr r0.xyzw, vThreadID.xyyy, l(1, 1, 1, 1)
+ store_uav_typed u1.xyzw, r0.xyzw, r1.xyzw
+ store_structured g0.x, vThreadIDInGroupFlattened.x, l(0), r1.x
+ store_structured g1.x, vThreadIDInGroupFlattened.x, l(0), r1.y
+ store_structured g2.x, vThreadIDInGroupFlattened.x, l(0), r1.z
+ store_structured g3.x, vThreadIDInGroupFlattened.x, l(0), r1.w
+endif
+ieq r0.x, cb0[0].y, l(2)
+if_nz r0.x
+ ret
+endif
+sync_g_t
+and r0.x, vThreadIDInGroupFlattened.x, l(27)
+if_z r0.x
+ iadd r0.xyz, vThreadIDInGroupFlattened.xxxx, l(2, 16, 18, 0)
+ ld_structured r2.x, r0.x, l(0), g0.xxxx
+ ld_structured r2.y, r0.x, l(0), g1.xxxx
+ ld_structured r2.z, r0.x, l(0), g2.xxxx
+ ld_structured r2.w, r0.x, l(0), g3.xxxx
+ ld_structured r3.x, r0.y, l(0), g0.xxxx
+ ld_structured r3.y, r0.y, l(0), g1.xxxx
+ ld_structured r3.z, r0.y, l(0), g2.xxxx
+ ld_structured r3.w, r0.y, l(0), g3.xxxx
+ ld_structured r4.x, r0.z, l(0), g0.xxxx
+ ld_structured r4.y, r0.z, l(0), g1.xxxx
+ ld_structured r4.z, r0.z, l(0), g2.xxxx
+ ld_structured r4.w, r0.z, l(0), g3.xxxx
+ add r0.xyzw, r1.xyzw, r2.xyzw
+ add r0.xyzw, r3.xyzw, r0.xyzw
+ add r0.xyzw, r4.xyzw, r0.xyzw
+ mul r1.xyzw, r0.xyzw, l(0.250000, 0.250000, 0.250000, 0.250000)
+ ushr r0.xyzw, vThreadID.xyyy, l(2, 2, 2, 2)
+ store_uav_typed u2.xyzw, r0.xyzw, r1.xyzw
+ store_structured g0.x, vThreadIDInGroupFlattened.x, l(0), r1.x
+ store_structured g1.x, vThreadIDInGroupFlattened.x, l(0), r1.y
+ store_structured g2.x, vThreadIDInGroupFlattened.x, l(0), r1.z
+ store_structured g3.x, vThreadIDInGroupFlattened.x, l(0), r1.w
+endif
+ieq r0.x, cb0[0].y, l(3)
+if_nz r0.x
+ ret
+endif
+sync_g_t
+if_z vThreadIDInGroupFlattened.x
+ ld_structured r0.x, l(4), l(0), g0.xxxx
+ ld_structured r0.y, l(4), l(0), g1.xxxx
+ ld_structured r0.z, l(4), l(0), g2.xxxx
+ ld_structured r0.w, l(4), l(0), g3.xxxx
+ ld_structured r2.x, l(32), l(0), g0.xxxx
+ ld_structured r2.y, l(32), l(0), g1.xxxx
+ ld_structured r2.z, l(32), l(0), g2.xxxx
+ ld_structured r2.w, l(32), l(0), g3.xxxx
+ ld_structured r3.x, l(36), l(0), g0.xxxx
+ ld_structured r3.y, l(36), l(0), g1.xxxx
+ ld_structured r3.z, l(36), l(0), g2.xxxx
+ ld_structured r3.w, l(36), l(0), g3.xxxx
+ add r0.xyzw, r0.xyzw, r1.xyzw
+ add r0.xyzw, r2.xyzw, r0.xyzw
+ add r0.xyzw, r3.xyzw, r0.xyzw
+ mul r0.xyzw, r0.xyzw, l(0.250000, 0.250000, 0.250000, 0.250000)
+ ushr r1.xyzw, vThreadID.xyyy, l(3, 3, 3, 3)
+ store_uav_typed u3.xyzw, r1.xyzw, r0.xyzw
+endif
+ret
+// Approximately 111 instruction slots used
+#endif
+
+inline constexpr BYTE g_csMipmap[] =
+{
+ 68, 88, 66, 67, 133, 122,
+ 5, 181, 163, 163, 140, 185,
+ 158, 179, 4, 65, 180, 238,
+ 158, 10, 1, 0, 0, 0,
+ 60, 17, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 200, 2, 0, 0, 216, 2,
+ 0, 0, 232, 2, 0, 0,
+ 160, 16, 0, 0, 82, 68,
+ 69, 70, 140, 2, 0, 0,
+ 1, 0, 0, 0, 88, 1,
+ 0, 0, 7, 0, 0, 0,
+ 60, 0, 0, 0, 0, 5,
+ 83, 67, 0, 1, 0, 0,
+ 100, 2, 0, 0, 82, 68,
+ 49, 49, 60, 0, 0, 0,
+ 24, 0, 0, 0, 32, 0,
+ 0, 0, 40, 0, 0, 0,
+ 36, 0, 0, 0, 12, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 1, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 42, 1, 0, 0,
+ 2, 0, 0, 0, 5, 0,
+ 0, 0, 4, 0, 0, 0,
+ 255, 255, 255, 255, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 13, 0, 0, 0, 49, 1,
+ 0, 0, 4, 0, 0, 0,
+ 5, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 57, 1, 0, 0, 4, 0,
+ 0, 0, 5, 0, 0, 0,
+ 4, 0, 0, 0, 255, 255,
+ 255, 255, 1, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 65, 1, 0, 0,
+ 4, 0, 0, 0, 5, 0,
+ 0, 0, 4, 0, 0, 0,
+ 255, 255, 255, 255, 2, 0,
+ 0, 0, 1, 0, 0, 0,
+ 13, 0, 0, 0, 73, 1,
+ 0, 0, 4, 0, 0, 0,
+ 5, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0,
+ 81, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 66, 105, 108, 105,
+ 110, 101, 97, 114, 67, 108,
+ 97, 109, 112, 0, 83, 114,
+ 99, 77, 105, 112, 0, 79,
+ 117, 116, 77, 105, 112, 49,
+ 0, 79, 117, 116, 77, 105,
+ 112, 50, 0, 79, 117, 116,
+ 77, 105, 112, 51, 0, 79,
+ 117, 116, 77, 105, 112, 52,
+ 0, 67, 66, 48, 0, 171,
+ 171, 171, 81, 1, 0, 0,
+ 3, 0, 0, 0, 112, 1,
+ 0, 0, 16, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 232, 1, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 2, 0, 0, 0,
+ 252, 1, 0, 0, 0, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 32, 2, 0, 0, 4, 0,
+ 0, 0, 4, 0, 0, 0,
+ 2, 0, 0, 0, 252, 1,
+ 0, 0, 0, 0, 0, 0,
+ 255, 255, 255, 255, 0, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 45, 2,
+ 0, 0, 8, 0, 0, 0,
+ 8, 0, 0, 0, 2, 0,
+ 0, 0, 64, 2, 0, 0,
+ 0, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 255, 255, 255, 255, 0, 0,
+ 0, 0, 83, 114, 99, 77,
+ 105, 112, 76, 101, 118, 101,
+ 108, 0, 100, 119, 111, 114,
+ 100, 0, 171, 171, 0, 0,
+ 19, 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 244, 1, 0, 0, 78, 117,
+ 109, 77, 105, 112, 76, 101,
+ 118, 101, 108, 115, 0, 84,
+ 101, 120, 101, 108, 83, 105,
+ 122, 101, 0, 102, 108, 111,
+ 97, 116, 50, 0, 171, 171,
+ 1, 0, 3, 0, 1, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 55, 2, 0, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 49,
+ 48, 46, 49, 0, 73, 83,
+ 71, 78, 8, 0, 0, 0,
+ 0, 0, 0, 0, 8, 0,
+ 0, 0, 79, 83, 71, 78,
+ 8, 0, 0, 0, 0, 0,
+ 0, 0, 8, 0, 0, 0,
+ 83, 72, 69, 88, 176, 13,
+ 0, 0, 80, 0, 5, 0,
+ 108, 3, 0, 0, 106, 8,
+ 0, 1, 89, 0, 0, 4,
+ 70, 142, 32, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 90, 0, 0, 3, 0, 96,
+ 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112,
+ 16, 0, 0, 0, 0, 0,
+ 85, 85, 0, 0, 156, 24,
+ 0, 4, 0, 224, 17, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 156, 24, 0, 4,
+ 0, 224, 17, 0, 1, 0,
+ 0, 0, 85, 85, 0, 0,
+ 156, 24, 0, 4, 0, 224,
+ 17, 0, 2, 0, 0, 0,
+ 85, 85, 0, 0, 156, 24,
+ 0, 4, 0, 224, 17, 0,
+ 3, 0, 0, 0, 85, 85,
+ 0, 0, 95, 0, 0, 2,
+ 0, 64, 2, 0, 95, 0,
+ 0, 2, 50, 0, 2, 0,
+ 104, 0, 0, 2, 6, 0,
+ 0, 0, 160, 0, 0, 5,
+ 0, 240, 17, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0,
+ 64, 0, 0, 0, 160, 0,
+ 0, 5, 0, 240, 17, 0,
+ 1, 0, 0, 0, 4, 0,
+ 0, 0, 64, 0, 0, 0,
+ 160, 0, 0, 5, 0, 240,
+ 17, 0, 2, 0, 0, 0,
+ 4, 0, 0, 0, 64, 0,
+ 0, 0, 160, 0, 0, 5,
+ 0, 240, 17, 0, 3, 0,
+ 0, 0, 4, 0, 0, 0,
+ 64, 0, 0, 0, 155, 0,
+ 0, 4, 8, 0, 0, 0,
+ 8, 0, 0, 0, 1, 0,
+ 0, 0, 86, 0, 0, 4,
+ 50, 0, 16, 0, 0, 0,
+ 0, 0, 70, 0, 2, 0,
+ 0, 0, 0, 10, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 128, 62, 0, 0,
+ 128, 62, 0, 0, 0, 0,
+ 0, 0, 0, 0, 56, 0,
+ 0, 8, 194, 0, 16, 0,
+ 0, 0, 0, 0, 6, 4,
+ 16, 0, 0, 0, 0, 0,
+ 166, 142, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 86, 0, 0, 6, 18, 0,
+ 16, 0, 1, 0, 0, 0,
+ 10, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 72, 0, 0, 141, 194, 0,
+ 0, 128, 67, 85, 21, 0,
+ 242, 0, 16, 0, 2, 0,
+ 0, 0, 230, 10, 16, 0,
+ 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 1, 0, 0, 0, 56, 0,
+ 0, 11, 114, 0, 16, 0,
+ 3, 0, 0, 0, 230, 138,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 64,
+ 0, 0, 0, 0, 0, 63,
+ 0, 0, 0, 63, 0, 0,
+ 0, 63, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0,
+ 16, 0, 3, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 50, 0, 0, 10,
+ 242, 0, 16, 0, 3, 0,
+ 0, 0, 230, 142, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 70, 4, 16, 0,
+ 0, 0, 0, 0, 230, 4,
+ 16, 0, 3, 0, 0, 0,
+ 72, 0, 0, 141, 194, 0,
+ 0, 128, 67, 85, 21, 0,
+ 242, 0, 16, 0, 4, 0,
+ 0, 0, 70, 0, 16, 0,
+ 3, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 7, 242, 0, 16, 0,
+ 2, 0, 0, 0, 70, 14,
+ 16, 0, 2, 0, 0, 0,
+ 70, 14, 16, 0, 4, 0,
+ 0, 0, 54, 0, 0, 5,
+ 18, 0, 16, 0, 3, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 56, 0,
+ 0, 8, 34, 0, 16, 0,
+ 3, 0, 0, 0, 58, 128,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 63,
+ 50, 0, 0, 10, 50, 0,
+ 16, 0, 0, 0, 0, 0,
+ 230, 138, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 0, 16, 0,
+ 3, 0, 0, 0, 72, 0,
+ 0, 141, 194, 0, 0, 128,
+ 67, 85, 21, 0, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 0, 16, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0,
+ 10, 0, 16, 0, 1, 0,
+ 0, 0, 0, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 14,
+ 16, 0, 2, 0, 0, 0,
+ 72, 0, 0, 141, 194, 0,
+ 0, 128, 67, 85, 21, 0,
+ 242, 0, 16, 0, 1, 0,
+ 0, 0, 230, 10, 16, 0,
+ 3, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 7, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 70, 14, 16, 0, 1, 0,
+ 0, 0, 56, 0, 0, 10,
+ 242, 0, 16, 0, 1, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 2, 64,
+ 0, 0, 0, 0, 128, 62,
+ 0, 0, 128, 62, 0, 0,
+ 128, 62, 0, 0, 128, 62,
+ 164, 0, 0, 6, 242, 224,
+ 17, 0, 0, 0, 0, 0,
+ 70, 5, 2, 0, 70, 14,
+ 16, 0, 1, 0, 0, 0,
+ 32, 0, 0, 8, 18, 0,
+ 16, 0, 2, 0, 0, 0,
+ 26, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 1, 0,
+ 0, 0, 31, 0, 4, 3,
+ 10, 0, 16, 0, 2, 0,
+ 0, 0, 62, 0, 0, 1,
+ 21, 0, 0, 1, 168, 0,
+ 0, 8, 18, 240, 17, 0,
+ 0, 0, 0, 0, 10, 64,
+ 2, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 10, 0,
+ 16, 0, 1, 0, 0, 0,
+ 168, 0, 0, 8, 18, 240,
+ 17, 0, 1, 0, 0, 0,
+ 10, 64, 2, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0,
+ 26, 0, 16, 0, 1, 0,
+ 0, 0, 168, 0, 0, 8,
+ 18, 240, 17, 0, 2, 0,
+ 0, 0, 10, 64, 2, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 42, 0, 16, 0,
+ 1, 0, 0, 0, 168, 0,
+ 0, 8, 18, 240, 17, 0,
+ 3, 0, 0, 0, 10, 64,
+ 2, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 58, 0,
+ 16, 0, 1, 0, 0, 0,
+ 190, 24, 0, 1, 1, 0,
+ 0, 6, 18, 0, 16, 0,
+ 2, 0, 0, 0, 10, 64,
+ 2, 0, 1, 64, 0, 0,
+ 9, 0, 0, 0, 31, 0,
+ 0, 3, 10, 0, 16, 0,
+ 2, 0, 0, 0, 30, 0,
+ 0, 9, 114, 0, 16, 0,
+ 2, 0, 0, 0, 6, 64,
+ 2, 0, 2, 64, 0, 0,
+ 1, 0, 0, 0, 8, 0,
+ 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 18, 0, 16, 0,
+ 3, 0, 0, 0, 10, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 34, 0, 16, 0,
+ 3, 0, 0, 0, 10, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 1, 0, 0, 0, 167, 0,
+ 0, 9, 66, 0, 16, 0,
+ 3, 0, 0, 0, 10, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 2, 0, 0, 0, 167, 0,
+ 0, 9, 130, 0, 16, 0,
+ 3, 0, 0, 0, 10, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 3, 0, 0, 0, 167, 0,
+ 0, 9, 18, 0, 16, 0,
+ 4, 0, 0, 0, 26, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 34, 0, 16, 0,
+ 4, 0, 0, 0, 26, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 1, 0, 0, 0, 167, 0,
+ 0, 9, 66, 0, 16, 0,
+ 4, 0, 0, 0, 26, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 2, 0, 0, 0, 167, 0,
+ 0, 9, 130, 0, 16, 0,
+ 4, 0, 0, 0, 26, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 3, 0, 0, 0, 167, 0,
+ 0, 9, 18, 0, 16, 0,
+ 5, 0, 0, 0, 42, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 34, 0, 16, 0,
+ 5, 0, 0, 0, 42, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 1, 0, 0, 0, 167, 0,
+ 0, 9, 66, 0, 16, 0,
+ 5, 0, 0, 0, 42, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 2, 0, 0, 0, 167, 0,
+ 0, 9, 130, 0, 16, 0,
+ 5, 0, 0, 0, 42, 0,
+ 16, 0, 2, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 3, 0, 0, 0, 50, 0,
+ 0, 12, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 128, 62, 0, 0, 128, 62,
+ 0, 0, 128, 62, 0, 0,
+ 128, 62, 70, 14, 16, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 7, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 14,
+ 16, 0, 4, 0, 0, 0,
+ 70, 14, 16, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 5, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 56, 0, 0, 10, 242, 0,
+ 16, 0, 1, 0, 0, 0,
+ 70, 14, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0,
+ 0, 0, 128, 62, 0, 0,
+ 128, 62, 0, 0, 128, 62,
+ 0, 0, 128, 62, 85, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 5,
+ 2, 0, 2, 64, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 164, 0,
+ 0, 7, 242, 224, 17, 0,
+ 1, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 70, 14, 16, 0, 1, 0,
+ 0, 0, 168, 0, 0, 8,
+ 18, 240, 17, 0, 0, 0,
+ 0, 0, 10, 64, 2, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 10, 0, 16, 0,
+ 1, 0, 0, 0, 168, 0,
+ 0, 8, 18, 240, 17, 0,
+ 1, 0, 0, 0, 10, 64,
+ 2, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 26, 0,
+ 16, 0, 1, 0, 0, 0,
+ 168, 0, 0, 8, 18, 240,
+ 17, 0, 2, 0, 0, 0,
+ 10, 64, 2, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0,
+ 42, 0, 16, 0, 1, 0,
+ 0, 0, 168, 0, 0, 8,
+ 18, 240, 17, 0, 3, 0,
+ 0, 0, 10, 64, 2, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 58, 0, 16, 0,
+ 1, 0, 0, 0, 21, 0,
+ 0, 1, 32, 0, 0, 8,
+ 18, 0, 16, 0, 0, 0,
+ 0, 0, 26, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 2, 0, 0, 0, 31, 0,
+ 4, 3, 10, 0, 16, 0,
+ 0, 0, 0, 0, 62, 0,
+ 0, 1, 21, 0, 0, 1,
+ 190, 24, 0, 1, 1, 0,
+ 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 10, 64,
+ 2, 0, 1, 64, 0, 0,
+ 27, 0, 0, 0, 31, 0,
+ 0, 3, 10, 0, 16, 0,
+ 0, 0, 0, 0, 30, 0,
+ 0, 9, 114, 0, 16, 0,
+ 0, 0, 0, 0, 6, 64,
+ 2, 0, 2, 64, 0, 0,
+ 2, 0, 0, 0, 16, 0,
+ 0, 0, 18, 0, 0, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 18, 0, 16, 0,
+ 2, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 34, 0, 16, 0,
+ 2, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 1, 0, 0, 0, 167, 0,
+ 0, 9, 66, 0, 16, 0,
+ 2, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 2, 0, 0, 0, 167, 0,
+ 0, 9, 130, 0, 16, 0,
+ 2, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 3, 0, 0, 0, 167, 0,
+ 0, 9, 18, 0, 16, 0,
+ 3, 0, 0, 0, 26, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 34, 0, 16, 0,
+ 3, 0, 0, 0, 26, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 1, 0, 0, 0, 167, 0,
+ 0, 9, 66, 0, 16, 0,
+ 3, 0, 0, 0, 26, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 2, 0, 0, 0, 167, 0,
+ 0, 9, 130, 0, 16, 0,
+ 3, 0, 0, 0, 26, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 3, 0, 0, 0, 167, 0,
+ 0, 9, 18, 0, 16, 0,
+ 4, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 34, 0, 16, 0,
+ 4, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 1, 0, 0, 0, 167, 0,
+ 0, 9, 66, 0, 16, 0,
+ 4, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 2, 0, 0, 0, 167, 0,
+ 0, 9, 130, 0, 16, 0,
+ 4, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 7, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 14,
+ 16, 0, 1, 0, 0, 0,
+ 70, 14, 16, 0, 2, 0,
+ 0, 0, 0, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 3, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 14, 16, 0, 4, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 56, 0,
+ 0, 10, 242, 0, 16, 0,
+ 1, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 128, 62, 0, 0, 128, 62,
+ 0, 0, 128, 62, 0, 0,
+ 128, 62, 85, 0, 0, 9,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 5, 2, 0,
+ 2, 64, 0, 0, 2, 0,
+ 0, 0, 2, 0, 0, 0,
+ 2, 0, 0, 0, 2, 0,
+ 0, 0, 164, 0, 0, 7,
+ 242, 224, 17, 0, 2, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 14,
+ 16, 0, 1, 0, 0, 0,
+ 168, 0, 0, 8, 18, 240,
+ 17, 0, 0, 0, 0, 0,
+ 10, 64, 2, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0,
+ 10, 0, 16, 0, 1, 0,
+ 0, 0, 168, 0, 0, 8,
+ 18, 240, 17, 0, 1, 0,
+ 0, 0, 10, 64, 2, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 26, 0, 16, 0,
+ 1, 0, 0, 0, 168, 0,
+ 0, 8, 18, 240, 17, 0,
+ 2, 0, 0, 0, 10, 64,
+ 2, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 42, 0,
+ 16, 0, 1, 0, 0, 0,
+ 168, 0, 0, 8, 18, 240,
+ 17, 0, 3, 0, 0, 0,
+ 10, 64, 2, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 1, 0,
+ 0, 0, 21, 0, 0, 1,
+ 32, 0, 0, 8, 18, 0,
+ 16, 0, 0, 0, 0, 0,
+ 26, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 3, 0,
+ 0, 0, 31, 0, 4, 3,
+ 10, 0, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 21, 0, 0, 1, 190, 24,
+ 0, 1, 31, 0, 0, 2,
+ 10, 64, 2, 0, 167, 0,
+ 0, 9, 18, 0, 16, 0,
+ 0, 0, 0, 0, 1, 64,
+ 0, 0, 4, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 34, 0, 16, 0,
+ 0, 0, 0, 0, 1, 64,
+ 0, 0, 4, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 1, 0, 0, 0, 167, 0,
+ 0, 9, 66, 0, 16, 0,
+ 0, 0, 0, 0, 1, 64,
+ 0, 0, 4, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 2, 0, 0, 0, 167, 0,
+ 0, 9, 130, 0, 16, 0,
+ 0, 0, 0, 0, 1, 64,
+ 0, 0, 4, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 3, 0, 0, 0, 167, 0,
+ 0, 9, 18, 0, 16, 0,
+ 2, 0, 0, 0, 1, 64,
+ 0, 0, 32, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 34, 0, 16, 0,
+ 2, 0, 0, 0, 1, 64,
+ 0, 0, 32, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 1, 0, 0, 0, 167, 0,
+ 0, 9, 66, 0, 16, 0,
+ 2, 0, 0, 0, 1, 64,
+ 0, 0, 32, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 2, 0, 0, 0, 167, 0,
+ 0, 9, 130, 0, 16, 0,
+ 2, 0, 0, 0, 1, 64,
+ 0, 0, 32, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 3, 0, 0, 0, 167, 0,
+ 0, 9, 18, 0, 16, 0,
+ 3, 0, 0, 0, 1, 64,
+ 0, 0, 36, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 0, 0, 0, 0, 167, 0,
+ 0, 9, 34, 0, 16, 0,
+ 3, 0, 0, 0, 1, 64,
+ 0, 0, 36, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 1, 0, 0, 0, 167, 0,
+ 0, 9, 66, 0, 16, 0,
+ 3, 0, 0, 0, 1, 64,
+ 0, 0, 36, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 2, 0, 0, 0, 167, 0,
+ 0, 9, 130, 0, 16, 0,
+ 3, 0, 0, 0, 1, 64,
+ 0, 0, 36, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 0, 0, 6, 240, 17, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 7, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 70, 14, 16, 0, 1, 0,
+ 0, 0, 0, 0, 0, 7,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0,
+ 2, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 7, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 70, 14, 16, 0, 3, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 56, 0,
+ 0, 10, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0,
+ 128, 62, 0, 0, 128, 62,
+ 0, 0, 128, 62, 0, 0,
+ 128, 62, 85, 0, 0, 9,
+ 242, 0, 16, 0, 1, 0,
+ 0, 0, 70, 5, 2, 0,
+ 2, 64, 0, 0, 3, 0,
+ 0, 0, 3, 0, 0, 0,
+ 3, 0, 0, 0, 3, 0,
+ 0, 0, 164, 0, 0, 7,
+ 242, 224, 17, 0, 3, 0,
+ 0, 0, 70, 14, 16, 0,
+ 1, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 21, 0, 0, 1, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 148, 0, 0, 0, 111, 0,
+ 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 22, 0, 0, 0,
+ 5, 0, 0, 0, 5, 0,
+ 0, 0, 4, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0
+};
+
+#endif // Q_OS_WIN
+
+#endif // CS_MIPMAP_P_H
diff --git a/src/gui/rhi/cs_tdr_p.h b/src/gui/rhi/cs_tdr_p.h
deleted file mode 100644
index 534e793ad2..0000000000
--- a/src/gui/rhi/cs_tdr_p.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef CS_TDR_P_H
-#define CS_TDR_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-
-#ifdef Q_OS_WIN
-
-#include <qt_windows.h>
-
-#if 0
-//
-// Generated by Microsoft (R) HLSL Shader Compiler 10.1
-//
-//
-// Buffer Definitions:
-//
-// cbuffer ConstantBuffer
-// {
-//
-// uint zero; // Offset: 0 Size: 4
-//
-// }
-//
-//
-// Resource Bindings:
-//
-// Name Type Format Dim HLSL Bind Count
-// ------------------------------ ---------- ------- ----------- -------------- ------
-// uav UAV uint buf u0 1
-// ConstantBuffer cbuffer NA NA cb0 1
-//
-//
-//
-// Input signature:
-//
-// Name Index Mask Register SysValue Format Used
-// -------------------- ----- ------ -------- -------- ------- ------
-// no Input
-//
-// Output signature:
-//
-// Name Index Mask Register SysValue Format Used
-// -------------------- ----- ------ -------- -------- ------- ------
-// no Output
-cs_5_0
-dcl_globalFlags refactoringAllowed
-dcl_constantbuffer CB0[1], immediateIndexed
-dcl_uav_typed_buffer (uint,uint,uint,uint) u0
-dcl_input vThreadID.x
-dcl_thread_group 256, 1, 1
-loop
- breakc_nz cb0[0].x
- store_uav_typed u0.xyzw, vThreadID.xxxx, cb0[0].xxxx
-endloop
-ret
-// Approximately 5 instruction slots used
-#endif
-
-const BYTE g_killDeviceByTimingOut[] =
-{
- 68, 88, 66, 67, 217, 62,
- 220, 38, 136, 51, 86, 245,
- 161, 96, 18, 35, 141, 17,
- 26, 13, 1, 0, 0, 0,
- 164, 2, 0, 0, 5, 0,
- 0, 0, 52, 0, 0, 0,
- 100, 1, 0, 0, 116, 1,
- 0, 0, 132, 1, 0, 0,
- 8, 2, 0, 0, 82, 68,
- 69, 70, 40, 1, 0, 0,
- 1, 0, 0, 0, 144, 0,
- 0, 0, 2, 0, 0, 0,
- 60, 0, 0, 0, 0, 5,
- 83, 67, 0, 1, 0, 0,
- 0, 1, 0, 0, 82, 68,
- 49, 49, 60, 0, 0, 0,
- 24, 0, 0, 0, 32, 0,
- 0, 0, 40, 0, 0, 0,
- 36, 0, 0, 0, 12, 0,
- 0, 0, 0, 0, 0, 0,
- 124, 0, 0, 0, 4, 0,
- 0, 0, 4, 0, 0, 0,
- 1, 0, 0, 0, 255, 255,
- 255, 255, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0,
- 0, 0, 128, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 0,
- 0, 0, 0, 0, 117, 97,
- 118, 0, 67, 111, 110, 115,
- 116, 97, 110, 116, 66, 117,
- 102, 102, 101, 114, 0, 171,
- 128, 0, 0, 0, 1, 0,
- 0, 0, 168, 0, 0, 0,
- 16, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 208, 0, 0, 0, 0, 0,
- 0, 0, 4, 0, 0, 0,
- 2, 0, 0, 0, 220, 0,
- 0, 0, 0, 0, 0, 0,
- 255, 255, 255, 255, 0, 0,
- 0, 0, 255, 255, 255, 255,
- 0, 0, 0, 0, 122, 101,
- 114, 111, 0, 100, 119, 111,
- 114, 100, 0, 171, 0, 0,
- 19, 0, 1, 0, 1, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 213, 0, 0, 0, 77, 105,
- 99, 114, 111, 115, 111, 102,
- 116, 32, 40, 82, 41, 32,
- 72, 76, 83, 76, 32, 83,
- 104, 97, 100, 101, 114, 32,
- 67, 111, 109, 112, 105, 108,
- 101, 114, 32, 49, 48, 46,
- 49, 0, 73, 83, 71, 78,
- 8, 0, 0, 0, 0, 0,
- 0, 0, 8, 0, 0, 0,
- 79, 83, 71, 78, 8, 0,
- 0, 0, 0, 0, 0, 0,
- 8, 0, 0, 0, 83, 72,
- 69, 88, 124, 0, 0, 0,
- 80, 0, 5, 0, 31, 0,
- 0, 0, 106, 8, 0, 1,
- 89, 0, 0, 4, 70, 142,
- 32, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 156, 8,
- 0, 4, 0, 224, 17, 0,
- 0, 0, 0, 0, 68, 68,
- 0, 0, 95, 0, 0, 2,
- 18, 0, 2, 0, 155, 0,
- 0, 4, 0, 1, 0, 0,
- 1, 0, 0, 0, 1, 0,
- 0, 0, 48, 0, 0, 1,
- 3, 0, 4, 4, 10, 128,
- 32, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 164, 0,
- 0, 7, 242, 224, 17, 0,
- 0, 0, 0, 0, 6, 0,
- 2, 0, 6, 128, 32, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 22, 0, 0, 1,
- 62, 0, 0, 1, 83, 84,
- 65, 84, 148, 0, 0, 0,
- 5, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 2, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 1, 0, 0, 0
-};
-
-#endif // Q_OS_WIN
-
-#endif // CS_TDR_P_H
diff --git a/src/gui/rhi/mipmap.hlsl b/src/gui/rhi/mipmap.hlsl
new file mode 100644
index 0000000000..ac293e07f9
--- /dev/null
+++ b/src/gui/rhi/mipmap.hlsl
@@ -0,0 +1,117 @@
+// Copyright (c) Microsoft. All rights reserved.
+// This code is licensed under the MIT License (MIT).
+// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
+// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
+// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
+// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
+
+RWTexture2D<float4> OutMip1 : register(u0);
+RWTexture2D<float4> OutMip2 : register(u1);
+RWTexture2D<float4> OutMip3 : register(u2);
+RWTexture2D<float4> OutMip4 : register(u3);
+Texture2D<float4> SrcMip : register(t0);
+SamplerState BilinearClamp : register(s0);
+
+cbuffer CB0 : register(b0)
+{
+ uint SrcMipLevel; // Texture level of source mip
+ uint NumMipLevels; // Number of OutMips to write: [1, 4]
+ float2 TexelSize; // 1.0 / OutMip1.Dimensions
+}
+
+// The reason for separating channels is to reduce bank conflicts in the
+// local data memory controller. A large stride will cause more threads
+// to collide on the same memory bank.
+groupshared float gs_R[64];
+groupshared float gs_G[64];
+groupshared float gs_B[64];
+groupshared float gs_A[64];
+
+void StoreColor( uint Index, float4 Color )
+{
+ gs_R[Index] = Color.r;
+ gs_G[Index] = Color.g;
+ gs_B[Index] = Color.b;
+ gs_A[Index] = Color.a;
+}
+
+float4 LoadColor( uint Index )
+{
+ return float4( gs_R[Index], gs_G[Index], gs_B[Index], gs_A[Index]);
+}
+
+[numthreads( 8, 8, 1 )]
+void csMain( uint GI : SV_GroupIndex, uint3 DTid : SV_DispatchThreadID )
+{
+ // Use 4 bilinear samples to guarantee we don't undersample when downsizing by more than 2x
+ // in both directions.
+ float2 UV1 = TexelSize * (DTid.xy + float2(0.25, 0.25));
+ float2 O = TexelSize * 0.5;
+ float4 Src1 = SrcMip.SampleLevel(BilinearClamp, UV1, SrcMipLevel);
+ Src1 += SrcMip.SampleLevel(BilinearClamp, UV1 + float2(O.x, 0.0), SrcMipLevel);
+ Src1 += SrcMip.SampleLevel(BilinearClamp, UV1 + float2(0.0, O.y), SrcMipLevel);
+ Src1 += SrcMip.SampleLevel(BilinearClamp, UV1 + float2(O.x, O.y), SrcMipLevel);
+ Src1 *= 0.25;
+
+ OutMip1[DTid.xy] = Src1;
+
+ // A scalar (constant) branch can exit all threads coherently.
+ if (NumMipLevels == 1)
+ return;
+
+ // Without lane swizzle operations, the only way to share data with other
+ // threads is through LDS.
+ StoreColor(GI, Src1);
+
+ // This guarantees all LDS writes are complete and that all threads have
+ // executed all instructions so far (and therefore have issued their LDS
+ // write instructions.)
+ GroupMemoryBarrierWithGroupSync();
+
+ // With low three bits for X and high three bits for Y, this bit mask
+ // (binary: 001001) checks that X and Y are even.
+ if ((GI & 0x9) == 0)
+ {
+ float4 Src2 = LoadColor(GI + 0x01);
+ float4 Src3 = LoadColor(GI + 0x08);
+ float4 Src4 = LoadColor(GI + 0x09);
+ Src1 = 0.25 * (Src1 + Src2 + Src3 + Src4);
+
+ OutMip2[DTid.xy / 2] = Src1;
+ StoreColor(GI, Src1);
+ }
+
+ if (NumMipLevels == 2)
+ return;
+
+ GroupMemoryBarrierWithGroupSync();
+
+ // This bit mask (binary: 011011) checks that X and Y are multiples of four.
+ if ((GI & 0x1B) == 0)
+ {
+ float4 Src2 = LoadColor(GI + 0x02);
+ float4 Src3 = LoadColor(GI + 0x10);
+ float4 Src4 = LoadColor(GI + 0x12);
+ Src1 = 0.25 * (Src1 + Src2 + Src3 + Src4);
+
+ OutMip3[DTid.xy / 4] = Src1;
+ StoreColor(GI, Src1);
+ }
+
+ if (NumMipLevels == 3)
+ return;
+
+ GroupMemoryBarrierWithGroupSync();
+
+ // This bit mask would be 111111 (X & Y multiples of 8), but only one
+ // thread fits that criteria.
+ if (GI == 0)
+ {
+ float4 Src2 = LoadColor(GI + 0x04);
+ float4 Src3 = LoadColor(GI + 0x20);
+ float4 Src4 = LoadColor(GI + 0x24);
+ Src1 = 0.25 * (Src1 + Src2 + Src3 + Src4);
+
+ OutMip4[DTid.xy / 8] = Src1;
+ }
+}
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 4ae75b5df5..a39709c726 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -1,68 +1,37 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qrhi_p_p.h"
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhi_p.h"
#include <qmath.h>
#include <QLoggingCategory>
-#include "qrhinull_p_p.h"
+#include "qrhinull_p.h"
#ifndef QT_NO_OPENGL
-#include "qrhigles2_p_p.h"
+#include "qrhigles2_p.h"
#endif
#if QT_CONFIG(vulkan)
-#include "qrhivulkan_p_p.h"
+#include "qrhivulkan_p.h"
#endif
#ifdef Q_OS_WIN
-#include "qrhid3d11_p_p.h"
+#include "qrhid3d11_p.h"
+#include "qrhid3d12_p.h"
#endif
-#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
-#include "qrhimetal_p_p.h"
+#if QT_CONFIG(metal)
+#include "qrhimetal_p.h"
#endif
+#include <memory>
+
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
/*!
\class QRhi
- \internal
- \inmodule QtGui
+ \ingroup painting-3D
+ \inmodule QtGuiPrivate
+ \inheaderfile rhi/qrhi.h
+ \since 6.6
\brief Accelerated 2D/3D graphics API abstraction.
@@ -73,50 +42,55 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\l{https://developer.apple.com/metal/}{Metal}, and
\l{https://www.khronos.org/vulkan/}{Vulkan}.
- Some of the main design goals are:
-
- \list
-
- \li Simple, minimal, understandable, extensible. Follow the proven path of the
- Qt Quick scenegraph.
-
- \li Aim to be a product - and in the bigger picture, part of a product (Qt) -
- that is usable out of the box both by internal (such as, Qt Quick) and,
- eventually, external users.
-
- \li Not a complete 1:1 wrapper for any of the underlying APIs. The feature set
- is tuned towards the needs of Qt's 2D and 3D offering (QPainter, Qt Quick, Qt
- 3D Studio). Iterate and evolve in a sustainable manner.
-
- \li Intrinsically cross-platform, without reinventing: abstracting
- cross-platform aspects of certain APIs (such as, OpenGL context creation and
- windowing system interfaces, Vulkan instance and surface management) is not in
- scope here. These are delegated to the existing QtGui facilities (QWindow,
- QOpenGLContext, QVulkanInstance) and its backing QPA architecture.
-
- \endlist
+ \warning The QRhi family of classes in the Qt Gui module, including QShader
+ and QShaderDescription, offer limited compatibility guarantees. There are
+ no source or binary compatibility guarantees for these classes, meaning the
+ API is only guaranteed to work with the Qt version the application was
+ developed against. Source incompatible changes are however aimed to be kept
+ at a minimum and will only be made in minor releases (6.7, 6.8, and so on).
+ To use these classes in an application, link to
+ \c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c
+ rhi prefix, for example \c{#include <rhi/qrhi.h>}.
Each QRhi instance is backed by a backend for a specific graphics API. The
selection of the backend is a run time choice and is up to the application
or library that creates the QRhi instance. Some backends are available on
multiple platforms (OpenGL, Vulkan, Null), while APIs specific to a given
platform are only available when running on the platform in question (Metal
- on macOS/iOS/tvOS, Direct3D on Windows).
+ on macOS/iOS, Direct3D on Windows).
The available backends currently are:
\list
- \li OpenGL 2.1 or OpenGL ES 2.0 or newer. Some extensions are utilized when
- present, for example to enable multisample framebuffers.
+ \li OpenGL 2.1 / OpenGL ES 2.0 or newer. Some extensions and newer core
+ specification features are utilized when present, for example to enable
+ multisample framebuffers or compute shaders. Operating in core profile
+ contexts is supported as well. If necessary, applications can query the
+ \l{QRhi::Feature}{feature flags} at runtime to check for features that are
+ not supported in the OpenGL context backing the QRhi. The OpenGL backend
+ builds on QOpenGLContext, QOpenGLFunctions, and the related cross-platform
+ infrastructure of the Qt GUI module.
- \li Direct3D 11.1
+ \li Direct3D 11.1 or newer, with Shader Model 5.0 or newer. When the D3D
+ runtime has no support for 11.1 features or Shader Model 5.0,
+ initialization using an accelerated graphics device will fail, but using
+ the
+ \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/directx-warp}{software
+ adapter} is still an option.
- \li Metal
+ \li Direct3D 12 on Windows 10 version 1703 and newer, with Shader Model 5.0
+ or newer. Qt requires ID3D12Device2 to be present, hence the requirement
+ for at least version 1703 of Windows 10. The D3D12 device is by default
+ created with specifying a minimum feature level of
+ \c{D3D_FEATURE_LEVEL_11_0}.
- \li Vulkan 1.0, optionally with some extensions that are part of Vulkan 1.1
+ \li Metal 1.2 or newer.
- \li Null - A "dummy" backend that issues no graphics calls at all.
+ \li Vulkan 1.0 or newer, optionally utilizing some Vulkan 1.1 level
+ features.
+
+ \li Null, a "dummy" backend that issues no graphics calls at all.
\endlist
@@ -126,15 +100,60 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
are then generated from that, together with reflection information (inputs,
outputs, shader resources). This is then packed into easily and efficiently
serializable QShader instances. The compilers and tools to generate such
- shaders are not part of QRhi, but the core classes for using such shaders,
- QShader and QShaderDescription, are.
+ shaders are not part of QRhi and the Qt GUI module, but the core classes
+ for using such shaders, QShader and QShaderDescription, are. The APIs and
+ tools for performing compilation and translation are part of the Qt Shader
+ Tools module.
+
+ See the \l{RHI Window Example} for an introductory example of creating a
+ portable, cross-platform application that performs accelerated 3D rendering
+ onto a QWindow using QRhi.
+
+ \section1 An Impression of the API
+
+ To provide a quick look at the API with a short yet complete example that
+ does not involve window-related setup, the following is a complete,
+ runnable cross-platform application that renders 20 frames off-screen, and
+ then saves the generated images to files after reading back the texture
+ contents from the GPU. For an example that renders on-screen, which then
+ involves setting up a QWindow and a swapchain, refer to the
+ \l{RHI Window Example}.
- \section2 Design Fundamentals
+ For brevity, the initialization of the QRhi is done based on the platform:
+ the sample code here chooses Direct 3D 12 on Windows, Metal on macOS and
+ iOS, and Vulkan otherwise. OpenGL and Direct 3D 11 are never used by this
+ application, but support for those could be introduced with a few
+ additional lines.
+
+ \snippet rhioffscreen/main.cpp 0
+
+ The result of the application is 20 \c PNG images (frame0.png -
+ frame19.png). These contain a rotating triangle with varying opacity over a
+ green background.
+
+ The vertex and fragment shaders are expected to be processed and packaged
+ into \c{.qsb} files. The Vulkan-compatible GLSL source code is the
+ following:
+
+ \e color.vert
+ \snippet rhioffscreen/color.vert 0
+
+ \e color.frag
+ \snippet rhioffscreen/color.frag 0
+
+ To manually compile and transpile these shaders to a number of targets
+ (SPIR-V, HLSL, MSL, GLSL) and generate the \c{.qsb} files the application
+ loads at run time, run \c{qsb --qt6 color.vert -o color.vert.qsb} and
+ \c{qsb --qt6 color.frag -o color.frag.qsb}. Alternatively, the Qt Shader
+ Tools module offers build system integration for CMake, the
+ \c qt_add_shaders() CMake function, that can achieve the same at build time.
+
+ \section1 Design Fundamentals
A QRhi cannot be instantiated directly. Instead, use the create()
function. Delete the QRhi instance normally to release the graphics device.
- \section3 Resources
+ \section2 Resources
Instances of classes deriving from QRhiResource, such as, QRhiBuffer,
QRhiTexture, etc., encapsulate zero, one, or more native graphics
@@ -142,10 +161,10 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
functions of the QRhi, such as, newBuffer(), newTexture(),
newTextureRenderTarget(), newSwapChain().
- \badcode
- vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
- if (!vbuf->create()) { error }
- ...
+ \code
+ QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData));
+ if (!vbuf->create()) { error(); }
+ // ...
delete vbuf;
\endcode
@@ -154,9 +173,10 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\li The returned value from functions like newBuffer() is always owned by
the caller.
- \li Just creating a QRhiResource subclass never allocates or initializes any
- native resources. That is only done when calling the \c create() function of a
- subclass, for example, QRhiBuffer::create() or QRhiTexture::create().
+ \li Just creating an instance of a QRhiResource subclass never allocates or
+ initializes any native resources. That is only done when calling the
+ \c create() function of a subclass, for example, QRhiBuffer::create() or
+ QRhiTexture::create().
\li The exceptions are
QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor(),
@@ -180,15 +200,15 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\li Note that this does not mean that a QRhiResource can freely be
destroy()'ed or deleted within a frame (that is, in a
- \l{QRhiCommandBuffer::beginFrame()}{beginFrame()} -
- \l{QRhiCommandBuffer::endFrame()}{endFrame()} section). As a general rule,
- all referenced QRhiResource objects must stay unchanged until the frame is
- submitted by calling \l{QRhiCommandBuffer::endFrame()}{endFrame()}. To ease
- this, QRhiResource::deleteLater() is provided as a convenience.
+ \l{QRhi::beginFrame()}{beginFrame()} - \l{QRhi::endFrame()}{endFrame()}
+ section). As a general rule, all referenced QRhiResource objects must stay
+ unchanged until the frame is submitted by calling
+ \l{QRhi::endFrame()}{endFrame()}. To ease this,
+ QRhiResource::deleteLater() is provided as a convenience.
\endlist
- \section3 Command buffers and deferred command execution
+ \section2 Command buffers and deferred command execution
Regardless of the design and capabilities of the underlying graphics API,
all QRhi backends implement some level of command buffers. No
@@ -215,7 +235,7 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
As a general rule, all referenced QRhiResource objects must stay valid and
unmodified until the frame is submitted by calling
- \l{QRhiCommandBuffer::endFrame()}{endFrame()}. On the other hand, calling
+ \l{QRhi::endFrame()}{endFrame()}. On the other hand, calling
\l{QRhiResource::destroy()}{destroy()} or deleting the QRhiResource are
always safe once the frame is submitted, regardless of the status of the
underlying native resources (which may still be in use by the GPU - but
@@ -223,10 +243,20 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
Unlike APIs like OpenGL, upload and copy type of commands cannot be mixed
with draw commands. The typical renderer will involve a sequence similar to
- the following: \c{(re)create resources} - \c{begin frame} - \c{record
- uploads and copies} - \c{start renderpass} - \c{record draw calls} - \c{end
- renderpass} - \c{end frame}. Recording copy type of operations happens via
- QRhiResourceUpdateBatch. Such operations are committed typically on
+ the following:
+
+ \list
+ \li (re)create resources
+ \li begin frame
+ \li record/issue uploads and copies
+ \li start recording a render pass
+ \li record draw calls
+ \li end render pass
+ \li end frame
+ \endlist
+
+ Recording copy type of operations happens via QRhiResourceUpdateBatch. Such
+ operations are committed typically on
\l{QRhiCommandBuffer::beginPass()}{beginPass()}.
When working with legacy rendering engines designed for OpenGL, the
@@ -245,7 +275,7 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
remain the primary way of operating since this is what fits Qt's various UI
technologies best.
- \section3 Threading
+ \section2 Threading
A QRhi instance and the associated resources can be created and used on any
thread but all usage must be limited to that one single thread. When
@@ -274,7 +304,7 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
(gui) thread, but becomes important when a separate, dedicated render
thread is used.
- \section3 Resource synchronization
+ \section2 Resource synchronization
QRhi does not expose APIs for resource barriers or image layout
transitions. Such synchronization is done implicitly by the backends, where
@@ -294,7 +324,7 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
different access (one for load, one for store) is supported even within the
same pass.
- \section3 Resource reuse
+ \section2 Resource reuse
From the user's point of view a QRhiResource is reusable immediately after
calling QRhiResource::destroy(). With the exception of swapchains, calling
@@ -314,26 +344,39 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
though there is a good chance that under the hood the QRhiBuffer is now
backed by a whole new native buffer.
- \badcode
- ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
+ \code
+ QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 256);
ubuf->create();
- srb = rhi->newShaderResourceBindings()
+ QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings()
srb->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf)
});
srb->create();
- ...
+ // ...
// now in a later frame we need to grow the buffer to a larger size
ubuf->setSize(512);
ubuf->create(); // same as ubuf->destroy(); ubuf->create();
- // that's it, srb needs no changes whatsoever
+ // srb needs no changes whatsoever, any references in it to ubuf
+ // stay valid. When it comes to internal details, such as that
+ // ubuf may now be backed by a completely different native buffer
+ // resource, that is is recognized and handled automatically by the
+ // next setShaderResources().
\endcode
- \section3 Pooled objects
+ QRhiTextureRenderTarget offers the same contract: calling
+ QRhiCommandBuffer::beginPass() is safe even when one of the render target's
+ associated textures or renderbuffers has been rebuilt (by calling \c
+ create() on it) since the creation of the render target object. This allows
+ the application to resize a texture by setting a new pixel size on the
+ QRhiTexture and calling create(), thus creating a whole new native texture
+ resource underneath, without having to update the QRhiTextureRenderTarget
+ as that will be done implicitly in beginPass().
+
+ \section2 Pooled objects
In addition to resources, there are pooled objects as well, such as,
QRhiResourceUpdateBatch. An instance is retrieved via a \c next function,
@@ -343,24 +386,25 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
QRhiCommandBuffer::beginPass() or QRhiCommandBuffer::endPass(). These
functions take care of returning the batch to the pool. Alternatively, a
batch can be "canceled" and returned to the pool without processing by
- calling QRhiResourceUpdateBatch::destroy().
+ calling QRhiResourceUpdateBatch::release().
A typical pattern is thus:
- \badcode
+ \code
QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
- ...
+ // ...
resUpdates->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
if (!image.isNull()) {
resUpdates->uploadTexture(texture, image);
image = QImage();
}
- ...
+ // ...
QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
+ // note the last argument
cb->beginPass(swapchain->currentFrameRenderTarget(), clearCol, clearDs, resUpdates);
\endcode
- \section3 Swapchain specifics
+ \section2 Swapchain specifics
QRhiSwapChain features some special semantics due to the peculiar nature of
swapchains.
@@ -391,30 +435,174 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\endlist
- \section3 Ownership
+ \section2 Ownership
The general rule is no ownership transfer. Creating a QRhi with an already
existing graphics device does not mean the QRhi takes ownership of the
device object. Similarly, ownership is not given away when a device or
texture object is "exported" via QRhi::nativeHandles() or
- QRhiTexture::nativeHandles(). Most importantly, passing pointers in structs
+ QRhiTexture::nativeTexture(). Most importantly, passing pointers in structs
and via setters does not transfer ownership.
- \section2 Troubleshooting
+ \section1 Troubleshooting and Profiling
- Errors are printed to the output via qWarning(). Additional debug messages
- can be enabled via the following logging categories. Messages from these
- categories are not printed by default unless explicitly enabled via
- QRhi::EnableProfiling or the facilities of QLoggingCategory (such as, the
- \c QT_LOGGING_RULES environment variable).
+ \section2 Error reporting
+
+ Functions such as \l QRhi::create() and the resource classes' \c create()
+ member functions (e.g., \l QRhiBuffer::create()) indicate failure with the
+ return value (\nullptr or
+ \c false, respectively). When working with QShader, \l QShader::fromSerialized()
+ returns an invalid QShader (for which \l{QShader::isValid()}{isValid()} returns
+ \c false) when the data passed to the function cannot be successfully deserialized.
+ Some functions, beginFrame() in particular, may also sometimes report "soft failures",
+ such as \l FrameOpSwapChainOutOfDate, which do not indicate an unrecoverable error,
+ but rather should be seen as a "try again later" response.
+
+ Warnings and errors may get printed at any time to the debug output via
+ qWarning(). It is therefore always advisable to inspect the output of the
+ application.
+
+ Additional debug messages can be enabled via the following logging
+ categories. Messages from these categories are not printed by default
+ unless explicitly enabled via QLoggingCategory or the \c QT_LOGGING_RULES
+ environment variable. For better interoperation with Qt Quick, the
+ environment variable \c{QSG_INFO} also enables these debug prints.
\list
\li \c{qt.rhi.general}
\endlist
- It is strongly advised to inspect the output with the logging categories
- (\c{qt.rhi.*}) enabled whenever a QRhi-based application is not behaving as
- expected.
+ Additionally, applications can query the \l{QRhi::backendName()}{QRhi
+ backend name} and
+ \l{QRhi::driverInfo()}{graphics device information} from a successfully
+ initialized QRhi. This can then be printed to the user or stored in the
+ application logs even in production builds, if desired.
+
+ \section2 Investigating rendering problems
+
+ When the rendering results are not as expected, or the application is
+ experiencing problems, always consider checking with the the native 3D
+ APIs' debug and validation facilities. QRhi itself features limited error
+ checking since replicating the already existing, vast amount of
+ functionality in the underlying layers is not reasonable.
+
+ \list
+
+ \li For Vulkan, controlling the
+ \l{https://github.com/KhronosGroup/Vulkan-ValidationLayers}{Vulkan
+ Validation Layers} is not in the scope of the QRhi, but rather can be
+ achieved by configuring the \l QVulkanInstance with the appropriate layers.
+ For example, call \c{instance.setLayers({ "VK_LAYER_KHRONOS_validation" });}
+ before invoking \l{QVulkanInstance::create()}{create()} on the QVulkanInstance.
+ (note that this assumes that the validation layers are actually installed
+ and available, e.g. from the Vulkan SDK) By default, QVulkanInstance conveniently
+ redirects the Vulkan debug messages to qDebug, meaning the validation messages get
+ printed just like other Qt warnings.
+
+ \li With Direct 3D 11 and 12, a graphics device with the debug layer
+ enabled can be requested by toggling the \c enableDebugLayer flag in the
+ appropriate \l{QRhiD3D11InitParams}{init params struct}. The messages appear on the
+ debug output, which is visible in Qt Creator's messages panel or via a tool
+ such as \l{https://learn.microsoft.com/en-us/sysinternals/downloads/debugview}{DebugView}.
+
+ \li For Metal, controlling Metal Validation is outside of QRhi's scope.
+ Rather, to enable validation, run the application with the environment
+ variable \c{METAL_DEVICE_WRAPPER_TYPE=1} set, or run the application within
+ XCode. There may also be further settings and environment variable in modern
+ XCode and macOS versions. See for instance
+ \l{https://developer.apple.com/documentation/metal/diagnosing_metal_programming_issues_early}{this
+ page}.
+
+ \endlist
+
+ \section2 Frame captures and performance profiling
+
+ A Qt application rendering with QRhi to a window while relying on a 3D API
+ under the hood, is, from the windowing and graphics pipeline perspective at
+ least, no different from any other (non-Qt) applications using the same 3D
+ API. This means that tools and practices for debugging and profiling
+ applications involving 3D graphics, such as games, all apply to such a Qt
+ application as well.
+
+ A few examples of tools that can provide insights into the rendering
+ internals of Qt applications that use QRhi, which includes Qt Quick and Qt
+ Quick 3D based projects as well:
+
+ \list
+
+ \li \l{https://renderdoc.org/}{RenderDoc} allows taking frame captures and
+ introspecting the recorded commands and pipeline state on Windows and Linux
+ for applications using OpenGL, Vulkan, D3D11, or D3D12. When trying to
+ figure out why some parts of the 3D scene do not show up as expected,
+ RenderDoc is often a fast and efficient way to check the pipeline stages
+ and the related state and discover the missing or incorrect value. It is
+ also a tool that is actively used when developing Qt itself.
+
+ \li For NVIDIA-based systems,
+ \l{https://developer.nvidia.com/nsight-graphics}{Nsight Graphics} provides
+ a graphics debugger tool on Windows and Linux. In addition to investigating the commands
+ in the frame and the pipeline, the vendor-specific tools allow looking at timings and
+ hardware performance information, which is not something simple frame captures can provide.
+
+ \li For AMD-based systems, the \l{https://gpuopen.com/rgp/}{Radeon GPU
+ Profiler} can be used to gain deeper insights into the application's
+ rendering and its performance.
+
+ \li As QRhi supports Direct 3D 12, using
+ \l{https://devblogs.microsoft.com/pix/download/}{PIX}, a performance tuning
+ and debugging tool for DirectX 12 games on Windows is an option as well.
+
+ \li On macOS,
+ \l{https://developer.apple.com/documentation/metal/debugging_tools/viewing_your_gpu_workload_with_the_metal_debugger}{the
+ XCode Metal debugger} can be used to take and introspect frame
+ captures, to investigate performance details, and debug shaders. In macOS 13 it is also possible
+ to enable an overlay that displays frame rate and other information for any Metal-based window by
+ setting the environment variable \c{MTL_HUD_ENABLED=1}.
+
+ \endlist
+
+ On mobile and embedded platforms, there may be vendor and platform-specific
+ tools, provided by the GPU or SoC vendor, available to perform performance
+ profiling of application using OpenGL ES or Vulkan.
+
+ When capturing frames, remember that objects and groups of commands can be
+ named via debug markers, as long as \l{QRhi::EnableDebugMarkers}{debug
+ markers were enabled} for the QRhi, and the graphics API in use supports
+ this. To annotate the command stream, call
+ \l{QRhiCommandBuffer::debugMarkBegin()}{debugMarkBegin()},
+ \l{QRhiCommandBuffer::debugMarkEnd()}{debugMarkEnd()} and/or
+ \l{QRhiCommandBuffer::debugMarkMsg()}{debugMarkMsg()}.
+ This can be particularly useful in larger frames with multiple render passes.
+ Resources are named by calling \l{QRhiResource::setName()}{setName()} before create().
+
+ To perform basic timing measurements on the CPU and GPU side within the
+ application, \l QElapsedTimer and
+ \l QRhiCommandBuffer::lastCompletedGpuTime() can be used. The latter is
+ only available with select graphics APIs at the moment and requires opting
+ in via the \l QRhi::EnableTimestamps flag.
+
+ \section2 Resource leak checking
+
+ When destroying a QRhi object without properly destroying all buffers,
+ textures, and other resources created from it, warnings about this are
+ printed to the debug output whenever the application is a debug build, or
+ when the \c QT_RHI_LEAK_CHECK environment variable is set to a non-zero
+ value. This is a simple way to discover design issues around resource
+ handling within the application rendering logic. Note however that some
+ platforms and underlying graphics APIs may perform their own allocation and
+ resource leak detection as well, over which Qt will have no direct control.
+ For example, when using Vulkan, the memory allocator may raise failing
+ assertions in debug builds when resources that own graphics memory
+ allocations are not destroyed before the QRhi. In addition, the Vulkan
+ validation layer, when enabled, will issue warnings about native graphics
+ resources that were not released. Similarly, with Direct 3D warnings may
+ get printed about unreleased COM objects when the application does not
+ destroy the QRhi and its resources in the correct order.
+
+ \sa {RHI Window Example}, QRhiCommandBuffer, QRhiResourceUpdateBatch,
+ QRhiShaderResourceBindings, QShader, QRhiBuffer, QRhiTexture,
+ QRhiRenderBuffer, QRhiSampler, QRhiTextureRenderTarget,
+ QRhiGraphicsPipeline, QRhiComputePipeline, QRhiSwapChain
*/
/*!
@@ -425,6 +613,7 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\value Vulkan
\value OpenGLES2
\value D3D11
+ \value D3D12
\value Metal
*/
@@ -432,17 +621,18 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\enum QRhi::Flag
Describes what special features to enable.
- \value EnableProfiling Enables gathering timing (CPU, GPU) and resource
- (QRhiBuffer, QRhiTexture, etc.) information and additional metadata. See
- QRhiProfiler. Avoid enabling in production builds as it may involve a
- performance penalty. Also enables debug messages from the \c{qt.rhi.*}
- logging categories.
-
\value EnableDebugMarkers Enables debug marker groups. Without this frame
debugging features like making debug groups and custom resource name
visible in external GPU debugging tools will not be available and functions
- like QRhiCommandBuffer::debugMarkBegin() will become a no-op. Avoid
- enabling in production builds as it may involve a performance penalty.
+ like QRhiCommandBuffer::debugMarkBegin() will become no-ops. Avoid enabling
+ in production builds as it may involve a small performance impact. Has no
+ effect when the QRhi::DebugMarkers feature is not reported as supported.
+
+ \value EnableTimestamps Enables GPU timestamp collection. When not set,
+ QRhiCommandBuffer::lastCompletedGpuTime() always returns 0. Enable this
+ only when needed since there may be a small amount of extra work involved
+ (e.g. timestamp queries), depending on the underlying graphics API. Has no
+ effect when the QRhi::Timestamps feature is not reported as supported.
\value PreferSoftwareRenderer Indicates that backends should prefer
choosing an adapter or physical device that renders in software on the CPU.
@@ -458,16 +648,35 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\value EnablePipelineCacheDataSave Enables retrieving the pipeline cache
contents, where applicable. When not set, pipelineCacheData() will return
- an empty blob always. Opting in is relevant in particular with backends
- where additional, potentially time consuming work is needed to maintain the
- data structures with the serialized, binary versions of shader programs. An
- example is OpenGL, where the "pipeline cache" is simulated by retrieving
- and loading shader program binaries. With backends where retrieving and
- restoring the pipeline cache contents is not supported, the flag has no
- effect. With some backends (such as, OpenGL) there are additional,
- disk-based caching mechanisms for shader binaries. Writing to those may get
- disabled whenever this flag is set since storing program binaries (OpenGL)
- to multiple caches is not sensible.
+ an empty blob always. With backends where retrieving and restoring the
+ pipeline cache contents is not supported, the flag has no effect and the
+ serialized cache data is always empty. The flag provides an opt-in
+ mechanism because the cost of maintaining the related data structures is
+ not insignificant with some backends. With Vulkan this feature maps
+ directly to VkPipelineCache, vkGetPipelineCacheData and
+ VkPipelineCacheCreateInfo::pInitialData. With Direct3D 11 there is no real
+ pipline cache, but the results of HLSL->DXBC compilations are stored and
+ can be serialized/deserialized via this mechanism. This allows skipping the
+ time consuming D3DCompile() in future runs of the applications for shaders
+ that come with HLSL source instead of offline pre-compiled bytecode. This
+ can provide a huge boost in startup and load times, if there is a lot of
+ HLSL source compilation happening. With OpenGL the "pipeline cache" is
+ simulated by retrieving and loading shader program binaries (if supported
+ by the driver). With OpenGL there are additional, disk-based caching
+ mechanisms for shader/program binaries provided by Qt. Writing to those may
+ get disabled whenever this flag is set since storing program binaries to
+ multiple caches is not sensible.
+
+ \value SuppressSmokeTestWarnings Indicates that, with backends where this
+ is relevant, certain, non-fatal QRhi::create() failures should not
+ produce qWarning() calls. For example, with D3D11, passing this flag
+ makes a number of warning messages (that appear due to QRhi::create()
+ failing) to become categorized debug prints instead under the commonly used
+ \c{qt.rhi.general} logging category. This can be used by engines, such as
+ Qt Quick, that feature fallback logic, i.e. they retry calling create()
+ with a different set of flags (such as, \l PreferSoftwareRenderer), in order
+ to hide the unconditional warnings from the output that would be printed
+ when the first create() attempt had failed.
*/
/*!
@@ -493,21 +702,34 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
Flag values to indicate what features are supported by the backend currently in use.
\value MultisampleTexture Indicates that textures with a sample count larger
- than 1 are supported.
+ than 1 are supported. In practice this feature will be unsupported with
+ OpenGL ES versions older than 3.1, and OpenGL older than 3.0.
\value MultisampleRenderBuffer Indicates that renderbuffers with a sample
- count larger than 1 are supported.
+ count larger than 1 are supported. In practice this feature will be
+ unsupported with OpenGL ES 2.0, and may also be unsupported with OpenGL 2.x
+ unless the relevant extensions are present.
\value DebugMarkers Indicates that debug marker groups (and so
QRhiCommandBuffer::debugMarkBegin()) are supported.
\value Timestamps Indicates that command buffer timestamps are supported.
- Relevant for QRhiProfiler::gpuFrameTimes().
-
- \value Instancing Indicates that instanced drawing is supported.
-
- \value CustomInstanceStepRate Indicates that instance step rates other than
- 1 are supported.
+ Relevant for QRhiCommandBuffer::lastCompletedGpuTime(). This can be
+ expected to be supported on Metal, Vulkan, Direct 3D 11 and 12, and OpenGL
+ contexts of version 3.3 or newer. However, with some of these APIs support
+ for timestamp queries is technically optional, and therefore it cannot be
+ guaranteed that this feature is always supported with every implementation
+ of them.
+
+ \value Instancing Indicates that instanced drawing is supported. In
+ practice this feature will be unsupported with OpenGL ES 2.0 and OpenGL
+ 3.2 or older.
+
+ \value CustomInstanceStepRate Indicates that instance step rates other
+ than 1 are supported. In practice this feature will always be unsupported
+ with OpenGL. In addition, running with Vulkan 1.0 without
+ VK_EXT_vertex_attribute_divisor will also lead to reporting false for this
+ feature.
\value PrimitiveRestart Indicates that restarting the assembly of
primitives when encountering an index value of 0xFFFF
@@ -535,7 +757,8 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
index buffer offsets (\c{indexOffset + firstIndex * indexComponentSize})
that are not 4 byte aligned are supported. When not supported, attempting
to issue a \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} with a
- non-aligned effective offset may lead to unspecified behavior.
+ non-aligned effective offset may lead to unspecified behavior. Relevant in
+ particular for Metal, where this will be reported as unsupported.
\value NPOTTextureRepeat Indicates that the
\l{QRhiSampler::Repeat}{Repeat} wrap mode and mipmap filtering modes are
@@ -546,8 +769,12 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\value RedOrAlpha8IsRed Indicates that the
\l{QRhiTexture::RED_OR_ALPHA8}{RED_OR_ALPHA8} format maps to a one
component 8-bit \c red format. This is the case for all backends except
- OpenGL, where \c{GL_ALPHA}, a one component 8-bit \c alpha format, is used
- instead. This is relevant for shader code that samples from the texture.
+ OpenGL when using either OpenGL ES or a non-core profile context. There
+ \c{GL_ALPHA}, a one component 8-bit \c alpha format, is used
+ instead. Using the special texture format allows having a single code
+ path for creating textures, leaving it up to the backend to decide the
+ actual format, while the feature flag can be used to pick the
+ appropriate shader variant for sampling the texture.
\value ElementIndexUint Indicates that 32-bit unsigned integer elements are
supported in the index buffer. In practice this is true everywhere except
@@ -556,12 +783,13 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
index buffer.
\value Compute Indicates that compute shaders, image load/store, and
- storage buffers are supported.
+ storage buffers are supported. OpenGL older than 4.3 and OpenGL ES older
+ than 3.1 have no compute support.
\value WideLines Indicates that lines with a width other than 1 are
supported. When reported as not supported, the line width set on the
graphics pipeline state is ignored. This can always be false with some
- backends (D3D11, Metal). With Vulkan, the value depends on the
+ backends (D3D11, D3D12, Metal). With Vulkan, the value depends on the
implementation. With OpenGL, wide lines are not supported in core profile
contexts.
@@ -574,50 +802,56 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
require the point size to be set in the shader explicitly whenever drawing
points, even when the size is 1, as they do not automatically default to 1.
- \value BaseVertex Indicates that \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()}
- supports the \c vertexOffset argument. When reported as not supported, the
- vertexOffset value in an indexed draw is ignored.
+ \value BaseVertex Indicates that
+ \l{QRhiCommandBuffer::drawIndexed()}{drawIndexed()} supports the \c
+ vertexOffset argument. When reported as not supported, the vertexOffset
+ value in an indexed draw is ignored. In practice this feature will be
+ unsupported with OpenGL and OpenGL ES versions lower than 3.2, and with
+ Metal on older iOS devices, including the iOS Simulator.
\value BaseInstance Indicates that instanced draw commands support the \c
firstInstance argument. When reported as not supported, the firstInstance
- value is ignored and the instance ID starts from 0.
+ value is ignored and the instance ID starts from 0. In practice this feature
+ will be unsupported with OpenGL, and with Metal on older iOS devices,
+ including the iOS Simulator.
\value TriangleFanTopology Indicates that QRhiGraphicsPipeline::setTopology()
- supports QRhiGraphicsPipeline::TriangleFan.
+ supports QRhiGraphicsPipeline::TriangleFan. In practice this feature will be
+ unsupported with Metal and Direct 3D 11/12.
\value ReadBackNonUniformBuffer Indicates that
\l{QRhiResourceUpdateBatch::readBackBuffer()}{reading buffer contents} is
supported for QRhiBuffer instances with a usage different than
- UniformBuffer. While this is supported in the majority of cases, it will be
- unsupported with OpenGL ES older than 3.0.
+ UniformBuffer. In practice this feature will be unsupported with OpenGL ES
+ 2.0.
\value ReadBackNonBaseMipLevel Indicates that specifying a mip level other
than 0 is supported when reading back texture contents. When not supported,
specifying a non-zero level in QRhiReadbackDescription leads to returning
an all-zero image. In practice this feature will be unsupported with OpenGL
- ES 2.0, while it will likely be supported everywhere else.
+ ES 2.0.
- \value TexelFetch Indicates that texelFetch() is available in shaders. In
- practice this will be reported as unsupported with OpenGL ES 2.0 and OpenGL
- 2.x contexts, because GLSL 100 es and versions before 130 do not support
- this function.
+ \value TexelFetch Indicates that texelFetch() and textureLod() are available
+ in shaders. In practice this will be reported as unsupported with OpenGL ES
+ 2.0 and OpenGL 2.x contexts, because GLSL 100 es and versions before 130 do
+ not support these functions.
\value RenderToNonBaseMipLevel Indicates that specifying a mip level other
than 0 is supported when creating a QRhiTextureRenderTarget with a
QRhiTexture as its color attachment. When not supported, create() will fail
whenever the target mip level is not zero. In practice this feature will be
- unsupported with OpenGL ES 2.0, while it will likely be supported everywhere
- else.
+ unsupported with OpenGL ES 2.0.
\value IntAttributes Indicates that specifying input attributes with
signed and unsigned integer types for a shader pipeline is supported. When
not supported, build() will succeed but just show a warning message and the
values of the target attributes will be broken. In practice this feature
- will be unsupported with OpenGL ES 2.0 and OpenGL 2.x, while it will likely
- be supported everywhere else.
+ will be unsupported with OpenGL ES 2.0 and OpenGL 2.x.
\value ScreenSpaceDerivatives Indicates that functions such as dFdx(),
- dFdy(), and fwidth() are supported in shaders.
+ dFdy(), and fwidth() are supported in shaders. In practice this feature will
+ be unsupported with OpenGL ES 2.0 without the GL_OES_standard_derivatives
+ extension.
\value ReadBackAnyTextureFormat Indicates that reading back texture
contents can be expected to work for any QRhiTexture::Format. Backends
@@ -660,6 +894,148 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
texture is supported. This can be unsupported with Vulkan 1.0 due to
relying on VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT which is a Vulkan 1.1
feature.
+
+ \value TextureArrays Indicates that texture arrays are supported and
+ QRhi::newTextureArray() is functional. Note that even when texture arrays
+ are not supported, arrays of textures are still available as those are two
+ independent features.
+
+ \value Tessellation Indicates that the tessellation control and evaluation
+ stages are supported. When reported as supported, the topology of a
+ QRhiGraphicsPipeline can be set to
+ \l{QRhiGraphicsPipeline::Patches}{Patches}, the number of control points
+ can be set via
+ \l{QRhiGraphicsPipeline::setPatchControlPointCount()}{setPatchControlPointCount()},
+ and shaders for tessellation control and evaluation can be specified in the
+ QRhiShaderStage list. Tessellation shaders have portability issues between
+ APIs (for example, translating GLSL/SPIR-V to HLSL is problematic due to
+ the way hull shaders are structured, whereas Metal uses a somewhat
+ different tessellation pipeline than others), and therefore unexpected
+ issues may still arise, even though basic functionality is implemented
+ across all the underlying APIs. For Direct 3D in particular, handwritten
+ HLSL hull and domain shaders must be injected into each QShader for the
+ tessellation control and evaluation stages, respectively, since qsb cannot
+ generate these from SPIR-V. Note that isoline tessellation should be
+ avoided as it will not be supported by all backends. The maximum patch
+ control point count portable between backends is 32.
+
+ \value GeometryShader Indicates that the geometry shader stage is
+ supported. When supported, a geometry shader can be specified in the
+ QRhiShaderStage list. Geometry Shaders are considered an experimental
+ feature in QRhi and can only be expected to be supported with Vulkan,
+ Direct 3D, OpenGL (3.2+) and OpenGL ES (3.2+), assuming the implementation
+ reports it as supported at run time. Geometry shaders have portability
+ issues between APIs, and therefore no guarantees can be given for a
+ universal solution. They will never be supported with Metal. Whereas with
+ Direct 3D a handwritten HLSL geometry shader must be injected into each
+ QShader for the geometry stage since qsb cannot generate this from SPIR-V.
+
+ \value TextureArrayRange Indicates that for
+ \l{QRhi::newTextureArray()}{texture arrays} it is possible to specify a
+ range that is exposed to the shaders. Normally all array layers are exposed
+ and it is up to the shader to select the layer (via the third coordinate
+ passed to texture() when sampling the \c sampler2DArray). When supported,
+ calling QRhiTexture::setArrayRangeStart() and
+ QRhiTexture::setArrayRangeLength() before
+ \l{QRhiTexture::create()}{building} or
+ \l{QRhiTexture::createFrom()}{importing} the native texture has an effect,
+ and leads to selecting only the specified range from the array. This will
+ be necessary in special cases, such as when working with accelerated video
+ decoding and Direct 3D 11, because a texture array with both
+ \c{D3D11_BIND_DECODER} and \c{D3D11_BIND_SHADER_RESOURCE} on it is only
+ usable as a shader resource if a single array layer is selected. Note that
+ all this is applicable only when the texture is used as a
+ QRhiShaderResourceBinding::SampledTexture or
+ QRhiShaderResourceBinding::Texture shader resource, and is not compatible
+ with image load/store. This feature is only available with some backends as
+ it does not map well to all graphics APIs, and it is only meant to provide
+ support for special cases anyhow. In practice the feature can be expected to
+ be supported with Direct3D 11/12 and Vulkan.
+
+ \value NonFillPolygonMode Indicates that setting a PolygonMode other than
+ the default Fill is supported for QRhiGraphicsPipeline. A common use case
+ for changing the mode to Line is to get wireframe rendering. This however
+ is not available as a core OpenGL ES feature, and is optional with Vulkan
+ as well as some mobile GPUs may not offer the feature.
+
+ \value OneDimensionalTextures Indicates that 1D textures are supported.
+ In practice this feature will be unsupported on OpenGL ES.
+
+ \value OneDimensionalTextureMipmaps Indicates that generating 1D texture
+ mipmaps are supported. In practice this feature will be unsupported on
+ backends that do not report support for
+ \l{OneDimensionalTextures}, Metal, and Direct 3D 12.
+
+ \value HalfAttributes Indicates that specifying input attributes with half
+ precision (16bit) floating point types for a shader pipeline is supported.
+ When not supported, build() will succeed but just show a warning message
+ and the values of the target attributes will be broken. In practice this
+ feature will be unsupported in some OpenGL ES 2.0 and OpenGL 2.x
+ implementations. Note that while Direct3D 11/12 does support half precision
+ input attributes, it does not support the half3 type. The D3D backends pass
+ half3 attributes as half4. To ensure cross platform compatibility, half3
+ inputs should be padded to 8 bytes.
+
+ \value RenderToOneDimensionalTexture Indicates that 1D texture render
+ targets are supported. In practice this feature will be unsupported on
+ backends that do not report support for
+ \l{OneDimensionalTextures}, and Metal.
+
+ \value ThreeDimensionalTextureMipmaps Indicates that generating 3D texture
+ mipmaps are supported. In practice this feature will be unsupported with
+ Direct 3D 12.
+
+ \value MultiView Indicates that multiview, see e.g.
+ \l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_multiview.html}{VK_KHR_multiview}
+ is supported. With OpenGL ES 2.0, Direct 3D 11, and OpenGL (ES)
+ implementations without \c{GL_OVR_multiview2} this feature will not be
+ supported. With Vulkan 1.1 and newer, and Direct 3D 12 multiview is
+ typically supported. When reported as supported, creating a
+ QRhiTextureRenderTarget with a QRhiColorAttachment that references a texture
+ array and has \l{QRhiColorAttachment::setMultiViewCount()}{multiViewCount}
+ set enables recording a render pass that uses multiview rendering. In addition,
+ any QRhiGraphicsPipeline used in that render pass must have
+ \l{QRhiGraphicsPipeline::setMultiViewCount()}{the same view count set}. Note that
+ multiview is only available in combination with 2D texture arrays. It cannot
+ be used to optimize the rendering into individual textures (e.g. two, for
+ the left and right eyes). Rather, the target of a multiview render pass is
+ always a texture array, automatically rendering to the layer (array element)
+ corresponding to each view. Therefore this feature implies \l TextureArrays
+ as well. Multiview rendering is not supported in combination with
+ tessellation or geometry shaders. See QRhiColorAttachment::setMultiViewCount()
+ for further details on multiview rendering. This enum value has been introduced in Qt 6.7.
+
+ \value TextureViewFormat Indicates that setting a
+ \l{QRhiTexture::setWriteViewFormat()}{view format} on a QRhiTexture is
+ effective. When reported as supported, setting the read (sampling) or write
+ (render target / image load-store) view mode changes the texture's viewing
+ format. When unsupported, setting a view format has no effect. Note that Qt
+ has no knowledge or control over format compatibility or resource view rules
+ in the underlying 3D API and its implementation. Passing in unsuitable,
+ incompatible formats may lead to errors and unspecified behavior. This is
+ provided mainly to allow "casting" rendering into a texture created with an
+ sRGB format to non-sRGB to avoid the unwanted linear->sRGB conversion on
+ shader writes. Other types of casting may or may not be functional,
+ depending on the underlying API. Currently implemented for Vulkan and Direct
+ 3D 12. With D3D12 the feature is available only if
+ \c CastingFullyTypedFormatSupported is supported, see
+ \l{https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html} (and
+ note that QRhi always uses fully typed formats for textures.) This enum
+ value has been introduced in Qt 6.8.
+
+ \value ResolveDepthStencil Indicates that resolving a multisample depth or
+ depth-stencil texture is supported. Otherwise,
+ \l{QRhiTextureRenderTargetDescription::setDepthResolveTexture()}{setting a
+ depth resolve texture} is not functional and must be avoided. Direct 3D 11
+ and 12 have no support for resolving depth/depth-stencil formats, and
+ therefore this feature will never be supported with those. Vulkan 1.0 has no
+ API to request resolving a depth-stencil attachment. Therefore, with Vulkan
+ this feature will only be supported with Vulkan 1.2 and up, and on 1.1
+ implementations with the appropriate extensions present. This feature is
+ provided for the rare case when resolving into a non-multisample depth
+ texture becomes necessary, for example when rendering into an
+ OpenXR-provided depth texture (XR_KHR_composition_layer_depth). This enum
+ value has been introduced in Qt 6.8.
*/
/*!
@@ -747,26 +1123,52 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
\value MaxThreadGroupZ The maximum size of a work/thread group in the Z
dimension. Effectively the maximum value of \c local_size_z in the compute
shader. Typically 64 or 256.
+
+ \value TextureArraySizeMax Maximum texture array size. Typically in range
+ 256 - 2048. Attempting to \l{QRhi::newTextureArray()}{create a texture
+ array} with more elements will likely fail.
+
+ \value MaxUniformBufferRange The number of bytes that can be exposed from a
+ uniform buffer to the shaders at once. On OpenGL ES 2.0 and 3.0
+ implementations this may be as low as 3584 bytes (224 four component, 32
+ bits per component vectors). Elsewhere the value is typically 16384 (1024
+ vec4s) or 65536 (4096 vec4s).
+
+ \value MaxVertexInputs The number of input attributes to the vertex shader.
+ The location in a QRhiVertexInputAttribute must be in range \c{[0,
+ MaxVertexInputs-1]}. The value may be as low as 8 with OpenGL ES 2.0.
+ Elsewhere, typical values are 16, 31, or 32.
+
+ \value MaxVertexOutputs The maximum number of outputs (4 component vector
+ \c out variables) from the vertex shader. The value may be as low as 8 with
+ OpenGL ES 2.0, and 15 with OpenGL ES 3.0 and some Metal devices. Elsewhere,
+ a typical value is 32.
*/
/*!
\class QRhiInitParams
- \internal
\inmodule QtGui
+ \since 6.6
\brief Base class for backend-specific initialization parameters.
Contains fields that are relevant to all backends.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
\class QRhiDepthStencilClearValue
- \internal
\inmodule QtGui
+ \since 6.6
\brief Specifies clear values for a depth or stencil buffer.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
- \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue()
+ \fn QRhiDepthStencilClearValue::QRhiDepthStencilClearValue() = default
Constructs a depth/stencil clear value with depth clear value 1.0f and
stencil clear value 0.
@@ -783,37 +1185,45 @@ QRhiDepthStencilClearValue::QRhiDepthStencilClearValue(float d, quint32 s)
}
/*!
+ \fn float QRhiDepthStencilClearValue::depthClearValue() const
+ \return the depth clear value. In most cases this is 1.0f.
+ */
+
+/*!
+ \fn void QRhiDepthStencilClearValue::setDepthClearValue(float d)
+ Sets the depth clear value to \a d.
+ */
+
+/*!
+ \fn quint32 QRhiDepthStencilClearValue::stencilClearValue() const
+ \return the stencil clear value. In most cases this is 0.
+ */
+
+/*!
+ \fn void QRhiDepthStencilClearValue::setStencilClearValue(quint32 s)
+ Sets the stencil clear value to \a s.
+ */
+
+/*!
+ \fn bool QRhiDepthStencilClearValue::operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
+
\return \c true if the values in the two QRhiDepthStencilClearValue objects
\a a and \a b are equal.
-
- \relates QRhiDepthStencilClearValue
*/
-bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
-{
- return a.depthClearValue() == b.depthClearValue()
- && a.stencilClearValue() == b.stencilClearValue();
-}
/*!
+ \fn bool QRhiDepthStencilClearValue::operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
+
\return \c false if the values in the two QRhiDepthStencilClearValue
objects \a a and \a b are equal; otherwise returns \c true.
- \relates QRhiDepthStencilClearValue
*/
-bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
-{
- return !(a == b);
-}
/*!
- \return the hash value for \a v, using \a seed to seed the calculation.
+ \fn size_t QRhiDepthStencilClearValue::qHash(const QRhiDepthStencilClearValue &v, size_t seed = 0) noexcept
- \relates QRhiDepthStencilClearValue
+ \return the hash value for \a v, using \a seed to seed the calculation.
*/
-size_t qHash(const QRhiDepthStencilClearValue &v, size_t seed) noexcept
-{
- return seed * (uint(qFloor(qreal(v.depthClearValue()) * 100)) + v.stencilClearValue());
-}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
@@ -828,8 +1238,8 @@ QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
/*!
\class QRhiViewport
- \internal
\inmodule QtGui
+ \since 6.6
\brief Specifies a viewport rectangle.
Used with QRhiCommandBuffer::setViewport().
@@ -839,20 +1249,23 @@ QDebug operator<<(QDebug dbg, const QRhiDepthStencilClearValue &v)
Typical usage is like the following:
- \badcode
+ \code
const QSize outputSizeInPixels = swapchain->currentPixelSize();
const QRhiViewport viewport(0, 0, outputSizeInPixels.width(), outputSizeInPixels.height());
- cb->beginPass(swapchain->currentFrameRenderTarget(), { 0, 0, 0, 1 }, { 1, 0 });
+ cb->beginPass(swapchain->currentFrameRenderTarget(), Qt::black, { 1.0f, 0 });
cb->setGraphicsPipeline(ps);
cb->setViewport(viewport);
- ...
+ // ...
\endcode
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
\sa QRhiCommandBuffer::setViewport(), QRhi::clipSpaceCorrMatrix(), QRhiScissor
*/
/*!
- \fn QRhiViewport::QRhiViewport()
+ \fn QRhiViewport::QRhiViewport() = default
Constructs a viewport description with an empty rectangle and a depth range
of 0.0f - 1.0f.
@@ -878,40 +1291,59 @@ QRhiViewport::QRhiViewport(float x, float y, float w, float h, float minDepth, f
}
/*!
+ \fn std::array<float, 4> QRhiViewport::viewport() const
+ \return the viewport x, y, width, and height.
+ */
+
+/*!
+ \fn void QRhiViewport::setViewport(float x, float y, float w, float h)
+ Sets the viewport's position and size to \a x, \a y, \a w, and \a h.
+
+ \note Viewports are specified in a coordinate system that has its origin in
+ the bottom-left.
+ */
+
+/*!
+ \fn float QRhiViewport::minDepth() const
+ \return the minDepth value of the depth range of the viewport.
+ */
+
+/*!
+ \fn void QRhiViewport::setMinDepth(float minDepth)
+ Sets the \a minDepth of the depth range of the viewport.
+ By default this is set to 0.0f.
+ */
+
+/*!
+ \fn float QRhiViewport::maxDepth() const
+ \return the maxDepth value of the depth range of the viewport.
+ */
+
+/*!
+ \fn void QRhiViewport::setMaxDepth(float maxDepth)
+ Sets the \a maxDepth of the depth range of the viewport.
+ By default this is set to 1.0f.
+ */
+
+/*!
+ \fn bool QRhiViewport::operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
+
\return \c true if the values in the two QRhiViewport objects
\a a and \a b are equal.
-
- \relates QRhiViewport
*/
-bool operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
-{
- return a.viewport() == b.viewport()
- && a.minDepth() == b.minDepth()
- && a.maxDepth() == b.maxDepth();
-}
/*!
+ \fn bool QRhiViewport::operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
+
\return \c false if the values in the two QRhiViewport
objects \a a and \a b are equal; otherwise returns \c true.
-
- \relates QRhiViewport
*/
-bool operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
-{
- return !(a == b);
-}
/*!
- \return the hash value for \a v, using \a seed to seed the calculation.
+ \fn size_t QRhiViewport::qHash(const QRhiViewport &v, size_t seed = 0) noexcept
- \relates QRhiViewport
+ \return the hash value for \a v, using \a seed to seed the calculation.
*/
-size_t qHash(const QRhiViewport &v, size_t seed) noexcept
-{
- const std::array<float, 4> r = v.viewport();
- return seed + uint(r[0]) + uint(r[1]) + uint(r[2]) + uint(r[3])
- + uint(qFloor(qreal(v.minDepth()) * 100)) + uint(qFloor(qreal(v.maxDepth()) * 100));
-}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QRhiViewport &v)
@@ -931,8 +1363,8 @@ QDebug operator<<(QDebug dbg, const QRhiViewport &v)
/*!
\class QRhiScissor
- \internal
\inmodule QtGui
+ \since 6.6
\brief Specifies a scissor rectangle.
Used with QRhiCommandBuffer::setScissor(). Setting a scissor rectangle is
@@ -946,11 +1378,14 @@ QDebug operator<<(QDebug dbg, const QRhiViewport &v)
appropriate. Therefore, any rendering logic targeting OpenGL can feed
scissor rectangles into QRhiScissor as-is, without any adaptation.
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
\sa QRhiCommandBuffer::setScissor(), QRhiViewport
*/
/*!
- \fn QRhiScissor::QRhiScissor()
+ \fn QRhiScissor::QRhiScissor() = default
Constructs an empty scissor.
*/
@@ -971,37 +1406,37 @@ QRhiScissor::QRhiScissor(int x, int y, int w, int h)
}
/*!
+ \fn std::array<int, 4> QRhiScissor::scissor() const
+ \return the scissor position and size.
+ */
+
+/*!
+ \fn void QRhiScissor::setScissor(int x, int y, int w, int h)
+ Sets the scissor position and size to \a x, \a y, \a w, \a h.
+
+ \note The position is always expected to be specified in a coordinate
+ system that has its origin in the bottom-left corner, like OpenGL.
+ */
+
+/*!
+ \fn bool QRhiScissor::operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
+
\return \c true if the values in the two QRhiScissor objects
\a a and \a b are equal.
-
- \relates QRhiScissor
*/
-bool operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
-{
- return a.scissor() == b.scissor();
-}
/*!
+ \fn bool QRhiScissor::operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
+
\return \c false if the values in the two QRhiScissor
objects \a a and \a b are equal; otherwise returns \c true.
-
- \relates QRhiScissor
*/
-bool operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
-{
- return !(a == b);
-}
/*!
- \return the hash value for \a v, using \a seed to seed the calculation.
+ \fn size_t QRhiScissor::qHash(const QRhiScissor &v, size_t seed = 0) noexcept
- \relates QRhiScissor
+ \return the hash value for \a v, using \a seed to seed the calculation.
*/
-size_t qHash(const QRhiScissor &v, size_t seed) noexcept
-{
- const std::array<int, 4> r = v.scissor();
- return seed + uint(r[0]) + uint(r[1]) + uint(r[2]) + uint(r[3]);
-}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QRhiScissor &s)
@@ -1019,8 +1454,8 @@ QDebug operator<<(QDebug dbg, const QRhiScissor &s)
/*!
\class QRhiVertexInputBinding
- \internal
\inmodule QtGui
+ \since 6.6
\brief Describes a vertex input binding.
Specifies the stride (in bytes, must be a multiple of 4), the
@@ -1035,10 +1470,10 @@ QDebug operator<<(QDebug dbg, const QRhiScissor &s)
Now let's assume also that 3 component vertex positions \c{(x, y, z)} and 2
component texture coordinates \c{(u, v)} are provided in a non-interleaved
- format in a buffer (or separate buffers even). Definining two bindings
+ format in a buffer (or separate buffers even). Defining two bindings
could then be done like this:
- \badcode
+ \code
QRhiVertexInputLayout inputLayout;
inputLayout.setBindings({
{ 3 * sizeof(float) },
@@ -1055,7 +1490,7 @@ QDebug operator<<(QDebug dbg, const QRhiScissor &s)
vertices, assuming we have a single buffer with first the positions and
then the texture coordinates:
- \badcode
+ \code
const QRhiCommandBuffer::VertexInput vbufBindings[] = {
{ cubeBuf, 0 },
{ cubeBuf, 36 * 3 * sizeof(float) }
@@ -1071,6 +1506,9 @@ QDebug operator<<(QDebug dbg, const QRhiScissor &s)
\note the stride must always be a multiple of 4.
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
\sa QRhiCommandBuffer::setVertexInput()
*/
@@ -1083,7 +1521,7 @@ QDebug operator<<(QDebug dbg, const QRhiScissor &s)
*/
/*!
- \fn QRhiVertexInputBinding::QRhiVertexInputBinding()
+ \fn QRhiVertexInputBinding::QRhiVertexInputBinding() = default
Constructs a default vertex input binding description.
*/
@@ -1095,7 +1533,7 @@ QDebug operator<<(QDebug dbg, const QRhiScissor &s)
\note \a stepRate other than 1 is only supported when
QRhi::CustomInstanceStepRate is reported to be supported.
*/
-QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, int stepRate)
+QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cls, quint32 stepRate)
: m_stride(stride),
m_classification(cls),
m_instanceStepRate(stepRate)
@@ -1103,38 +1541,54 @@ QRhiVertexInputBinding::QRhiVertexInputBinding(quint32 stride, Classification cl
}
/*!
+ \fn quint32 QRhiVertexInputBinding::stride() const
+ \return the stride in bytes.
+ */
+
+/*!
+ \fn void QRhiVertexInputBinding::setStride(quint32 s)
+ Sets the stride to \a s.
+ */
+
+/*!
+ \fn QRhiVertexInputBinding::Classification QRhiVertexInputBinding::classification() const
+ \return the input data classification.
+ */
+
+/*!
+ \fn void QRhiVertexInputBinding::setClassification(Classification c)
+ Sets the input data classification \a c. By default this is set to PerVertex.
+ */
+
+/*!
+ \fn quint32 QRhiVertexInputBinding::instanceStepRate() const
+ \return the instance step rate.
+ */
+
+/*!
+ \fn void QRhiVertexInputBinding::setInstanceStepRate(quint32 rate)
+ Sets the instance step \a rate. By default this is set to 1.
+ */
+
+/*!
+ \fn bool QRhiVertexInputBinding::operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
+
\return \c true if the values in the two QRhiVertexInputBinding objects
\a a and \a b are equal.
-
- \relates QRhiVertexInputBinding
*/
-bool operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
-{
- return a.stride() == b.stride()
- && a.classification() == b.classification()
- && a.instanceStepRate() == b.instanceStepRate();
-}
/*!
+ \fn bool QRhiVertexInputBinding::operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
+
\return \c false if the values in the two QRhiVertexInputBinding
objects \a a and \a b are equal; otherwise returns \c true.
-
- \relates QRhiVertexInputBinding
*/
-bool operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
-{
- return !(a == b);
-}
/*!
- \return the hash value for \a v, using \a seed to seed the calculation.
+ \fn size_t QRhiVertexInputBinding::qHash(const QRhiVertexInputBinding &v, size_t seed = 0) noexcept
- \relates QRhiVertexInputBinding
+ \return the hash value for \a v, using \a seed to seed the calculation.
*/
-size_t qHash(const QRhiVertexInputBinding &v, size_t seed) noexcept
-{
- return seed + v.stride() + v.classification();
-}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
@@ -1150,14 +1604,15 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
/*!
\class QRhiVertexInputAttribute
- \internal
\inmodule QtGui
+ \since 6.6
\brief Describes a single vertex input element.
The members specify the binding number, location, format, and offset for a
single vertex input element.
- \note For HLSL it is assumed that the vertex shader uses
+ \note For HLSL it is assumed that the vertex shader translated from SPIR-V
+ uses
\c{TEXCOORD<location>} as the semantic for each input. Hence no separate
semantic name and index.
@@ -1173,7 +1628,7 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
non-interleaved format in a buffer (or separate buffers even). Once two
bindings are defined, the attributes could be specified as:
- \badcode
+ \code
QRhiVertexInputLayout inputLayout;
inputLayout.setBindings({
{ 3 * sizeof(float) },
@@ -1190,7 +1645,7 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
vertices, assuming we have a single buffer with first the positions and
then the texture coordinates:
- \badcode
+ \code
const QRhiCommandBuffer::VertexInput vbufBindings[] = {
{ cubeBuf, 0 },
{ cubeBuf, 36 * 3 * sizeof(float) }
@@ -1202,7 +1657,7 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
binding, with multiple attributes referring to that same buffer binding
point:
- \badcode
+ \code
QRhiVertexInputLayout inputLayout;
inputLayout.setBindings({
{ 5 * sizeof(float) }
@@ -1215,11 +1670,14 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
and then:
- \badcode
+ \code
const QRhiCommandBuffer::VertexInput vbufBinding(interleavedCubeBuf, 0);
cb->setVertexInput(0, 1, &vbufBinding);
\endcode
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
\sa QRhiCommandBuffer::setVertexInput()
*/
@@ -1242,10 +1700,30 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b)
\value SInt3 Three component signed integer vector
\value SInt2 Two component signed integer vector
\value SInt Signed integer
+ \value Half4 Four component half precision (16 bit) float vector
+ \value Half3 Three component half precision (16 bit) float vector
+ \value Half2 Two component half precision (16 bit) float vector
+ \value Half Half precision (16 bit) float
+ \value UShort4 Four component unsigned short (16 bit) integer vector
+ \value UShort3 Three component unsigned short (16 bit) integer vector
+ \value UShort2 Two component unsigned short (16 bit) integer vector
+ \value UShort Unsigned short (16 bit) integer
+ \value SShort4 Four component signed short (16 bit) integer vector
+ \value SShort3 Three component signed short (16 bit) integer vector
+ \value SShort2 Two component signed short (16 bit) integer vector
+ \value SShort Signed short (16 bit) integer
+
+ \note Support for half precision floating point attributes is indicated at
+ run time by the QRhi::Feature::HalfAttributes feature flag.
+
+ \note Direct3D 11/12 supports 16 bit input attributes, but does not support
+ the Half3, UShort3 or SShort3 types. The D3D backends pass through Half3 as
+ Half4, UShort3 as UShort4, and SShort3 as SShort4. To ensure cross platform
+ compatibility, 16 bit inputs should be padded to 8 bytes.
*/
/*!
- \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute()
+ \fn QRhiVertexInputAttribute::QRhiVertexInputAttribute() = default
Constructs a default vertex input attribute description.
*/
@@ -1270,39 +1748,85 @@ QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Fo
}
/*!
+ \fn int QRhiVertexInputAttribute::binding() const
+ \return the binding point index.
+ */
+
+/*!
+ \fn void QRhiVertexInputAttribute::setBinding(int b)
+ Sets the binding point index to \a b.
+ By default this is set to 0.
+ */
+
+/*!
+ \fn int QRhiVertexInputAttribute::location() const
+ \return the location of the vertex input element.
+ */
+
+/*!
+ \fn void QRhiVertexInputAttribute::setLocation(int loc)
+ Sets the location of the vertex input element to \a loc.
+ By default this is set to 0.
+ */
+
+/*!
+ \fn QRhiVertexInputAttribute::Format QRhiVertexInputAttribute::format() const
+ \return the format of the vertex input element.
+ */
+
+/*!
+ \fn void QRhiVertexInputAttribute::setFormat(Format f)
+ Sets the format of the vertex input element to \a f.
+ By default this is set to Float4.
+ */
+
+/*!
+ \fn quint32 QRhiVertexInputAttribute::offset() const
+ \return the byte offset for the input element.
+ */
+
+/*!
+ \fn void QRhiVertexInputAttribute::setOffset(quint32 ofs)
+ Sets the byte offset for the input element to \a ofs.
+ */
+
+/*!
+ \fn int QRhiVertexInputAttribute::matrixSlice() const
+
+ \return the matrix slice if the input element corresponds to a row or
+ column of a matrix, or -1 if not relevant.
+ */
+
+/*!
+ \fn void QRhiVertexInputAttribute::setMatrixSlice(int slice)
+
+ Sets the matrix \a slice. By default this is set to -1, and should be set
+ to a >= 0 value only when this attribute corresponds to a row or column of
+ a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming 4
+ consecutive vertex input locations), in which case it is the index of the
+ row or column. \c{location - matrixSlice} must always be equal to the \c
+ location for the first row or column of the unrolled matrix.
+ */
+
+/*!
+ \fn bool QRhiVertexInputAttribute::operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
+
\return \c true if the values in the two QRhiVertexInputAttribute objects
\a a and \a b are equal.
-
- \relates QRhiVertexInputAttribute
*/
-bool operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
-{
- return a.binding() == b.binding()
- && a.location() == b.location()
- && a.format() == b.format()
- && a.offset() == b.offset();
-}
/*!
+ \fn bool QRhiVertexInputAttribute::operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
+
\return \c false if the values in the two QRhiVertexInputAttribute
objects \a a and \a b are equal; otherwise returns \c true.
-
- \relates QRhiVertexInputAttribute
*/
-bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
-{
- return !(a == b);
-}
/*!
- \return the hash value for \a v, using \a seed to seed the calculation.
+ \fn size_t QRhiVertexInputAttribute::qHash(const QRhiVertexInputAttribute &v, size_t seed = 0) noexcept
- \relates QRhiVertexInputAttribute
+ \return the hash value for \a v, using \a seed to seed the calculation.
*/
-size_t qHash(const QRhiVertexInputAttribute &v, size_t seed) noexcept
-{
- return seed + uint(v.binding()) + uint(v.location()) + uint(v.format()) + v.offset();
-}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
@@ -1317,53 +1841,235 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputAttribute &a)
}
#endif
+QRhiVertexInputAttribute::Format QRhiImplementation::shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const
+{
+ switch (type) {
+ case QShaderDescription::Vec4:
+ return QRhiVertexInputAttribute::Float4;
+ case QShaderDescription::Vec3:
+ return QRhiVertexInputAttribute::Float3;
+ case QShaderDescription::Vec2:
+ return QRhiVertexInputAttribute::Float2;
+ case QShaderDescription::Float:
+ return QRhiVertexInputAttribute::Float;
+
+ case QShaderDescription::Int4:
+ return QRhiVertexInputAttribute::SInt4;
+ case QShaderDescription::Int3:
+ return QRhiVertexInputAttribute::SInt3;
+ case QShaderDescription::Int2:
+ return QRhiVertexInputAttribute::SInt2;
+ case QShaderDescription::Int:
+ return QRhiVertexInputAttribute::SInt;
+
+ case QShaderDescription::Uint4:
+ return QRhiVertexInputAttribute::UInt4;
+ case QShaderDescription::Uint3:
+ return QRhiVertexInputAttribute::UInt3;
+ case QShaderDescription::Uint2:
+ return QRhiVertexInputAttribute::UInt2;
+ case QShaderDescription::Uint:
+ return QRhiVertexInputAttribute::UInt;
+
+ case QShaderDescription::Half4:
+ return QRhiVertexInputAttribute::Half4;
+ case QShaderDescription::Half3:
+ return QRhiVertexInputAttribute::Half3;
+ case QShaderDescription::Half2:
+ return QRhiVertexInputAttribute::Half2;
+ case QShaderDescription::Half:
+ return QRhiVertexInputAttribute::Half;
+
+ default:
+ Q_UNREACHABLE_RETURN(QRhiVertexInputAttribute::Float);
+ }
+}
+
+quint32 QRhiImplementation::byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const
+{
+ switch (format) {
+ case QRhiVertexInputAttribute::Float4:
+ return 4 * sizeof(float);
+ case QRhiVertexInputAttribute::Float3:
+ return 4 * sizeof(float); // vec3 still takes 16 bytes
+ case QRhiVertexInputAttribute::Float2:
+ return 2 * sizeof(float);
+ case QRhiVertexInputAttribute::Float:
+ return sizeof(float);
+
+ case QRhiVertexInputAttribute::UNormByte4:
+ return 4 * sizeof(quint8);
+ case QRhiVertexInputAttribute::UNormByte2:
+ return 2 * sizeof(quint8);
+ case QRhiVertexInputAttribute::UNormByte:
+ return sizeof(quint8);
+
+ case QRhiVertexInputAttribute::UInt4:
+ return 4 * sizeof(quint32);
+ case QRhiVertexInputAttribute::UInt3:
+ return 4 * sizeof(quint32); // ivec3 still takes 16 bytes
+ case QRhiVertexInputAttribute::UInt2:
+ return 2 * sizeof(quint32);
+ case QRhiVertexInputAttribute::UInt:
+ return sizeof(quint32);
+
+ case QRhiVertexInputAttribute::SInt4:
+ return 4 * sizeof(qint32);
+ case QRhiVertexInputAttribute::SInt3:
+ return 4 * sizeof(qint32); // uvec3 still takes 16 bytes
+ case QRhiVertexInputAttribute::SInt2:
+ return 2 * sizeof(qint32);
+ case QRhiVertexInputAttribute::SInt:
+ return sizeof(qint32);
+
+ case QRhiVertexInputAttribute::Half4:
+ return 4 * sizeof(qfloat16);
+ case QRhiVertexInputAttribute::Half3:
+ return 4 * sizeof(qfloat16); // half3 still takes 8 bytes
+ case QRhiVertexInputAttribute::Half2:
+ return 2 * sizeof(qfloat16);
+ case QRhiVertexInputAttribute::Half:
+ return sizeof(qfloat16);
+
+ case QRhiVertexInputAttribute::UShort4:
+ return 4 * sizeof(quint16);
+ case QRhiVertexInputAttribute::UShort3:
+ return 4 * sizeof(quint16); // ivec3 still takes 8 bytes
+ case QRhiVertexInputAttribute::UShort2:
+ return 2 * sizeof(quint16);
+ case QRhiVertexInputAttribute::UShort:
+ return sizeof(quint16);
+
+ case QRhiVertexInputAttribute::SShort4:
+ return 4 * sizeof(qint16);
+ case QRhiVertexInputAttribute::SShort3:
+ return 4 * sizeof(qint16); // uvec3 still takes 8 bytes
+ case QRhiVertexInputAttribute::SShort2:
+ return 2 * sizeof(qint16);
+ case QRhiVertexInputAttribute::SShort:
+ return sizeof(qint16);
+
+ default:
+ Q_UNREACHABLE_RETURN(1);
+ }
+}
+
/*!
\class QRhiVertexInputLayout
- \internal
\inmodule QtGui
+ \since 6.6
\brief Describes the layout of vertex inputs consumed by a vertex shader.
The vertex input layout is defined by the collections of
QRhiVertexInputBinding and QRhiVertexInputAttribute.
+
+ As an example, let's assume that we have a single buffer with 3 component
+ vertex positions and 2 component UV coordinates interleaved (\c x, \c y, \c
+ z, \c u, \c v), that the position and UV are expected at input locations 0
+ and 1 by the vertex shader, and that the vertex buffer will be bound at
+ binding point 0 using
+ \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()} later on:
+
+ \code
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({
+ { 5 * sizeof(float) }
+ });
+ inputLayout.setAttributes({
+ { 0, 0, QRhiVertexInputAttribute::Float3, 0 },
+ { 0, 1, QRhiVertexInputAttribute::Float2, 3 * sizeof(float) }
+ });
+ \endcode
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
- \fn QRhiVertexInputLayout::QRhiVertexInputLayout()
+ \fn QRhiVertexInputLayout::QRhiVertexInputLayout() = default
Constructs an empty vertex input layout description.
*/
/*!
+ \fn void QRhiVertexInputLayout::setBindings(std::initializer_list<QRhiVertexInputBinding> list)
+ Sets the bindings from the specified \a list.
+ */
+
+/*!
+ \fn template<typename InputIterator> void QRhiVertexInputLayout::setBindings(InputIterator first, InputIterator last)
+ Sets the bindings using the iterators \a first and \a last.
+ */
+
+/*!
+ \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cbeginBindings() const
+ \return a const iterator pointing to the first item in the binding list.
+ */
+
+/*!
+ \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::cendBindings() const
+ \return a const iterator pointing just after the last item in the binding list.
+ */
+
+/*!
+ \fn const QRhiVertexInputBinding *QRhiVertexInputLayout::bindingAt(qsizetype index) const
+ \return the binding at the given \a index.
+ */
+
+/*!
+ \fn qsizetype QRhiVertexInputLayout::bindingCount() const
+ \return the number of bindings.
+ */
+
+/*!
+ \fn void QRhiVertexInputLayout::setAttributes(std::initializer_list<QRhiVertexInputAttribute> list)
+ Sets the attributes from the specified \a list.
+ */
+
+/*!
+ \fn template<typename InputIterator> void QRhiVertexInputLayout::setAttributes(InputIterator first, InputIterator last)
+ Sets the attributes using the iterators \a first and \a last.
+ */
+
+/*!
+ \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cbeginAttributes() const
+ \return a const iterator pointing to the first item in the attribute list.
+ */
+
+/*!
+ \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::cendAttributes() const
+ \return a const iterator pointing just after the last item in the attribute list.
+ */
+
+/*!
+ \fn const QRhiVertexInputAttribute *QRhiVertexInputLayout::attributeAt(qsizetype index) const
+ \return the attribute at the given \a index.
+ */
+
+/*!
+ \fn qsizetype QRhiVertexInputLayout::attributeCount() const
+ \return the number of attributes.
+ */
+
+/*!
+ \fn bool QRhiVertexInputLayout::operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
+
\return \c true if the values in the two QRhiVertexInputLayout objects
\a a and \a b are equal.
-
- \relates QRhiVertexInputLayout
*/
-bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
-{
- return a.m_bindings == b.m_bindings && a.m_attributes == b.m_attributes;
-}
/*!
+ \fn bool QRhiVertexInputLayout::operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
+
\return \c false if the values in the two QRhiVertexInputLayout
objects \a a and \a b are equal; otherwise returns \c true.
-
- \relates QRhiVertexInputLayout
*/
-bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
-{
- return !(a == b);
-}
/*!
- \return the hash value for \a v, using \a seed to seed the calculation.
+ \fn size_t QRhiVertexInputLayout::qHash(const QRhiVertexInputLayout &v, size_t seed = 0) noexcept
- \relates QRhiVertexInputLayout
+ \return the hash value for \a v, using \a seed to seed the calculation.
*/
-size_t qHash(const QRhiVertexInputLayout &v, size_t seed) noexcept
-{
- return qHash(v.m_bindings, seed) + qHash(v.m_attributes, seed);
-}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
@@ -1378,9 +2084,39 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
/*!
\class QRhiShaderStage
- \internal
\inmodule QtGui
+ \since 6.6
\brief Specifies the type and the shader code for a shader stage in the pipeline.
+
+ When setting up a QRhiGraphicsPipeline, a collection of shader stages are
+ specified. The QRhiShaderStage contains a QShader and some associated
+ metadata, such as the graphics pipeline stage, and the
+ \l{QShader::Variant}{shader variant} to select. There is no need to specify
+ the shader language or version because the QRhi backend in use at runtime
+ will take care of choosing the appropriate shader version from the
+ collection within the QShader.
+
+ The typical usage is in combination with
+ QRhiGraphicsPipeline::setShaderStages(), shown here with a simple approach
+ to load the QShader from \c{.qsb} files generated offline or at build time:
+
+ \code
+ QShader getShader(const QString &name)
+ {
+ QFile f(name);
+ return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader();
+ }
+
+ QShader vs = getShader("material.vert.qsb");
+ QShader fs = getShader("material.frag.qsb");
+ pipeline->setShaderStages({
+ { QRhiShaderStage::Vertex, vs },
+ { QRhiShaderStage::Fragment, fs }
+ });
+ \endcode
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -1388,18 +2124,63 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputLayout &v)
Specifies the type of the shader stage.
\value Vertex Vertex stage
- \value Fragment Fragment (pixel) stage
- \value Compute Compute stage (this may not always be supported at run time)
+
+ \value TessellationControl Tessellation control (hull shader) stage. Must
+ be used only when the QRhi::Tessellation feature is supported.
+
+ \value TessellationEvaluation Tessellation evaluation (domain shader)
+ stage. Must be used only when the QRhi::Tessellation feature is supported.
+
+ \value Fragment Fragment (pixel shader) stage
+
+ \value Compute Compute stage. Must be used only when the QRhi::Compute
+ feature is supported.
+
+ \value Geometry Geometry stage. Must be used only when the
+ QRhi::GeometryShader feature is supported.
*/
/*!
- \fn QRhiShaderStage::QRhiShaderStage()
+ \fn QRhiShaderStage::QRhiShaderStage() = default
Constructs a shader stage description for the vertex stage with an empty
QShader.
*/
/*!
+ \fn QRhiShaderStage::Type QRhiShaderStage::type() const
+ \return the type of the stage.
+ */
+
+/*!
+ \fn void QRhiShaderStage::setType(Type t)
+
+ Sets the type of the stage to \a t. Setters should rarely be needed in
+ pratice. Most applications will likely use the QRhiShaderStage constructor
+ in most cases.
+ */
+
+/*!
+ \fn QShader QRhiShaderStage::shader() const
+ \return the QShader to be used for this stage in the graphics pipeline.
+ */
+
+/*!
+ \fn void QRhiShaderStage::setShader(const QShader &s)
+ Sets the shader collection \a s.
+ */
+
+/*!
+ \fn QShader::Variant QRhiShaderStage::shaderVariant() const
+ \return the requested shader variant.
+ */
+
+/*!
+ \fn void QRhiShaderStage::setShaderVariant(QShader::Variant v)
+ Sets the requested shader variant \a v.
+ */
+
+/*!
Constructs a shader stage description with the \a type of the stage and the
\a shader.
@@ -1416,38 +2197,24 @@ QRhiShaderStage::QRhiShaderStage(Type type, const QShader &shader, QShader::Vari
}
/*!
+ \fn bool QRhiShaderStage::operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
+
\return \c true if the values in the two QRhiShaderStage objects
\a a and \a b are equal.
-
- \relates QRhiShaderStage
*/
-bool operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
-{
- return a.type() == b.type()
- && a.shader() == b.shader()
- && a.shaderVariant() == b.shaderVariant();
-}
/*!
+ \fn bool QRhiShaderStage::operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
+
\return \c false if the values in the two QRhiShaderStage
objects \a a and \a b are equal; otherwise returns \c true.
-
- \relates QRhiShaderStage
*/
-bool operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
-{
- return !(a == b);
-}
/*!
- \return the hash value for \a v, using \a seed to seed the calculation.
+ \fn size_t QRhiShaderStage::qHash(const QRhiShaderStage &v, size_t seed = 0) noexcept
- \relates QRhiShaderStage
+ \return the hash value for \a v, using \a seed to seed the calculation.
*/
-size_t qHash(const QRhiShaderStage &v, size_t seed) noexcept
-{
- return v.type() + qHash(v.shader(), seed) + v.shaderVariant();
-}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
@@ -1463,12 +2230,14 @@ QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
/*!
\class QRhiColorAttachment
- \internal
\inmodule QtGui
+ \since 6.6
\brief Describes the a single color attachment of a render target.
A color attachment is either a QRhiTexture or a QRhiRenderBuffer. The
- former, when texture() is set, is used in most cases.
+ former, i.e. when texture() is set, is used in most cases.
+ QRhiColorAttachment is commonly used in combination with
+ QRhiTextureRenderTargetDescription.
\note texture() and renderBuffer() cannot be both set (be non-null at the
same time).
@@ -1483,7 +2252,7 @@ QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
When targeting a non-multisample texture, the layer() and level() indicate
the targeted layer (face index \c{0-5} for cubemaps) and mip level. For 3D
textures layer() specifies the slice (one 2D image within the 3D texture)
- to render to.
+ to render to. For texture arrays layer() is the array index.
When texture() or renderBuffer() is multisample, resolveTexture() can be
set optionally. When set, samples are resolved automatically into that
@@ -1495,10 +2264,15 @@ QDebug operator<<(QDebug dbg, const QRhiShaderStage &s)
\note when resolving is enabled, the multisample data may not be written
out at all. This means that the multisample texture() must not be used
afterwards with shaders for sampling when resolveTexture() is set.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ \sa QRhiTextureRenderTargetDescription
*/
/*!
- \fn QRhiColorAttachment::QRhiColorAttachment()
+ \fn QRhiColorAttachment::QRhiColorAttachment() = default
Constructs an empty color attachment description.
*/
@@ -1522,9 +2296,194 @@ QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
}
/*!
+ \fn QRhiTexture *QRhiColorAttachment::texture() const
+
+ \return the texture this attachment description references, or \nullptr if
+ there is none.
+ */
+
+/*!
+ \fn void QRhiColorAttachment::setTexture(QRhiTexture *tex)
+
+ Sets the texture \a tex.
+
+ \note texture() and renderBuffer() cannot be both set (be non-null at the
+ same time).
+ */
+
+/*!
+ \fn QRhiRenderBuffer *QRhiColorAttachment::renderBuffer() const
+
+ \return the renderbuffer this attachment description references, or
+ \nullptr if there is none.
+
+ In practice associating a QRhiRenderBuffer with a QRhiColorAttachment makes
+ the most sense when setting up multisample rendering via a multisample
+ \l{QRhiRenderBuffer::Type}{color} renderbuffer that is then resolved into a
+ non-multisample texture at the end of the render pass.
+ */
+
+/*!
+ \fn void QRhiColorAttachment::setRenderBuffer(QRhiRenderBuffer *rb)
+
+ Sets the renderbuffer \a rb.
+
+ \note texture() and renderBuffer() cannot be both set (be non-null at the
+ same time).
+ */
+
+/*!
+ \fn int QRhiColorAttachment::layer() const
+ \return the layer index (cubemap face or array layer). 0 by default.
+ */
+
+/*!
+ \fn void QRhiColorAttachment::setLayer(int layer)
+ Sets the \a layer index.
+ */
+
+/*!
+ \fn int QRhiColorAttachment::level() const
+ \return the mip level. 0 by default.
+ */
+
+/*!
+ \fn void QRhiColorAttachment::setLevel(int level)
+ Sets the mip \a level.
+ */
+
+/*!
+ \fn QRhiTexture *QRhiColorAttachment::resolveTexture() const
+
+ \return the resolve texture this attachment description references, or
+ \nullptr if there is none.
+
+ Setting a non-null resolve texture is applicable when the attachment
+ references a multisample texture or renderbuffer. The QRhiTexture in the
+ resolveTexture() is then a non-multisample 2D texture (or texture array)
+ with the same size (but a sample count of 1). The multisample content is
+ automatically resolved into this texture at the end of each render pass.
+ */
+
+/*!
+ \fn void QRhiColorAttachment::setResolveTexture(QRhiTexture *tex)
+
+ Sets the resolve texture \a tex.
+
+ \a tex is expected to be a 2D texture or a 2D texture array. In either
+ case, resolving targets a single mip level of a single layer (array
+ element) of \a tex. The mip level and array layer are specified by
+ resolveLevel() and resolveLayer().
+
+ An exception is \l{setMultiViewCount()}{multiview}: when the color
+ attachment is associated with a texture array and multiview is enabled, the
+ resolve texture must also be a texture array with sufficient elements for
+ all views. In this case all elements that correspond to views are resolved
+ automatically; the behavior is similar to the following pseudo-code:
+ \badcode
+ for (i = 0; i < multiViewCount(); ++i)
+ resolve texture's layer() + i into resolveTexture's resolveLayer() + i
+ \endcode
+
+ Setting a non-multisample texture to resolve a multisample texture or
+ renderbuffer automatically at the end of the render pass is often
+ preferable to working with multisample textures (and not setting a resolve
+ texture), because it avoids the need for writing dedicated fragment shaders
+ that work exclusively with multisample textures (\c sampler2DMS, \c
+ texelFetch, etc.), and rather allows using the same shader as one would if
+ the attachment's texture was not multisampled to begin with. This comes at
+ the expense of an additional resource (the non-multisample \a tex).
+ */
+
+/*!
+ \fn int QRhiColorAttachment::resolveLayer() const
+ \return the currently set resolve texture layer. Defaults to 0.
+ */
+
+/*!
+ \fn void QRhiColorAttachment::setResolveLayer(int layer)
+ Sets the resolve texture \a layer to use.
+ */
+
+/*!
+ \fn int QRhiColorAttachment::resolveLevel() const
+ \return the currently set resolve texture mip level. Defaults to 0.
+ */
+
+/*!
+ \fn void QRhiColorAttachment::setResolveLevel(int level)
+ Sets the resolve texture mip \a level to use.
+ */
+
+/*!
+ \fn int QRhiColorAttachment::multiViewCount() const
+
+ \return the currently set number of views. Defaults to 0 which indicates
+ the render target with this color attachment is not going to be used with
+ multiview rendering.
+
+ \since 6.7
+ */
+
+/*!
+ \fn void QRhiColorAttachment::setMultiViewCount(int count)
+
+ Sets the view \a count. Setting a value larger than 1 indicates that the
+ render target with this color attachment is going to be used with multiview
+ rendering. The default value is 0. Values smaller than 2 indicate no
+ multiview rendering.
+
+ When \a count is set to \c 2 or greater, the color attachment must be
+ associated with a 2D texture array. layer() and multiViewCount() together
+ define the range of texture array elements that are targeted during
+ multiview rendering.
+
+ For example, if \c layer is \c 0 and \c multiViewCount is \c 2, the texture
+ array must have 2 (or more) elements, and the multiview rendering will
+ target elements 0 and 1. The \c{gl_ViewIndex} variable in the shaders has a
+ value of \c 0 or \c 1 then, where view \c 0 corresponds to the texture array
+ element \c 0, and view \c 1 to the array element \c 1.
+
+ \note Setting a \a count larger than 1, using a texture array as texture(),
+ and calling \l{QRhiCommandBuffer::beginPass()}{beginPass()} on a
+ QRhiTextureRenderTarget with this color attachment implies multiview
+ rendering for the entire render pass. multiViewCount() should not be set
+ unless multiview rendering is wanted. Multiview cannot be used with texture
+ types other than 2D texture arrays. (although 3D textures may work,
+ depending on the graphics API and backend; applications are nonetheless
+ advised not to rely on that and only use 2D texture arrays as the render
+ targets of multiview rendering)
+
+ See
+ \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
+ for more details regarding multiview rendering. Do note that Qt requires
+ \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview2.txt}{GL_OVR_multiview2}
+ as well, when running on OpenGL (ES).
+
+ Multiview rendering is available only when the
+ \l{QRhi::MultiView}{MultiView} feature is reported as supported from
+ \l{QRhi::isFeatureSupported()}{isFeatureSupported()}.
+
+ \note For portability, be aware of limitations that exist for multiview
+ rendering with some of the graphics APIs. It is recommended that multiview
+ render passes do not rely on any of the features that
+ \l{https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt}{GL_OVR_multiview}
+ declares as unsupported. The one exception is shader stage outputs other
+ than \c{gl_Position} depending on \c{gl_ViewIndex}: that can be relied on
+ (even with OpenGL) because QRhi never reports multiview as supported without
+ \c{GL_OVR_multiview2} also being present.
+
+ \note Multiview rendering is not supported in combination with tessellation
+ or geometry shaders, even though some implementations of some graphics APIs
+ may allow this.
+
+ \since 6.7
+ */
+
+/*!
\class QRhiTextureRenderTargetDescription
- \internal
\inmodule QtGui
+ \since 6.6
\brief Describes the color and depth or depth/stencil attachments of a render target.
A texture render target has zero or more textures as color attachments,
@@ -1533,10 +2492,97 @@ QRhiColorAttachment::QRhiColorAttachment(QRhiRenderBuffer *renderBuffer)
\note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
non-null at the same time).
+
+ Let's look at some example usages in combination with
+ QRhiTextureRenderTarget.
+
+ Due to the constructors, the targeting a texture (and no depth/stencil
+ buffer) is simple:
+
+ \code
+ QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256), 1, QRhiTexture::RenderTarget);
+ texture->create();
+ QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture }));
+ \endcode
+
+ The following creates a texture render target that is set up to target mip
+ level #2 of a texture:
+
+ \code
+ QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget | QRhiTexture::MipMapped);
+ texture->create();
+ QRhiColorAttachment colorAtt(texture);
+ colorAtt.setLevel(2);
+ QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt });
+ \endcode
+
+ Another example, this time to render into a depth texture:
+
+ \code
+ QRhiTexture *shadowMap = rhi->newTexture(QRhiTexture::D32F, QSize(1024, 1024), 1, QRhiTexture::RenderTarget);
+ shadowMap->create();
+ QRhiTextureRenderTargetDescription rtDesc;
+ rtDesc.setDepthTexture(shadowMap);
+ QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
+ \endcode
+
+ A very common case, having a texture as the color attachment and a
+ renderbuffer as depth/stencil to enable depth testing:
+
+ \code
+ QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1. QRhiTexture::RenderTarget);
+ texture->create();
+ QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512));
+ depthStencil->create();
+ QRhiTextureRenderTargetDescription rtDesc({ texture }, depthStencil);
+ QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget(rtDesc);
+ \endcode
+
+ Finally, to enable multisample rendering in a portable manner (so also
+ supporting OpenGL ES 3.0), using a QRhiRenderBuffer as the (multisample)
+ color buffer and then resolving into a regular (non-multisample) 2D
+ texture. To enable depth testing, a depth-stencil buffer, which also must
+ use the same sample count, is used as well:
+
+ \code
+ QRhiRenderBuffer *colorBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::Color, QSize(512, 512), 4); // 4x MSAA
+ colorBuffer->create();
+ QRhiRenderBuffer *depthStencil = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(512, 512), 4);
+ depthStencil->create();
+ QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget);
+ texture->create();
+ QRhiColorAttachment colorAtt(colorBuffer);
+ colorAtt.setResolveTexture(texture);
+ QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ colorAtt, depthStencil });
+ \endcode
+
+ \note when multisample resolving is enabled, the multisample data may not be
+ written out at all. This means that the multisample texture in a color
+ attachment must not be used afterwards with shaders for sampling (or other
+ purposes) whenever a resolve texture is set, since the multisample color
+ buffer is merely an intermediate storage then that gets no data written back
+ on some GPU architectures at all. See
+ \l{QRhiTextureRenderTarget::Flag}{PreserveColorContents} for more details.
+
+ \note When using setDepthTexture(), not setDepthStencilBuffer(), and the
+ depth (stencil) data is not of interest afterwards, set the
+ DoNotStoreDepthStencilContents flag on the QRhiTextureRenderTarget. This
+ allows indicating to the underlying 3D API that the depth/stencil data can
+ be discarded, leading potentially to better performance with tiled GPU
+ architectures. When the depth-stencil buffer is a QRhiRenderBuffer (and also
+ for the multisample color texture, see previous note) this is implicit, but
+ with a depth (stencil) QRhiTexture the intention needs to be declared
+ explicitly. By default QRhi assumes that the data is of interest (e.g., the
+ depth texture is sampled in a shader afterwards).
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ \sa QRhiColorAttachment, QRhiTextureRenderTarget
*/
/*!
- \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription()
+ \fn QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription() = default
Constructs an empty texture render target description.
*/
@@ -1578,9 +2624,125 @@ QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRh
}
/*!
+ \fn void QRhiTextureRenderTargetDescription::setColorAttachments(std::initializer_list<QRhiColorAttachment> list)
+ Sets the \a list of color attachments.
+ */
+
+/*!
+ \fn template<typename InputIterator> void QRhiTextureRenderTargetDescription::setColorAttachments(InputIterator first, InputIterator last)
+ Sets the list of color attachments via the iterators \a first and \a last.
+ */
+
+/*!
+ \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cbeginColorAttachments() const
+ \return a const iterator pointing to the first item in the attachment list.
+ */
+
+/*!
+ \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::cendColorAttachments() const
+ \return a const iterator pointing just after the last item in the attachment list.
+ */
+
+/*!
+ \fn const QRhiColorAttachment *QRhiTextureRenderTargetDescription::colorAttachmentAt(qsizetype index) const
+ \return the color attachment at the specified \a index.
+ */
+
+/*!
+ \fn qsizetype QRhiTextureRenderTargetDescription::colorAttachmentCount() const
+ \return the number of currently set color attachments.
+ */
+
+/*!
+ \fn QRhiRenderBuffer *QRhiTextureRenderTargetDescription::depthStencilBuffer() const
+ \return the renderbuffer used as depth-stencil buffer, or \nullptr if none was set.
+ */
+
+/*!
+ \fn void QRhiTextureRenderTargetDescription::setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer)
+
+ Sets the \a renderBuffer for depth-stencil. Not mandatory, e.g. when no
+ depth test/write or stencil-related features are used within any graphics
+ pipelines in any of the render passes for this render target, it can be
+ left set to \nullptr.
+
+ \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
+ non-null at the same time).
+
+ Using a QRhiRenderBuffer over a 2D QRhiTexture as the depth or
+ depth/stencil buffer is very common, and is the recommended approach for
+ applications. Using a QRhiTexture, and so setDepthTexture() becomes
+ relevant if the depth data is meant to be accessed (e.g. sampled in a
+ shader) afterwards, or when
+ \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering} is
+ involved (because then the depth texture must be a texture array).
+
+ \sa setDepthTexture()
+ */
+
+/*!
+ \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthTexture() const
+ \return the currently referenced depth texture, or \nullptr if none was set.
+ */
+
+/*!
+ \fn void QRhiTextureRenderTargetDescription::setDepthTexture(QRhiTexture *texture)
+
+ Sets the \a texture for depth-stencil. This is an alternative to
+ setDepthStencilBuffer(), where instead of a QRhiRenderBuffer a QRhiTexture
+ with a suitable type (e.g., QRhiTexture::D32F) is provided.
+
+ \note depthStencilBuffer() and depthTexture() cannot be both set (cannot be
+ non-null at the same time).
+
+ \a texture can either be a 2D texture or a 2D texture array (when texture
+ arrays are supported). Specifying a texture array is relevant in particular
+ with
+ \l{QRhiColorAttachment::setMultiViewCount()}{multiview rendering}.
+
+ \note If \a texture is a format with a stencil component, such as
+ \l QRhiTexture::D24S8, it will serve as the stencil buffer as well.
+
+ \sa setDepthStencilBuffer()
+ */
+
+/*!
+ \fn QRhiTexture *QRhiTextureRenderTargetDescription::depthResolveTexture() const
+
+ \return the texture to which a multisample depth (or depth-stencil) texture
+ (or texture array) is resolved to. \nullptr if there is none, which is the
+ most common case.
+
+ \since 6.8
+ \sa QRhiColorAttachment::resolveTexture(), depthTexture()
+ */
+
+/*!
+ \fn void QRhiTextureRenderTargetDescription::setDepthResolveTexture(QRhiTexture *tex)
+
+ Sets the depth (or depth-stencil) resolve texture \a tex.
+
+ \a tex is expected to be a 2D texture or a 2D texture array with a format
+ matching the texture set via setDepthTexture().
+
+ \note Resolving depth (or depth-stencil) data is only functional when the
+ \l ResolveDepthStencil feature is reported as supported at run time. Support
+ for depth-stencil resolve is not universally available among the graphics
+ APIs. Designs assuming unconditional availability of depth-stencil resolve
+ are therefore non-portable, and should be avoided.
+
+ \note As an additional limitation for OpenGL ES in particular, setting a
+ depth resolve texture may only be functional in combination with
+ setDepthTexture(), not with setDepthStencilBuffer().
+
+ \since 6.8
+ \sa QRhiColorAttachment::setResolveTexture(), setDepthTexture()
+ */
+
+/*!
\class QRhiTextureSubresourceUploadDescription
- \internal
\inmodule QtGui
+ \since 6.6
\brief Describes the source for one mip level in a layer in a texture upload operation.
The source content is specified either as a QImage or as a raw blob. The
@@ -1626,10 +2788,26 @@ QRhiTextureRenderTargetDescription::QRhiTextureRenderTargetDescription(const QRh
QRhi::ImageDataStride is reported as
\l{QRhi::isFeatureSupported()}{supported}. In practice this can be expected
to be supported everywhere except for OpenGL ES 2.0.
+
+ \note When a QImage is given, the stride returned from
+ QImage::bytesPerLine() is taken into account automatically.
+
+ \warning When a QImage is given and the QImage does not own the underlying
+ pixel data, it is up to the caller to ensure that the associated data stays
+ valid until the end of the frame. (just submitting the resource update batch
+ is not sufficient, the data must stay valid until QRhi::endFrame() is called
+ in order to be portable across all backends) If this cannot be ensured, the
+ caller is strongly encouraged to call QImage::detach() on the image before
+ passing it to uploadTexture().
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ \sa QRhiTextureUploadDescription
*/
/*!
- \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription()
+ \fn QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription() = default
Constructs an empty subresource description.
@@ -1662,7 +2840,7 @@ QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription
\a data can safely be destroyed or changed once this function returns.
*/
-QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, int size)
+QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription(const void *data, quint32 size)
: m_data(reinterpret_cast<const char *>(data), size)
{
}
@@ -1677,10 +2855,109 @@ QRhiTextureSubresourceUploadDescription::QRhiTextureSubresourceUploadDescription
}
/*!
+ \fn QImage QRhiTextureSubresourceUploadDescription::image() const
+ \return the currently set QImage.
+ */
+
+/*!
+ \fn void QRhiTextureSubresourceUploadDescription::setImage(const QImage &image)
+
+ Sets \a image.
+ Upon textures loading, the image data will be read as is, with no formats conversions.
+
+ \note image() and data() cannot be both set at the same time.
+ */
+
+/*!
+ \fn QByteArray QRhiTextureSubresourceUploadDescription::data() const
+ \return the currently set raw pixel data.
+ */
+
+/*!
+ \fn void QRhiTextureSubresourceUploadDescription::setData(const QByteArray &data)
+
+ Sets \a data.
+
+ \note image() and data() cannot be both set at the same time.
+ */
+
+/*!
+ \fn quint32 QRhiTextureSubresourceUploadDescription::dataStride() const
+ \return the currently set data stride.
+ */
+
+/*!
+ \fn void QRhiTextureSubresourceUploadDescription::setDataStride(quint32 stride)
+
+ Sets the data \a stride in bytes. By default this is 0 and not always
+ relevant. When providing raw data(), and the stride is not specified via
+ setDataStride(), the stride (row pitch, row length in bytes) of the
+ provided data must be equal to \c{width * pixelSize} where \c pixelSize is
+ the number of bytes used for one pixel, and there must be no additional
+ padding between rows. Otherwise, if there is additional space between the
+ lines, set a non-zero \a stride. All this is applicable only when raw image
+ data is provided, and is not necessary when working QImage since that has
+ its own \l{QImage::bytesPerLine()}{stride} value.
+
+ \note Setting the stride via setDataStride() is only functional when
+ QRhi::ImageDataStride is reported as
+ \l{QRhi::isFeatureSupported()}{supported}.
+
+ \note When a QImage is given, the stride returned from
+ QImage::bytesPerLine() is taken into account automatically and therefore
+ there is no need to set the data stride manually.
+ */
+
+/*!
+ \fn QPoint QRhiTextureSubresourceUploadDescription::destinationTopLeft() const
+ \return the currently set destination top-left position. Defaults to (0, 0).
+ */
+
+/*!
+ \fn void QRhiTextureSubresourceUploadDescription::setDestinationTopLeft(const QPoint &p)
+ Sets the destination top-left position \a p.
+ */
+
+/*!
+ \fn QSize QRhiTextureSubresourceUploadDescription::sourceSize() const
+
+ \return the source size in pixels. Defaults to a default-constructed QSize,
+ which indicates the entire subresource.
+ */
+
+/*!
+ \fn void QRhiTextureSubresourceUploadDescription::setSourceSize(const QSize &size)
+
+ Sets the source \a size in pixels.
+
+ \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
+ internally, depending on the format and the backend.
+ */
+
+/*!
+ \fn QPoint QRhiTextureSubresourceUploadDescription::sourceTopLeft() const
+ \return the currently set source top-left position. Defaults to (0, 0).
+ */
+
+/*!
+ \fn void QRhiTextureSubresourceUploadDescription::setSourceTopLeft(const QPoint &p)
+
+ Sets the source top-left position \a p.
+
+ \note Setting sourceSize() or sourceTopLeft() may trigger a QImage copy
+ internally, depending on the format and the backend.
+ */
+
+/*!
\class QRhiTextureUploadEntry
- \internal
\inmodule QtGui
- \brief Describes one layer (face for cubemaps) in a texture upload operation.
+ \since 6.6
+
+ \brief Describes one layer (face for cubemaps, slice for 3D textures,
+ element for texture arrays) in a texture upload operation.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -1706,18 +2983,61 @@ QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
}
/*!
+ \fn int QRhiTextureUploadEntry::layer() const
+ \return the currently set layer index (cubemap face, array layer). Defaults to 0.
+ */
+
+/*!
+ \fn void QRhiTextureUploadEntry::setLayer(int layer)
+ Sets the \a layer.
+ */
+
+/*!
+ \fn int QRhiTextureUploadEntry::level() const
+ \return the currently set mip level. Defaults to 0.
+ */
+
+/*!
+ \fn void QRhiTextureUploadEntry::setLevel(int level)
+ Sets the mip \a level.
+ */
+
+/*!
+ \fn QRhiTextureSubresourceUploadDescription QRhiTextureUploadEntry::description() const
+ \return the currently set subresource description.
+ */
+
+/*!
+ \fn void QRhiTextureUploadEntry::setDescription(const QRhiTextureSubresourceUploadDescription &desc)
+ Sets the subresource description \a desc.
+ */
+
+/*!
\class QRhiTextureUploadDescription
- \internal
\inmodule QtGui
+ \since 6.6
\brief Describes a texture upload operation.
Used with QRhiResourceUpdateBatch::uploadTexture(). That function has two
variants: one taking a QImage and one taking a
QRhiTextureUploadDescription. The former is a convenience version,
internally creating a QRhiTextureUploadDescription with a single image
- targeting level 0 for layer 0. However, when cubemaps, pre-generated mip
- images, or compressed textures are involved, applications will have to work
- directly with this class instead.
+ targeting level 0 for layer 0.
+
+ An example of the the common, simple case of wanting to upload the contents
+ of a QImage to a QRhiTexture with a matching pixel size:
+
+ \code
+ QImage image(256, 256, QImage::Format_RGBA8888);
+ image.fill(Qt::green); // or could use a QPainter targeting image
+ QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(256, 256));
+ texture->create();
+ QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
+ u->uploadTexture(texture, image);
+ \endcode
+
+ When cubemaps, pre-generated mip images, compressed textures, or partial
+ uploads are involved, applications will have to use this class instead.
QRhiTextureUploadDescription also enables specifying batched uploads, which
are useful for example when generating an atlas or glyph cache texture:
@@ -1733,32 +3053,35 @@ QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
For example, specifying the faces of a cubemap could look like the following:
- \badcode
+ \code
QImage faces[6];
- ...
- QList<QRhiTextureUploadEntry> entries;
+ // ...
+ QVarLengthArray<QRhiTextureUploadEntry, 6> entries;
for (int i = 0; i < 6; ++i)
entries.append(QRhiTextureUploadEntry(i, 0, faces[i]));
- QRhiTextureUploadDescription desc(entries);
+ QRhiTextureUploadDescription desc;
+ desc.setEntries(entries.cbegin(), entries.cend());
resourceUpdates->uploadTexture(texture, desc);
\endcode
Another example that specifies mip images for a compressed texture:
- \badcode
- QRhiTextureUploadDescription desc;
+ \code
+ QList<QRhiTextureUploadEntry> entries;
const int mipCount = rhi->mipLevelsForSize(compressedTexture->pixelSize());
for (int level = 0; level < mipCount; ++level) {
const QByteArray compressedDataForLevel = ..
- desc.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
+ entries.append(QRhiTextureUploadEntry(0, level, compressedDataForLevel));
}
+ QRhiTextureUploadDescription desc;
+ desc.setEntries(entries.cbegin(), entries.cend());
resourceUpdates->uploadTexture(compressedTexture, desc);
\endcode
With partial uploads targeting the same subresource, it is recommended to
batch them into a single upload request, whenever possible:
- \badcode
+ \code
QRhiTextureSubresourceUploadDescription subresDesc(image);
subresDesc.setSourceSize(QSize(10, 10));
subResDesc.setDestinationTopLeft(QPoint(50, 40));
@@ -1772,6 +3095,11 @@ QRhiTextureUploadEntry::QRhiTextureUploadEntry(int layer, int level,
QRhiTextureUploadDescription desc({ entry, entry2});
resourceUpdates->uploadTexture(texture, desc);
\endcode
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ \sa QRhiResourceUpdateBatch
*/
/*!
@@ -1804,9 +3132,39 @@ QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list
}
/*!
+ \fn void QRhiTextureUploadDescription::setEntries(std::initializer_list<QRhiTextureUploadEntry> list)
+ Sets the \a list of entries.
+ */
+
+/*!
+ \fn template<typename InputIterator> void QRhiTextureUploadDescription::setEntries(InputIterator first, InputIterator last)
+ Sets the list of entries using the iterators \a first and \a last.
+ */
+
+/*!
+ \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cbeginEntries() const
+ \return a const iterator pointing to the first item in the entry list.
+ */
+
+/*!
+ \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::cendEntries() const
+ \return a const iterator pointing just after the last item in the entry list.
+ */
+
+/*!
+ \fn const QRhiTextureUploadEntry *QRhiTextureUploadDescription::entryAt(qsizetype index) const
+ \return the entry at \a index.
+ */
+
+/*!
+ \fn qsizetype QRhiTextureUploadDescription::entryCount() const
+ \return the number of entries.
+ */
+
+/*!
\class QRhiTextureCopyDescription
- \internal
\inmodule QtGui
+ \since 6.6
\brief Describes a texture-to-texture copy operation.
An empty pixelSize() indicates that the entire subresource is to be copied.
@@ -1820,12 +3178,15 @@ QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list
sourceTopLeft(), and destinationTopLeft() must fit the source and
destination textures, respectively. The behavior is undefined otherwise.
- With cubemap and 3D textures one face or slice can be copied at a time. The
- face or slice is specified by the source and destination layer indices.
- With mipmapped textures one mip level can be copied at a time. The source
- and destination layer and mip level indices can differ, but the size and
- position must be carefully controlled to avoid out of bounds copies, in
- which case the behavior is undefined.
+ With cubemaps, 3D textures, and texture arrays one face or slice can be
+ copied at a time. The face or slice is specified by the source and
+ destination layer indices. With mipmapped textures one mip level can be
+ copied at a time. The source and destination layer and mip level indices can
+ differ, but the size and position must be carefully controlled to avoid out
+ of bounds copies, in which case the behavior is undefined.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -1835,9 +3196,83 @@ QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list
*/
/*!
+ \fn QSize QRhiTextureCopyDescription::pixelSize() const
+ \return the size of the region to copy.
+
+ \note An empty pixelSize() indicates that the entire subresource is to be
+ copied. A default constructed copy description therefore leads to copying
+ the entire subresource at level 0 of layer 0.
+ */
+
+/*!
+ \fn void QRhiTextureCopyDescription::setPixelSize(const QSize &sz)
+ Sets the size of the region to copy to \a sz.
+ */
+
+/*!
+ \fn int QRhiTextureCopyDescription::sourceLayer() const
+ \return the source array layer (cubemap face or array layer index). Defaults to 0.
+ */
+
+/*!
+ \fn void QRhiTextureCopyDescription::setSourceLayer(int layer)
+ Sets the source array \a layer.
+ */
+
+/*!
+ \fn int QRhiTextureCopyDescription::sourceLevel() const
+ \return the source mip level. Defaults to 0.
+ */
+
+/*!
+ \fn void QRhiTextureCopyDescription::setSourceLevel(int level)
+ Sets the source mip \a level.
+ */
+
+/*!
+ \fn QPoint QRhiTextureCopyDescription::sourceTopLeft() const
+ \return the source top-left position (in pixels). Defaults to (0, 0).
+ */
+
+/*!
+ \fn void QRhiTextureCopyDescription::setSourceTopLeft(const QPoint &p)
+ Sets the source top-left position to \a p.
+ */
+
+/*!
+ \fn int QRhiTextureCopyDescription::destinationLayer() const
+ \return the destination array layer (cubemap face or array layer index). Default to 0.
+ */
+
+/*!
+ \fn void QRhiTextureCopyDescription::setDestinationLayer(int layer)
+ Sets the destination array \a layer.
+ */
+
+/*!
+ \fn int QRhiTextureCopyDescription::destinationLevel() const
+ \return the destionation mip level. Defaults to 0.
+ */
+
+/*!
+ \fn void QRhiTextureCopyDescription::setDestinationLevel(int level)
+ Sets the destination mip \a level.
+ */
+
+/*!
+ \fn QPoint QRhiTextureCopyDescription::destinationTopLeft() const
+ \return the destionation top-left position in pixels. Defaults to (0, 0).
+ */
+
+/*!
+ \fn void QRhiTextureCopyDescription::setDestinationTopLeft(const QPoint &p)
+ Sets the destination top-left position \a p.
+ */
+
+/*!
\class QRhiReadbackDescription
- \internal
\inmodule QtGui
+ \since 6.6
\brief Describes a readback (reading back texture contents from possibly GPU-only memory) operation.
The source of the readback operation is either a QRhiTexture or the
@@ -1855,10 +3290,13 @@ QRhiTextureUploadDescription::QRhiTextureUploadDescription(std::initializer_list
\note Multisample textures cannot be read back. Readbacks are supported for
multisample swapchain buffers however.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
- \fn QRhiReadbackDescription::QRhiReadbackDescription()
+ \fn QRhiReadbackDescription::QRhiReadbackDescription() = default
Constructs an empty texture readback description.
@@ -1882,32 +3320,140 @@ QRhiReadbackDescription::QRhiReadbackDescription(QRhiTexture *texture)
}
/*!
+ \fn QRhiTexture *QRhiReadbackDescription::texture() const
+
+ \return the QRhiTexture that is read back. Can be left set to \nullptr
+ which indicates that the backbuffer of the current swapchain is to be used
+ instead.
+ */
+
+/*!
+ \fn void QRhiReadbackDescription::setTexture(QRhiTexture *tex)
+
+ Sets the texture \a tex as the source of the readback operation.
+
+ Setting \nullptr is valid too, in which case the current swapchain's
+ current backbuffer is used. (but then the readback cannot be issued in a
+ non-swapchain-based frame)
+
+ \note Multisample textures cannot be read back. Readbacks are supported for
+ multisample swapchain buffers however.
+
+ \note Textures used in readbacks must be created with
+ QRhiTexture::UsedAsTransferSource.
+
+ \note Swapchains used in readbacks must be created with
+ QRhiSwapChain::UsedAsTransferSource.
+ */
+
+/*!
+ \fn int QRhiReadbackDescription::layer() const
+
+ \return the currently set array layer (cubemap face, array index). Defaults to 0.
+
+ Applicable only when the source of the readback is a QRhiTexture.
+ */
+
+/*!
+ \fn void QRhiReadbackDescription::setLayer(int layer)
+ Sets the array \a layer to read back.
+ */
+
+/*!
+ \fn int QRhiReadbackDescription::level() const
+
+ \return the currently set mip level. Defaults to 0.
+
+ Applicable only when the source of the readback is a QRhiTexture.
+ */
+
+/*!
+ \fn void QRhiReadbackDescription::setLevel(int level)
+ Sets the mip \a level to read back.
+ */
+
+/*!
\class QRhiReadbackResult
- \internal
\inmodule QtGui
- \brief Describes the results of a potentially asynchronous readback operation.
+ \since 6.6
+ \brief Describes the results of a potentially asynchronous buffer or texture readback operation.
When \l completed is set, the function is invoked when the \l data is
available. \l format and \l pixelSize are set upon completion together with
\l data.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+ */
+
+/*!
+ \variable QRhiReadbackResult::completed
+
+ Callback that is invoked upon completion, on the thread the QRhi operates
+ on. Can be left set to \nullptr, in which case no callback is invoked.
+ */
+
+/*!
+ \variable QRhiReadbackResult::format
+
+ Valid only for textures, the texture format.
+ */
+
+/*!
+ \variable QRhiReadbackResult::pixelSize
+
+ Valid only for textures, the size in pixels.
+ */
+
+/*!
+ \variable QRhiReadbackResult::data
+
+ The buffer or image data.
+
+ \sa QRhiResourceUpdateBatch::readBackTexture(), QRhiResourceUpdateBatch::readBackBuffer()
*/
+
/*!
\class QRhiNativeHandles
- \internal
\inmodule QtGui
+ \since 6.6
\brief Base class for classes exposing backend-specific collections of native resource objects.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
\class QRhiResource
- \internal
\inmodule QtGui
+ \since 6.6
\brief Base class for classes encapsulating native resource objects.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
- \fn QRhiResource::Type QRhiResource::resourceType() const
+ \enum QRhiResource::Type
+ Specifies type of the resource.
+
+ \value Buffer
+ \value Texture
+ \value Sampler
+ \value RenderBuffer
+ \value RenderPassDescriptor
+ \value SwapChainRenderTarget
+ \value TextureRenderTarget
+ \value ShaderResourceBindings
+ \value GraphicsPipeline
+ \value SwapChain
+ \value ComputePipeline
+ \value CommandBuffer
+ */
+
+/*!
+ \fn virtual QRhiResource::Type QRhiResource::resourceType() const = 0
\return the type of the resource.
*/
@@ -1939,7 +3485,7 @@ QRhiResource::~QRhiResource()
}
/*!
- \fn void QRhiResource::destroy()
+ \fn virtual void QRhiResource::destroy() = 0
Releases (or requests deferred releasing of) the underlying native graphics
resources. Safe to call multiple times, subsequent invocations will be a
@@ -1953,7 +3499,7 @@ QRhiResource::~QRhiResource()
released until the frame is submitted by QRhi::endFrame().
The QRhiResource destructor also performs the same task, so calling this
- function is not necessary before destroying a QRhiResource.
+ function is not necessary before deleting a QRhiResource.
\sa deleteLater()
*/
@@ -1966,11 +3512,42 @@ QRhiResource::~QRhiResource()
requirement of not altering QRhiResource objects that are referenced by the
frame being recorded.
+ If the QRhi that created this object is already destroyed, the object is
+ deleted immediately.
+
+ Using deleteLater() can be a useful convenience in many cases, and it
+ complements the low-level guarantee (that the underlying native graphics
+ objects are never destroyed until it is safe to do so and it is known for
+ sure that they are not used by the GPU in an still in-flight frame), by
+ offering a way to make sure the C++ object instances (of QRhiBuffer,
+ QRhiTexture, etc.) themselves also stay valid until the end of the current
+ frame.
+
+ The following example shows a convenient way of creating a throwaway buffer
+ that is only used in one frame and gets automatically released in
+ endFrame(). (when it comes to the underlying native buffer(s), the usual
+ guarantee applies: the QRhi backend defers the releasing of those until it
+ is guaranteed that the frame in which the buffer is accessed by the GPU has
+ completed)
+
+ \code
+ rhi->beginFrame(swapchain);
+ QRhiBuffer *buf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, 256);
+ buf->deleteLater(); // !
+ u = rhi->nextResourceUpdateBatch();
+ u->uploadStaticBuffer(buf, data);
+ // ... draw with buf
+ rhi->endFrame();
+ \endcode
+
\sa destroy()
*/
void QRhiResource::deleteLater()
{
- m_rhi->addDeleteLater(this);
+ if (m_rhi)
+ m_rhi->addDeleteLater(this);
+ else
+ delete this;
}
/*!
@@ -1984,11 +3561,10 @@ QByteArray QRhiResource::name() const
/*!
Sets a \a name for the object.
- This has two uses: to get descriptive names for the native graphics
+ This allows getting descriptive names for the native graphics
resources visible in graphics debugging tools, such as
\l{https://renderdoc.org/}{RenderDoc} and
- \l{https://developer.apple.com/xcode/}{XCode}, and in the output stream of
- QRhiProfiler.
+ \l{https://developer.apple.com/xcode/}{XCode}.
When it comes to naming native objects by relaying the name via the
appropriate graphics API, note that the name is ignored when
@@ -2005,7 +3581,6 @@ QByteArray QRhiResource::name() const
void QRhiResource::setName(const QByteArray &name)
{
m_objectName = name;
- m_objectName.replace(',', '_'); // cannot contain comma for QRhiProfiler
}
/*!
@@ -2020,10 +3595,141 @@ quint64 QRhiResource::globalResourceId() const
}
/*!
+ \return the QRhi that created this resource.
+
+ If the QRhi that created this object is already destroyed, the result is
+ \nullptr.
+ */
+QRhi *QRhiResource::rhi() const
+{
+ return m_rhi ? m_rhi->q : nullptr;
+}
+
+/*!
\class QRhiBuffer
- \internal
\inmodule QtGui
+ \since 6.6
\brief Vertex, index, or uniform (constant) buffer resource.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ A QRhiBuffer encapsulates zero, one, or more native buffer objects (such as
+ a \c VkBuffer or \c MTLBuffer). With some graphics APIs and backends
+ certain types of buffers may not use a native buffer object at all (e.g.
+ OpenGL if uniform buffer objects are not used), but this is transparent to
+ the user of the QRhiBuffer API. Similarly, the fact that some types of
+ buffers may use two or three native buffers underneath, in order to allow
+ efficient per-frame content update without stalling the GPU pipeline, is
+ mostly invisible to the applications and libraries.
+
+ A QRhiBuffer instance is always created by calling
+ \l{QRhi::newBuffer()}{the QRhi's newBuffer() function}. This creates no
+ native graphics resources. To do that, call create() after setting the
+ appropriate options, such as the type, usage flags, size, although in most cases these
+ are already set based on the arguments passed to
+ \l{QRhi::newBuffer()}{newBuffer()}.
+
+ \section2 Example usage
+
+ To create a uniform buffer for a shader where the GLSL uniform block
+ contains a single \c mat4 member, and update the contents:
+
+ \code
+ QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64);
+ if (!ubuf->create()) { error(); }
+ QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
+ QMatrix4x4 mvp;
+ // ... set up the modelview-projection matrix
+ batch->updateDynamicBuffer(ubuf, 0, 64, mvp.constData());
+ // ...
+ commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
+ \endcode
+
+ An example of creating a buffer with vertex data:
+
+ \code
+ const float vertices[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
+ QRhiBuffer *vbuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertices));
+ if (!vbuf->create()) { error(); }
+ QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
+ batch->uploadStaticBuffer(vbuf, vertices);
+ // ...
+ commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
+ \endcode
+
+ An index buffer:
+
+ \code
+ static const quint16 indices[] = { 0, 1, 2 };
+ QRhiBuffer *ibuf = rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(indices));
+ if (!ibuf->create()) { error(); }
+ QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
+ batch->uploadStaticBuffer(ibuf, indices);
+ // ...
+ commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
+ \endcode
+
+ \section2 Common patterns
+
+ A call to create() destroys any existing native resources if create() was
+ successfully called before. If those native resources are still in use by
+ an in-flight frame (i.e., there's a chance they are still read by the GPU),
+ the destroying of those resources is deferred automatically. Thus a very
+ common and convenient pattern to safely increase the size of an already
+ initialized buffer is the following. In practice this drops and creates a
+ whole new set of native resources underneath, so it is not necessarily a
+ cheap operation, but is more convenient and still faster than the
+ alternatives, because by not destroying the \c buf object itself, all
+ references to it stay valid in other data structures (e.g., in any
+ QRhiShaderResourceBinding the QRhiBuffer is referenced from).
+
+ \code
+ if (buf->size() < newSize) {
+ buf->setSize(newSize);
+ if (!buf->create()) { error(); }
+ }
+ // continue using buf, fill it with new data
+ \endcode
+
+ When working with uniform buffers, it will sometimes be necessary to
+ combine data for multiple draw calls into a single buffer for efficiency
+ reasons. Be aware of the aligment requirements: with some graphics APIs
+ offsets for a uniform buffer must be aligned to 256 bytes. This applies
+ both to QRhiShaderResourceBinding and to the dynamic offsets passed to
+ \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}. Use the
+ \l{QRhi::ubufAlignment()}{ubufAlignment()} and
+ \l{QRhi::ubufAligned()}{ubufAligned()} functions to create portable code.
+ As an example, the following is an outline for issuing multiple (\c N) draw
+ calls with the same pipeline and geometry, but with a different data in the
+ uniform buffers exposed at binding point 0. This assumes the buffer is
+ exposed via
+ \l{QRhiShaderResourceBinding::uniformBufferWithDynamicOffset()}{uniformBufferWithDynamicOffset()}
+ which allows passing a QRhiCommandBuffer::DynamicOffset list to
+ \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()}.
+
+ \code
+ const int N = 2;
+ const int UB_SIZE = 64 + 4; // assuming a uniform block with { mat4 matrix; float opacity; }
+ const int ONE_UBUF_SIZE = rhi->ubufAligned(UB_SIZE);
+ const int TOTAL_UBUF_SIZE = N * ONE_UBUF_SIZE;
+ QRhiBuffer *ubuf = rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, TOTAL_UBUF_SIZE);
+ if (!ubuf->create()) { error(); }
+ QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
+ for (int i = 0; i < N; ++i) {
+ batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE, 64, matrix.constData());
+ batch->updateDynamicBuffer(ubuf, i * ONE_UBUF_SIZE + 64, 4, &opacity);
+ }
+ // ...
+ // beginPass(), set pipeline, etc., and then:
+ for (int i = 0; i < N; ++i) {
+ QRhiCommandBuffer::DynamicOffset dynOfs[] = { { 0, i * ONE_UBUF_SIZE } };
+ cb->setShaderResources(srb, 1, dynOfs);
+ cb->draw(36);
+ }
+ \endcode
+
+ \sa QRhiResourceUpdateBatch, QRhi, QRhiCommandBuffer
*/
/*!
@@ -2059,42 +3765,29 @@ quint64 QRhiResource::globalResourceId() const
Flag values to specify how the buffer is going to be used.
\value VertexBuffer Vertex buffer. This allows the QRhiBuffer to be used in
- \l{setVertexInput()}{QRhiCommandBuffer::setVertexInput()}.
+ \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
\value IndexBuffer Index buffer. This allows the QRhiBuffer to be used in
- \l{setVertexInput()}{QRhiCommandBuffer::setVertexInput()}.
+ \l{QRhiCommandBuffer::setVertexInput()}{setVertexInput()}.
\value UniformBuffer Uniform buffer (also called constant buffer). This
allows the QRhiBuffer to be used in combination with
- \l{UniformBuffer}{QRhiShaderResourceBinding::UniformBuffer}. When
+ \l{QRhiShaderResourceBinding::UniformBuffer}{UniformBuffer}. When
\l{QRhi::NonDynamicUniformBuffers}{NonDynamicUniformBuffers} is reported as
not supported, this usage can only be combined with the type Dynamic.
\value StorageBuffer Storage buffer. This allows the QRhiBuffer to be used
- in combination with \l{BufferLoad}{QRhiShaderResourceBinding::BufferLoad},
- \l{BufferStore}{QRhiShaderResourceBinding::BufferStore}, or
- \l{BufferLoadStore}{QRhiShaderResourceBinding::BufferLoadStore}. This usage
+ in combination with \l{QRhiShaderResourceBinding::BufferLoad}{BufferLoad},
+ \l{QRhiShaderResourceBinding::BufferStore}{BufferStore}, or
+ \l{QRhiShaderResourceBinding::BufferLoadStore}{BufferLoadStore}. This usage
can only be combined with the types Immutable or Static, and is only
available when the \l{QRhi::Compute}{Compute feature} is reported as
supported.
*/
/*!
- \fn void QRhiBuffer::setSize(int sz)
-
- Sets the size of the buffer in bytes. The size is normally specified in
- QRhi::newBuffer() so this function is only used when the size has to be
- changed. As with other setters, the size only takes effect when calling
- create(), and for already created buffers this involves releasing the previous
- native resource and creating new ones under the hood.
-
- Backends may choose to allocate buffers bigger than \a sz in order to
- fulfill alignment requirements. This is hidden from the applications and
- size() will always report the size requested in \a sz.
- */
-
-/*!
\class QRhiBuffer::NativeBuffer
+ \inmodule QtGui
\brief Contains information about the underlying native resources of a buffer.
*/
@@ -2106,10 +3799,13 @@ quint64 QRhiResource::globalResourceId() const
objects array are pointers to a GLuint. With Vulkan, the native handle is a
VkBuffer, so the elements of the array are pointers to a VkBuffer. With
Direct3D 11 and Metal the elements are pointers to a ID3D11Buffer or
- MTLBuffer pointer, respectively.
+ MTLBuffer pointer, respectively. With Direct3D 12, the elements are
+ pointers to a ID3D12Resource.
\note Pay attention to the fact that the elements are always pointers to
the native buffer handle type, even if the native type itself is a pointer.
+ (so the elements are \c{VkBuffer *} on Vulkan, even though VkBuffer itself
+ is a pointer on 64-bit architectures).
*/
/*!
@@ -2130,7 +3826,7 @@ quint64 QRhiResource::globalResourceId() const
/*!
\internal
*/
-QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, int size_)
+QRhiBuffer::QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, quint32 size_)
: QRhiResource(rhi),
m_type(type_), m_usage(usage_), m_size(size_)
{
@@ -2145,7 +3841,7 @@ QRhiResource::Type QRhiBuffer::resourceType() const
}
/*!
- \fn bool QRhiBuffer::create()
+ \fn virtual bool QRhiBuffer::create() = 0
Creates the corresponding native graphics resources. If there are already
resources present due to an earlier create() with no corresponding
@@ -2156,6 +3852,50 @@ QRhiResource::Type QRhiBuffer::resourceType() const
*/
/*!
+ \fn QRhiBuffer::Type QRhiBuffer::type() const
+ \return the buffer type.
+ */
+
+/*!
+ \fn void QRhiBuffer::setType(Type t)
+ Sets the buffer's type to \a t.
+ */
+
+/*!
+ \fn QRhiBuffer::UsageFlags QRhiBuffer::usage() const
+ \return the buffer's usage flags.
+ */
+
+/*!
+ \fn void QRhiBuffer::setUsage(UsageFlags u)
+ Sets the buffer's usage flags to \a u.
+ */
+
+/*!
+ \fn quint32 QRhiBuffer::size() const
+
+ \return the buffer's size in bytes.
+
+ This is always the value that was passed to setSize() or QRhi::newBuffer().
+ Internally, the native buffers may be bigger if that is required by the
+ underlying graphics API.
+ */
+
+/*!
+ \fn void QRhiBuffer::setSize(quint32 sz)
+
+ Sets the size of the buffer in bytes. The size is normally specified in
+ QRhi::newBuffer() so this function is only used when the size has to be
+ changed. As with other setters, the size only takes effect when calling
+ create(), and for already created buffers this involves releasing the previous
+ native resource and creating new ones under the hood.
+
+ Backends may choose to allocate buffers bigger than \a sz in order to
+ fulfill alignment requirements. This is hidden from the applications and
+ size() will always report the size requested in \a sz.
+ */
+
+/*!
\return the underlying native resources for this buffer. The returned value
will be empty if exposing the underlying native resources is not supported by
the backend.
@@ -2214,7 +3954,7 @@ QRhiBuffer::NativeBuffer QRhiBuffer::nativeBuffer()
depending on the backend.
\warning When updating buffer data via this method, the update must be done
- in every frame, otherwise backends that perform double or tripple buffering
+ in every frame, otherwise backends that perform double or triple buffering
of resources may end up in unexpected behavior.
\warning Partial updates are not possible with this approach since some
@@ -2243,18 +3983,18 @@ void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
/*!
\class QRhiRenderBuffer
- \internal
\inmodule QtGui
+ \since 6.6
\brief Renderbuffer resource.
Renderbuffers cannot be sampled or read but have some benefits over
textures in some cases:
- A DepthStencil renderbuffer may be lazily allocated and be backed by
+ A \l DepthStencil renderbuffer may be lazily allocated and be backed by
transient memory with some APIs. On some platforms this may mean the
depth/stencil buffer uses no physical backing at all.
- Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
+ \l Color renderbuffers are useful since QRhi::MultisampleRenderBuffer may be
supported even when QRhi::MultisampleTexture is not.
How the renderbuffer is implemented by a backend is not exposed to the
@@ -2268,6 +4008,9 @@ void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
QRhi provides automatic sizing behavior to match the color buffers, which
means calling setPixelSize() and create() are not necessary for such
renderbuffers.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -2279,6 +4022,22 @@ void QRhiBuffer::endFullDynamicBufferUpdateForCurrentFrame()
*/
/*!
+ \struct QRhiRenderBuffer::NativeRenderBuffer
+ \inmodule QtGui
+ \brief Wraps a native renderbuffer object.
+ */
+
+/*!
+ \variable QRhiRenderBuffer::NativeRenderBuffer::object
+ \brief 64-bit integer containing the native object handle.
+
+ Used with QRhiRenderBuffer::createFrom().
+
+ With OpenGL the native handle is a GLuint value. \c object is expected to
+ be a valid OpenGL renderbuffer object ID.
+ */
+
+/*!
\enum QRhiRenderBuffer::Flag
Flag values for flags() and setFlags()
@@ -2315,7 +4074,7 @@ QRhiResource::Type QRhiRenderBuffer::resourceType() const
}
/*!
- \fn bool QRhiRenderBuffer::create()
+ \fn virtual bool QRhiRenderBuffer::create() = 0
Creates the corresponding native graphics resources. If there are already
resources present due to an earlier create() with no corresponding
@@ -2364,16 +4123,121 @@ bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
}
/*!
- \fn QRhiTexture::Format QRhiRenderBuffer::backingFormat() const
+ \fn QRhiRenderBuffer::Type QRhiRenderBuffer::type() const
+ \return the renderbuffer type.
+ */
+
+/*!
+ \fn void QRhiRenderBuffer::setType(Type t)
+ Sets the type to \a t.
+ */
+
+/*!
+ \fn QSize QRhiRenderBuffer::pixelSize() const
+ \return the pixel size.
+ */
+
+/*!
+ \fn void QRhiRenderBuffer::setPixelSize(const QSize &sz)
+ Sets the size (in pixels) to \a sz.
+ */
+
+/*!
+ \fn int QRhiRenderBuffer::sampleCount() const
+ \return the sample count. 1 means no multisample antialiasing.
+ */
+
+/*!
+ \fn void QRhiRenderBuffer::setSampleCount(int s)
+ Sets the sample count to \a s.
+ */
+
+/*!
+ \fn QRhiRenderBuffer::Flags QRhiRenderBuffer::flags() const
+ \return the flags.
+ */
+
+/*!
+ \fn void QRhiRenderBuffer::setFlags(Flags f)
+ Sets the flags to \a f.
+ */
+
+/*!
+ \fn virtual QRhiTexture::Format QRhiRenderBuffer::backingFormat() const = 0
\internal
*/
/*!
\class QRhiTexture
- \internal
\inmodule QtGui
+ \since 6.6
\brief Texture resource.
+
+ A QRhiTexture encapsulates a native texture object, such as a \c VkImage or
+ \c MTLTexture.
+
+ A QRhiTexture instance is always created by calling
+ \l{QRhi::newTexture()}{the QRhi's newTexture() function}. This creates no
+ native graphics resources. To do that, call create() after setting the
+ appropriate options, such as the format and size, although in most cases
+ these are already set based on the arguments passed to
+ \l{QRhi::newTexture()}{newTexture()}.
+
+ Setting the \l{QRhiTexture::Flags}{flags} correctly is essential, otherwise
+ various errors can occur depending on the underlying QRhi backend and
+ graphics API. For example, when a texture will be rendered into from a
+ render pass via QRhiTextureRenderTarget, the texture must be created with
+ the \l RenderTarget flag set. Similarly, when the texture is going to be
+ \l{QRhiResourceUpdateBatch::readBackTexture()}{read back}, the \l
+ UsedAsTransferSource flag must be set upfront. Mipmapped textures must have
+ the MipMapped flag set. And so on. It is not possible to change the flags
+ once create() has succeeded. To release the existing and create a new
+ native texture object with the changed settings, call the setters and call
+ create() again. This then might be a potentially expensive operation.
+
+ \section2 Example usage
+
+ To create a 2D texture with a size of 512x512 pixels and set its contents to all green:
+
+ \code
+ QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, QSize(512, 512));
+ if (!texture->create()) { error(); }
+ QRhiResourceUpdateBatch *batch = rhi->nextResourceUpdateBatch();
+ QImage image(512, 512, QImage::Format_RGBA8888);
+ image.fill(Qt::green);
+ batch->uploadTexture(texture, image);
+ // ...
+ commandBuffer->resourceUpdate(batch); // or, alternatively, pass 'batch' to a beginPass() call
+ \endcode
+
+ \section2 Common patterns
+
+ A call to create() destroys any existing native resources if create() was
+ successfully called before. If those native resources are still in use by
+ an in-flight frame (i.e., there's a chance they are still read by the GPU),
+ the destroying of those resources is deferred automatically. Thus a very
+ common and convenient pattern to safely change the size of an already
+ existing texture is the following. In practice this drops and creates a
+ whole new native texture resource underneath, so it is not necessarily a
+ cheap operation, but is more convenient and still faster than the
+ alternatives, because by not destroying the \c texture object itself, all
+ references to it stay valid in other data structures (e.g., in any
+ QShaderResourceBinding the QRhiTexture is referenced from).
+
+ \code
+ // determine newSize, e.g. based on the swapchain's output size or other factors
+ if (texture->pixelSize() != newSize) {
+ texture->setPixelSize(newSize);
+ if (!texture->create()) { error(); }
+ }
+ // continue using texture, fill it with new data
+ \endcode
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ \sa QRhiResourceUpdateBatch, QRhi, QRhiTextureRenderTarget
*/
/*!
@@ -2420,10 +4284,34 @@ bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
\value ThreeDimensional The texture is a 3D texture. Such textures should
be created with the QRhi::newTexture() overload taking a depth in addition
to width and height. A 3D texture can have mipmaps but cannot be
- multisample. When rendering into a 3D texture, the layer specified in the
- render target's color attachment refers to a slice in range [0..depth-1].
- The underlying graphics API may not support 3D textures at run time.
- Support is indicated by the QRhi::ThreeDimensionalTextures feature.
+ multisample. When rendering into, or uploading data to a 3D texture, the \c
+ layer specified in the render target's color attachment or the upload
+ description refers to a single slice in range [0..depth-1]. The underlying
+ graphics API may not support 3D textures at run time. Support is indicated
+ by the QRhi::ThreeDimensionalTextures feature.
+
+ \value TextureRectangleGL The texture should use the GL_TEXTURE_RECTANGLE
+ target with OpenGL. This flag is ignored with other graphics APIs. Just
+ like ExternalOES, this flag is useful when working with platform APIs where
+ native OpenGL texture objects received from the platform are wrapped in a
+ QRhiTexture, and the platform can only provide textures for a non-2D
+ texture target.
+
+ \value TextureArray The texture is a texture array, i.e. a single texture
+ object that is a homogeneous array of 2D textures. Texture arrays are
+ created with QRhi::newTextureArray(). The underlying graphics API may not
+ support texture array objects at run time. Support is indicated by the
+ QRhi::TextureArrays feature. When rendering into, or uploading data to a
+ texture array, the \c layer specified in the render target's color
+ attachment or the upload description selects a single element in the array.
+
+ \value OneDimensional The texture is a 1D texture. Such textures can be
+ created by passing a 0 height and depth to QRhi::newTexture(). Note that
+ there can be limitations on one dimensional textures depending on the
+ underlying graphics API. For example, rendering to them or using them with
+ mipmap-based filtering may be unsupported. This is indicated by the
+ QRhi::OneDimensionalTextures and QRhi::OneDimensionalTextureMipmaps
+ feature flags.
*/
/*!
@@ -2453,6 +4341,19 @@ bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
\value RGBA32F Four components, 32-bit float per component.
+ \value R16F One component, 16-bit float.
+
+ \value R32F One component, 32-bit float.
+
+ \value RGB10A2 Four components, unsigned normalized 10 bit R, G, and B,
+ 2-bit alpha. This is a packed format so native endianness applies. Note
+ that there is no BGR10A2. This is because RGB10A2 maps to
+ DXGI_FORMAT_R10G10B10A2_UNORM with D3D, MTLPixelFormatRGB10A2Unorm with
+ Metal, VK_FORMAT_A2B10G10R10_UNORM_PACK32 with Vulkan, and
+ GL_RGB10_A2/GL_RGB/GL_UNSIGNED_INT_2_10_10_10_REV on OpenGL (ES). This is
+ the only universally supported RGB30 option. The corresponding QImage
+ formats are QImage::Format_BGR30 and QImage::Format_A2BGR30_Premultiplied.
+
\value D16 16-bit depth (normalized unsigned integer)
\value D24 24-bit depth (normalized unsigned integer)
@@ -2490,7 +4391,8 @@ bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
*/
/*!
- \class QRhiTexture::NativeTexture
+ \struct QRhiTexture::NativeTexture
+ \inmodule QtGui
\brief Contains information about the underlying native resources of a texture.
*/
@@ -2499,9 +4401,10 @@ bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
\brief 64-bit integer containing the native object handle.
With OpenGL, the native handle is a GLuint value, so \c object can then be
- cast to a GLuint. With Vulkan, the native handle is a VkImage, so \c
- object can be cast to a VkImage. With Direct3D 11 and Metal \c
- object contains a ID3D11Texture2D or MTLTexture pointer, respectively.
+ cast to a GLuint. With Vulkan, the native handle is a VkImage, so \c object
+ can be cast to a VkImage. With Direct3D 11 and Metal \c object contains a
+ ID3D11Texture2D or MTLTexture pointer, respectively. With Direct3D 12
+ \c object contains a ID3D12Resource pointer.
*/
/*!
@@ -2515,9 +4418,10 @@ bool QRhiRenderBuffer::createFrom(NativeRenderBuffer src)
\internal
*/
QRhiTexture::QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
- int sampleCount_, Flags flags_)
+ int arraySize_, int sampleCount_, Flags flags_)
: QRhiResource(rhi),
- m_format(format_), m_pixelSize(pixelSize_), m_depth(depth_), m_sampleCount(sampleCount_), m_flags(flags_)
+ m_format(format_), m_pixelSize(pixelSize_), m_depth(depth_),
+ m_arraySize(arraySize_), m_sampleCount(sampleCount_), m_flags(flags_)
{
}
@@ -2530,7 +4434,7 @@ QRhiResource::Type QRhiTexture::resourceType() const
}
/*!
- \fn bool QRhiTexture::create()
+ \fn virtual bool QRhiTexture::create() = 0
Creates the corresponding native graphics resources. If there are already
resources present due to an earlier create() with no corresponding
@@ -2553,13 +4457,16 @@ QRhiTexture::NativeTexture QRhiTexture::nativeTexture()
}
/*!
- Similar to create() except that no new native textures are created. Instead,
- the native texture resources specified by \a src is used.
+ Similar to create(), except that no new native textures are created.
+ Instead, the native texture resources specified by \a src is used.
This allows importing an existing native texture object (which must belong
to the same device or sharing context, depending on the graphics API) from
an external graphics engine.
+ \return true if the specified existing native texture object has been
+ successfully wrapped as a non-owning QRhiTexture.
+
\note format(), pixelSize(), sampleCount(), and flags() must still be set
correctly. Passing incorrect sizes and other values to QRhi::newTexture()
and then following it with a createFrom() expecting that the native texture
@@ -2572,6 +4479,10 @@ QRhiTexture::NativeTexture QRhiTexture::nativeTexture()
The opposite of this operation, exposing a QRhiTexture-created native
texture object to a foreign engine, is possible via nativeTexture().
+ \note When importing a 3D texture, or a texture array object, or, with
+ OpenGL ES, an external texture, it is then especially important to set the
+ corresponding flags (ThreeDimensional, TextureArray, ExternalOES) via
+ setFlags() before calling this function.
*/
bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)
{
@@ -2582,7 +4493,7 @@ bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)
/*!
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 layouts. This function allows communicating the expected \a layout the
image backing the QRhiTexture is in after the native rendering commands.
For example, consider rendering into a QRhiTexture's VkImage directly with
@@ -2598,6 +4509,9 @@ bool QRhiTexture::createFrom(QRhiTexture::NativeTexture src)
This function has no effect with QRhi backends where the underlying
graphics API does not expose a concept of image layouts.
+
+ \note With Vulkan \a layout is a \c VkImageLayout. With Direct 3D 12 \a
+ layout is a value composed of the bits from \c D3D12_RESOURCE_STATES.
*/
void QRhiTexture::setNativeLayout(int layout)
{
@@ -2605,10 +4519,196 @@ void QRhiTexture::setNativeLayout(int layout)
}
/*!
+ \fn QRhiTexture::Format QRhiTexture::format() const
+ \return the texture format.
+ */
+
+/*!
+ \fn void QRhiTexture::setFormat(QRhiTexture::Format fmt)
+
+ Sets the requested texture format to \a fmt.
+
+ \note The value set is only taken into account upon the next call to
+ create(), i.e. when the underlying graphics resource are (re)created.
+ Setting a new value is futile otherwise and must be avoided since it can
+ lead to inconsistent state.
+ */
+
+/*!
+ \fn QSize QRhiTexture::pixelSize() const
+ \return the size in pixels.
+ */
+
+/*!
+ \fn void QRhiTexture::setPixelSize(const QSize &sz)
+
+ Sets the texture size, specified in pixels, to \a sz.
+
+ \note The value set is only taken into account upon the next call to
+ create(), i.e. when the underlying graphics resource are (re)created.
+ Setting a new value is futile otherwise and must be avoided since it can
+ lead to inconsistent state. The same applies to all other setters as well.
+ */
+
+/*!
+ \fn int QRhiTexture::depth() const
+ \return the depth for 3D textures.
+ */
+
+/*!
+ \fn void QRhiTexture::setDepth(int depth)
+ Sets the \a depth for a 3D texture.
+ */
+
+/*!
+ \fn int QRhiTexture::arraySize() const
+ \return the texture array size.
+ */
+
+/*!
+ \fn void QRhiTexture::setArraySize(int arraySize)
+ Sets the texture \a arraySize.
+ */
+
+/*!
+ \fn int QRhiTexture::arrayRangeStart() const
+
+ \return the first array layer when setArrayRange() was called.
+
+ \sa setArrayRange()
+ */
+
+/*!
+ \fn int QRhiTexture::arrayRangeLength() const
+
+ \return the exposed array range size when setArrayRange() was called.
+
+ \sa setArrayRange()
+*/
+
+/*!
+ \fn void QRhiTexture::setArrayRange(int startIndex, int count)
+
+ Normally all array layers are exposed and it is up to the shader to select
+ the layer via the third coordinate passed to the \c{texture()} GLSL
+ function when sampling the \c sampler2DArray. When QRhi::TextureArrayRange
+ is reported as supported, calling setArrayRange() before create() or
+ createFrom() requests selecting only the specified range, \a count elements
+ starting from \a startIndex. The shader logic can then be written with this
+ in mind.
+
+ \sa QRhi::TextureArrayRange
+ */
+
+/*!
+ \fn Flags QRhiTexture::flags() const
+ \return the texture flags.
+ */
+
+/*!
+ \fn void QRhiTexture::setFlags(Flags f)
+ Sets the texture flags to \a f.
+ */
+
+/*!
+ \fn int QRhiTexture::sampleCount() const
+ \return the sample count. 1 means no multisample antialiasing.
+ */
+
+/*!
+ \fn void QRhiTexture::setSampleCount(int s)
+ Sets the sample count to \a s.
+ */
+
+/*!
+ \struct QRhiTexture::ViewFormat
+ \inmodule QtGui
+ \since 6.8
+ \brief Specifies the view format for reading or writing from or to the texture.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+ */
+
+/*!
+ \variable QRhiTexture::ViewFormat::format
+ */
+
+/*!
+ \variable QRhiTexture::ViewFormat::srgb
+ */
+
+/*!
+ \fn QRhiTexture::ViewFormat QRhiTexture::readViewFormat() const
+ \since 6.8
+ \return the view format used when sampling the texture. When not called, the view
+ format is assumed to be the same as format().
+ */
+
+/*!
+ \fn void QRhiTexture::setReadViewFormat(const ViewFormat &fmt)
+ \since 6.8
+
+ Sets the shader resource view format (or the format of the view used for
+ sampling the texture) to \a fmt. By default the same format (and sRGB-ness)
+ is used as the texture itself, and in most cases this function does not need
+ to be called.
+
+ This setting is only taken into account when the \l TextureViewFormat
+ feature is reported as supported.
+
+ \note This functionality is provided to allow "casting" between
+ non-sRGB and sRGB in order to get the shader reads perform, or not perform,
+ the implicit sRGB conversions. Other types of casting may or may not be
+ functional.
+ */
+
+/*!
+ \fn QRhiTexture::ViewFormat QRhiTexture::writeViewFormat() const
+ \since 6.8
+ \return the view format used when writing to the texture and when using it
+ with image load/store. When not called, the view format is assumed to be the
+ same as format().
+ */
+
+/*!
+ \fn void QRhiTexture::setWriteViewFormat(const ViewFormat &fmt)
+ \since 6.8
+
+ Sets the render target view format to \a fmt. By default the same format
+ (and sRGB-ness) is used as the texture itself, and in most cases this
+ function does not need to be called.
+
+ One common use case for providing a write view format is working with
+ externally provided textures that, outside of our control, use an sRGB
+ format with 3D APIs such as Vulkan or Direct 3D, but the rendering engine is
+ already prepared to handle linearization and conversion to sRGB at the end
+ of its shading pipeline. In this case what is wanted when rendering into
+ such a texture is a render target view (e.g. VkImageView) that has the same,
+ but non-sRGB format. (if e.g. from an OpenXR implementation one gets a
+ VK_FORMAT_R8G8B8A8_SRGB texture, it is likely that rendering into it should
+ be done using a VK_FORMAT_R8G8B8A8_UNORM view, if that is what the rendering
+ engine's pipeline requires; in this example one would call this function
+ with a ViewFormat that has a format of QRhiTexture::RGBA8 and \c srgb set to
+ \c false).
+
+ This setting is only taken into account when the \l TextureViewFormat
+ feature is reported as supported.
+
+ \note This functionality is provided to allow "casting" between
+ non-sRGB and sRGB in order to get the shader write not perform, or perform,
+ the implicit sRGB conversions. Other types of casting may or may not be
+ functional.
+ */
+
+/*!
\class QRhiSampler
- \internal
\inmodule QtGui
+ \since 6.6
\brief Sampler resource.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -2665,14 +4765,91 @@ QRhiResource::Type QRhiSampler::resourceType() const
}
/*!
+ \fn QRhiSampler::Filter QRhiSampler::magFilter() const
+ \return the magnification filter mode.
+ */
+
+/*!
+ \fn void QRhiSampler::setMagFilter(Filter f)
+ Sets the magnification filter mode to \a f.
+ */
+
+/*!
+ \fn QRhiSampler::Filter QRhiSampler::minFilter() const
+ \return the minification filter mode.
+ */
+
+/*!
+ \fn void QRhiSampler::setMinFilter(Filter f)
+ Sets the minification filter mode to \a f.
+ */
+
+/*!
+ \fn QRhiSampler::Filter QRhiSampler::mipmapMode() const
+ \return the mipmap filter mode.
+ */
+
+/*!
+ \fn void QRhiSampler::setMipmapMode(Filter f)
+
+ Sets the mipmap filter mode to \a f.
+
+ Leave this set to None when the texture has no mip levels, or when the mip
+ levels are not to be taken into account.
+ */
+
+/*!
+ \fn QRhiSampler::AddressMode QRhiSampler::addressU() const
+ \return the horizontal wrap mode.
+ */
+
+/*!
+ \fn void QRhiSampler::setAddressU(AddressMode mode)
+ Sets the horizontal wrap \a mode.
+ */
+
+/*!
+ \fn QRhiSampler::AddressMode QRhiSampler::addressV() const
+ \return the vertical wrap mode.
+ */
+
+/*!
+ \fn void QRhiSampler::setAddressV(AddressMode mode)
+ Sets the vertical wrap \a mode.
+ */
+
+/*!
+ \fn QRhiSampler::AddressMode QRhiSampler::addressW() const
+ \return the depth wrap mode.
+ */
+
+/*!
+ \fn void QRhiSampler::setAddressW(AddressMode mode)
+ Sets the depth wrap \a mode.
+ */
+
+/*!
+ \fn QRhiSampler::CompareOp QRhiSampler::textureCompareOp() const
+ \return the texture comparison function.
+ */
+
+/*!
+ \fn void QRhiSampler::setTextureCompareOp(CompareOp op)
+ Sets the texture comparison function \a op.
+ */
+
+/*!
\class QRhiRenderPassDescriptor
- \internal
\inmodule QtGui
+ \since 6.6
\brief Render pass resource.
A render pass, if such a concept exists in the underlying graphics API, is
a collection of attachments (color, depth, stencil) and describes how those
attachments are used.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -2692,7 +4869,7 @@ QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
}
/*!
- \fn bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
+ \fn virtual bool QRhiRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const = 0
\return true if the \a other QRhiRenderPassDescriptor is compatible with
this one, meaning \c this and \a other can be used interchangebly in
@@ -2713,11 +4890,21 @@ QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
\l{QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()}{created}
from the same QRhiTextureRenderTarget are always compatible.
- \sa newCompatibleRenderPassDescriptor()
+ Similarly to QRhiShaderResourceBindings, compatibility can also be tested
+ without having two existing objects available. Extracting the opaque blob by
+ calling serializedFormat() allows testing for compatibility by comparing the
+ returned vector to another QRhiRenderPassDescriptor's
+ serializedFormat(). This has benefits in certain situations, because it
+ allows testing the compatibility of a QRhiRenderPassDescriptor with a
+ QRhiGraphicsPipeline even when the QRhiRenderPassDescriptor the pipeline was
+ originally built was is no longer available (but the data returned from its
+ serializedFormat() still is).
+
+ \sa newCompatibleRenderPassDescriptor(), serializedFormat()
*/
/*!
- \fn QRhiRenderPassDescriptor *QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() const
+ \fn virtual QRhiRenderPassDescriptor *QRhiRenderPassDescriptor::newCompatibleRenderPassDescriptor() const = 0
\return a new QRhiRenderPassDescriptor that is
\l{isCompatible()}{compatible} with this one.
@@ -2738,6 +4925,24 @@ QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
*/
/*!
+ \fn virtual QVector<quint32> QRhiRenderPassDescriptor::serializedFormat() const = 0
+
+ \return a vector of integers containing an opaque blob describing the data
+ relevant for \l{isCompatible()}{compatibility}.
+
+ Given two QRhiRenderPassDescriptor objects \c rp1 and \c rp2, if the data
+ returned from this function is identical, then \c{rp1->isCompatible(rp2)},
+ and vice versa hold true as well.
+
+ \note The returned data is meant to be used for storing in memory and
+ comparisons during the lifetime of the QRhi the object belongs to. It is not
+ meant for storing on disk, reusing between processes, or using with multiple
+ QRhi instances with potentially different backends.
+
+ \sa isCompatible()
+ */
+
+/*!
\return a pointer to a backend-specific QRhiNativeHandles subclass, such as
QRhiVulkanRenderPassNativeHandles. The returned value is \nullptr when exposing
the underlying native resources is not supported by the backend.
@@ -2751,9 +4956,21 @@ const QRhiNativeHandles *QRhiRenderPassDescriptor::nativeHandles()
/*!
\class QRhiRenderTarget
- \internal
\inmodule QtGui
+ \since 6.6
\brief Represents an onscreen (swapchain) or offscreen (texture) render target.
+
+ Applications do not create an instance of this class directly. Rather, it
+ is the subclass QRhiTextureRenderTarget that is instantiable by clients of
+ the API via \l{QRhi::newTextureRenderTarget()}{newTextureRenderTarget()}.
+ The other subclass is QRhiSwapChainRenderTarget, which is the type
+ QRhiSwapChain returns when calling
+ \l{QRhiSwapChain::currentFrameRenderTarget()}{currentFrameRenderTarget()}.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ \sa QRhiSwapChainRenderTarget, QRhiTextureRenderTarget
*/
/*!
@@ -2765,21 +4982,25 @@ QRhiRenderTarget::QRhiRenderTarget(QRhiImplementation *rhi)
}
/*!
- \return the resource type.
- */
-QRhiResource::Type QRhiRenderTarget::resourceType() const
-{
- return RenderTarget;
-}
-
-/*!
- \fn QSize QRhiRenderTarget::pixelSize() const
+ \fn virtual QSize QRhiRenderTarget::pixelSize() const = 0
\return the size in pixels.
+
+ Valid only after create() has been called successfully. Until then the
+ result is a default-constructed QSize.
+
+ With QRhiTextureRenderTarget the returned size is the size of the
+ associated attachments at the time of create(), in practice the size of the
+ first color attachment, or the depth/stencil buffer if there are no color
+ attachments. If the associated textures or renderbuffers are resized and
+ rebuilt afterwards, then pixelSize() performs an implicit call to create()
+ in order to rebuild the underlying data structures. This implicit check is
+ similar to what QRhiCommandBuffer::beginPass() does, and ensures that the
+ returned size is always up-to-date.
*/
/*!
- \fn float QRhiRenderTarget::devicePixelRatio() const
+ \fn virtual float QRhiRenderTarget::devicePixelRatio() const = 0
\return the device pixel ratio. For QRhiTextureRenderTarget this is always
1. For targets retrieved from a QRhiSwapChain the value reflects the
@@ -2788,29 +5009,94 @@ QRhiResource::Type QRhiRenderTarget::resourceType() const
*/
/*!
- \class QRhiTextureRenderTarget
+ \fn virtual int QRhiRenderTarget::sampleCount() const = 0
+
+ \return the sample count or 1 if multisample antialiasing is not relevant for
+ this render target.
+ */
+
+/*!
+ \fn QRhiRenderPassDescriptor *QRhiRenderTarget::renderPassDescriptor() const
+
+ \return the associated QRhiRenderPassDescriptor.
+ */
+
+/*!
+ \fn void QRhiRenderTarget::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
+
+ Sets the QRhiRenderPassDescriptor \a desc for use with this render target.
+ */
+
+/*!
\internal
+ */
+QRhiSwapChainRenderTarget::QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_)
+ : QRhiRenderTarget(rhi),
+ m_swapchain(swapchain_)
+{
+}
+
+/*!
+ \class QRhiSwapChainRenderTarget
+ \inmodule QtGui
+ \since 6.6
+ \brief Swapchain render target resource.
+
+ When targeting the color buffers of a swapchain, active render target is a
+ QRhiSwapChainRenderTarget. This is what
+ QRhiSwapChain::currentFrameRenderTarget() returns.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ \sa QRhiSwapChain
+ */
+
+/*!
+ \return the resource type.
+ */
+QRhiResource::Type QRhiSwapChainRenderTarget::resourceType() const
+{
+ return SwapChainRenderTarget;
+}
+
+/*!
+ \fn QRhiSwapChain *QRhiSwapChainRenderTarget::swapChain() const
+
+ \return the swapchain object.
+ */
+
+/*!
+ \class QRhiTextureRenderTarget
\inmodule QtGui
+ \since 6.6
\brief Texture render target resource.
A texture render target allows rendering into one or more textures,
optionally with a depth texture or depth/stencil renderbuffer.
+ For multisample rendering the common approach is to use a renderbuffer as
+ the color attachment and set the non-multisample destination texture as the
+ \c{resolve texture}.
+
\note Textures used in combination with QRhiTextureRenderTarget must be
created with the QRhiTexture::RenderTarget flag.
The simplest example of creating a render target with a texture as its
single color attachment:
- \badcode
- texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
+ \code
+ QRhiTexture *texture = rhi->newTexture(QRhiTexture::RGBA8, size, 1, QRhiTexture::RenderTarget);
texture->create();
- rt = rhi->newTextureRenderTarget({ texture });
+ QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ texture });
rp = rt->newCompatibleRenderPassDescriptor();
rt->setRenderPassDescriptor(rt);
rt->create();
// rt can now be used with beginPass()
\endcode
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -2825,7 +5111,19 @@ QRhiResource::Type QRhiRenderTarget::resourceType() const
\value PreserveColorContents Indicates that the contents of the color
attachments is to be loaded when starting a render pass, instead of
clearing. This is potentially more expensive, especially on mobile (tiled)
- GPUs, but allows preserving the existing contents between passes.
+ GPUs, but allows preserving the existing contents between passes. When doing
+ multisample rendering with a resolve texture set, setting this flag also
+ requests the multisample color data to be stored (written out) to the
+ multisample texture or render buffer. (for non-multisample rendering the
+ color data is always stored, but for MSAA storing the multisample data
+ decreases efficiency for certain GPU architectures, hence defaulting to not
+ writing it out) Note however that this is non-portable: in some cases there
+ is no intermediate multisample texture on the graphics API level, e.g. when
+ using OpenGL ES's \c{GL_EXT_multisampled_render_to_texture} as it is all
+ implicit, handled by the OpenGL ES implementation. In that case,
+ PreserveColorContents will likely have no effect. Therefore, avoid relying
+ on this flag when using multisample rendering and the color attachment is
+ using a multisample QRhiTexture (not QRhiRenderBuffer).
\value PreserveDepthStencilContents Indicates that the contents of the
depth texture is to be loaded when starting a render pass, instead
@@ -2833,6 +5131,13 @@ QRhiResource::Type QRhiRenderTarget::resourceType() const
(QRhiTextureRenderTargetDescription::depthTexture() is set) because
depth/stencil renderbuffers may not have any physical backing and data may
not be written out in the first place.
+
+ \value DoNotStoreDepthStencilContents Indicates that the contents of the
+ depth texture does not need to be written out. Relevant only when a
+ QRhiTexture, not QRhiRenderBuffer, is used as the depth-stencil buffer,
+ because for QRhiRenderBuffer this is implicit. When a depthResolveTexture is
+ set, the flag is not relevant, because the behavior is then as if the flag
+ was set. This enum value is introduced in Qt 6.8.
*/
/*!
@@ -2856,7 +5161,7 @@ QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
}
/*!
- \fn QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor()
+ \fn virtual QRhiRenderPassDescriptor *QRhiTextureRenderTarget::newCompatibleRenderPassDescriptor() = 0
\return a new QRhiRenderPassDescriptor that is compatible with this render
target.
@@ -2866,14 +5171,15 @@ QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
describes the attachments (color, depth/stencil) and the load/store
behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
- be used in combination with a render target that has the same
+ be used in combination with a render target that has a
+ \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
QRhiRenderPassDescriptor set.
Two QRhiTextureRenderTarget instances can share the same render pass
descriptor as long as they have the same number and type of attachments.
The associated QRhiTexture or QRhiRenderBuffer instances are not part of
the render pass descriptor so those can differ in the two
- QRhiTextureRenderTarget intances.
+ QRhiTextureRenderTarget instances.
\note resources, such as QRhiTexture instances, referenced in description()
must already have create() called on them.
@@ -2882,7 +5188,7 @@ QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
*/
/*!
- \fn bool QRhiTextureRenderTarget::create()
+ \fn virtual bool QRhiTextureRenderTarget::create() = 0
Creates the corresponding native graphics resources. If there are already
resources present due to an earlier create() with no corresponding
@@ -2906,9 +5212,29 @@ QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
*/
/*!
+ \fn QRhiTextureRenderTargetDescription QRhiTextureRenderTarget::description() const
+ \return the render target description.
+ */
+
+/*!
+ \fn void QRhiTextureRenderTarget::setDescription(const QRhiTextureRenderTargetDescription &desc)
+ Sets the render target description \a desc.
+ */
+
+/*!
+ \fn QRhiTextureRenderTarget::Flags QRhiTextureRenderTarget::flags() const
+ \return the currently set flags.
+ */
+
+/*!
+ \fn void QRhiTextureRenderTarget::setFlags(Flags f)
+ Sets the flags to \a f.
+ */
+
+/*!
\class QRhiShaderResourceBindings
- \internal
\inmodule QtGui
+ \since 6.6
\brief Encapsulates resources for making buffer, texture, sampler resources visible to shaders.
A QRhiShaderResourceBindings is a collection of QRhiShaderResourceBinding
@@ -2929,19 +5255,19 @@ QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
QRhiShaderResourceBindings could be created and then passed to
QRhiGraphicsPipeline::setShaderResourceBindings():
- \badcode
- srb = rhi->newShaderResourceBindings();
+ \code
+ QRhiShaderResourceBindings *srb = rhi->newShaderResourceBindings();
srb->setBindings({
QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, ubuf),
QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, texture, sampler)
});
srb->create();
- ...
- ps = rhi->newGraphicsPipeline();
- ...
+ // ...
+ QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
+ // ...
ps->setShaderResourceBindings(srb);
ps->create();
- ...
+ // ...
cb->setGraphicsPipeline(ps);
cb->setShaderResources(); // binds srb
\endcode
@@ -2960,22 +5286,34 @@ QRhiResource::Type QRhiTextureRenderTarget::resourceType() const
srb argument. As long as the layouts (so the number of bindings and the
binding points) match between two QRhiShaderResourceBindings, they can both
be used with the same pipeline, assuming the pipeline was created with one of
- them in the first place.
+ them in the first place. See isLayoutCompatible() for more details.
- \badcode
- srb2 = rhi->newShaderResourceBindings();
- ...
+ \code
+ QRhiShaderResourceBindings *srb2 = rhi->newShaderResourceBindings();
+ // ...
cb->setGraphicsPipeline(ps);
cb->setShaderResources(srb2); // binds srb2
\endcode
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
+ \typedef QRhiShaderResourceBindingSet
+ \relates QRhi
+ \since 6.7
+
+ Synonym for QRhiShaderResourceBindings.
+*/
+
+/*!
\internal
*/
QRhiShaderResourceBindings::QRhiShaderResourceBindings(QRhiImplementation *rhi)
: QRhiResource(rhi)
{
+ m_layoutDesc.reserve(BINDING_PREALLOC * QRhiShaderResourceBinding::LAYOUT_DESC_ENTRIES_PER_BINDING);
}
/*!
@@ -2998,8 +5336,14 @@ QRhiResource::Type QRhiShaderResourceBindings::resourceType() const
then safely be passed to QRhiCommandBuffer::setShaderResources(), and so
be used with the pipeline in place of this QRhiShaderResourceBindings.
- This function can be called before create() as well. The bindings must
- already be set via setBindings() however.
+ \note This function must only be called after a successful create(), because
+ it relies on data generated during the baking of the underlying data
+ structures. This way the function can implement a comparison approach that
+ is more efficient than iterating through two binding lists and calling
+ QRhiShaderResourceBinding::isLayoutCompatible() on each pair. This becomes
+ relevant especially when this function is called at a high frequency.
+
+ \sa serializedLayoutDescription()
*/
bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBindings *other) const
{
@@ -3018,26 +5362,80 @@ bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBind
&& m_layoutDesc == other->m_layoutDesc;
}
+/*!
+ \fn QVector<quint32> QRhiShaderResourceBindings::serializedLayoutDescription() const
+
+ \return a vector of integers containing an opaque blob describing the layout
+ of the binding list, i.e. the data relevant for
+ \l{isLayoutCompatible()}{layout compatibility tests}.
+
+ Given two objects \c srb1 and \c srb2, if the data returned from this
+ function is identical, then \c{srb1->isLayoutCompatible(srb2)}, and vice
+ versa hold true as well.
+
+ \note The returned data is meant to be used for storing in memory and
+ comparisons during the lifetime of the QRhi the object belongs to. It is not
+ meant for storing on disk, reusing between processes, or using with multiple
+ QRhi instances with potentially different backends.
+
+ \sa isLayoutCompatible()
+ */
+
void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
{
srb->m_layoutDescHash = 0;
srb->m_layoutDesc.clear();
- for (const QRhiShaderResourceBinding &b : qAsConst(srb->m_bindings)) {
- const QRhiShaderResourceBinding::Data *d = b.data();
- // must match QRhiShaderResourceBinding::isLayoutCompatible()
- srb->m_layoutDescHash ^= uint(d->binding) ^ uint(d->stage) ^ uint(d->type);
- srb->m_layoutDesc << uint(d->binding) << uint(d->stage) << uint(d->type);
+ auto layoutDescAppender = std::back_inserter(srb->m_layoutDesc);
+ for (const QRhiShaderResourceBinding &b : std::as_const(srb->m_bindings)) {
+ const QRhiShaderResourceBinding::Data *d = &b.d;
+ srb->m_layoutDescHash ^= uint(d->binding) ^ uint(d->stage) ^ uint(d->type)
+ ^ uint(d->arraySize());
+ layoutDescAppender = d->serialize(layoutDescAppender);
}
}
/*!
+ \fn void QRhiShaderResourceBindings::setBindings(std::initializer_list<QRhiShaderResourceBinding> list)
+ Sets the \a list of bindings.
+ */
+
+/*!
+ \fn template<typename InputIterator> void QRhiShaderResourceBindings::setBindings(InputIterator first, InputIterator last)
+ Sets the list of bindings from the iterators \a first and \a last.
+ */
+
+/*!
+ \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cbeginBindings() const
+ \return a const iterator pointing to the first item in the binding list.
+ */
+
+/*!
+ \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::cendBindings() const
+ \return a const iterator pointing just after the last item in the binding list.
+ */
+
+/*!
+ \fn const QRhiShaderResourceBinding *QRhiShaderResourceBindings::bindingAt(qsizetype index) const
+ \return the binding at the specified \a index.
+ */
+
+/*!
+ \fn qsizetype QRhiShaderResourceBindings::bindingCount() const
+ \return the number of bindings.
+ */
+
+/*!
\class QRhiShaderResourceBinding
- \internal
\inmodule QtGui
+ \since 6.6
\brief Describes the shader resource for a single binding point.
- A QRhiShaderResourceBinding cannot be constructed directly. Instead, use
- the static functions uniformBuffer(), sampledTexture() to get an instance.
+ A QRhiShaderResourceBinding cannot be constructed directly. Instead, use the
+ static functions such as uniformBuffer() or sampledTexture() to get an
+ instance.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -3046,7 +5444,15 @@ void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
\value UniformBuffer Uniform buffer
- \value SampledTexture Combined image sampler
+ \value SampledTexture Combined image sampler (a texture and sampler pair).
+ Even when the shading language associated with the underlying 3D API has no
+ support for this concept (e.g. D3D and HLSL), this is still supported
+ because the shader translation layer takes care of the appropriate
+ translation and remapping of binding points or shader registers.
+
+ \value Texture Texture (separate)
+
+ \value Sampler Sampler (separate)
\value ImageLoad Image load (with GLSL this maps to doing imageLoad() on a
single level - and either one or all layers - of a texture exposed to the
@@ -3072,8 +5478,11 @@ void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
Flag values to indicate which stages the shader resource is visible in
\value VertexStage Vertex stage
- \value FragmentStage Fragment (pixel) stage
+ \value TessellationControlStage Tessellation control (hull shader) stage
+ \value TessellationEvaluationStage Tessellation evaluation (domain shader) stage
+ \value FragmentStage Fragment (pixel shader) stage
\value ComputeStage Compute stage
+ \value GeometryStage Geometry stage
*/
/*!
@@ -3083,14 +5492,18 @@ void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
For example, \c a and \c b below are not equal, but are compatible layout-wise:
- \badcode
+ \code
auto a = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, buffer);
auto b = QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage, someOtherBuffer, 256);
\endcode
*/
bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBinding &other) const
{
- return d.binding == other.d.binding && d.stage == other.d.stage && d.type == other.d.type;
+ // everything that goes into a VkDescriptorSetLayoutBinding must match
+ return d.binding == other.d.binding
+ && d.stage == other.d.stage
+ && d.type == other.d.type
+ && d.arraySize() == other.d.arraySize();
}
/*!
@@ -3106,6 +5519,9 @@ bool QRhiShaderResourceBinding::isLayoutCompatible(const QRhiShaderResourceBindi
suitable for creating pipelines. Such a pipeline must then always be used
together with another, layout compatible QRhiShaderResourceBindings with
resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ \note If the size of \a buf exceeds the limit reported for
+ QRhi::MaxUniformBufferRange, unexpected errors may occur.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
int binding, StageFlags stage, QRhiBuffer *buf)
@@ -3140,9 +5556,12 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
suitable for creating pipelines. Such a pipeline must then always be used
together with another, layout compatible QRhiShaderResourceBindings with
resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
+ unexpected errors may occur.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
- int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
+ int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
{
Q_ASSERT(size > 0);
QRhiShaderResourceBinding b;
@@ -3174,9 +5593,12 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBuffer(
suitable for creating pipelines. Such a pipeline must then always be used
together with another, layout compatible QRhiShaderResourceBindings with
resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ \note If \a size exceeds the limit reported for QRhi::MaxUniformBufferRange,
+ unexpected errors may occur.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(
- int binding, StageFlags stage, QRhiBuffer *buf, int size)
+ int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
{
Q_ASSERT(size > 0);
QRhiShaderResourceBinding b;
@@ -3205,6 +5627,14 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOff
together with another, layout compatible QRhiShaderResourceBindings with
resources present passed to QRhiCommandBuffer::setShaderResources().
+ \note A shader may not be able to consume more than 16 textures/samplers,
+ depending on the underlying graphics API. This hard limit must be kept in
+ mind in renderer design. This does not apply to texture arrays which
+ consume a single binding point (shader register) and can contain 256-2048
+ textures, depending on the underlying graphics API. Arrays of textures (see
+ sampledTextures()) are however no different in this regard than using the
+ same number of individual textures.
+
\sa sampledTextures()
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
@@ -3215,8 +5645,7 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
b.d.stage = stage;
b.d.type = SampledTexture;
b.d.u.stex.count = 1;
- b.d.u.stex.texSamplers[0].tex = tex;
- b.d.u.stex.texSamplers[0].sampler = sampler;
+ b.d.u.stex.texSamplers[0] = { tex, sampler };
return b;
}
@@ -3267,12 +5696,128 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
if (texSamplers)
b.d.u.stex.texSamplers[i] = texSamplers[i];
else
- b.d.u.stex.texSamplers[i] = {};
+ b.d.u.stex.texSamplers[i] = { nullptr, nullptr };
+ }
+ return b;
+}
+
+/*!
+ \return a shader resource binding for the given binding number, pipeline
+ stages, and texture specified by \a binding, \a stage, \a tex.
+
+ \note This function is equivalent to calling textures() with a
+ \c count of 1.
+
+ \note \a tex can be null. It is valid to create a
+ QRhiShaderResourceBindings with unspecified resources, but such an object
+ cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
+ suitable for creating pipelines. Such a pipeline must then always be used
+ together with another, layout compatible QRhiShaderResourceBindings with
+ resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ This creates a binding for a separate texture (image) object, whereas
+ sampledTexture() is suitable for combined image samplers. In
+ Vulkan-compatible GLSL code separate textures are declared as \c texture2D
+ as opposed to \c sampler2D: \c{layout(binding = 1) uniform texture2D tex;}
+
+ \note A shader may not be able to consume more than 16 textures, depending
+ on the underlying graphics API. This hard limit must be kept in mind in
+ renderer design. This does not apply to texture arrays which consume a
+ single binding point (shader register) and can contain 256-2048 textures,
+ depending on the underlying graphics API. Arrays of textures (see
+ sampledTextures()) are however no different in this regard than using the
+ same number of individual textures.
+
+ \sa textures(), sampler()
+ */
+QRhiShaderResourceBinding QRhiShaderResourceBinding::texture(int binding, StageFlags stage, QRhiTexture *tex)
+{
+ QRhiShaderResourceBinding b;
+ b.d.binding = binding;
+ b.d.stage = stage;
+ b.d.type = Texture;
+ b.d.u.stex.count = 1;
+ b.d.u.stex.texSamplers[0] = { tex, nullptr };
+ return b;
+}
+
+/*!
+ \return a shader resource binding for the given binding number, pipeline
+ stages, and the array of (separate) textures specified by \a binding, \a
+ stage, \a count, and \a tex.
+
+ \note \a count must be at least 1, and not larger than 16.
+
+ \note When \a count is 1, this function is equivalent to texture().
+
+ \warning All elements of the array must be specified.
+
+ \note \a tex can be null. It is valid to create a
+ QRhiShaderResourceBindings with unspecified resources, but such an object
+ cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
+ suitable for creating pipelines. Such a pipeline must then always be used
+ together with another, layout compatible QRhiShaderResourceBindings with
+ resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ \sa texture(), sampler()
+ */
+QRhiShaderResourceBinding QRhiShaderResourceBinding::textures(int binding, StageFlags stage, int count, QRhiTexture **tex)
+{
+ Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
+ QRhiShaderResourceBinding b;
+ b.d.binding = binding;
+ b.d.stage = stage;
+ b.d.type = Texture;
+ b.d.u.stex.count = count;
+ for (int i = 0; i < count; ++i) {
+ if (tex)
+ b.d.u.stex.texSamplers[i] = { tex[i], nullptr };
+ else
+ b.d.u.stex.texSamplers[i] = { nullptr, nullptr };
}
return b;
}
/*!
+ \return a shader resource binding for the given binding number, pipeline
+ stages, and sampler specified by \a binding, \a stage, \a sampler.
+
+ \note \a sampler can be null. It is valid to create a
+ QRhiShaderResourceBindings with unspecified resources, but such an object
+ cannot be used with QRhiCommandBuffer::setShaderResources(). It is however
+ suitable for creating pipelines. Such a pipeline must then always be used
+ together with another, layout compatible QRhiShaderResourceBindings with
+ resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ Arrays of separate samplers are not supported.
+
+ This creates a binding for a separate sampler object, whereas
+ sampledTexture() is suitable for combined image samplers. In
+ Vulkan-compatible GLSL code separate samplers are declared as \c sampler
+ as opposed to \c sampler2D: \c{layout(binding = 2) uniform sampler samp;}
+
+ With both a \c texture2D and \c sampler present, they can be used together
+ to sample the texture: \c{fragColor = texture(sampler2D(tex, samp),
+ texcoord);}.
+
+ \note A shader may not be able to consume more than 16 samplers, depending
+ on the underlying graphics API. This hard limit must be kept in mind in
+ renderer design.
+
+ \sa texture()
+ */
+QRhiShaderResourceBinding QRhiShaderResourceBinding::sampler(int binding, StageFlags stage, QRhiSampler *sampler)
+{
+ QRhiShaderResourceBinding b;
+ b.d.binding = binding;
+ b.d.stage = stage;
+ b.d.type = Sampler;
+ b.d.u.stex.count = 1;
+ b.d.u.stex.texSamplers[0] = { nullptr, sampler };
+ return b;
+}
+
+/*!
\return a shader resource binding for a read-only storage image with the
given \a binding number and pipeline \a stage. The image load operations
will have access to all layers of the specified \a level. (so if the texture
@@ -3287,6 +5832,13 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
pipelines. Such a pipeline must then always be used together with another,
layout compatible QRhiShaderResourceBindings with resources present passed
to QRhiCommandBuffer::setShaderResources().
+
+ \note Image load/store is only guaranteed to be available within a compute
+ pipeline. While some backends may support using these resources in a
+ graphics pipeline as well, this is not universally supported, and even when
+ it is, unexpected problems may arise when it comes to barriers and
+ synchronization. Therefore, avoid using such resources with shaders other
+ than compute.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
int binding, StageFlags stage, QRhiTexture *tex, int level)
@@ -3315,6 +5867,13 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoad(
pipelines. Such a pipeline must then always be used together with another,
layout compatible QRhiShaderResourceBindings with resources present passed
to QRhiCommandBuffer::setShaderResources().
+
+ \note Image load/store is only guaranteed to be available within a compute
+ pipeline. While some backends may support using these resources in a
+ graphics pipeline as well, this is not universally supported, and even when
+ it is, unexpected problems may arise when it comes to barriers and
+ synchronization. Therefore, avoid using such resources with shaders other
+ than compute.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
int binding, StageFlags stage, QRhiTexture *tex, int level)
@@ -3343,6 +5902,13 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::imageStore(
pipelines. Such a pipeline must then always be used together with another,
layout compatible QRhiShaderResourceBindings with resources present passed
to QRhiCommandBuffer::setShaderResources().
+
+ \note Image load/store is only guaranteed to be available within a compute
+ pipeline. While some backends may support using these resources in a
+ graphics pipeline as well, this is not universally supported, and even when
+ it is, unexpected problems may arise when it comes to barriers and
+ synchronization. Therefore, avoid using such resources with shaders other
+ than compute.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
int binding, StageFlags stage, QRhiTexture *tex, int level)
@@ -3369,6 +5935,13 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::imageLoadStore(
suitable for creating pipelines. Such a pipeline must then always be used
together with another, layout compatible QRhiShaderResourceBindings with
resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ \note Buffer load/store is only guaranteed to be available within a compute
+ pipeline. While some backends may support using these resources in a
+ graphics pipeline as well, this is not universally supported, and even when
+ it is, unexpected problems may arise when it comes to barriers and
+ synchronization. Therefore, avoid using such resources with shaders other
+ than compute.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
int binding, StageFlags stage, QRhiBuffer *buf)
@@ -3397,9 +5970,16 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
suitable for creating pipelines. Such a pipeline must then always be used
together with another, layout compatible QRhiShaderResourceBindings with
resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ \note Buffer load/store is only guaranteed to be available within a compute
+ pipeline. While some backends may support using these resources in a
+ graphics pipeline as well, this is not universally supported, and even when
+ it is, unexpected problems may arise when it comes to barriers and
+ synchronization. Therefore, avoid using such resources with shaders other
+ than compute.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
- int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
+ int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
{
Q_ASSERT(size > 0);
QRhiShaderResourceBinding b;
@@ -3425,6 +6005,13 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoad(
suitable for creating pipelines. Such a pipeline must then always be used
together with another, layout compatible QRhiShaderResourceBindings with
resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ \note Buffer load/store is only guaranteed to be available within a compute
+ pipeline. While some backends may support using these resources in a
+ graphics pipeline as well, this is not universally supported, and even when
+ it is, unexpected problems may arise when it comes to barriers and
+ synchronization. Therefore, avoid using such resources with shaders other
+ than compute.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
int binding, StageFlags stage, QRhiBuffer *buf)
@@ -3453,9 +6040,16 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
suitable for creating pipelines. Such a pipeline must then always be used
together with another, layout compatible QRhiShaderResourceBindings with
resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ \note Buffer load/store is only guaranteed to be available within a compute
+ pipeline. While some backends may support using these resources in a
+ graphics pipeline as well, this is not universally supported, and even when
+ it is, unexpected problems may arise when it comes to barriers and
+ synchronization. Therefore, avoid using such resources with shaders other
+ than compute.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
- int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
+ int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
{
Q_ASSERT(size > 0);
QRhiShaderResourceBinding b;
@@ -3481,6 +6075,13 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferStore(
suitable for creating pipelines. Such a pipeline must then always be used
together with another, layout compatible QRhiShaderResourceBindings with
resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ \note Buffer load/store is only guaranteed to be available within a compute
+ pipeline. While some backends may support using these resources in a
+ graphics pipeline as well, this is not universally supported, and even when
+ it is, unexpected problems may arise when it comes to barriers and
+ synchronization. Therefore, avoid using such resources with shaders other
+ than compute.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
int binding, StageFlags stage, QRhiBuffer *buf)
@@ -3509,9 +6110,16 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
suitable for creating pipelines. Such a pipeline must then always be used
together with another, layout compatible QRhiShaderResourceBindings with
resources present passed to QRhiCommandBuffer::setShaderResources().
+
+ \note Buffer load/store is only guaranteed to be available within a compute
+ pipeline. While some backends may support using these resources in a
+ graphics pipeline as well, this is not universally supported, and even when
+ it is, unexpected problems may arise when it comes to barriers and
+ synchronization. Therefore, avoid using such resources with shaders other
+ than compute.
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
- int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size)
+ int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size)
{
Q_ASSERT(size > 0);
QRhiShaderResourceBinding b;
@@ -3536,8 +6144,8 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::bufferLoadStore(
*/
bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept
{
- const QRhiShaderResourceBinding::Data *da = a.data();
- const QRhiShaderResourceBinding::Data *db = b.data();
+ const QRhiShaderResourceBinding::Data *da = QRhiImplementation::shaderResourceBindingData(a);
+ const QRhiShaderResourceBinding::Data *db = QRhiImplementation::shaderResourceBindingData(b);
if (da == db)
return true;
@@ -3570,10 +6178,20 @@ bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBind
}
}
break;
+ case QRhiShaderResourceBinding::Texture:
+ if (da->u.stex.count != db->u.stex.count)
+ return false;
+ for (int i = 0; i < da->u.stex.count; ++i) {
+ if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex)
+ return false;
+ }
+ break;
+ case QRhiShaderResourceBinding::Sampler:
+ if (da->u.stex.texSamplers[0].sampler != db->u.stex.texSamplers[0].sampler)
+ return false;
+ break;
case QRhiShaderResourceBinding::ImageLoad:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::ImageStore:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::ImageLoadStore:
if (da->u.simage.tex != db->u.simage.tex
|| da->u.simage.level != db->u.simage.level)
@@ -3582,9 +6200,7 @@ bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBind
}
break;
case QRhiShaderResourceBinding::BufferLoad:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::BufferStore:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::BufferLoadStore:
if (da->u.sbuf.buf != db->u.sbuf.buf
|| da->u.sbuf.offset != db->u.sbuf.offset
@@ -3594,8 +6210,7 @@ bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBind
}
break;
default:
- Q_UNREACHABLE();
- return false;
+ Q_UNREACHABLE_RETURN(false);
}
return true;
@@ -3619,41 +6234,44 @@ bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBind
*/
size_t qHash(const QRhiShaderResourceBinding &b, size_t seed) noexcept
{
- const QRhiShaderResourceBinding::Data *d = b.data();
- size_t h = uint(d->binding) ^ uint(d->stage) ^ uint(d->type) ^ seed;
+ const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, d->binding);
+ seed = hash(seed, d->stage);
+ seed = hash(seed, d->type);
switch (d->type) {
case QRhiShaderResourceBinding::UniformBuffer:
- h ^= qHash(reinterpret_cast<quintptr>(d->u.ubuf.buf));
+ seed = hash(seed, reinterpret_cast<quintptr>(d->u.ubuf.buf));
break;
case QRhiShaderResourceBinding::SampledTexture:
- h ^= qHash(reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
- h ^= qHash(reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
+ seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
+ seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
+ break;
+ case QRhiShaderResourceBinding::Texture:
+ seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].tex));
+ break;
+ case QRhiShaderResourceBinding::Sampler:
+ seed = hash(seed, reinterpret_cast<quintptr>(d->u.stex.texSamplers[0].sampler));
break;
case QRhiShaderResourceBinding::ImageLoad:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::ImageStore:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::ImageLoadStore:
- h ^= qHash(reinterpret_cast<quintptr>(d->u.simage.tex));
+ seed = hash(seed, reinterpret_cast<quintptr>(d->u.simage.tex));
break;
case QRhiShaderResourceBinding::BufferLoad:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::BufferStore:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::BufferLoadStore:
- h ^= qHash(reinterpret_cast<quintptr>(d->u.sbuf.buf));
- break;
- default:
+ seed = hash(seed, reinterpret_cast<quintptr>(d->u.sbuf.buf));
break;
}
- return h;
+ return seed;
}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
{
QDebugStateSaver saver(dbg);
- const QRhiShaderResourceBinding::Data *d = b.data();
+ const QRhiShaderResourceBinding::Data *d = QRhiImplementation::shaderResourceBindingData(b);
dbg.nospace() << "QRhiShaderResourceBinding("
<< "binding=" << d->binding
<< " stage=" << d->stage
@@ -3675,6 +6293,18 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
}
dbg.nospace() << ')';
break;
+ case QRhiShaderResourceBinding::Texture:
+ dbg.nospace() << " Textures("
+ << "count=" << d->u.stex.count;
+ for (int i = 0; i < d->u.stex.count; ++i)
+ dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex;
+ dbg.nospace() << ')';
+ break;
+ case QRhiShaderResourceBinding::Sampler:
+ dbg.nospace() << " Sampler("
+ << " sampler=" << d->u.stex.texSamplers[0].sampler
+ << ')';
+ break;
case QRhiShaderResourceBinding::ImageLoad:
dbg.nospace() << " ImageLoad("
<< "texture=" << d->u.simage.tex
@@ -3736,18 +6366,44 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
/*!
\class QRhiGraphicsPipeline
- \internal
\inmodule QtGui
+ \since 6.6
\brief Graphics pipeline state resource.
+ Represents a graphics pipeline. What exactly this map to in the underlying
+ native graphics API, varies. Where there is a concept of pipeline objects,
+ for example with Vulkan, the QRhi backend will create such an object upon
+ calling create(). Elsewhere, for example with OpenGL, the
+ QRhiGraphicsPipeline may merely collect the various state, and create()'s
+ main task is to set up the corresponding shader program, but deferring
+ looking at any of the requested state to a later point.
+
+ As with all QRhiResource subclasses, the two-phased initialization pattern
+ applies: setting any values via the setters, for example setDepthTest(), is
+ only effective after calling create(). Avoid changing any values once the
+ QRhiGraphicsPipeline has been initialized via create(). To change some
+ state, set the new value and call create() again. However, that will
+ effectively release all underlying native resources and create new ones. As
+ a result, it may be a heavy, expensive operation. Rather, prefer creating
+ multiple pipelines with the different states, and
+ \l{QRhiCommandBuffer::setGraphicsPipeline()}{switch between them} when
+ recording the render pass.
+
\note Setting the shader stages is mandatory. There must be at least one
stage, and there must be a vertex stage.
\note Setting the shader resource bindings is mandatory. The referenced
QRhiShaderResourceBindings must already have create() called on it by the
time create() is called. Associating with a QRhiShaderResourceBindings that
- has no bindings is also valid, as long as no shader in any stage expects
- any resources.
+ has no bindings is also valid, as long as no shader in any stage expects any
+ resources. Using a QRhiShaderResourceBindings object that does not specify
+ any actual resources (i.e., the buffers, textures, etc. for the binding
+ points are set to \nullptr) is valid as well, as long as a
+ \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
+ QRhiShaderResourceBindings, that specifies resources for all the bindings,
+ is going to be set via
+ \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} when
+ recording the render pass.
\note Setting the render pass descriptor is mandatory. To obtain a
QRhiRenderPassDescriptor that can be passed to setRenderPassDescriptor(),
@@ -3760,20 +6416,49 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
render target's color and depth stencil attachments.
\note The depth test, depth write, and stencil test are disabled by
- default.
+ default. The face culling mode defaults to no culling.
\note stencilReadMask() and stencilWriteMask() apply to both faces. They
both default to 0xFF.
- */
-/*!
- \fn void QRhiGraphicsPipeline::setTargetBlends(const QList<TargetBlend> &blends)
+ \section2 Example usage
+
+ All settings of a graphics pipeline have defaults which might be suitable
+ to many applications. Therefore a minimal example of creating a graphics
+ pipeline could be the following. This assumes that the vertex shader takes
+ a single \c{vec3 position} input at the input location 0. With the
+ QRhiShaderResourceBindings and QRhiRenderPassDescriptor objects, plus the
+ QShader collections for the vertex and fragment stages, a pipeline could be
+ created like this:
- Sets the blend specification for color attachments. Each element in \a
- blends corresponds to a color attachment of the render target.
+ \code
+ QRhiShaderResourceBindings *srb;
+ QRhiRenderPassDescriptor *rpDesc;
+ QShader vs, fs;
+ // ...
+
+ QRhiVertexInputLayout inputLayout;
+ inputLayout.setBindings({ { 3 * sizeof(float) } });
+ inputLayout.setAttributes({ { 0, 0, QRhiVertexInputAttribute::Float3, 0 } });
- By default no blends are set, which is a shortcut to disabling blending and
- enabling color write for all four channels.
+ QRhiGraphicsPipeline *ps = rhi->newGraphicsPipeline();
+ ps->setShaderStages({ { QRhiShaderStage::Vertex, vs }, { QRhiShaderStage::Fragment, fs } });
+ ps->setVertexInputLayout(inputLayout);
+ ps->setShaderResourceBindings(srb);
+ ps->setRenderPassDescriptor(rpDesc);
+ if (!ps->create()) { error(); }
+ \endcode
+
+ The above code creates a pipeline object that uses the defaults for many
+ settings and states. For example, it will use a \l Triangles topology, no
+ backface culling, blending is disabled but color write is enabled for all
+ four channels, depth test/write are disabled, stencil operations are
+ disabled.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ \sa QRhiCommandBuffer, QRhi
*/
/*!
@@ -3818,6 +6503,9 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
\value Lines
\value LineStrip
\value Points
+
+ \value Patches (only available if QRhi::Tessellation is supported, and
+ requires the tessellation stages to be present in the pipeline)
*/
/*!
@@ -3912,21 +6600,102 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBindings &srb)
*/
/*!
- \class QRhiGraphicsPipeline::TargetBlend
- \internal
+ \enum QRhiGraphicsPipeline::PolygonMode
+ \brief Specifies the polygon rasterization mode
+
+ Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) specifies
+ the fill mode used when rasterizing polygons. Polygons may be drawn as
+ solids (Fill), or as a wire mesh (Line).
+
+ Support for non-fill polygon modes is optional and is indicated by the
+ QRhi::NonFillPolygonMode feature. With OpenGL ES and some Vulkan
+ implementations the feature will likely be reported as unsupported, which
+ then means values other than Fill cannot be used.
+
+ \value Fill The interior of the polygon is filled (default)
+ \value Line Boundary edges of the polygon are drawn as line segments.
+ */
+
+/*!
+ \struct QRhiGraphicsPipeline::TargetBlend
\inmodule QtGui
+ \since 6.6
\brief Describes the blend state for one color attachment.
Defaults to color write enabled, blending disabled. The blend values are
set up for pre-multiplied alpha (One, OneMinusSrcAlpha, One,
- OneMinusSrcAlpha) by default.
+ OneMinusSrcAlpha) by default. This means that to get the alpha blending
+ mode Qt Quick uses, it is enough to set the \c enable flag to true while
+ leaving other values at their defaults.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
- \class QRhiGraphicsPipeline::StencilOpState
- \internal
+ \variable QRhiGraphicsPipeline::TargetBlend::colorWrite
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::TargetBlend::enable
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::TargetBlend::srcColor
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::TargetBlend::dstColor
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::TargetBlend::opColor
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::TargetBlend::srcAlpha
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::TargetBlend::dstAlpha
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::TargetBlend::opAlpha
+ */
+
+/*!
+ \struct QRhiGraphicsPipeline::StencilOpState
\inmodule QtGui
+ \since 6.6
\brief Describes the stencil operation state.
+
+ The default-constructed StencilOpState has the following set:
+ \list
+ \li failOp - \l Keep
+ \li depthFailOp - \l Keep
+ \li passOp - \l Keep
+ \li compareOp \l Always
+ \endlist
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::StencilOpState::failOp
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::StencilOpState::depthFailOp
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::StencilOpState::passOp
+ */
+
+/*!
+ \variable QRhiGraphicsPipeline::StencilOpState::compareOp
*/
/*!
@@ -3946,7 +6715,7 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
}
/*!
- \fn bool QRhiGraphicsPipeline::create()
+ \fn virtual bool QRhiGraphicsPipeline::create() = 0
Creates the corresponding native graphics resources. If there are already
resources present due to an earlier create() with no corresponding
@@ -3954,23 +6723,132 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
\return \c true when successful, \c false when a graphics operation failed.
Regardless of the return value, calling destroy() is always safe.
+
+ \note This may be, depending on the underlying graphics API, an expensive
+ operation, especially when shaders get compiled/optimized from source or
+ from an intermediate bytecode format to the GPU's own instruction set.
+ Where applicable, the QRhi backend automatically sets up the relevant
+ non-persistent facilities to accelerate this, for example the Vulkan
+ backend automatically creates a \c VkPipelineCache to improve data reuse
+ during the lifetime of the application.
+
+ \note Drivers may also employ various persistent (disk-based) caching
+ strategies for shader and pipeline data, which is hidden to and is outside
+ of Qt's control. In some cases, depending on the graphics API and the QRhi
+ backend, there are facilities within QRhi for manually managing such a
+ cache, allowing the retrieval of a serializable blob that can then be
+ reloaded in the future runs of the application to ensure faster pipeline
+ creation times. See QRhi::pipelineCacheData() and
+ QRhi::setPipelineCacheData() for details. Note also that when working with
+ a QRhi instance managed by a higher level Qt framework, such as Qt Quick,
+ it is possible that such disk-based caching is taken care of automatically,
+ for example QQuickWindow uses a disk-based pipeline cache by default (which
+ comes in addition to any driver-level caching).
+ */
+
+/*!
+ \fn QRhiGraphicsPipeline::Flags QRhiGraphicsPipeline::flags() const
+ \return the currently set flags.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setFlags(Flags f)
+ Sets the flags \a f.
+ */
+
+/*!
+ \fn QRhiGraphicsPipeline::Topology QRhiGraphicsPipeline::topology() const
+ \return the currently set primitive topology.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setTopology(Topology t)
+ Sets the primitive topology \a t.
+ */
+
+/*!
+ \fn QRhiGraphicsPipeline::CullMode QRhiGraphicsPipeline::cullMode() const
+ \return the currently set face culling mode.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setCullMode(CullMode mode)
+ Sets the specified face culling \a mode.
+ */
+
+/*!
+ \fn QRhiGraphicsPipeline::FrontFace QRhiGraphicsPipeline::frontFace() const
+ \return the currently set front face mode.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setFrontFace(FrontFace f)
+ Sets the front face mode \a f.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setTargetBlends(std::initializer_list<TargetBlend> list)
+
+ Sets the \a list of render target blend settings. This is a list because
+ when multiple render targets are used (i.e., a QRhiTextureRenderTarget with
+ more than one QRhiColorAttachment), there needs to be a TargetBlend
+ structure per render target (color attachment).
+
+ By default there is one default-constructed TargetBlend set.
+
+ \sa QRhi::MaxColorAttachments
+ */
+
+/*!
+ \fn template<typename InputIterator> void QRhiGraphicsPipeline::setTargetBlends(InputIterator first, InputIterator last)
+ Sets the list of render target blend settings from the iterators \a first and \a last.
+ */
+
+/*!
+ \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cbeginTargetBlends() const
+ \return a const iterator pointing to the first item in the render target blend setting list.
+ */
+
+/*!
+ \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::cendTargetBlends() const
+ \return a const iterator pointing just after the last item in the render target blend setting list.
+ */
+
+/*!
+ \fn const QRhiGraphicsPipeline::TargetBlend *QRhiGraphicsPipeline::targetBlendAt(qsizetype index) const
+ \return the render target blend setting at the specified \a index.
+ */
+
+/*!
+ \fn qsizetype QRhiGraphicsPipeline::targetBlendCount() const
+ \return the number of render target blend settings.
+ */
+
+/*!
+ \fn bool QRhiGraphicsPipeline::hasDepthTest() const
+ \return true if depth testing is enabled.
*/
/*!
\fn void QRhiGraphicsPipeline::setDepthTest(bool enable)
- Enables or disables depth testing. Both depth test and the writing out of
- depth data are disabled by default.
+ Enables or disables depth testing based on \a enable. Both depth test and
+ the writing out of depth data are disabled by default.
\sa setDepthWrite()
*/
/*!
+ \fn bool QRhiGraphicsPipeline::hasDepthWrite() const
+ \return true if depth write is enabled.
+ */
+
+/*!
\fn void QRhiGraphicsPipeline::setDepthWrite(bool enable)
- Controls the writing out of depth data into the depth buffer. By default
- this is disabled. Depth write is typically enabled together with the depth
- test.
+ Controls the writing out of depth data into the depth buffer based on
+ \a enable. By default this is disabled. Depth write is typically enabled
+ together with the depth test.
\note Enabling depth write without having depth testing enabled may not
lead to the desired result, and should be avoided.
@@ -3979,9 +6857,233 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
*/
/*!
+ \fn QRhiGraphicsPipeline::CompareOp QRhiGraphicsPipeline::depthOp() const
+ \return the depth comparison function.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setDepthOp(CompareOp op)
+ Sets the depth comparison function \a op.
+ */
+
+/*!
+ \fn bool QRhiGraphicsPipeline::hasStencilTest() const
+ \return true if stencil testing is enabled.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setStencilTest(bool enable)
+ Enables or disables stencil tests based on \a enable.
+ By default this is disabled.
+ */
+
+/*!
+ \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilFront() const
+ \return the current stencil test state for front faces.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setStencilFront(const StencilOpState &state)
+ Sets the stencil test \a state for front faces.
+ */
+
+/*!
+ \fn QRhiGraphicsPipeline::StencilOpState QRhiGraphicsPipeline::stencilBack() const
+ \return the current stencil test state for back faces.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setStencilBack(const StencilOpState &state)
+ Sets the stencil test \a state for back faces.
+ */
+
+/*!
+ \fn quint32 QRhiGraphicsPipeline::stencilReadMask() const
+ \return the currrent stencil read mask.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setStencilReadMask(quint32 mask)
+ Sets the stencil read \a mask. The default value is 0xFF.
+ */
+
+/*!
+ \fn quint32 QRhiGraphicsPipeline::stencilWriteMask() const
+ \return the current stencil write mask.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setStencilWriteMask(quint32 mask)
+ Sets the stencil write \a mask. The default value is 0xFF.
+ */
+
+/*!
+ \fn int QRhiGraphicsPipeline::sampleCount() const
+ \return the currently set sample count. 1 means no multisample antialiasing.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setSampleCount(int s)
+
+ Sets the sample count. Typical values for \a s are 1, 4, or 8. The pipeline
+ must always be compatible with the render target, i.e. the sample counts
+ must match.
+
+ \sa QRhi::supportedSampleCounts()
+ */
+
+/*!
+ \fn float QRhiGraphicsPipeline::lineWidth() const
+ \return the currently set line width. The default is 1.0f.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setLineWidth(float width)
+
+ Sets the line \a width. If the QRhi::WideLines feature is reported as
+ unsupported at runtime, values other than 1.0f are ignored.
+ */
+
+/*!
+ \fn int QRhiGraphicsPipeline::depthBias() const
+ \return the currently set depth bias.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setDepthBias(int bias)
+ Sets the depth \a bias. The default value is 0.
+ */
+
+/*!
+ \fn float QRhiGraphicsPipeline::slopeScaledDepthBias() const
+ \return the currently set slope scaled depth bias.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setSlopeScaledDepthBias(float bias)
+ Sets the slope scaled depth \a bias. The default value is 0.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setShaderStages(std::initializer_list<QRhiShaderStage> list)
+ Sets the \a list of shader stages.
+ */
+
+/*!
+ \fn template<typename InputIterator> void QRhiGraphicsPipeline::setShaderStages(InputIterator first, InputIterator last)
+ Sets the list of shader stages from the iterators \a first and \a last.
+ */
+
+/*!
+ \fn const QRhiShaderStage *QRhiGraphicsPipeline::cbeginShaderStages() const
+ \return a const iterator pointing to the first item in the shader stage list.
+ */
+
+/*!
+ \fn const QRhiShaderStage *QRhiGraphicsPipeline::cendShaderStages() const
+ \return a const iterator pointing just after the last item in the shader stage list.
+ */
+
+/*!
+ \fn const QRhiShaderStage *QRhiGraphicsPipeline::shaderStageAt(qsizetype index) const
+ \return the shader stage at the specified \a index.
+ */
+
+/*!
+ \fn qsizetype QRhiGraphicsPipeline::shaderStageCount() const
+ \return the number of shader stages in this pipeline.
+ */
+
+/*!
+ \fn QRhiVertexInputLayout QRhiGraphicsPipeline::vertexInputLayout() const
+ \return the currently set vertex input layout specification.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setVertexInputLayout(const QRhiVertexInputLayout &layout)
+ Specifies the vertex input \a layout.
+ */
+
+/*!
+ \fn QRhiShaderResourceBindings *QRhiGraphicsPipeline::shaderResourceBindings() const
+ \return the currently associated QRhiShaderResourceBindings object.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
+
+ Associates with \a srb describing the resource binding layout and the
+ resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional,
+ because only the layout matters during pipeline creation. Therefore, the \a
+ srb passed in here can leave the actual buffer or texture objects
+ unspecified (\nullptr) as long as there is another,
+ \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
+ QRhiShaderResourceBindings bound via
+ \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
+ recording the draw calls.
+ */
+
+/*!
+ \fn QRhiRenderPassDescriptor *QRhiGraphicsPipeline::renderPassDescriptor() const
+ \return the currently set QRhiRenderPassDescriptor.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
+ Associates with the specified QRhiRenderPassDescriptor \a desc.
+ */
+
+/*!
+ \fn int QRhiGraphicsPipeline::patchControlPointCount() const
+ \return the currently set patch control point count.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setPatchControlPointCount(int count)
+
+ Sets the number of patch control points to \a count. The default value is
+ 3. This is used only when the topology is set to \l Patches.
+ */
+
+/*!
+ \fn QRhiGraphicsPipeline::PolygonMode QRhiGraphicsPipeline::polygonMode() const
+ \return the polygon mode.
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setPolygonMode(PolygonMode mode)
+ Sets the polygon \a mode. The default is Fill.
+
+ \sa QRhi::NonFillPolygonMode
+ */
+
+/*!
+ \fn int QRhiGraphicsPipeline::multiViewCount() const
+ \return the view count. The default is 0, indicating no multiview rendering.
+ \since 6.7
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setMultiViewCount(int count)
+ Sets the view \a count for multiview rendering. The default is 0,
+ indicating no multiview rendering.
+ \a count must be 2 or larger to trigger multiview rendering.
+
+ Multiview is only available when the \l{QRhi::MultiView}{MultiView feature}
+ is reported as supported. The render target must be a 2D texture array, and
+ the color attachment for the render target must have the same \a count set.
+
+ See QRhiColorAttachment::setMultiViewCount() for further details on
+ multiview rendering.
+
+ \since 6.7
+ \sa QRhi::MultiView, QRhiColorAttachment::setMultiViewCount()
+ */
+
+/*!
\class QRhiSwapChain
- \internal
\inmodule QtGui
+ \since 6.6
\brief Swapchain resource.
A swapchain enables presenting rendering results to a surface. A swapchain
@@ -3991,7 +7093,7 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
Below is a typical pattern for creating and managing a swapchain and some
associated resources in order to render onto a QWindow:
- \badcode
+ \code
void init()
{
sc = rhi->newSwapChain();
@@ -4037,7 +7139,7 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
Releasing the swapchain must happen while the QWindow and the underlying
native window is fully up and running. Building on the previous example:
- \badcode
+ \code
void releaseSwapChain()
{
if (hasSwapChain) {
@@ -4069,7 +7171,7 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
events. QExposeEvent is a loosely specified event that is sent whenever a
window gets mapped, obscured, and resized, depending on the platform.
- \badcode
+ \code
void Window::exposeEvent(QExposeEvent *)
{
// initialize and start rendering when the window becomes usable for graphics purposes
@@ -4115,6 +7217,9 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
command at the end of a frame. For OpenGL, it is necessary to request the
appropriate sample count also via QSurfaceFormat, by calling
QSurfaceFormat::setDefaultFormat() before initializing the QRhi.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -4135,12 +7240,13 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
with premultiplied alpha. In that case the behavior with this flag set is
expected to be equivalent to SurfaceHasPreMulAlpha.
- \value sRGB Requests to pick an sRGB format for the swapchain and/or its
- render target views, where applicable. Note that this implies that sRGB
- framebuffer update and blending will get enabled for all content targeting
- this swapchain, and opting out is not possible. For OpenGL, set
- \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the QSurfaceFormat of
- the QWindow in addition.
+ \value sRGB Requests to pick an sRGB format for the swapchain's color
+ buffers and/or render target views, where applicable. Note that this
+ implies that sRGB framebuffer update and blending will get enabled for all
+ content targeting this swapchain, and opting out is not possible. For
+ OpenGL, set \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the
+ QSurfaceFormat of the QWindow in addition. Applicable only when the
+ swapchain format is set to QRhiSwapChain::SDR.
\value UsedAsTransferSource Indicates the swapchain will be used as the
source of a readback in QRhiResourceUpdateBatch::readBackTexture().
@@ -4169,6 +7275,39 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
*/
/*!
+ \enum QRhiSwapChain::Format
+ Describes the swapchain format. The default format is SDR.
+
+ This enum is used with
+ \l{QRhiSwapChain::isFormatSupported()}{isFormatSupported()} to check
+ upfront if creating the swapchain with the given format is supported by the
+ platform and the window's associated screen, and with
+ \l{QRhiSwapChain::setFormat()}{setFormat()}
+ to set the requested format in the swapchain before calling
+ \l{QRhiSwapChain::createOrResize()}{createOrResize()} for the first time.
+
+ \value SDR 8-bit RGBA or BGRA, depending on the backend and platform. With
+ OpenGL ES in particular, it could happen that the platform provides less
+ than 8 bits (e.g. due to EGL and the QSurfaceFormat choosing a 565 or 444
+ format - this is outside the control of QRhi). Standard dynamic range. May
+ be combined with setting the QRhiSwapChain::sRGB flag.
+
+ \value HDRExtendedSrgbLinear 16-bit float RGBA, high dynamic range,
+ extended linear sRGB (scRGB) color space. This involves Rec. 709 primaries
+ (same as SDR/sRGB) and linear colors. Conversion to the display's native
+ color space (such as, HDR10) is performed by the windowing system. On
+ Windows this is the canonical color space of the system compositor, and is
+ the recommended format for HDR swapchains in general on desktop platforms.
+
+ \value HDR10 10-bit unsigned int RGB or BGR with 2 bit alpha, high dynamic
+ range, HDR10 (Rec. 2020) color space with an ST2084 PQ transfer function.
+
+ \value HDRExtendedDisplayP3Linear 16-bit float RGBA, high dynamic range,
+ extended linear Display P3 color space. The primary choice for HDR on
+ platforms such as iOS and VisionOS.
+ */
+
+/*!
\internal
*/
QRhiSwapChain::QRhiSwapChain(QRhiImplementation *rhi)
@@ -4211,7 +7350,7 @@ QRhiResource::Type QRhiSwapChain::resourceType() const
*/
/*!
- \fn QSize QRhiSwapChain::surfacePixelSize()
+ \fn virtual QSize QRhiSwapChain::surfacePixelSize() = 0
\return The size of the window's associated surface or layer.
@@ -4219,13 +7358,13 @@ QRhiResource::Type QRhiSwapChain::resourceType() const
QWindow::devicePixelRatio()}. With some graphics APIs and windowing system
interfaces (for example, Vulkan) there is a theoretical possibility for a
surface to assume a size different from the associated window. To support
- these cases, rendering logic must always base size-derived calculations
+ these cases, \b{rendering logic must always base size-derived calculations
(such as, viewports) on the size reported from QRhiSwapChain, and never on
- the size queried from QWindow.
+ the size queried from QWindow}.
- \note Can also be called before createOrResize(), if at least window() is
- already set) This in combination with currentPixelSize() allows to detect
- when a swapchain needs to be resized. However, watch out for the fact that
+ \note \b{Can also be called before createOrResize(), if at least window() is
+ already set. This in combination with currentPixelSize() allows to detect
+ when a swapchain needs to be resized.} However, watch out for the fact that
the size of the underlying native object (surface, layer, or similar) is
"live", so whenever this function is called, it returns the latest value
reported by the underlying implementation, without any atomicity guarantee.
@@ -4246,17 +7385,58 @@ QRhiResource::Type QRhiSwapChain::resourceType() const
*/
/*!
- \fn QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer()
+ \fn virtual bool QRhiSwapChain::isFormatSupported(Format f) = 0
- \return a command buffer on which rendering commands can be recorded. Only
- valid within a QRhi::beginFrame() - QRhi::endFrame() block where
- beginFrame() was called with this swapchain.
+ \return true if the given swapchain format \a f is supported. SDR is always
+ supported.
- \note the value must not be cached and reused between frames
+ \note Can be called independently of createOrResize(), but window() must
+ already be set. Calling without the window set may lead to unexpected
+ results depending on the backend and platform (most likely false for any
+ HDR format), because HDR format support is usually tied to the output
+ (screen) to which the swapchain's associated window belongs at any given
+ time. If the result is true for a HDR format, then creating the swapchain
+ with that format is expected to succeed as long as the window is not moved
+ to another screen in the meantime.
+
+ The main use of this function is to call it before the first
+ createOrResize() after the window is already set. This allow the QRhi
+ backends to perform platform or windowing system specific queries to
+ determine if the window (and the screen it is on) is capable of true HDR
+ output with the specified format.
+
+ When the format is reported as supported, call setFormat() to set the
+ requested format and call createOrResize(). Be aware of the consequences
+ however: successfully requesting a HDR format will involve having to deal
+ with a different color space, possibly doing white level correction for
+ non-HDR-aware content, adjusting tonemapping methods, adjusting offscreen
+ render target settings, etc.
+
+ \sa setFormat()
+ */
+
+/*!
+ \fn virtual QRhiCommandBuffer *QRhiSwapChain::currentFrameCommandBuffer() = 0
+
+ \return a command buffer on which rendering commands and resource updates
+ can be recorded within a \l{QRhi::beginFrame()}{beginFrame} -
+ \l{QRhi::endFrame()}{endFrame} block, assuming beginFrame() was called with
+ this swapchain.
+
+ \note The returned object is valid also after endFrame(), up until the next
+ beginFrame(), but the returned command buffer should not be used to record
+ any commands then. Rather, it can be used to query data collected during
+ the frame (or previous frames), for example by calling
+ \l{QRhiCommandBuffer::lastCompletedGpuTime()}{lastCompletedGpuTime()}.
+
+ \note The value must not be cached and reused between frames. The caller
+ should not hold on to the returned object once
+ \l{QRhi::beginFrame()}{beginFrame()} is called again. Instead, the command
+ buffer object should be queried again by calling this function.
*/
/*!
- \fn QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget()
+ \fn virtual QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget() = 0
\return a render target that can used with beginPass() in order to render
the swapchain's current backbuffer. Only valid within a
@@ -4267,7 +7447,35 @@ QRhiResource::Type QRhiSwapChain::resourceType() const
*/
/*!
- \fn bool QRhiSwapChain::createOrResize()
+ \enum QRhiSwapChain::StereoTargetBuffer
+ Selects the backbuffer to use with a stereoscopic swapchain.
+
+ \value LeftBuffer
+ \value RightBuffer
+ */
+
+/*!
+ \return a render target that can be used with beginPass() in order to
+ render to the swapchain's left or right backbuffer. This overload should be
+ used only with stereoscopic rendering, that is, when the associated QWindow
+ is backed by two color buffers, one for each eye, instead of just one.
+
+ When stereoscopic rendering is not supported, the return value will be
+ the default target. It is supported by all hardware backends except for Metal, in
+ combination with \l QSurfaceFormat::StereoBuffers, assuming it is supported
+ by the graphics and display driver stack at run time. Metal and Null backends
+ are going to return the default render target from this overload.
+
+ \note the value must not be cached and reused between frames
+ */
+QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
+{
+ Q_UNUSED(targetBuffer);
+ return currentFrameRenderTarget();
+}
+
+/*!
+ \fn virtual bool QRhiSwapChain::createOrResize() = 0
Creates the swapchain if not already done and resizes the swapchain buffers
to match the current size of the targeted surface. Call this whenever the
@@ -4283,9 +7491,352 @@ QRhiResource::Type QRhiSwapChain::resourceType() const
*/
/*!
+ \fn QWindow *QRhiSwapChain::window() const
+ \return the currently set window.
+ */
+
+/*!
+ \fn void QRhiSwapChain::setWindow(QWindow *window)
+ Sets the \a window.
+ */
+
+/*!
+ \fn QRhiSwapChainProxyData QRhiSwapChain::proxyData() const
+ \return the currently set proxy data.
+ */
+
+/*!
+ \fn void QRhiSwapChain::setProxyData(const QRhiSwapChainProxyData &d)
+ Sets the proxy data \a d.
+
+ \sa QRhi::updateSwapChainProxyData()
+ */
+
+/*!
+ \fn QRhiSwapChain::Flags QRhiSwapChain::flags() const
+ \return the currently set flags.
+ */
+
+/*!
+ \fn void QRhiSwapChain::setFlags(Flags f)
+ Sets the flags \a f.
+ */
+
+/*!
+ \fn QRhiSwapChain::Format QRhiSwapChain::format() const
+ \return the currently set format.
+ */
+
+/*!
+ \fn void QRhiSwapChain::setFormat(Format f)
+ Sets the format \a f.
+
+ Avoid setting formats that are reported as unsupported from
+ isFormatSupported(). Note that support for a given format may depend on the
+ screen the swapchain's associated window is opened on. On some platforms,
+ such as Windows and macOS, for HDR output to work it is necessary to have
+ HDR output enabled in the display settings.
+
+ See isFormatSupported(), \l QRhiSwapChainHdrInfo, and \l Format for more
+ information on high dynamic range output.
+ */
+
+/*!
+ \fn QRhiRenderBuffer *QRhiSwapChain::depthStencil() const
+ \return the currently associated renderbuffer for depth-stencil.
+ */
+
+/*!
+ \fn void QRhiSwapChain::setDepthStencil(QRhiRenderBuffer *ds)
+ Sets the renderbuffer \a ds for use as a depth-stencil buffer.
+ */
+
+/*!
+ \fn int QRhiSwapChain::sampleCount() const
+ \return the currently set sample count. 1 means no multisample antialiasing.
+ */
+
+/*!
+ \fn void QRhiSwapChain::setSampleCount(int samples)
+
+ Sets the sample count. Common values for \a samples are 1 (no MSAA), 4 (4x
+ MSAA), or 8 (8x MSAA).
+
+ \sa QRhi::supportedSampleCounts()
+ */
+
+/*!
+ \fn QRhiRenderPassDescriptor *QRhiSwapChain::renderPassDescriptor() const
+ \return the currently associated QRhiRenderPassDescriptor object.
+ */
+
+/*!
+ \fn void QRhiSwapChain::setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
+ Associates with the QRhiRenderPassDescriptor \a desc.
+ */
+
+/*!
+ \fn virtual QRhiRenderPassDescriptor *QRhiSwapChain::newCompatibleRenderPassDescriptor() = 0;
+
+ \return a new QRhiRenderPassDescriptor that is compatible with this swapchain.
+
+ The returned value is used in two ways: it can be passed to
+ setRenderPassDescriptor() and
+ QRhiGraphicsPipeline::setRenderPassDescriptor(). A render pass descriptor
+ describes the attachments (color, depth/stencil) and the load/store
+ behavior that can be affected by flags(). A QRhiGraphicsPipeline can only
+ be used in combination with a swapchain that has a
+ \l{QRhiRenderPassDescriptor::isCompatible()}{compatible}
+ QRhiRenderPassDescriptor set.
+
+ \sa createOrResize()
+ */
+
+/*!
+ \struct QRhiSwapChainHdrInfo
+ \inmodule QtGui
+ \since 6.6
+
+ \brief Describes the high dynamic range related information of the
+ swapchain's associated output.
+
+ To perform HDR-compatible tonemapping, where the target range is not [0,1],
+ one often needs to know the maximum luminance of the display the
+ swapchain's window is associated with. While this is often made
+ user-configurable (think brightness, gamma and similar settings in games),
+ it can be highly useful to set defaults based on the values reported by the
+ display itself, thus providing a decent starting point.
+
+ There are some problems however: the information is exposed in different
+ forms on different platforms, whereas with cross-platform graphics APIs
+ there is often no associated solution at all, because managing such
+ information is not in the scope of the API (and may rather be retrievable
+ via other platform-specific means, if any).
+
+ With Metal on macOS/iOS, there is no luminance values exposed in the
+ platform APIs. Instead, the maximum color component value, that would be
+ 1.0 in a non-HDR setup, is provided. The \c limitsType field indicates what
+ kind of information is available. It is then up to the clients of QRhi to
+ access the correct data from the \c limits union and use it as they see
+ fit.
+
+ With an API like Vulkan, where there is no way to get such information, the
+ values are always the built-in defaults.
+
+ Therefore, the struct returned from QRhiSwapChain::hdrInfo() contains
+ either some hard-coded defaults or real values received from an API such as
+ DXGI (IDXGIOutput6) or Cocoa (NSScreen). When no platform queries are
+ available (or needs using platform facilities out of scope for QRhi), the
+ hard-coded defaults are a maximum luminance of 1000 nits and an SDR white
+ level of 200.
+
+ The struct also exposes the presumed luminance behavior of the platform and
+ its compositor, to indicate what a color component value of 1.0 is treated
+ as in a HDR color buffer. In some cases it will be necessary to perform
+ color correction of non-HDR content composited with HDR content. To enable
+ this, the SDR white level is queried from the system on some platforms
+ (Windows) and exposed here.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ \sa QRhiSwapChain::hdrInfo()
+ */
+
+/*!
+ \enum QRhiSwapChainHdrInfo::LimitsType
+
+ \value LuminanceInNits Indicates that the \l limits union has its
+ \c luminanceInNits struct set
+
+ \value ColorComponentValue Indicates that the \l limits union has its
+ \c colorComponentValue struct set
+*/
+
+/*!
+ \enum QRhiSwapChainHdrInfo::LuminanceBehavior
+
+ \value SceneReferred Indicates that the color value of 1.0 is interpreted
+ as 80 nits. This is the behavior of HDR-enabled windows with the Windows
+ compositor. See
+ \l{https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range}{this
+ page} for more information on HDR on Windows.
+
+ \value DisplayReferred Indicates that the color value of 1.0 is interpreted
+ as the value of the SDR white. (which can be e.g. 200 nits, but will vary
+ depending on screen brightness) This is the behavior of HDR-enabled windows
+ on Apple platforms. See
+ \l{https://developer.apple.com/documentation/metal/hdr_content/displaying_hdr_content_in_a_metal_layer}{this
+ page} for more information on Apple's EDR system.
+*/
+
+/*!
+ \variable QRhiSwapChainHdrInfo::limitsType
+
+ With Metal on macOS/iOS, there is no luminance values exposed in the
+ platform APIs. Instead, the maximum color component value, that would be
+ 1.0 in a non-HDR setup, is provided. This value indicates what kind of
+ information is available in \l limits.
+
+ \sa QRhiSwapChain::hdrInfo()
+*/
+
+/*!
+ \variable QRhiSwapChainHdrInfo::limits
+
+ Contains the actual values queried from the graphics API or the platform.
+ The type of data is indicated by \l limitsType. This is therefore a union.
+ There are currently two options:
+
+ Luminance values in nits:
+
+ \code
+ struct {
+ float minLuminance;
+ float maxLuminance;
+ } luminanceInNits;
+ \endcode
+
+ On Windows the minimum and maximum luminance depends on the screen
+ brightness. While not relevant for desktops, on laptops the screen
+ brightness may change at any time. Increasing brightness implies decreased
+ maximum luminance. In addition, the results may also be dependent on the
+ HDR Content Brightness set in Windows Settings' System/Display/HDR view,
+ if there is such a setting.
+
+ Note however that the changes made to the laptop screen's brightness or in
+ the system settings while the application is running are not necessarily
+ reflected in the returned values, meaning calling hdrInfo() again may still
+ return the same luminance range as before for the rest of the process'
+ lifetime. The exact behavior is up to DXGI and Qt has no control over it.
+
+ \note The Windows compositor works in scene-referred mode for HDR content.
+ A color component value of 1.0 corresponds to a luminance of 80 nits. When
+ rendering non-HDR content (e.g. 2D UI elements), the correction of the
+ white level is often necessary. (e.g., outputting the fragment color (1, 1,
+ 1) will likely lead to showing a shade of white that is too dim on-screen)
+ See \l sdrWhiteLevel.
+
+ For macOS/iOS, the current maximum and potential maximum color
+ component values are provided:
+
+ \code
+ struct {
+ float maxColorComponentValue;
+ float maxPotentialColorComponentValue;
+ } colorComponentValue;
+ \endcode
+
+ The value may depend on the screen brightness, which on laptops means that
+ the result may change in the next call to hdrInfo() if the brightness was
+ changed in the meantime. The maximum screen brightness implies a maximum
+ color value of 1.0.
+
+ \note Apple's EDR is display-referred. 1.0 corresponds to a luminance level
+ of SDR white (e.g. 200 nits), the value of which varies based on the screen
+ brightness and possibly other settings. The exact luminance value for that,
+ or the maximum luminance of the display, are not exposed to the
+ applications.
+
+ \note It has been observed that the color component values are not set to
+ the correct larger-than-1 value right away on startup on some macOS
+ systems, but the values tend to change during or after the first frame.
+
+ \sa QRhiSwapChain::hdrInfo()
+*/
+
+/*!
+ \variable QRhiSwapChainHdrInfo::luminanceBehavior
+
+ Describes the platform's presumed behavior with regards to color values.
+
+ \sa sdrWhiteLevel
+ */
+
+/*!
+ \variable QRhiSwapChainHdrInfo::sdrWhiteLevel
+
+ On Windows this is the dynamic SDR white level in nits. The value is
+ dependent on the screen brightness (on laptops), and the SDR or HDR Content
+ Brightness settings in the Windows settings' System/Display/HDR view.
+
+ To perform white level correction for non-HDR (SDR) content, such as 2D UI
+ elemenents, multiply the final color with sdrWhiteLevel / 80.0 whenever
+ \l luminanceBehavior is SceneReferred. (assuming Windows and a linear
+ extended sRGB (scRGB) color space)
+
+ On other platforms the value is always a pre-defined value, 200. This may
+ not match the system's actual SDR white level, but the value of this
+ variable is not relevant in practice when the \l luminanceBehavior is
+ DisplayReferred, because then the color component value of 1.0 refers to
+ the SDR white by default.
+
+ \sa luminanceBehavior
+*/
+
+/*!
+ \return the HDR information for the associated display.
+
+ Do not assume that this is a cheap operation. Depending on the platform,
+ this function makes various platform queries which may have a performance
+ impact.
+
+ \note Can be called before createOrResize() as long as the window is
+ \l{setWindow()}{set}.
+
+ \note What happens when moving a window with an initialized swapchain
+ between displays (HDR to HDR with different characteristics, HDR to SDR,
+ etc.) is not currently well-defined and depends heavily on the windowing
+ system and compositor, with potentially varying behavior between platforms.
+ Currently QRhi only guarantees that hdrInfo() returns valid data, if
+ available, for the display to which the swapchain's associated window
+ belonged at the time of createOrResize().
+
+ \sa QRhiSwapChainHdrInfo
+ */
+QRhiSwapChainHdrInfo QRhiSwapChain::hdrInfo()
+{
+ QRhiSwapChainHdrInfo info;
+ info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
+ info.limits.luminanceInNits.minLuminance = 0.0f;
+ info.limits.luminanceInNits.maxLuminance = 1000.0f;
+ info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred;
+ info.sdrWhiteLevel = 200.0f;
+ return info;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiSwapChainHdrInfo &info)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QRhiSwapChainHdrInfo(";
+ switch (info.limitsType) {
+ case QRhiSwapChainHdrInfo::LuminanceInNits:
+ dbg.nospace() << " minLuminance=" << info.limits.luminanceInNits.minLuminance
+ << " maxLuminance=" << info.limits.luminanceInNits.maxLuminance;
+ break;
+ case QRhiSwapChainHdrInfo::ColorComponentValue:
+ dbg.nospace() << " maxColorComponentValue=" << info.limits.colorComponentValue.maxColorComponentValue;
+ dbg.nospace() << " maxPotentialColorComponentValue=" << info.limits.colorComponentValue.maxPotentialColorComponentValue;
+ break;
+ }
+ switch (info.luminanceBehavior) {
+ case QRhiSwapChainHdrInfo::SceneReferred:
+ dbg.nospace() << " scene-referred, SDR white level=" << info.sdrWhiteLevel;
+ break;
+ case QRhiSwapChainHdrInfo::DisplayReferred:
+ dbg.nospace() << " display-referred";
+ break;
+ }
+ dbg.nospace() << ')';
+ return dbg;
+}
+#endif
+
+/*!
\class QRhiComputePipeline
- \internal
\inmodule QtGui
+ \since 6.6
\brief Compute pipeline state resource.
\note Setting the shader resource bindings is mandatory. The referenced
@@ -4293,6 +7844,9 @@ QRhiResource::Type QRhiSwapChain::resourceType() const
time create() is called.
\note Setting the shader is mandatory.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -4322,15 +7876,59 @@ QRhiComputePipeline::QRhiComputePipeline(QRhiImplementation *rhi)
}
/*!
+ \fn QRhiComputePipeline::Flags QRhiComputePipeline::flags() const
+ \return the currently set flags.
+ */
+
+/*!
+ \fn void QRhiComputePipeline::setFlags(Flags f)
+ Sets the flags \a f.
+ */
+
+/*!
+ \fn QRhiShaderStage QRhiComputePipeline::shaderStage() const
+ \return the currently set shader.
+ */
+
+/*!
+ \fn void QRhiComputePipeline::setShaderStage(const QRhiShaderStage &stage)
+
+ Sets the shader to use. \a stage can only refer to the
+ \l{QRhiShaderStage::Compute}{compute stage}.
+ */
+
+/*!
+ \fn QRhiShaderResourceBindings *QRhiComputePipeline::shaderResourceBindings() const
+ \return the currently associated QRhiShaderResourceBindings object.
+ */
+
+/*!
+ \fn void QRhiComputePipeline::setShaderResourceBindings(QRhiShaderResourceBindings *srb)
+
+ Associates with \a srb describing the resource binding layout and the
+ resources (QRhiBuffer, QRhiTexture) themselves. The latter is optional. As
+ with graphics pipelines, the \a srb passed in here can leave the actual
+ buffer or texture objects unspecified (\nullptr) as long as there is
+ another,
+ \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible}
+ QRhiShaderResourceBindings bound via
+ \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} before
+ recording the dispatch call.
+ */
+
+/*!
\class QRhiCommandBuffer
- \internal
\inmodule QtGui
+ \since 6.6
\brief Command buffer resource.
Not creatable by applications at the moment. The only ways to obtain a
valid QRhiCommandBuffer are to get it from the targeted swapchain via
QRhiSwapChain::currentFrameCommandBuffer(), or, in case of rendering
completely offscreen, initializing one via QRhi::beginOffscreenFrame().
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -4391,7 +7989,7 @@ QRhiResource::Type QRhiCommandBuffer::resourceType() const
return CommandBuffer;
}
-static const char *resourceTypeStr(QRhiResource *res)
+static const char *resourceTypeStr(const QRhiResource *res)
{
switch (res->resourceType()) {
case QRhiResource::Buffer:
@@ -4404,8 +8002,8 @@ static const char *resourceTypeStr(QRhiResource *res)
return "RenderBuffer";
case QRhiResource::RenderPassDescriptor:
return "RenderPassDescriptor";
- case QRhiResource::RenderTarget:
- return "RenderTarget";
+ case QRhiResource::SwapChainRenderTarget:
+ return "SwapChainRenderTarget";
case QRhiResource::TextureRenderTarget:
return "TextureRenderTarget";
case QRhiResource::ShaderResourceBindings:
@@ -4418,11 +8016,9 @@ static const char *resourceTypeStr(QRhiResource *res)
return "ComputePipeline";
case QRhiResource::CommandBuffer:
return "CommandBuffer";
- default:
- Q_UNREACHABLE();
- break;
}
- return "";
+
+ Q_UNREACHABLE_RETURN("");
}
QRhiImplementation::~QRhiImplementation()
@@ -4439,11 +8035,21 @@ QRhiImplementation::~QRhiImplementation()
// release builds: opt-in
static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK");
#endif
- if (leakCheck && !resources.isEmpty()) {
- qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
- q, int(resources.count()));
- for (QRhiResource *res : qAsConst(resources)) {
- qWarning(" %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
+ if (!resources.isEmpty()) {
+ if (leakCheck) {
+ qWarning("QRhi %p going down with %d unreleased resources that own native graphics objects. This is not nice.",
+ q, int(resources.size()));
+ }
+ for (auto it = resources.cbegin(), end = resources.cend(); it != end; ++it) {
+ QRhiResource *res = it.key();
+ const bool ownsNativeResources = it.value();
+ if (leakCheck && ownsNativeResources)
+ qWarning(" %s resource %p (%s)", resourceTypeStr(res), res, res->m_objectName.constData());
+
+ // Null out the resource's rhi pointer. This is why it makes sense to do null
+ // checks in the destroy() implementations of the various resource types. It
+ // allows to survive in bad applications that somehow manage to destroy a
+ // resource of a QRhi after the QRhi itself.
res->m_rhi = nullptr;
}
}
@@ -4621,6 +8227,10 @@ void QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSi
bpc = 4;
break;
+ case QRhiTexture::RGB10A2:
+ bpc = 4;
+ break;
+
case QRhiTexture::D16:
bpc = 2;
break;
@@ -4643,21 +8253,15 @@ void QRhiImplementation::textureFormatInfo(QRhiTexture::Format format, const QSi
*bytesPerPixel = bpc;
}
-// Approximate because it excludes subresource alignment or multisampling.
-quint32 QRhiImplementation::approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize, int depth,
- int mipCount, int layerCount)
+bool QRhiImplementation::isStencilSupportingFormat(QRhiTexture::Format format) const
{
- quint32 approxSize = 0;
- for (int level = 0; level < mipCount; ++level) {
- quint32 byteSize = 0;
- const QSize size(qFloor(qreal(qMax(1, baseSize.width() >> level))),
- qFloor(qreal(qMax(1, baseSize.height() >> level))));
- textureFormatInfo(format, size, nullptr, &byteSize, nullptr);
- approxSize += byteSize;
+ switch (format) {
+ case QRhiTexture::D24S8:
+ return true;
+ default:
+ break;
}
- approxSize *= depth; // 3D texture depth or 1 otherwise
- approxSize *= uint(layerCount); // 6 for cubemaps or 1 otherwise
- return approxSize;
+ return false;
}
bool QRhiImplementation::sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps)
@@ -4701,7 +8305,7 @@ bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBin
const int CHECKED_BINDINGS_COUNT = 64;
bool bindingSeen[CHECKED_BINDINGS_COUNT] = {};
for (auto it = srb->cbeginBindings(), end = srb->cendBindings(); it != end; ++it) {
- const int binding = it->data()->binding;
+ const int binding = shaderResourceBindingData(*it)->binding;
if (binding >= CHECKED_BINDINGS_COUNT)
continue;
if (binding < 0) {
@@ -4709,7 +8313,7 @@ bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBin
bindingsOk = false;
continue;
}
- switch (it->data()->type) {
+ switch (shaderResourceBindingData(*it)->type) {
case QRhiShaderResourceBinding::UniformBuffer:
if (!bindingSeen[binding]) {
bindingSeen[binding] = true;
@@ -4726,10 +8330,24 @@ bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBin
bindingsOk = false;
}
break;
+ case QRhiShaderResourceBinding::Texture:
+ if (!bindingSeen[binding]) {
+ bindingSeen[binding] = true;
+ } else {
+ qWarning("Texture duplicates an existing binding number %d", binding);
+ bindingsOk = false;
+ }
+ break;
+ case QRhiShaderResourceBinding::Sampler:
+ if (!bindingSeen[binding]) {
+ bindingSeen[binding] = true;
+ } else {
+ qWarning("Sampler duplicates an existing binding number %d", binding);
+ bindingsOk = false;
+ }
+ break;
case QRhiShaderResourceBinding::ImageLoad:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::ImageStore:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::ImageLoadStore:
if (!bindingSeen[binding]) {
bindingSeen[binding] = true;
@@ -4739,9 +8357,7 @@ bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBin
}
break;
case QRhiShaderResourceBinding::BufferLoad:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::BufferStore:
- Q_FALLTHROUGH();
case QRhiShaderResourceBinding::BufferLoadStore:
if (!bindingSeen[binding]) {
bindingSeen[binding] = true;
@@ -4751,7 +8367,7 @@ bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBin
}
break;
default:
- qWarning("Unknown binding type %d", int(it->data()->type));
+ qWarning("Unknown binding type %d", int(shaderResourceBindingData(*it)->type));
bindingsOk = false;
break;
}
@@ -4767,6 +8383,41 @@ bool QRhiImplementation::sanityCheckShaderResourceBindings(QRhiShaderResourceBin
return true;
}
+int QRhiImplementation::effectiveSampleCount(int sampleCount) const
+{
+ // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
+ const int s = qBound(1, sampleCount, 64);
+ const QList<int> supported = supportedSampleCounts();
+ int result = 1;
+
+ // Stay compatible with Qt 5 in that requesting an unsupported sample count
+ // is not an error (although we still do a categorized debug print about
+ // this), and rather a supported value, preferably a close one, not just 1,
+ // is used instead. This is actually deviating from Qt 5 as that performs a
+ // clamping only and does not handle cases such as when sample count 2 is
+ // not supported but 4 is. (OpenGL handles things like that gracefully,
+ // other APIs may not, so improve this by picking the next largest, or in
+ // absence of that, the largest value; this with the goal to not reduce
+ // quality by rather picking a larger-than-requested value than a smaller one)
+
+ for (int i = 0, ie = supported.count(); i != ie; ++i) {
+ // assumes the 'supported' list is sorted
+ if (supported[i] >= s) {
+ result = supported[i];
+ break;
+ }
+ }
+
+ if (result != s) {
+ if (result == 1 && !supported.isEmpty())
+ result = supported.last();
+ qCDebug(QRHI_LOG_INFO, "Attempted to set unsupported sample count %d, using %d instead",
+ sampleCount, result);
+ }
+
+ return result;
+}
+
/*!
\internal
*/
@@ -4782,30 +8433,64 @@ QRhi::~QRhi()
if (!d)
return;
+ runCleanup();
+
qDeleteAll(d->pendingDeleteResources);
d->pendingDeleteResources.clear();
- runCleanup();
-
d->destroy();
delete d;
}
+void QRhiImplementation::prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags)
+{
+ q = rhi;
+
+ // Play nice with QSG_INFO since that is still the most commonly used
+ // way to get graphics info printed from Qt Quick apps, and the Quick
+ // scenegraph is our primary user.
+ if (qEnvironmentVariableIsSet("QSG_INFO"))
+ const_cast<QLoggingCategory &>(QRHI_LOG_INFO()).setEnabled(QtDebugMsg, true);
+
+ debugMarkers = flags.testFlag(QRhi::EnableDebugMarkers);
+
+ implType = impl;
+ implThread = QThread::currentThread();
+}
+
/*!
- \return a new QRhi instance with a backend for the graphics API specified by \a impl.
+ \return a new QRhi instance with a backend for the graphics API specified
+ by \a impl with the specified \a flags.
\a params must point to an instance of one of the backend-specific
subclasses of QRhiInitParams, such as, QRhiVulkanInitParams,
- QRhiMetalInitParams, QRhiD3D11InitParams, QRhiGles2InitParams. See these
- classes for examples on creating a QRhi.
-
- \a flags is optional. It is used to enable profile and debug related
- features that are potentially expensive and should only be used during
- development.
+ QRhiMetalInitParams, QRhiD3D11InitParams, QRhiD3D12InitParams,
+ QRhiGles2InitParams. See these classes for examples on creating a QRhi.
+
+ QRhi by design does not implement any fallback logic: if the specified API
+ cannot be initialized, create() will fail, with warnings printed on the
+ debug output by the backends. The clients of QRhi, for example Qt Quick,
+ may however provide additional logic that allow falling back to an API
+ different than what was requested, depending on the platform. If the
+ intention is just to test if initialization would succeed when calling
+ create() at later point, it is preferable to use probe() instead of
+ create(), because with some backends probing can be implemented in a more
+ lightweight manner as opposed to create(), which performs full
+ initialization of the infrastructure and is wasteful if that QRhi instance
+ is then thrown immediately away.
+
+ \a importDevice allows using an already existing graphics device, without
+ QRhi creating its own. When not null, this parameter must point to an
+ instance of one of the subclasses of QRhiNativeHandles:
+ QRhiVulkanNativeHandles, QRhiD3D11NativeHandles, QRhiD3D12NativeHandles,
+ QRhiMetalNativeHandles, QRhiGles2NativeHandles. The exact details and
+ semantics depend on the backand and the underlying graphics API.
+
+ \sa probe()
*/
QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRhiNativeHandles *importDevice)
{
- QScopedPointer<QRhi> r(new QRhi);
+ std::unique_ptr<QRhi> r(new QRhi);
switch (impl) {
case Null:
@@ -4840,7 +8525,7 @@ QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRh
break;
#endif
case Metal:
-#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
+#if QT_CONFIG(metal)
r->d = new QRhiMetal(static_cast<QRhiMetalInitParams *>(params),
static_cast<QRhiMetalNativeHandles *>(importDevice));
break;
@@ -4848,35 +8533,116 @@ QRhi *QRhi::create(Implementation impl, QRhiInitParams *params, Flags flags, QRh
qWarning("This platform has no Metal support");
break;
#endif
- default:
+ case D3D12:
+#ifdef Q_OS_WIN
+#ifdef QRHI_D3D12_AVAILABLE
+ r->d = new QRhiD3D12(static_cast<QRhiD3D12InitParams *>(params),
+ static_cast<QRhiD3D12NativeHandles *>(importDevice));
+ break;
+#else
+ qWarning("Qt was built without Direct3D 12 support. "
+ "This is likely due to having ancient SDK headers (such as d3d12.h) in the Qt build environment. "
+ "Rebuild Qt with an SDK supporting D3D12 features introduced in Windows 10 version 1703, "
+ "or use an MSVC build as those typically are built with more up-to-date SDKs.");
+ break;
+#endif
+#else
+ qWarning("This platform has no Direct3D 12 support");
break;
+#endif
}
if (r->d) {
- r->d->q = r.data();
+ r->d->prepareForCreate(r.get(), impl, flags);
+ if (r->d->create(flags))
+ return r.release();
+ }
- if (flags.testFlag(EnableProfiling)) {
- QRhiProfilerPrivate *profD = QRhiProfilerPrivate::get(&r->d->profiler);
- profD->rhiDWhenEnabled = r->d;
- const_cast<QLoggingCategory &>(QRHI_LOG_INFO()).setEnabled(QtDebugMsg, true);
- }
+ return nullptr;
+}
+
+/*!
+ \return true if create() can be expected to succeed when called the given
+ \a impl and \a params.
- // Play nice with QSG_INFO since that is still the most commonly used
- // way to get graphics info printed from Qt Quick apps, and the Quick
- // scenegraph is our primary user.
- if (qEnvironmentVariableIsSet("QSG_INFO"))
- const_cast<QLoggingCategory &>(QRHI_LOG_INFO()).setEnabled(QtDebugMsg, true);
+ For some backends this is equivalent to calling create(), checking its
+ return value, and then destroying the resulting QRhi.
- r->d->debugMarkers = flags.testFlag(EnableDebugMarkers);
+ For others, in particular with Metal, there may be a specific probing
+ implementation, which allows testing in a more lightweight manner without
+ polluting the debug output with warnings upon failures.
- if (r->d->create(flags)) {
- r->d->implType = impl;
- r->d->implThread = QThread::currentThread();
- return r.take();
- }
+ \sa create()
+ */
+bool QRhi::probe(QRhi::Implementation impl, QRhiInitParams *params)
+{
+ bool ok = false;
+
+ // The only place currently where this makes sense is Metal, where the API
+ // is simple enough so that a special probing function - doing nothing but
+ // a MTLCreateSystemDefaultDevice - is reasonable. Elsewhere, just call
+ // create() and then drop the result.
+
+ if (impl == Metal) {
+#if QT_CONFIG(metal)
+ ok = QRhiMetal::probe(static_cast<QRhiMetalInitParams *>(params));
+#endif
+ } else {
+ QRhi *rhi = create(impl, params);
+ ok = rhi != nullptr;
+ delete rhi;
}
+ return ok;
+}
- return nullptr;
+/*!
+ \struct QRhiSwapChainProxyData
+ \inmodule QtGui
+ \since 6.6
+
+ \brief Opaque data describing native objects needed to set up a swapchain.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ \sa QRhi::updateSwapChainProxyData()
+ */
+
+/*!
+ Generates and returns a QRhiSwapChainProxyData struct containing opaque
+ data specific to the backend and graphics API specified by \a impl. \a
+ window is the QWindow a swapchain is targeting.
+
+ The returned struct can be passed to QRhiSwapChain::setProxyData(). This
+ makes sense in threaded rendering systems: this static function is expected
+ to be called on the \b{main (gui) thread}, unlike all QRhi operations, then
+ transferred to the thread working with the QRhi and QRhiSwapChain and passed
+ on to the swapchain. This allows doing native platform queries that are
+ only safe to be called on the main thread, for example to query the
+ CAMetalLayer from a NSView, and then passing on the data to the
+ QRhiSwapChain living on the rendering thread. With the Metal example, doing
+ the view.layer access on a dedicated rendering thread causes a warning in
+ the Xcode Thread Checker. With the data proxy mechanism, this is avoided.
+
+ When threads are not involved, generating and passing on the
+ QRhiSwapChainProxyData is not required: backends are guaranteed to be able
+ to query whatever is needed on their own, and if everything lives on the
+ main (gui) thread, that should be sufficient.
+
+ \note \a impl should match what the QRhi is created with. For example,
+ calling with QRhi::Metal on a non-Apple platform will not generate any
+ useful data.
+ */
+QRhiSwapChainProxyData QRhi::updateSwapChainProxyData(QRhi::Implementation impl, QWindow *window)
+{
+#if QT_CONFIG(metal)
+ if (impl == Metal)
+ return QRhiMetal::updateSwapChainProxyData(window);
+#else
+ Q_UNUSED(impl);
+ Q_UNUSED(window);
+#endif
+ return {};
}
/*!
@@ -4888,11 +8654,12 @@ QRhi::Implementation QRhi::backend() const
}
/*!
- \return the backend type as string for this QRhi.
+ \return a friendly name for the backend \a impl, usually the name of the 3D
+ API in use.
*/
-const char *QRhi::backendName() const
+const char *QRhi::backendName(Implementation impl)
{
- switch (d->implType) {
+ switch (impl) {
case QRhi::Null:
return "Null";
case QRhi::Vulkan:
@@ -4903,16 +8670,28 @@ const char *QRhi::backendName() const
return "D3D11";
case QRhi::Metal:
return "Metal";
- default:
- return "Unknown";
+ case QRhi::D3D12:
+ return "D3D12";
}
+
+ Q_UNREACHABLE_RETURN("Unknown");
+}
+
+/*!
+ \return the backend type as string for this QRhi.
+ */
+const char *QRhi::backendName() const
+{
+ return backendName(d->implType);
}
/*!
\enum QRhiDriverInfo::DeviceType
- Specifies the graphics device's type, when the information is available. In
- practice this is only applicable with Vulkan and Metal. With others the
- value will always be UnknownDevice.
+ Specifies the graphics device's type, when the information is available.
+
+ In practice this is only applicable with Vulkan and Metal. With Direct 3D
+ 11 and 12, using an adapter with the software flag set leads to the value
+ \c CpuDevice. Otherwise, and with OpenGL, the value is always UnknownDevice.
\value UnknownDevice
\value IntegratedDevice
@@ -4924,9 +8703,8 @@ const char *QRhi::backendName() const
/*!
\struct QRhiDriverInfo
- \internal
\inmodule QtGui
- \since 6.1
+ \since 6.6
\brief Describes the physical device, adapter, or graphics API
implementation that is used by an initialized QRhi.
@@ -4938,8 +8716,35 @@ const char *QRhi::backendName() const
\c{GL_VERSION}. The deviceId is always 0 for OpenGL. vendorId is always 0
for OpenGL and Metal. deviceType is always UnknownDevice for OpenGL and
Direct 3D.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
+/*!
+ \variable QRhiDriverInfo::deviceName
+
+ \sa QRhi::driverInfo()
+*/
+
+/*!
+ \variable QRhiDriverInfo::deviceId
+
+ \sa QRhi::driverInfo()
+*/
+
+/*!
+ \variable QRhiDriverInfo::vendorId
+
+ \sa QRhi::driverInfo()
+*/
+
+/*!
+ \variable QRhiDriverInfo::deviceType
+
+ \sa QRhi::driverInfo(), QRhiDriverInfo::DeviceType
+*/
+
#ifndef QT_NO_DEBUG_STREAM
static inline const char *deviceTypeStr(QRhiDriverInfo::DeviceType type)
{
@@ -4956,9 +8761,9 @@ static inline const char *deviceTypeStr(QRhiDriverInfo::DeviceType type)
return "Virtual";
case QRhiDriverInfo::CpuDevice:
return "Cpu";
- default:
- return "";
}
+
+ Q_UNREACHABLE_RETURN(nullptr);
}
QDebug operator<<(QDebug dbg, const QRhiDriverInfo &info)
{
@@ -5007,6 +8812,33 @@ void QRhi::addCleanupCallback(const CleanupCallback &callback)
}
/*!
+ \overload
+
+ Registers \a callback to be invoked either when the QRhi is destroyed or
+ when runCleanup() is called. This overload takes an opaque pointer, \a key,
+ that is used to ensure that a given callback is registered (and so called)
+ only once.
+
+ \sa removeCleanupCallback()
+ */
+void QRhi::addCleanupCallback(const void *key, const CleanupCallback &callback)
+{
+ d->addCleanupCallback(key, callback);
+}
+
+/*!
+ Deregisters the callback with \a key. If no cleanup callback was registered
+ with \a key, the function does nothing. Callbacks registered without a key
+ cannot be removed.
+
+ \sa addCleanupCallback()
+ */
+void QRhi::removeCleanupCallback(const void *key)
+{
+ d->removeCleanupCallback(key);
+}
+
+/*!
Invokes all registered cleanup functions. The list of cleanup callbacks it
then cleared. Normally destroying the QRhi does this automatically, but
sometimes it can be useful to trigger cleanup in order to release all
@@ -5016,16 +8848,21 @@ void QRhi::addCleanupCallback(const CleanupCallback &callback)
*/
void QRhi::runCleanup()
{
- for (const CleanupCallback &f : qAsConst(d->cleanupCallbacks))
+ for (const CleanupCallback &f : std::as_const(d->cleanupCallbacks))
f(this);
d->cleanupCallbacks.clear();
+
+ for (auto it = d->keyedCleanupCallbacks.cbegin(), end = d->keyedCleanupCallbacks.cend(); it != end; ++it)
+ it.value()(this);
+
+ d->keyedCleanupCallbacks.clear();
}
/*!
\class QRhiResourceUpdateBatch
- \internal
\inmodule QtGui
+ \since 6.6
\brief Records upload and copy type of operations.
With QRhi it is no longer possible to perform copy type of operations at
@@ -5041,6 +8878,9 @@ void QRhi::runCleanup()
To get an available, empty batch from the pool, call
QRhi::nextResourceUpdateBatch().
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
@@ -5084,29 +8924,26 @@ void QRhiResourceUpdateBatch::release()
that is then merged into another when starting to first render pass later
on:
- \badcode
- void init()
- {
- ...
- initialUpdates = rhi->nextResourceUpdateBatch();
- initialUpdates->uploadStaticBuffer(vbuf, vertexData);
- initialUpdates->uploadStaticBuffer(ibuf, indexData);
- ...
- }
+ \code
+ void init()
+ {
+ initialUpdates = rhi->nextResourceUpdateBatch();
+ initialUpdates->uploadStaticBuffer(vbuf, vertexData);
+ initialUpdates->uploadStaticBuffer(ibuf, indexData);
+ // ...
+ }
- void render()
- {
- ...
- QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
- if (initialUpdates) {
- resUpdates->merge(initialUpdates);
- initialUpdates->release();
- initialUpdates = nullptr;
+ void render()
+ {
+ QRhiResourceUpdateBatch *resUpdates = rhi->nextResourceUpdateBatch();
+ if (initialUpdates) {
+ resUpdates->merge(initialUpdates);
+ initialUpdates->release();
+ initialUpdates = nullptr;
+ }
+ // resUpdates->updateDynamicBuffer(...);
+ cb->beginPass(rt, clearCol, clearDs, resUpdates);
}
- resUpdates->updateDynamicBuffer(...);
- ...
- cb->beginPass(rt, clearCol, clearDs, resUpdates);
- }
\endcode
*/
void QRhiResourceUpdateBatch::merge(QRhiResourceUpdateBatch *other)
@@ -5148,10 +8985,10 @@ bool QRhiResourceUpdateBatch::hasOptimalCapacity() const
\note QRhi transparently manages double buffering in order to prevent
stalling the graphics pipeline. The fact that a QRhiBuffer may have
- multiple native underneath can be safely ignored when using the QRhi and
- QRhiResourceUpdateBatch.
+ multiple native buffer objects underneath can be safely ignored when using
+ the QRhi and QRhiResourceUpdateBatch.
*/
-void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, int offset, int size, const void *data)
+void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
{
if (size > 0) {
const int idx = d->activeBufferOpCount++;
@@ -5171,7 +9008,7 @@ void QRhiResourceUpdateBatch::updateDynamicBuffer(QRhiBuffer *buf, int offset, i
are specified by \a data which must have at least \a size bytes available.
\a data can safely be destroyed or changed once this function returns.
*/
-void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, int offset, int size, const void *data)
+void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
{
if (size > 0) {
const int idx = d->activeBufferOpCount++;
@@ -5183,6 +9020,8 @@ void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, int offset, in
}
/*!
+ \overload
+
Enqueues updating the entire QRhiBuffer \a buf created with the type
QRhiBuffer::Immutable or QRhiBuffer::Static.
*/
@@ -5204,7 +9043,7 @@ void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *da
A readback is asynchronous. \a result contains a callback that is invoked
when the operation has completed. The data is provided in
- QRhiBufferReadbackResult::data. Upon successful completion that QByteArray
+ QRhiReadbackResult::data. Upon successful completion that QByteArray
will have a size equal to \a size. On failure the QByteArray will be empty.
\note Reading buffers with a usage different than QRhiBuffer::UniformBuffer
@@ -5221,7 +9060,7 @@ void QRhiResourceUpdateBatch::uploadStaticBuffer(QRhiBuffer *buf, const void *da
\sa readBackTexture(), QRhi::isFeatureSupported(), QRhi::resourceLimit()
*/
-void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result)
+void QRhiResourceUpdateBatch::readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
{
const int idx = d->activeBufferOpCount++;
if (idx < d->bufferOps.size())
@@ -5268,6 +9107,11 @@ void QRhiResourceUpdateBatch::uploadTexture(QRhiTexture *tex, const QImage &imag
\note The source texture \a src must be created with
QRhiTexture::UsedAsTransferSource.
+
+ \note The format of the textures must match. With most graphics
+ APIs the data is copied as-is without any format conversions. If
+ \a dst and \a src are created with different formats, unspecified
+ issues may arise.
*/
void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
{
@@ -5290,10 +9134,10 @@ void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, co
application. Therefore, \a result provides not just the data but also a
callback as operations on the batch are asynchronous by nature:
- \badcode
- beginFrame(sc);
- beginPass
- ...
+ \code
+ rhi->beginFrame(swapchain);
+ cb->beginPass(swapchain->currentFrameRenderTarget(), colorClear, dsClear);
+ // ...
QRhiReadbackResult *rbResult = new QRhiReadbackResult;
rbResult->completed = [rbResult] {
{
@@ -5304,11 +9148,11 @@ void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, co
}
delete rbResult;
};
- u = nextResourceUpdateBatch();
+ QRhiResourceUpdateBatch *u = nextResourceUpdateBatch();
QRhiReadbackDescription rb; // no texture -> uses the current backbuffer of sc
u->readBackTexture(rb, rbResult);
- endPass(u);
- endFrame(sc);
+ cb->endPass(u);
+ rhi->endFrame(swapchain);
\endcode
\note The texture must be created with QRhiTexture::UsedAsTransferSource.
@@ -5334,8 +9178,8 @@ void QRhiResourceUpdateBatch::copyTexture(QRhiTexture *dst, QRhiTexture *src, co
QRhi::MaxAsyncReadbackFrames.
A single readback operation copies one mip level of one layer (cubemap face
- or 3D slice) at a time. The level and layer are specified by the respective
- fields in \a rb.
+ or 3D slice or texture array element) at a time. The level and layer are
+ specified by the respective fields in \a rb.
\sa readBackBuffer(), QRhi::resourceLimit()
*/
@@ -5385,11 +9229,43 @@ void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex)
\note Can be called outside beginFrame() - endFrame() as well since a batch
instance just collects data on its own, it does not perform any operations.
- \warning The maximum number of batches is 64. When this limit is reached,
- the function will return null until a batch is returned to the pool.
+ Due to not being tied to a frame being recorded, the following sequence is
+ valid for example:
+
+ \code
+ rhi->beginFrame(swapchain);
+ QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
+ u->uploadStaticBuffer(buf, data);
+ // ... do not commit the batch
+ rhi->endFrame();
+ // u stays valid (assuming buf stays valid as well)
+ rhi->beginFrame(swapchain);
+ swapchain->currentFrameCommandBuffer()->resourceUpdate(u);
+ // ... draw with buf
+ rhi->endFrame();
+ \endcode
+
+ \warning The maximum number of batches per QRhi is 64. When this limit is
+ reached, the function will return null until a batch is returned to the
+ pool.
*/
QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
{
+ // By default we prefer spreading out the utilization of the 64 batches as
+ // much as possible, meaning we won't pick the first one even if it's free,
+ // but prefer picking one after the last picked one. Relevant due to how
+ // QVLA and QRhiBufferData allocations behind the bufferOps are reused; in
+ // typical Qt Quick scenes this leads to a form of (eventually) seeding all
+ // the 64 resource batches with buffer operation data allocations which are
+ // then reused in subsequent frames. This comes at the expense of using
+ // more memory, but has proven good results when (CPU) profiling typical
+ // Quick/Quick3D apps.
+ //
+ // Prefering memory over performance means that we always pick the first
+ // free batch, and triggering the aggressive deallocating of all backing
+ // memory (see trimOpLists) before returning it.
+ static const bool preferMemoryOverPerformance = qEnvironmentVariableIntValue("QT_RHI_MINIMIZE_POOLS");
+
auto nextFreeBatch = [this]() -> QRhiResourceUpdateBatch * {
auto isFree = [this](int i) -> QRhiResourceUpdateBatch * {
const quint64 mask = 1ULL << quint64(i);
@@ -5397,7 +9273,8 @@ QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
d->resUpdPoolMap |= mask;
QRhiResourceUpdateBatch *u = d->resUpdPool[i];
QRhiResourceUpdateBatchPrivate::get(u)->poolIndex = i;
- d->lastResUpdIdx = i;
+ if (!preferMemoryOverPerformance)
+ d->lastResUpdIdx = i;
return u;
}
return nullptr;
@@ -5416,7 +9293,7 @@ QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
QRhiResourceUpdateBatch *u = nextFreeBatch();
if (!u) {
- const int oldSize = d->resUpdPool.count();
+ const int oldSize = d->resUpdPool.size();
const int newSize = oldSize + qMin(4, qMax(0, 64 - oldSize));
d->resUpdPool.resize(newSize);
for (int i = oldSize; i < newSize; ++i)
@@ -5426,6 +9303,9 @@ QRhiResourceUpdateBatch *QRhi::nextResourceUpdateBatch()
qWarning("Resource update batch pool exhausted (max is 64)");
}
+ if (preferMemoryOverPerformance && u)
+ u->d->trimOpLists();
+
return u;
}
@@ -5439,6 +9319,16 @@ void QRhiResourceUpdateBatchPrivate::free()
const quint64 mask = 1ULL << quint64(poolIndex);
rhi->resUpdPoolMap &= ~mask;
poolIndex = -1;
+
+ // textureOps is cleared, to not keep the potentially large image pixel
+ // data alive, but it is expected that the container keeps the list alloc
+ // at least. Only trimOpList() goes for the more aggressive route with squeeze.
+ textureOps.clear();
+
+ // bufferOps is not touched, to allow reusing allocations (incl. in the
+ // elements' QRhiBufferData) as much as possible when this batch is used
+ // again in the future, which is important for performance, in particular
+ // with Qt Quick.
}
void QRhiResourceUpdateBatchPrivate::merge(QRhiResourceUpdateBatchPrivate *other)
@@ -5466,19 +9356,28 @@ bool QRhiResourceUpdateBatchPrivate::hasOptimalCapacity() const
void QRhiResourceUpdateBatchPrivate::trimOpLists()
{
- Q_ASSERT(poolIndex == -1); // must not be in use
+ // Unlike free(), this is expected to aggressively deallocate all memory
+ // used by both the buffer and texture operation lists. (i.e. using
+ // squeeze() to only keep the stack prealloc of the QVLAs)
+ //
+ // This (e.g. just the destruction of bufferOps elements) may have a
+ // non-negligible performance impact e.g. with Qt Quick with scenes where
+ // there are lots of buffer operations per frame.
activeBufferOpCount = 0;
bufferOps.clear();
+ bufferOps.squeeze();
activeTextureOpCount = 0;
textureOps.clear();
+ textureOps.squeeze();
}
/*!
- Sometimes committing resource updates is necessary without starting a
- render pass. Not often needed, updates should typically be passed to
- beginPass (or endPass, in case of readbacks) instead.
+ Sometimes committing resource updates is necessary or just more convenient
+ without starting a render pass. Calling this function with \a
+ resourceUpdates is an alternative to passing \a resourceUpdates to a
+ beginPass() call (or endPass(), which would be typical in case of readbacks).
\note Cannot be called inside a pass.
*/
@@ -5517,6 +9416,29 @@ void QRhiCommandBuffer::resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates)
called inside a pass. Also, with the exception of setGraphicsPipeline(),
they expect to have a pipeline set already on the command buffer.
Unspecified issues may arise otherwise, depending on the backend.
+
+ If \a rt is a QRhiTextureRenderTarget, beginPass() performs a check to see
+ if the texture and renderbuffer objects referenced from the render target
+ are up-to-date. This is similar to what setShaderResources() does for
+ QRhiShaderResourceBindings. If any of the attachments had been rebuilt
+ since QRhiTextureRenderTarget::create(), an implicit call to create() is
+ made on \a rt. Therefore, if \a rt has a QRhiTexture color attachment \c
+ texture, and one needs to make the texture a different size, the following
+ is then valid:
+ \code
+ QRhiTextureRenderTarget *rt = rhi->newTextureRenderTarget({ { texture } });
+ rt->create();
+ // ...
+ texture->setPixelSize(new_size);
+ texture->create();
+ cb->beginPass(rt, colorClear, dsClear); // this is ok, no explicit rt->create() is required before
+ \endcode
+
+ \a flags allow controlling certain advanced functionality. One commonly used
+ flag is \c ExternalContents. This should be specified whenever
+ beginExternal() will be called within the pass started by this function.
+
+ \sa endPass(), BeginPassFlags
*/
void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
const QColor &colorClearValue,
@@ -5532,6 +9454,8 @@ void QRhiCommandBuffer::beginPass(QRhiRenderTarget *rt,
\a resourceUpdates, when not null, specifies a resource update batch that
is to be committed and then released.
+
+ \sa beginPass()
*/
void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
{
@@ -5550,9 +9474,12 @@ void QRhiCommandBuffer::endPass(QRhiResourceUpdateBatch *resourceUpdates)
\note This function can only be called inside a render pass, meaning
between a beginPass() and endPass() call.
+
+ \note The new graphics pipeline \a ps must be a valid pointer.
*/
void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
{
+ Q_ASSERT(ps != nullptr);
m_rhi->setGraphicsPipeline(this, ps);
}
@@ -5577,6 +9504,13 @@ void QRhiCommandBuffer::setGraphicsPipeline(QRhiGraphicsPipeline *ps)
srb. In this case setShaderResources() must be called even if \a srb is
the same as in the last call.
+ When \a srb is not null, the QRhiShaderResourceBindings object the pipeline
+ was built with in create() is guaranteed to be not accessed in any form. In
+ fact, it does not need to be valid even at this point: destroying the
+ pipeline's associated srb after create() and instead explicitly specifying
+ another, \l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout
+ compatible} one in every setShaderResources() call is valid.
+
\a dynamicOffsets allows specifying buffer offsets for uniform buffers that
were associated with \a srb via
QRhiShaderResourceBinding::uniformBufferWithDynamicOffset(). This is
@@ -5642,7 +9576,7 @@ void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
floats for position (so 5 floats per vertex: x, y, r, g, b). A QRhiGraphicsPipeline for
this shader can then be created using the input layout:
- \badcode
+ \code
QRhiVertexInputLayout inputLayout;
inputLayout.setBindings({
{ 5 * sizeof(float) }
@@ -5655,11 +9589,10 @@ void QRhiCommandBuffer::setShaderResources(QRhiShaderResourceBindings *srb,
Here there is one buffer binding (binding number 0), with two inputs
referencing it. When recording the pass, once the pipeline is set, the
- vertex bindings can be specified simply like the following (using C++11
- initializer syntax), assuming vbuf is the QRhiBuffer with all the
- interleaved position+color data:
+ vertex bindings can be specified simply like the following, assuming vbuf
+ is the QRhiBuffer with all the interleaved position+color data:
- \badcode
+ \code
const QRhiCommandBuffer::VertexInput vbufBinding(vbuf, 0);
cb->setVertexInput(0, 1, &vbufBinding);
\endcode
@@ -5799,8 +9732,9 @@ void QRhiCommandBuffer::drawIndexed(quint32 indexCount,
}
/*!
- Records a named debug group on the command buffer. This is shown in
- graphics debugging tools such as \l{https://renderdoc.org/}{RenderDoc} and
+ Records a named debug group on the command buffer with the specified \a
+ name. This is shown in graphics debugging tools such as
+ \l{https://renderdoc.org/}{RenderDoc} and
\l{https://developer.apple.com/xcode/}{XCode}. The end of the grouping is
indicated by debugMarkEnd().
@@ -5858,6 +9792,8 @@ void QRhiCommandBuffer::debugMarkMsg(const QByteArray &msg)
\note Compute is only available when the \l{QRhi::Compute}{Compute} feature
is reported as supported.
+
+ \a flags is not currently used.
*/
void QRhiCommandBuffer::beginComputePass(QRhiResourceUpdateBatch *resourceUpdates, BeginPassFlags flags)
{
@@ -5941,9 +9877,9 @@ const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
called when the pass recording was started with specifying
QRhiCommandBuffer::ExternalContent.
- With Vulkan or Metal one can query the native command buffer or encoder
- objects via nativeHandles() and enqueue commands to them. With OpenGL or
- Direct3D 11 the (device) context can be retrieved from
+ With Vulkan, Metal, or Direct3D 12 one can query the native command buffer
+ or encoder objects via nativeHandles() and enqueue commands to them. With
+ OpenGL or Direct3D 11 the (device) context can be retrieved from
QRhi::nativeHandles(). However, this must never be done without ensuring
the QRhiCommandBuffer's state stays up-to-date. Hence the requirement for
wrapping any externally added command recording between beginExternal() and
@@ -5991,6 +9927,72 @@ void QRhiCommandBuffer::endExternal()
}
/*!
+ \return the last available timestamp, in seconds, when
+ \l QRhi::EnableTimestamps was enabled when creating the QRhi. The value
+ indicates the elapsed time on the GPU during the last completed frame.
+
+ \note Do not expect results other than 0 when the QRhi::Timestamps feature
+ is not reported as supported, or when QRhi::EnableTimestamps was not passed
+ to QRhi::create(). There are exceptions to this, because with some graphics
+ APIs (Metal) timings are available without having to perform extra
+ operations (timestamp queries), but portable applications should always
+ consciously opt-in to timestamp collection when they know it is needed, and
+ call this function accordingly.
+
+ Care must be exercised with the interpretation of the value, as its
+ precision and granularity is often not controlled by Qt, and depends on the
+ underlying graphics API and its implementation. In particular, comparing
+ the values between different graphics APIs and hardware is discouraged and
+ may be meaningless.
+
+ When the frame was recorded with \l{QRhi::beginFrame()}{beginFrame()} and
+ \l{QRhi::endFrame()}{endFrame()}, i.e., with a swapchain, the timing values
+ will likely become available asynchronously. The returned value may
+ therefore be 0 (e.g., for the first 1-2 frames) or the last known value
+ referring to some previous frame. The value my also
+ become 0 again under certain conditions, such as when resizing the window.
+ It can be expected that the most up-to-date available value is retrieved in
+ beginFrame() and becomes queriable via this function once beginFrame()
+ returns.
+
+ \note Do not assume that the value refers to the previous
+ (\c{currently_recorded - 1}) frame. It may refer to \c{currently_recorded -
+ 2} or \c{currently_recorded - 3} as well. The exact behavior may depend on
+ the graphics API and its implementation.
+
+ On the other hand, with offscreen frames the returned value is up-to-date
+ once \l{QRhi::endOffscreenFrame()}{endOffscreenFrame()} returns, because
+ offscreen frames reduce GPU pipelining and wait the the commands to be
+ complete.
+
+ \note This means that, unlike with swapchain frames, with offscreen frames
+ the returned value is guaranteed to refer to the frame that has just been
+ submitted and completed. (assuming this function is called after
+ endOffscreenFrame() but before the next beginOffscreenFrame())
+
+ Watch out for the consequences of GPU frequency scaling and GPU clock
+ changes, depending on the platform. For example, on Windows the returned
+ timing may vary in a quite wide range between frames with modern graphics
+ cards, even when submitting frames with a similar, or the same workload.
+ This is out of scope for Qt to control and solve, generally speaking.
+ However, the D3D12 backend automatically calls
+ \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate}{ID3D12Device::SetStablePowerState()}
+ whenever the environment variable \c QT_D3D_STABLE_POWER_STATE is set to a
+ non-zero value. This can greatly stabilize the result. It can also have a
+ non-insignificant effect on the CPU-side timings measured via QElapsedTimer
+ for example, especially when offscreen frames are involved.
+
+ \note Do not and never ship applications to production with
+ \c QT_D3D_STABLE_POWER_STATE set. See the Windows API documentation for details.
+
+ \sa QRhi::Timestamps, QRhi::EnableTimestamps
+ */
+double QRhiCommandBuffer::lastCompletedGpuTime()
+{
+ return m_rhi->lastCompletedGpuTime(this);
+}
+
+/*!
\return the value (typically an offset) \a v aligned to the uniform buffer
alignment given by by ubufAlignment().
*/
@@ -6003,7 +10005,7 @@ int QRhi::ubufAligned(int v) const
/*!
\return the number of mip levels for a given \a size.
*/
-int QRhi::mipLevelsForSize(const QSize &size) const
+int QRhi::mipLevelsForSize(const QSize &size)
{
return qFloor(std::log2(qMax(size.width(), size.height()))) + 1;
}
@@ -6012,7 +10014,7 @@ int QRhi::mipLevelsForSize(const QSize &size) const
\return the texture image size for a given \a mipLevel, calculated based on
the level 0 size given in \a baseLevelSize.
*/
-QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize) const
+QSize QRhi::sizeForMipLevel(int mipLevel, const QSize &baseLevelSize)
{
const int w = qMax(1, baseLevelSize.width() >> mipLevel);
const int h = qMax(1, baseLevelSize.height() >> mipLevel);
@@ -6126,7 +10128,8 @@ int QRhi::resourceLimit(ResourceLimit limit) const
for the device, context, and similar concepts used by the backend.
Cast to QRhiVulkanNativeHandles, QRhiD3D11NativeHandles,
- QRhiGles2NativeHandles, QRhiMetalNativeHandles as appropriate.
+ QRhiD3D12NativeHandles, QRhiGles2NativeHandles, or QRhiMetalNativeHandles
+ as appropriate.
\note No ownership is transferred, neither for the returned pointer nor for
any native objects.
@@ -6158,18 +10161,6 @@ bool QRhi::makeThreadLocalNativeContextCurrent()
}
/*!
- \return the associated QRhiProfiler instance.
-
- An instance is always available for each QRhi, but it is not very useful
- without EnableProfiling because no data is collected without setting the
- flag upon creation.
- */
-QRhiProfiler *QRhi::profiler()
-{
- return &d->profiler;
-}
-
-/*!
Attempts to release resources in the backend's caches. This can include both
CPU and GPU resources. Only memory and resources that can be recreated
automatically are in scope. As an example, if the backend's
@@ -6239,13 +10230,15 @@ bool QRhi::isDeviceLost() const
}
/*!
- \return a binary \a data blob with data collected from the
+ \return a binary data blob with data collected from the
QRhiGraphicsPipeline and QRhiComputePipeline successfully created during
the lifetime of this QRhi.
By saving and then, in subsequent runs of the same application, reloading
the cache data, pipeline and shader creation times can potentially be
- accelerated.
+ reduced. What exactly the cache and its serialized version includes is not
+ specified, is always specific to the backend used, and in some cases also
+ dependent on the particular implementation of the graphics API.
When the PipelineCacheDataLoadSave is reported as unsupported, the returned
QByteArray is empty.
@@ -6254,15 +10247,25 @@ bool QRhi::isDeviceLost() const
create(), the returned QByteArray may be empty, even when the
PipelineCacheDataLoadSave feature is supported.
- When the returned data is non-empty, it is always specific to the QRhi
- backend, the graphics device, and the driver implementation in use. QRhi
+ When the returned data is non-empty, it is always specific to the Qt
+ version and QRhi backend. In addition, in some cases there is a strong
+ dependency to the graphics device and the exact driver version used. QRhi
takes care of adding the appropriate header and safeguards that ensure that
- the data can always be passed safely to setPipelineCacheData().
+ the data can always be passed safely to setPipelineCacheData(), therefore
+ attempting to load data from a run on another version of a driver will be
+ handled safely and gracefully.
\note Calling releaseCachedResources() may, depending on the backend, clear
the pipeline data collected. A subsequent call to this function may then
not return any data.
+ See EnablePipelineCacheDataSave for further details about this feature.
+
+ \note Minimize the number of calls to this function. Retrieving the blob is
+ not always a cheap operation, and therefore this function should only be
+ called at a low frequency, ideally only once e.g. when closing the
+ application.
+
\sa setPipelineCacheData(), create(), isFeatureSupported()
*/
QByteArray QRhi::pipelineCacheData()
@@ -6276,13 +10279,14 @@ QByteArray QRhi::pipelineCacheData()
When the PipelineCacheDataLoadSave is reported as unsupported, the function
is safe to call, but has no effect.
- The blob returned by pipelineCacheData() is always specific to a QRhi
- backend, a graphics device, and a given version of the graphics driver.
- QRhi takes care of adding the appropriate header and safeguards that ensure
- that the data can always be passed safely to this function. If there is a
- mismatch, e.g. because the driver has been upgraded to a newer version, or
- because the data was generated from a different QRhi backend, a warning is
- printed and \a data is safely ignored.
+ The blob returned by pipelineCacheData() is always specific to the Qt
+ version, the QRhi backend, and, in some cases, also to the graphics device,
+ and a given version of the graphics driver. QRhi takes care of adding the
+ appropriate header and safeguards that ensure that the data can always be
+ passed safely to this function. If there is a mismatch, e.g. because the
+ driver has been upgraded to a newer version, or because the data was
+ generated from a different QRhi backend, a warning is printed and \a data
+ is safely ignored.
With Vulkan, this maps directly to VkPipelineCache. Calling this function
creates a new Vulkan pipeline cache object, with its initial data sourced
@@ -6290,11 +10294,32 @@ QByteArray QRhi::pipelineCacheData()
created QRhiGraphicsPipeline and QRhiComputePipeline objects, thus
accelerating, potentially, the pipeline creation.
+ With other APIs there is no real pipeline cache, but they may provide a
+ cache with bytecode from shader compilations (D3D) or program binaries
+ (OpenGL). In applications that perform a lot of shader compilation from
+ source at run time this can provide a significant boost in subsequent runs
+ if the "pipeline cache" is pre-seeded from an earlier run using this
+ function.
+
\note QRhi cannot give any guarantees that \a data has an effect on the
pipeline and shader creation performance. With APIs like Vulkan, it is up
to the driver to decide if \a data is used for some purpose, or if it is
ignored.
+ See EnablePipelineCacheDataSave for further details about this feature.
+
+ \note This mechanism offered by QRhi is independent of the drivers' own
+ internal caching mechanism, if any. This means that, depending on the
+ graphics API and its implementation, the exact effects of retrieving and
+ then reloading \a data are not predictable. Improved performance may not be
+ visible at all in case other caching mechanisms outside of Qt's control are
+ already active.
+
+ \note Minimize the number of calls to this function. Loading the blob is
+ not always a cheap operation, and therefore this function should only be
+ called at a low frequency, ideally only once e.g. when starting the
+ application.
+
\sa pipelineCacheData(), isFeatureSupported()
*/
void QRhi::setPipelineCacheData(const QByteArray &data)
@@ -6303,6 +10328,137 @@ void QRhi::setPipelineCacheData(const QByteArray &data)
}
/*!
+ \struct QRhiStats
+ \inmodule QtGui
+ \since 6.6
+
+ \brief Statistics provided from the underlying memory allocator.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+ */
+
+/*!
+ \variable QRhiStats::totalPipelineCreationTime
+
+ The total time in milliseconds spent in graphics and compute pipeline
+ creation, which usually involves shader compilation or cache lookups, and
+ potentially expensive processing.
+
+ \note The value should not be compared between different backends since the
+ concept of "pipelines" and what exactly happens under the hood during, for
+ instance, a call to QRhiGraphicsPipeline::create(), differ greatly between
+ graphics APIs and their implementations.
+
+ \sa QRhi::statistics()
+*/
+
+/*!
+ \variable QRhiStats::blockCount
+
+ Statistic reported from the Vulkan or D3D12 memory allocator.
+
+ \sa QRhi::statistics()
+*/
+
+/*!
+ \variable QRhiStats::allocCount
+
+ Statistic reported from the Vulkan or D3D12 memory allocator.
+
+ \sa QRhi::statistics()
+*/
+
+/*!
+ \variable QRhiStats::usedBytes
+
+ Statistic reported from the Vulkan or D3D12 memory allocator.
+
+ \sa QRhi::statistics()
+*/
+
+/*!
+ \variable QRhiStats::unusedBytes
+
+ Statistic reported from the Vulkan or D3D12 memory allocator.
+
+ \sa QRhi::statistics()
+*/
+
+/*!
+ \variable QRhiStats::totalUsageBytes
+
+ Valid only with D3D12 currently. Matches IDXGIAdapter3::QueryVideoMemoryInfo().
+
+ \sa QRhi::statistics()
+*/
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QRhiStats &info)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QRhiStats("
+ << "totalPipelineCreationTime=" << info.totalPipelineCreationTime
+ << " blockCount=" << info.blockCount
+ << " allocCount=" << info.allocCount
+ << " usedBytes=" << info.usedBytes
+ << " unusedBytes=" << info.unusedBytes
+ << " totalUsageBytes=" << info.totalUsageBytes
+ << ')';
+ return dbg;
+}
+#endif
+
+/*!
+ Gathers and returns statistics about the timings and allocations of
+ graphics resources.
+
+ Data about memory allocations is only available with some backends, where
+ such operations are under Qt's control. With graphics APIs where there is
+ no lower level control over resource memory allocations, this will never be
+ supported and all relevant fields in the results are 0.
+
+ With Vulkan in particular, the values are valid always, and are queried
+ from the underlying memory allocator library. This gives an insight into
+ the memory requirements of the active buffers and textures.
+
+ The same is true for Direct 3D 12. In addition to the memory allocator
+ library's statistics, here the result also includes a \c totalUsageBytes
+ field which reports the total size including additional resources that are
+ not under the memory allocator library's control (swapchain buffers,
+ descriptor heaps, etc.), as reported by DXGI.
+
+ The values correspond to all types of memory used, combined. (i.e. video +
+ system in case of a discreet GPU)
+
+ Additional data, such as the total time in milliseconds spent in graphics
+ and compute pipeline creation (which usually involves shader compilation or
+ cache lookups, and potentially expensive processing) is available with most
+ backends.
+
+ \note The elapsed times for operations such as pipeline creation may be
+ affected by various factors. The results should not be compared between
+ different backends since the concept of "pipelines" and what exactly
+ happens under the hood during, for instance, a call to
+ QRhiGraphicsPipeline::create(), differ greatly between graphics APIs and
+ their implementations.
+
+ \note Additionally, many drivers will likely employ various caching
+ strategies for shaders, programs, pipelines. (independently of Qt's own
+ similar facilities, such as setPipelineCacheData() or the OpenGL-specific
+ program binary disk cache). Because such internal behavior is transparent
+ to the API client, Qt and QRhi have no knowledge or control over the exact
+ caching strategy, persistency, invalidation of the cached data, etc. When
+ reading timings, such as the time spent on pipeline creation, the potential
+ presence and unspecified behavior of driver-level caching mechanisms should
+ be kept in mind.
+ */
+QRhiStats QRhi::statistics() const
+{
+ return d->statistics();
+}
+
+/*!
\return a new graphics pipeline resource.
\sa QRhiResource::destroy()
@@ -6351,7 +10507,7 @@ QRhiShaderResourceBindings *QRhi::newShaderResourceBindings()
*/
QRhiBuffer *QRhi::newBuffer(QRhiBuffer::Type type,
QRhiBuffer::UsageFlags usage,
- int size)
+ quint32 size)
{
return d->createBuffer(type, usage, size);
}
@@ -6386,14 +10542,21 @@ QRhiRenderBuffer *QRhi::newRenderBuffer(QRhiRenderBuffer::Type type,
}
/*!
- \return a new texture with the specified \a format, \a pixelSize, \a
+ \return a new 1D or 2D texture with the specified \a format, \a pixelSize, \a
sampleCount, and \a flags.
+ A 1D texture array must have QRhiTexture::OneDimensional set in \a flags. This
+ function will implicitly set this flag if the \a pixelSize height is 0.
+
\note \a format specifies the requested internal and external format,
meaning the data to be uploaded to the texture will need to be in a
compatible format, while the native texture may (but is not guaranteed to,
in case of OpenGL at least) use this format internally.
+ \note 1D textures are only functional when the OneDimensionalTextures feature is
+ reported as supported at run time. Further, mipmaps on 1D textures are only
+ functional when the OneDimensionalTextureMipmaps feature is reported at run time.
+
\sa QRhiResource::destroy()
*/
QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
@@ -6401,19 +10564,32 @@ QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
int sampleCount,
QRhiTexture::Flags flags)
{
- return d->createTexture(format, pixelSize, 1, sampleCount, flags);
+ if (pixelSize.height() == 0)
+ flags |= QRhiTexture::OneDimensional;
+
+ return d->createTexture(format, pixelSize, 1, 0, sampleCount, flags);
}
/*!
- \return a new texture with the specified \a format, \a width, \a height, \a
- depth, \a sampleCount, and \a flags.
+ \return a new 1D, 2D or 3D texture with the specified \a format, \a width, \a
+ height, \a depth, \a sampleCount, and \a flags.
This overload is suitable for 3D textures because it allows specifying \a
depth. A 3D texture must have QRhiTexture::ThreeDimensional set in \a
flags, but using this overload that can be omitted because the flag is set
- implicitly whenever \a depth is greater than 0. For 2D and cube textures \a
+ implicitly whenever \a depth is greater than 0. For 1D, 2D and cube textures \a
depth should be set to 0.
+ A 1D texture must have QRhiTexture::OneDimensional set in \a flags. This overload
+ will implicitly set this flag if both \a height and \a depth are 0.
+
+ \note 3D textures are only functional when the ThreeDimensionalTextures
+ feature is reported as supported at run time.
+
+ \note 1D textures are only functional when the OneDimensionalTextures feature is
+ reported as supported at run time. Further, mipmaps on 1D textures are only
+ functional when the OneDimensionalTextureMipmaps feature is reported at run time.
+
\overload
*/
QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
@@ -6424,7 +10600,51 @@ QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
if (depth > 0)
flags |= QRhiTexture::ThreeDimensional;
- return d->createTexture(format, QSize(width, height), depth, sampleCount, flags);
+ if (height == 0 && depth == 0)
+ flags |= QRhiTexture::OneDimensional;
+
+ return d->createTexture(format, QSize(width, height), depth, 0, sampleCount, flags);
+}
+
+/*!
+ \return a new 1D or 2D texture array with the specified \a format, \a arraySize,
+ \a pixelSize, \a sampleCount, and \a flags.
+
+ This function implicitly sets QRhiTexture::TextureArray in \a flags.
+
+ A 1D texture array must have QRhiTexture::OneDimensional set in \a flags. This
+ function will implicitly set this flag if the \a pixelSize height is 0.
+
+ \note Do not confuse texture arrays with arrays of textures. A QRhiTexture
+ created by this function is usable with 1D or 2D array samplers in the shader, for
+ example: \c{layout(binding = 1) uniform sampler2DArray texArr;}. Arrays of
+ textures refers to a list of textures that are exposed to the shader via
+ QRhiShaderResourceBinding::sampledTextures() and a count > 1, and declared
+ in the shader for example like this: \c{layout(binding = 1) uniform
+ sampler2D textures[4];}
+
+ \note This is only functional when the TextureArrays feature is reported as
+ supported at run time.
+
+ \note 1D textures are only functional when the OneDimensionalTextures feature is
+ reported as supported at run time. Further, mipmaps on 1D textures are only
+ functional when the OneDimensionalTextureMipmaps feature is reported at run time.
+
+
+ \sa newTexture()
+ */
+QRhiTexture *QRhi::newTextureArray(QRhiTexture::Format format,
+ int arraySize,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiTexture::Flags flags)
+{
+ flags |= QRhiTexture::TextureArray;
+
+ if (pixelSize.height() == 0)
+ flags |= QRhiTexture::OneDimensional;
+
+ return d->createTexture(format, pixelSize, 1, arraySize, sampleCount, flags);
}
/*!
@@ -6432,6 +10652,14 @@ QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
+ \note Setting \a mipmapMode to a value other than \c None implies that
+ images for all relevant mip levels will be provided either via
+ \l{QRhiResourceUpdateBatch::uploadTexture()}{texture uploads} or by calling
+ \l{QRhiResourceUpdateBatch::generateMips()}{generateMips()} on the texture
+ that is used with this sampler. Attempting to use the sampler with a
+ texture that has no data for all relevant mip levels will lead to rendering
+ errors, with the exact behavior dependent on the underlying graphics API.
+
\sa QRhiResource::destroy()
*/
QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
@@ -6600,7 +10828,7 @@ bool QRhi::isRecordingFrame() const
C++ containers and other types. It may also be similar to what an OpenGL or
Direct 3D 11 implementation performs internally for certain type of objects.
- In practice, such double (or tripple) buffering resources is realized in
+ In practice, such double (or triple) buffering resources is realized in
the Vulkan, Metal, and similar QRhi backends by having a fixed number of
native resource (such as, VkBuffer) \c slots behind a QRhiResource. That
can then be indexed by a frame slot index running 0, 1, ..,
@@ -6608,7 +10836,7 @@ bool QRhi::isRecordingFrame() const
All this is managed transparently to the users of QRhi. However,
applications that integrate rendering done directly with the graphics API
- may want to perform a similar double or tripple buffering of their own
+ may want to perform a similar double or triple buffering of their own
graphics resources. That is then most easily achieved by knowing the values
of the maximum number of in-flight frames (retrievable via resourceLimit())
and the current frame (slot) index (returned by this function).
@@ -6635,26 +10863,29 @@ int QRhi::currentFrameSlot() const
beginOffscreenFrame, endOffscreenFrame, beginFrame, ...) is possible too
but it does reduce parallelism so it should be done only infrequently.
- Offscreen frames do not let the CPU - potentially - generate another frame
+ Offscreen frames do not let the CPU potentially generate another frame
while the GPU is still processing the previous one. This has the side
effect that if readbacks are scheduled, the results are guaranteed to be
available once endOffscreenFrame() returns. That is not the case with
- frames targeting a swapchain.
+ frames targeting a swapchain: there the GPU is potentially better utilized,
+ but working with readback operations needs more care from the application
+ because endFrame(), unlike endOffscreenFrame(), does not guarantee that the
+ results from the readback are available at that point.
The skeleton of rendering a frame without a swapchain and then reading the
frame contents back could look like the following:
- \badcode
- QRhiReadbackResult rbResult;
- QRhiCommandBuffer *cb;
- beginOffscreenFrame(&cb);
- beginPass
- ...
- u = nextResourceUpdateBatch();
- u->readBackTexture(rb, &rbResult);
- endPass(u);
- endOffscreenFrame();
- // image data available in rbResult
+ \code
+ QRhiReadbackResult rbResult;
+ QRhiCommandBuffer *cb;
+ rhi->beginOffscreenFrame(&cb);
+ cb->beginPass(rt, colorClear, dsClear);
+ // ...
+ u = nextResourceUpdateBatch();
+ u->readBackTexture(rb, &rbResult);
+ cb->endPass(u);
+ rhi->endOffscreenFrame();
+ // image data available in rbResult
\endcode
\sa endOffscreenFrame(), beginFrame()
@@ -6672,7 +10903,9 @@ QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrame
}
/*!
- Ends and waits for the offscreen frame.
+ Ends, submits, and waits for the offscreen frame.
+
+ \a flags is not currently used.
\sa beginOffscreenFrame()
*/
@@ -6713,6 +10946,9 @@ QRhi::FrameOpResult QRhi::finish()
With some backend this list of supported values is fixed in advance, while
with some others the (physical) device properties indicate what is
supported at run time.
+
+ \sa QRhiRenderBuffer::setSampleCount(), QRhiTexture::setSampleCount(),
+ QRhiGraphicsPipeline::setSampleCount(), QRhiSwapChain::setSampleCount()
*/
QList<int> QRhi::supportedSampleCounts() const
{
@@ -6734,7 +10970,7 @@ int QRhi::ubufAlignment() const
return d->ubufAlignment();
}
-static QBasicAtomicInteger<QRhiGlobalObjectIdGenerator::Type> counter = Q_BASIC_ATOMIC_INITIALIZER(0);
+Q_CONSTINIT static QBasicAtomicInteger<QRhiGlobalObjectIdGenerator::Type> counter = Q_BASIC_ATOMIC_INITIALIZER(0);
QRhiGlobalObjectIdGenerator::Type QRhiGlobalObjectIdGenerator::newId()
{
@@ -6835,13 +11071,18 @@ QRhiPassResourceTracker::BufferStage QRhiPassResourceTracker::toPassTrackerBuffe
// pick the earlier stage (as this is going to be dstAccessMask)
if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
return QRhiPassResourceTracker::BufVertexStage;
+ if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
+ return QRhiPassResourceTracker::BufTCStage;
+ if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
+ return QRhiPassResourceTracker::BufTEStage;
if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
return QRhiPassResourceTracker::BufFragmentStage;
if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
return QRhiPassResourceTracker::BufComputeStage;
+ if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
+ return QRhiPassResourceTracker::BufGeometryStage;
- Q_UNREACHABLE();
- return QRhiPassResourceTracker::BufVertexStage;
+ Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::BufVertexStage);
}
QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages)
@@ -6849,13 +11090,18 @@ QRhiPassResourceTracker::TextureStage QRhiPassResourceTracker::toPassTrackerText
// pick the earlier stage (as this is going to be dstAccessMask)
if (stages.testFlag(QRhiShaderResourceBinding::VertexStage))
return QRhiPassResourceTracker::TexVertexStage;
+ if (stages.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
+ return QRhiPassResourceTracker::TexTCStage;
+ if (stages.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
+ return QRhiPassResourceTracker::TexTEStage;
if (stages.testFlag(QRhiShaderResourceBinding::FragmentStage))
return QRhiPassResourceTracker::TexFragmentStage;
if (stages.testFlag(QRhiShaderResourceBinding::ComputeStage))
return QRhiPassResourceTracker::TexComputeStage;
+ if (stages.testFlag(QRhiShaderResourceBinding::GeometryStage))
+ return QRhiPassResourceTracker::TexGeometryStage;
- Q_UNREACHABLE();
- return QRhiPassResourceTracker::TexVertexStage;
+ Q_UNREACHABLE_RETURN(QRhiPassResourceTracker::TexVertexStage);
}
QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhi.h b/src/gui/rhi/qrhi.h
new file mode 100644
index 0000000000..d20b7e00d1
--- /dev/null
+++ b/src/gui/rhi/qrhi.h
@@ -0,0 +1,2026 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHI_H
+#define QRHI_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the RHI API, with limited compatibility guarantees.
+// Usage of this API may make your code source and binary incompatible with
+// future versions of Qt.
+//
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qthread.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qimage.h>
+#include <functional>
+#include <array>
+
+#include <rhi/qshader.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindow;
+class QRhi;
+class QRhiImplementation;
+class QRhiBuffer;
+class QRhiRenderBuffer;
+class QRhiTexture;
+class QRhiSampler;
+class QRhiCommandBuffer;
+class QRhiResourceUpdateBatch;
+class QRhiResourceUpdateBatchPrivate;
+class QRhiSwapChain;
+
+class Q_GUI_EXPORT QRhiDepthStencilClearValue
+{
+public:
+ QRhiDepthStencilClearValue() = default;
+ QRhiDepthStencilClearValue(float d, quint32 s);
+
+ float depthClearValue() const { return m_d; }
+ void setDepthClearValue(float d) { m_d = d; }
+
+ quint32 stencilClearValue() const { return m_s; }
+ void setStencilClearValue(quint32 s) { m_s = s; }
+
+private:
+ float m_d = 1.0f;
+ quint32 m_s = 0;
+
+ friend bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
+ {
+ return a.m_d == b.m_d && a.m_s == b.m_s;
+ }
+
+ friend bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiDepthStencilClearValue &v, size_t seed = 0) noexcept
+ {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, v.m_d);
+ seed = hash(seed, v.m_s);
+ return seed;
+ }
+};
+
+Q_DECLARE_TYPEINFO(QRhiDepthStencilClearValue, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiDepthStencilClearValue &);
+#endif
+
+class Q_GUI_EXPORT QRhiViewport
+{
+public:
+ QRhiViewport() = default;
+ QRhiViewport(float x, float y, float w, float h, float minDepth = 0.0f, float maxDepth = 1.0f);
+
+ std::array<float, 4> viewport() const { return m_rect; }
+ void setViewport(float x, float y, float w, float h) {
+ m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h;
+ }
+
+ float minDepth() const { return m_minDepth; }
+ void setMinDepth(float minDepth) { m_minDepth = minDepth; }
+
+ float maxDepth() const { return m_maxDepth; }
+ void setMaxDepth(float maxDepth) { m_maxDepth = maxDepth; }
+
+private:
+ std::array<float, 4> m_rect { { 0.0f, 0.0f, 0.0f, 0.0f } };
+ float m_minDepth = 0.0f;
+ float m_maxDepth = 1.0f;
+
+ friend bool operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept
+ {
+ return a.m_rect == b.m_rect
+ && a.m_minDepth == b.m_minDepth
+ && a.m_maxDepth == b.m_maxDepth;
+ }
+
+ friend bool operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiViewport &v, size_t seed = 0) noexcept
+ {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, v.m_rect[0]);
+ seed = hash(seed, v.m_rect[1]);
+ seed = hash(seed, v.m_rect[2]);
+ seed = hash(seed, v.m_rect[3]);
+ seed = hash(seed, v.m_minDepth);
+ seed = hash(seed, v.m_maxDepth);
+ return seed;
+ }
+};
+
+Q_DECLARE_TYPEINFO(QRhiViewport, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiViewport &);
+#endif
+
+class Q_GUI_EXPORT QRhiScissor
+{
+public:
+ QRhiScissor() = default;
+ QRhiScissor(int x, int y, int w, int h);
+
+ std::array<int, 4> scissor() const { return m_rect; }
+ void setScissor(int x, int y, int w, int h) {
+ m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h;
+ }
+
+private:
+ std::array<int, 4> m_rect { { 0, 0, 0, 0 } };
+
+ friend bool operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept
+ {
+ return a.m_rect == b.m_rect;
+ }
+
+ friend bool operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiScissor &v, size_t seed = 0) noexcept
+ {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, v.m_rect[0]);
+ seed = hash(seed, v.m_rect[1]);
+ seed = hash(seed, v.m_rect[2]);
+ seed = hash(seed, v.m_rect[3]);
+ return seed;
+ }
+};
+
+Q_DECLARE_TYPEINFO(QRhiScissor, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiScissor &);
+#endif
+
+class Q_GUI_EXPORT QRhiVertexInputBinding
+{
+public:
+ enum Classification {
+ PerVertex,
+ PerInstance
+ };
+
+ QRhiVertexInputBinding() = default;
+ QRhiVertexInputBinding(quint32 stride, Classification cls = PerVertex, quint32 stepRate = 1);
+
+ quint32 stride() const { return m_stride; }
+ void setStride(quint32 s) { m_stride = s; }
+
+ Classification classification() const { return m_classification; }
+ void setClassification(Classification c) { m_classification = c; }
+
+ quint32 instanceStepRate() const { return m_instanceStepRate; }
+ void setInstanceStepRate(quint32 rate) { m_instanceStepRate = rate; }
+
+private:
+ quint32 m_stride = 0;
+ Classification m_classification = PerVertex;
+ quint32 m_instanceStepRate = 1;
+
+ friend bool operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
+ {
+ return a.m_stride == b.m_stride
+ && a.m_classification == b.m_classification
+ && a.m_instanceStepRate == b.m_instanceStepRate;
+ }
+
+ friend bool operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiVertexInputBinding &v, size_t seed = 0) noexcept
+ {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, v.m_stride);
+ seed = hash(seed, v.m_classification);
+ seed = hash(seed, v.m_instanceStepRate);
+ return seed;
+ }
+};
+
+Q_DECLARE_TYPEINFO(QRhiVertexInputBinding, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputBinding &);
+#endif
+
+class Q_GUI_EXPORT QRhiVertexInputAttribute
+{
+public:
+ enum Format {
+ Float4,
+ Float3,
+ Float2,
+ Float,
+ UNormByte4,
+ UNormByte2,
+ UNormByte,
+ UInt4,
+ UInt3,
+ UInt2,
+ UInt,
+ SInt4,
+ SInt3,
+ SInt2,
+ SInt,
+ Half4,
+ Half3,
+ Half2,
+ Half,
+ UShort4,
+ UShort3,
+ UShort2,
+ UShort,
+ SShort4,
+ SShort3,
+ SShort2,
+ SShort,
+ };
+
+ QRhiVertexInputAttribute() = default;
+ QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice = -1);
+
+ int binding() const { return m_binding; }
+ void setBinding(int b) { m_binding = b; }
+
+ int location() const { return m_location; }
+ void setLocation(int loc) { m_location = loc; }
+
+ Format format() const { return m_format; }
+ void setFormat(Format f) { m_format = f; }
+
+ quint32 offset() const { return m_offset; }
+ void setOffset(quint32 ofs) { m_offset = ofs; }
+
+ int matrixSlice() const { return m_matrixSlice; }
+ void setMatrixSlice(int slice) { m_matrixSlice = slice; }
+
+private:
+ int m_binding = 0;
+ int m_location = 0;
+ Format m_format = Float4;
+ quint32 m_offset = 0;
+ int m_matrixSlice = -1;
+
+ friend bool operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
+ {
+ return a.m_binding == b.m_binding
+ && a.m_location == b.m_location
+ && a.m_format == b.m_format
+ && a.m_offset == b.m_offset;
+ // matrixSlice excluded intentionally
+ }
+
+ friend bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiVertexInputAttribute &v, size_t seed = 0) noexcept
+ {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, v.m_binding);
+ seed = hash(seed, v.m_location);
+ seed = hash(seed, v.m_format);
+ seed = hash(seed, v.m_offset);
+ return seed;
+ }
+};
+
+Q_DECLARE_TYPEINFO(QRhiVertexInputAttribute, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputAttribute &);
+#endif
+
+class Q_GUI_EXPORT QRhiVertexInputLayout
+{
+public:
+ QRhiVertexInputLayout() = default;
+
+ void setBindings(std::initializer_list<QRhiVertexInputBinding> list) { m_bindings = list; }
+ template<typename InputIterator>
+ void setBindings(InputIterator first, InputIterator last)
+ {
+ m_bindings.clear();
+ std::copy(first, last, std::back_inserter(m_bindings));
+ }
+ const QRhiVertexInputBinding *cbeginBindings() const { return m_bindings.cbegin(); }
+ const QRhiVertexInputBinding *cendBindings() const { return m_bindings.cend(); }
+ const QRhiVertexInputBinding *bindingAt(qsizetype index) const { return &m_bindings.at(index); }
+ qsizetype bindingCount() const { return m_bindings.count(); }
+
+ void setAttributes(std::initializer_list<QRhiVertexInputAttribute> list) { m_attributes = list; }
+ template<typename InputIterator>
+ void setAttributes(InputIterator first, InputIterator last)
+ {
+ m_attributes.clear();
+ std::copy(first, last, std::back_inserter(m_attributes));
+ }
+ const QRhiVertexInputAttribute *cbeginAttributes() const { return m_attributes.cbegin(); }
+ const QRhiVertexInputAttribute *cendAttributes() const { return m_attributes.cend(); }
+ const QRhiVertexInputAttribute *attributeAt(qsizetype index) const { return &m_attributes.at(index); }
+ qsizetype attributeCount() const { return m_attributes.count(); }
+
+private:
+ QVarLengthArray<QRhiVertexInputBinding, 8> m_bindings;
+ QVarLengthArray<QRhiVertexInputAttribute, 8> m_attributes;
+
+ friend bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
+ {
+ return a.m_bindings == b.m_bindings && a.m_attributes == b.m_attributes;
+ }
+
+ friend bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiVertexInputLayout &v, size_t seed = 0) noexcept
+ {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, v.m_bindings);
+ seed = hash(seed, v.m_attributes);
+ return seed;
+ }
+
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &);
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &);
+#endif
+
+class Q_GUI_EXPORT QRhiShaderStage
+{
+public:
+ enum Type {
+ Vertex,
+ TessellationControl,
+ TessellationEvaluation,
+ Geometry,
+ Fragment,
+ Compute
+ };
+
+ QRhiShaderStage() = default;
+ QRhiShaderStage(Type type, const QShader &shader,
+ QShader::Variant v = QShader::StandardShader);
+
+ Type type() const { return m_type; }
+ void setType(Type t) { m_type = t; }
+
+ QShader shader() const { return m_shader; }
+ void setShader(const QShader &s) { m_shader = s; }
+
+ QShader::Variant shaderVariant() const { return m_shaderVariant; }
+ void setShaderVariant(QShader::Variant v) { m_shaderVariant = v; }
+
+private:
+ Type m_type = Vertex;
+ QShader m_shader;
+ QShader::Variant m_shaderVariant = QShader::StandardShader;
+
+ friend bool operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
+ {
+ return a.m_type == b.m_type
+ && a.m_shader == b.m_shader
+ && a.m_shaderVariant == b.m_shaderVariant;
+ }
+
+ friend bool operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept
+ {
+ return !(a == b);
+ }
+
+ friend size_t qHash(const QRhiShaderStage &v, size_t seed = 0) noexcept
+ {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, v.m_type);
+ seed = hash(seed, v.m_shader);
+ seed = hash(seed, v.m_shaderVariant);
+ return seed;
+ }
+};
+
+Q_DECLARE_TYPEINFO(QRhiShaderStage, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderStage &);
+#endif
+
+using QRhiGraphicsShaderStage = QRhiShaderStage;
+
+class Q_GUI_EXPORT QRhiShaderResourceBinding
+{
+public:
+ enum Type {
+ UniformBuffer,
+ SampledTexture,
+ Texture,
+ Sampler,
+ ImageLoad,
+ ImageStore,
+ ImageLoadStore,
+ BufferLoad,
+ BufferStore,
+ BufferLoadStore
+ };
+
+ enum StageFlag {
+ VertexStage = 1 << 0,
+ TessellationControlStage = 1 << 1,
+ TessellationEvaluationStage = 1 << 2,
+ GeometryStage = 1 << 3,
+ FragmentStage = 1 << 4,
+ ComputeStage = 1 << 5
+ };
+ Q_DECLARE_FLAGS(StageFlags, StageFlag)
+
+ QRhiShaderResourceBinding() = default;
+
+ bool isLayoutCompatible(const QRhiShaderResourceBinding &other) const;
+
+ static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf);
+ static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size);
+ static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, quint32 size);
+
+ static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler);
+
+ struct TextureAndSampler {
+ QRhiTexture *tex;
+ QRhiSampler *sampler;
+ };
+ static QRhiShaderResourceBinding sampledTextures(int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers);
+
+ static QRhiShaderResourceBinding texture(int binding, StageFlags stage, QRhiTexture *tex);
+ static QRhiShaderResourceBinding textures(int binding, StageFlags stage, int count, QRhiTexture **tex);
+ static QRhiShaderResourceBinding sampler(int binding, StageFlags stage, QRhiSampler *sampler);
+
+ static QRhiShaderResourceBinding imageLoad(int binding, StageFlags stage, QRhiTexture *tex, int level);
+ static QRhiShaderResourceBinding imageStore(int binding, StageFlags stage, QRhiTexture *tex, int level);
+ static QRhiShaderResourceBinding imageLoadStore(int binding, StageFlags stage, QRhiTexture *tex, int level);
+
+ static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf);
+ static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size);
+ static QRhiShaderResourceBinding bufferStore(int binding, StageFlags stage, QRhiBuffer *buf);
+ static QRhiShaderResourceBinding bufferStore(int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size);
+ static QRhiShaderResourceBinding bufferLoadStore(int binding, StageFlags stage, QRhiBuffer *buf);
+ static QRhiShaderResourceBinding bufferLoadStore(int binding, StageFlags stage, QRhiBuffer *buf, quint32 offset, quint32 size);
+
+ struct Data
+ {
+ int binding;
+ QRhiShaderResourceBinding::StageFlags stage;
+ QRhiShaderResourceBinding::Type type;
+ struct UniformBufferData {
+ QRhiBuffer *buf;
+ quint32 offset;
+ quint32 maybeSize;
+ bool hasDynamicOffset;
+ };
+ static constexpr int MAX_TEX_SAMPLER_ARRAY_SIZE = 16;
+ struct TextureAndOrSamplerData {
+ int count;
+ TextureAndSampler texSamplers[MAX_TEX_SAMPLER_ARRAY_SIZE];
+ };
+ struct StorageImageData {
+ QRhiTexture *tex;
+ int level;
+ };
+ struct StorageBufferData {
+ QRhiBuffer *buf;
+ quint32 offset;
+ quint32 maybeSize;
+ };
+ union {
+ UniformBufferData ubuf;
+ TextureAndOrSamplerData stex;
+ StorageImageData simage;
+ StorageBufferData sbuf;
+ } u;
+
+ int arraySize() const
+ {
+ return type == QRhiShaderResourceBinding::SampledTexture || type == QRhiShaderResourceBinding::Texture
+ ? u.stex.count
+ : 1;
+ }
+
+ template<typename Output>
+ Output serialize(Output dst) const
+ {
+ // must write out exactly LAYOUT_DESC_ENTRIES_PER_BINDING elements here
+ *dst++ = quint32(binding);
+ *dst++ = quint32(stage);
+ *dst++ = quint32(type);
+ *dst++ = quint32(arraySize());
+ return dst;
+ }
+ };
+
+ static constexpr int LAYOUT_DESC_ENTRIES_PER_BINDING = 4;
+
+ template<typename Output>
+ static void serializeLayoutDescription(const QRhiShaderResourceBinding *first,
+ const QRhiShaderResourceBinding *last,
+ Output dst)
+ {
+ while (first != last) {
+ dst = first->d.serialize(dst);
+ ++first;
+ }
+ }
+
+private:
+ Data d;
+ friend class QRhiImplementation;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiShaderResourceBinding::StageFlags)
+
+Q_DECLARE_TYPEINFO(QRhiShaderResourceBinding, Q_PRIMITIVE_TYPE);
+
+Q_GUI_EXPORT bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept;
+Q_GUI_EXPORT bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept;
+Q_GUI_EXPORT size_t qHash(const QRhiShaderResourceBinding &b, size_t seed = 0) noexcept;
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBinding &);
+#endif
+
+class Q_GUI_EXPORT QRhiColorAttachment
+{
+public:
+ QRhiColorAttachment() = default;
+ QRhiColorAttachment(QRhiTexture *texture);
+ QRhiColorAttachment(QRhiRenderBuffer *renderBuffer);
+
+ QRhiTexture *texture() const { return m_texture; }
+ void setTexture(QRhiTexture *tex) { m_texture = tex; }
+
+ QRhiRenderBuffer *renderBuffer() const { return m_renderBuffer; }
+ void setRenderBuffer(QRhiRenderBuffer *rb) { m_renderBuffer = rb; }
+
+ int layer() const { return m_layer; }
+ void setLayer(int layer) { m_layer = layer; }
+
+ int level() const { return m_level; }
+ void setLevel(int level) { m_level = level; }
+
+ QRhiTexture *resolveTexture() const { return m_resolveTexture; }
+ void setResolveTexture(QRhiTexture *tex) { m_resolveTexture = tex; }
+
+ int resolveLayer() const { return m_resolveLayer; }
+ void setResolveLayer(int layer) { m_resolveLayer = layer; }
+
+ int resolveLevel() const { return m_resolveLevel; }
+ void setResolveLevel(int level) { m_resolveLevel = level; }
+
+ int multiViewCount() const { return m_multiViewCount; }
+ void setMultiViewCount(int count) { m_multiViewCount = count; }
+
+private:
+ QRhiTexture *m_texture = nullptr;
+ QRhiRenderBuffer *m_renderBuffer = nullptr;
+ int m_layer = 0;
+ int m_level = 0;
+ QRhiTexture *m_resolveTexture = nullptr;
+ int m_resolveLayer = 0;
+ int m_resolveLevel = 0;
+ int m_multiViewCount = 0;
+};
+
+Q_DECLARE_TYPEINFO(QRhiColorAttachment, Q_RELOCATABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiTextureRenderTargetDescription
+{
+public:
+ QRhiTextureRenderTargetDescription() = default;
+ QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment);
+ QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiRenderBuffer *depthStencilBuffer);
+ QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiTexture *depthTexture);
+
+ void setColorAttachments(std::initializer_list<QRhiColorAttachment> list) { m_colorAttachments = list; }
+ template<typename InputIterator>
+ void setColorAttachments(InputIterator first, InputIterator last)
+ {
+ m_colorAttachments.clear();
+ std::copy(first, last, std::back_inserter(m_colorAttachments));
+ }
+ const QRhiColorAttachment *cbeginColorAttachments() const { return m_colorAttachments.cbegin(); }
+ const QRhiColorAttachment *cendColorAttachments() const { return m_colorAttachments.cend(); }
+ const QRhiColorAttachment *colorAttachmentAt(qsizetype index) const { return &m_colorAttachments.at(index); }
+ qsizetype colorAttachmentCount() const { return m_colorAttachments.count(); }
+
+ QRhiRenderBuffer *depthStencilBuffer() const { return m_depthStencilBuffer; }
+ void setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer) { m_depthStencilBuffer = renderBuffer; }
+
+ QRhiTexture *depthTexture() const { return m_depthTexture; }
+ void setDepthTexture(QRhiTexture *texture) { m_depthTexture = texture; }
+
+ QRhiTexture *depthResolveTexture() const { return m_depthResolveTexture; }
+ void setDepthResolveTexture(QRhiTexture *tex) { m_depthResolveTexture = tex; }
+
+private:
+ QVarLengthArray<QRhiColorAttachment, 8> m_colorAttachments;
+ QRhiRenderBuffer *m_depthStencilBuffer = nullptr;
+ QRhiTexture *m_depthTexture = nullptr;
+ QRhiTexture *m_depthResolveTexture = nullptr;
+};
+
+class Q_GUI_EXPORT QRhiTextureSubresourceUploadDescription
+{
+public:
+ QRhiTextureSubresourceUploadDescription() = default;
+ explicit QRhiTextureSubresourceUploadDescription(const QImage &image);
+ QRhiTextureSubresourceUploadDescription(const void *data, quint32 size);
+ explicit QRhiTextureSubresourceUploadDescription(const QByteArray &data);
+
+ QImage image() const { return m_image; }
+ void setImage(const QImage &image) { m_image = image; }
+
+ QByteArray data() const { return m_data; }
+ void setData(const QByteArray &data) { m_data = data; }
+
+ quint32 dataStride() const { return m_dataStride; }
+ void setDataStride(quint32 stride) { m_dataStride = stride; }
+
+ QPoint destinationTopLeft() const { return m_destinationTopLeft; }
+ void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
+
+ QSize sourceSize() const { return m_sourceSize; }
+ void setSourceSize(const QSize &size) { m_sourceSize = size; }
+
+ QPoint sourceTopLeft() const { return m_sourceTopLeft; }
+ void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
+
+private:
+ QImage m_image;
+ QByteArray m_data;
+ quint32 m_dataStride = 0;
+ QPoint m_destinationTopLeft;
+ QSize m_sourceSize;
+ QPoint m_sourceTopLeft;
+};
+
+Q_DECLARE_TYPEINFO(QRhiTextureSubresourceUploadDescription, Q_RELOCATABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiTextureUploadEntry
+{
+public:
+ QRhiTextureUploadEntry() = default;
+ QRhiTextureUploadEntry(int layer, int level, const QRhiTextureSubresourceUploadDescription &desc);
+
+ int layer() const { return m_layer; }
+ void setLayer(int layer) { m_layer = layer; }
+
+ int level() const { return m_level; }
+ void setLevel(int level) { m_level = level; }
+
+ QRhiTextureSubresourceUploadDescription description() const { return m_desc; }
+ void setDescription(const QRhiTextureSubresourceUploadDescription &desc) { m_desc = desc; }
+
+private:
+ int m_layer = 0;
+ int m_level = 0;
+ QRhiTextureSubresourceUploadDescription m_desc;
+};
+
+Q_DECLARE_TYPEINFO(QRhiTextureUploadEntry, Q_RELOCATABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiTextureUploadDescription
+{
+public:
+ QRhiTextureUploadDescription() = default;
+ QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry);
+ QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list);
+
+ void setEntries(std::initializer_list<QRhiTextureUploadEntry> list) { m_entries = list; }
+ template<typename InputIterator>
+ void setEntries(InputIterator first, InputIterator last)
+ {
+ m_entries.clear();
+ std::copy(first, last, std::back_inserter(m_entries));
+ }
+ const QRhiTextureUploadEntry *cbeginEntries() const { return m_entries.cbegin(); }
+ const QRhiTextureUploadEntry *cendEntries() const { return m_entries.cend(); }
+ const QRhiTextureUploadEntry *entryAt(qsizetype index) const { return &m_entries.at(index); }
+ qsizetype entryCount() const { return m_entries.count(); }
+
+private:
+ QVarLengthArray<QRhiTextureUploadEntry, 16> m_entries;
+};
+
+class Q_GUI_EXPORT QRhiTextureCopyDescription
+{
+public:
+ QRhiTextureCopyDescription() = default;
+
+ QSize pixelSize() const { return m_pixelSize; }
+ void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
+
+ int sourceLayer() const { return m_sourceLayer; }
+ void setSourceLayer(int layer) { m_sourceLayer = layer; }
+
+ int sourceLevel() const { return m_sourceLevel; }
+ void setSourceLevel(int level) { m_sourceLevel = level; }
+
+ QPoint sourceTopLeft() const { return m_sourceTopLeft; }
+ void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
+
+ int destinationLayer() const { return m_destinationLayer; }
+ void setDestinationLayer(int layer) { m_destinationLayer = layer; }
+
+ int destinationLevel() const { return m_destinationLevel; }
+ void setDestinationLevel(int level) { m_destinationLevel = level; }
+
+ QPoint destinationTopLeft() const { return m_destinationTopLeft; }
+ void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
+
+private:
+ QSize m_pixelSize;
+ int m_sourceLayer = 0;
+ int m_sourceLevel = 0;
+ QPoint m_sourceTopLeft;
+ int m_destinationLayer = 0;
+ int m_destinationLevel = 0;
+ QPoint m_destinationTopLeft;
+};
+
+Q_DECLARE_TYPEINFO(QRhiTextureCopyDescription, Q_RELOCATABLE_TYPE);
+
+class Q_GUI_EXPORT QRhiReadbackDescription
+{
+public:
+ QRhiReadbackDescription() = default;
+ QRhiReadbackDescription(QRhiTexture *texture);
+
+ QRhiTexture *texture() const { return m_texture; }
+ void setTexture(QRhiTexture *tex) { m_texture = tex; }
+
+ int layer() const { return m_layer; }
+ void setLayer(int layer) { m_layer = layer; }
+
+ int level() const { return m_level; }
+ void setLevel(int level) { m_level = level; }
+
+private:
+ QRhiTexture *m_texture = nullptr;
+ int m_layer = 0;
+ int m_level = 0;
+};
+
+Q_DECLARE_TYPEINFO(QRhiReadbackDescription, Q_RELOCATABLE_TYPE);
+
+struct Q_GUI_EXPORT QRhiNativeHandles
+{
+};
+
+class Q_GUI_EXPORT QRhiResource
+{
+public:
+ enum Type {
+ Buffer,
+ Texture,
+ Sampler,
+ RenderBuffer,
+ RenderPassDescriptor,
+ SwapChainRenderTarget,
+ TextureRenderTarget,
+ ShaderResourceBindings,
+ GraphicsPipeline,
+ SwapChain,
+ ComputePipeline,
+ CommandBuffer
+ };
+
+ virtual ~QRhiResource();
+
+ virtual Type resourceType() const = 0;
+
+ virtual void destroy() = 0;
+
+ void deleteLater();
+
+ QByteArray name() const;
+ void setName(const QByteArray &name);
+
+ quint64 globalResourceId() const;
+
+ QRhi *rhi() const;
+
+protected:
+ QRhiResource(QRhiImplementation *rhi);
+ Q_DISABLE_COPY(QRhiResource)
+ friend class QRhiImplementation;
+ QRhiImplementation *m_rhi = nullptr;
+ quint64 m_id;
+ QByteArray m_objectName;
+};
+
+class Q_GUI_EXPORT QRhiBuffer : public QRhiResource
+{
+public:
+ enum Type {
+ Immutable,
+ Static,
+ Dynamic
+ };
+
+ enum UsageFlag {
+ VertexBuffer = 1 << 0,
+ IndexBuffer = 1 << 1,
+ UniformBuffer = 1 << 2,
+ StorageBuffer = 1 << 3
+ };
+ Q_DECLARE_FLAGS(UsageFlags, UsageFlag)
+
+ struct NativeBuffer {
+ const void *objects[3];
+ int slotCount;
+ };
+
+ QRhiResource::Type resourceType() const override;
+
+ Type type() const { return m_type; }
+ void setType(Type t) { m_type = t; }
+
+ UsageFlags usage() const { return m_usage; }
+ void setUsage(UsageFlags u) { m_usage = u; }
+
+ quint32 size() const { return m_size; }
+ void setSize(quint32 sz) { m_size = sz; }
+
+ virtual bool create() = 0;
+
+ virtual NativeBuffer nativeBuffer();
+
+ virtual char *beginFullDynamicBufferUpdateForCurrentFrame();
+ virtual void endFullDynamicBufferUpdateForCurrentFrame();
+
+protected:
+ QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, quint32 size_);
+ Type m_type;
+ UsageFlags m_usage;
+ quint32 m_size;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiBuffer::UsageFlags)
+
+class Q_GUI_EXPORT QRhiTexture : public QRhiResource
+{
+public:
+ enum Flag {
+ RenderTarget = 1 << 0,
+ CubeMap = 1 << 2,
+ MipMapped = 1 << 3,
+ sRGB = 1 << 4,
+ UsedAsTransferSource = 1 << 5,
+ UsedWithGenerateMips = 1 << 6,
+ UsedWithLoadStore = 1 << 7,
+ UsedAsCompressedAtlas = 1 << 8,
+ ExternalOES = 1 << 9,
+ ThreeDimensional = 1 << 10,
+ TextureRectangleGL = 1 << 11,
+ TextureArray = 1 << 12,
+ OneDimensional = 1 << 13
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ enum Format {
+ UnknownFormat,
+
+ RGBA8,
+ BGRA8,
+ R8,
+ RG8,
+ R16,
+ RG16,
+ RED_OR_ALPHA8,
+
+ RGBA16F,
+ RGBA32F,
+ R16F,
+ R32F,
+
+ RGB10A2,
+
+ D16,
+ D24,
+ D24S8,
+ D32F,
+
+ BC1,
+ BC2,
+ BC3,
+ BC4,
+ BC5,
+ BC6H,
+ BC7,
+
+ ETC2_RGB8,
+ ETC2_RGB8A1,
+ ETC2_RGBA8,
+
+ ASTC_4x4,
+ ASTC_5x4,
+ ASTC_5x5,
+ ASTC_6x5,
+ ASTC_6x6,
+ ASTC_8x5,
+ ASTC_8x6,
+ ASTC_8x8,
+ ASTC_10x5,
+ ASTC_10x6,
+ ASTC_10x8,
+ ASTC_10x10,
+ ASTC_12x10,
+ ASTC_12x12
+ };
+
+ struct NativeTexture {
+ quint64 object;
+ int layout; // or state
+ };
+
+ QRhiResource::Type resourceType() const override;
+
+ Format format() const { return m_format; }
+ void setFormat(Format fmt) { m_format = fmt; }
+
+ QSize pixelSize() const { return m_pixelSize; }
+ void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
+
+ int depth() const { return m_depth; }
+ void setDepth(int depth) { m_depth = depth; }
+
+ int arraySize() const { return m_arraySize; }
+ void setArraySize(int arraySize) { m_arraySize = arraySize; }
+
+ int arrayRangeStart() const { return m_arrayRangeStart; }
+ int arrayRangeLength() const { return m_arrayRangeLength; }
+ void setArrayRange(int startIndex, int count)
+ {
+ m_arrayRangeStart = startIndex;
+ m_arrayRangeLength = count;
+ }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ int sampleCount() const { return m_sampleCount; }
+ void setSampleCount(int s) { m_sampleCount = s; }
+
+ struct ViewFormat {
+ QRhiTexture::Format format;
+ bool srgb;
+ };
+ ViewFormat readViewFormat() const { return m_readViewFormat; }
+ void setReadViewFormat(const ViewFormat &fmt) { m_readViewFormat = fmt; }
+ ViewFormat writeViewFormat() const { return m_writeViewFormat; }
+ void setWriteViewFormat(const ViewFormat &fmt) { m_writeViewFormat = fmt; }
+
+ virtual bool create() = 0;
+ virtual NativeTexture nativeTexture();
+ virtual bool createFrom(NativeTexture src);
+ virtual void setNativeLayout(int layout);
+
+protected:
+ QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
+ int arraySize_, int sampleCount_, Flags flags_);
+ Format m_format;
+ QSize m_pixelSize;
+ int m_depth;
+ int m_arraySize;
+ int m_sampleCount;
+ Flags m_flags;
+ int m_arrayRangeStart = -1;
+ int m_arrayRangeLength = -1;
+ ViewFormat m_readViewFormat = { UnknownFormat, false };
+ ViewFormat m_writeViewFormat = { UnknownFormat, false };
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTexture::Flags)
+
+class Q_GUI_EXPORT QRhiSampler : public QRhiResource
+{
+public:
+ enum Filter {
+ None,
+ Nearest,
+ Linear
+ };
+
+ enum AddressMode {
+ Repeat,
+ ClampToEdge,
+ Mirror,
+ };
+
+ enum CompareOp {
+ Never,
+ Less,
+ Equal,
+ LessOrEqual,
+ Greater,
+ NotEqual,
+ GreaterOrEqual,
+ Always
+ };
+
+ QRhiResource::Type resourceType() const override;
+
+ Filter magFilter() const { return m_magFilter; }
+ void setMagFilter(Filter f) { m_magFilter = f; }
+
+ Filter minFilter() const { return m_minFilter; }
+ void setMinFilter(Filter f) { m_minFilter = f; }
+
+ Filter mipmapMode() const { return m_mipmapMode; }
+ void setMipmapMode(Filter f) { m_mipmapMode = f; }
+
+ AddressMode addressU() const { return m_addressU; }
+ void setAddressU(AddressMode mode) { m_addressU = mode; }
+
+ AddressMode addressV() const { return m_addressV; }
+ void setAddressV(AddressMode mode) { m_addressV = mode; }
+
+ AddressMode addressW() const { return m_addressW; }
+ void setAddressW(AddressMode mode) { m_addressW = mode; }
+
+ CompareOp textureCompareOp() const { return m_compareOp; }
+ void setTextureCompareOp(CompareOp op) { m_compareOp = op; }
+
+ virtual bool create() = 0;
+
+protected:
+ QRhiSampler(QRhiImplementation *rhi,
+ Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
+ AddressMode u_, AddressMode v_, AddressMode w_);
+ Filter m_magFilter;
+ Filter m_minFilter;
+ Filter m_mipmapMode;
+ AddressMode m_addressU;
+ AddressMode m_addressV;
+ AddressMode m_addressW;
+ CompareOp m_compareOp;
+};
+
+class Q_GUI_EXPORT QRhiRenderBuffer : public QRhiResource
+{
+public:
+ enum Type {
+ DepthStencil,
+ Color
+ };
+
+ enum Flag {
+ UsedWithSwapChainOnly = 1 << 0
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ struct NativeRenderBuffer {
+ quint64 object;
+ };
+
+ QRhiResource::Type resourceType() const override;
+
+ Type type() const { return m_type; }
+ void setType(Type t) { m_type = t; }
+
+ QSize pixelSize() const { return m_pixelSize; }
+ void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
+
+ int sampleCount() const { return m_sampleCount; }
+ void setSampleCount(int s) { m_sampleCount = s; }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ virtual bool create() = 0;
+ virtual bool createFrom(NativeRenderBuffer src);
+
+ virtual QRhiTexture::Format backingFormat() const = 0;
+
+protected:
+ QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
+ int sampleCount_, Flags flags_, QRhiTexture::Format backingFormatHint_);
+ Type m_type;
+ QSize m_pixelSize;
+ int m_sampleCount;
+ Flags m_flags;
+ QRhiTexture::Format m_backingFormatHint;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiRenderBuffer::Flags)
+
+class Q_GUI_EXPORT QRhiRenderPassDescriptor : public QRhiResource
+{
+public:
+ QRhiResource::Type resourceType() const override;
+
+ virtual bool isCompatible(const QRhiRenderPassDescriptor *other) const = 0;
+ virtual const QRhiNativeHandles *nativeHandles();
+
+ virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const = 0;
+
+ virtual QVector<quint32> serializedFormat() const = 0;
+
+protected:
+ QRhiRenderPassDescriptor(QRhiImplementation *rhi);
+};
+
+class Q_GUI_EXPORT QRhiRenderTarget : public QRhiResource
+{
+public:
+ virtual QSize pixelSize() const = 0;
+ virtual float devicePixelRatio() const = 0;
+ virtual int sampleCount() const = 0;
+
+ QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
+ void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
+
+protected:
+ QRhiRenderTarget(QRhiImplementation *rhi);
+ QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
+};
+
+class Q_GUI_EXPORT QRhiSwapChainRenderTarget : public QRhiRenderTarget
+{
+public:
+ QRhiResource::Type resourceType() const override;
+ QRhiSwapChain *swapChain() const { return m_swapchain; }
+
+protected:
+ QRhiSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain_);
+ QRhiSwapChain *m_swapchain;
+};
+
+class Q_GUI_EXPORT QRhiTextureRenderTarget : public QRhiRenderTarget
+{
+public:
+ enum Flag {
+ PreserveColorContents = 1 << 0,
+ PreserveDepthStencilContents = 1 << 1,
+ DoNotStoreDepthStencilContents = 1 << 2
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QRhiResource::Type resourceType() const override;
+
+ QRhiTextureRenderTargetDescription description() const { return m_desc; }
+ void setDescription(const QRhiTextureRenderTargetDescription &desc) { m_desc = desc; }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0;
+
+ virtual bool create() = 0;
+
+protected:
+ QRhiTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc_, Flags flags_);
+ QRhiTextureRenderTargetDescription m_desc;
+ Flags m_flags;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTextureRenderTarget::Flags)
+
+class Q_GUI_EXPORT QRhiShaderResourceBindings : public QRhiResource
+{
+public:
+ QRhiResource::Type resourceType() const override;
+
+ void setBindings(std::initializer_list<QRhiShaderResourceBinding> list) { m_bindings = list; }
+ template<typename InputIterator>
+ void setBindings(InputIterator first, InputIterator last)
+ {
+ m_bindings.clear();
+ std::copy(first, last, std::back_inserter(m_bindings));
+ }
+ const QRhiShaderResourceBinding *cbeginBindings() const { return m_bindings.cbegin(); }
+ const QRhiShaderResourceBinding *cendBindings() const { return m_bindings.cend(); }
+ const QRhiShaderResourceBinding *bindingAt(qsizetype index) const { return &m_bindings.at(index); }
+ qsizetype bindingCount() const { return m_bindings.count(); }
+
+ bool isLayoutCompatible(const QRhiShaderResourceBindings *other) const;
+
+ QVector<quint32> serializedLayoutDescription() const { return m_layoutDesc; }
+
+ virtual bool create() = 0;
+
+ enum UpdateFlag {
+ BindingsAreSorted = 0x01
+ };
+ Q_DECLARE_FLAGS(UpdateFlags, UpdateFlag)
+
+ virtual void updateResources(UpdateFlags flags = {}) = 0;
+
+protected:
+ static constexpr int BINDING_PREALLOC = 12;
+ QRhiShaderResourceBindings(QRhiImplementation *rhi);
+ QVarLengthArray<QRhiShaderResourceBinding, BINDING_PREALLOC> m_bindings;
+ size_t m_layoutDescHash = 0;
+ // Intentionally not using QVLA for m_layoutDesc: clients like Qt Quick are much
+ // better served with an implicitly shared container here, because they will likely
+ // throw this directly into structs serving as cache keys.
+ QVector<quint32> m_layoutDesc;
+ friend class QRhiImplementation;
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
+#endif
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiShaderResourceBindings::UpdateFlags)
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
+#endif
+
+// The proper name. Until it gets rolled out universally, have the better name
+// as a typedef. Eventually it should be reversed (the old name being a typedef
+// to the new one).
+using QRhiShaderResourceBindingSet = QRhiShaderResourceBindings;
+
+class Q_GUI_EXPORT QRhiGraphicsPipeline : public QRhiResource
+{
+public:
+ enum Flag {
+ UsesBlendConstants = 1 << 0,
+ UsesStencilRef = 1 << 1,
+ UsesScissor = 1 << 2,
+ CompileShadersWithDebugInfo = 1 << 3
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ enum Topology {
+ Triangles,
+ TriangleStrip,
+ TriangleFan,
+ Lines,
+ LineStrip,
+ Points,
+ Patches
+ };
+
+ enum CullMode {
+ None,
+ Front,
+ Back
+ };
+
+ enum FrontFace {
+ CCW,
+ CW
+ };
+
+ enum ColorMaskComponent {
+ R = 1 << 0,
+ G = 1 << 1,
+ B = 1 << 2,
+ A = 1 << 3
+ };
+ Q_DECLARE_FLAGS(ColorMask, ColorMaskComponent)
+
+ enum BlendFactor {
+ Zero,
+ One,
+ SrcColor,
+ OneMinusSrcColor,
+ DstColor,
+ OneMinusDstColor,
+ SrcAlpha,
+ OneMinusSrcAlpha,
+ DstAlpha,
+ OneMinusDstAlpha,
+ ConstantColor,
+ OneMinusConstantColor,
+ ConstantAlpha,
+ OneMinusConstantAlpha,
+ SrcAlphaSaturate,
+ Src1Color,
+ OneMinusSrc1Color,
+ Src1Alpha,
+ OneMinusSrc1Alpha
+ };
+
+ enum BlendOp {
+ Add,
+ Subtract,
+ ReverseSubtract,
+ Min,
+ Max
+ };
+
+ struct TargetBlend {
+ ColorMask colorWrite = ColorMask(0xF); // R | G | B | A
+ bool enable = false;
+ BlendFactor srcColor = One;
+ BlendFactor dstColor = OneMinusSrcAlpha;
+ BlendOp opColor = Add;
+ BlendFactor srcAlpha = One;
+ BlendFactor dstAlpha = OneMinusSrcAlpha;
+ BlendOp opAlpha = Add;
+ };
+
+ enum CompareOp {
+ Never,
+ Less,
+ Equal,
+ LessOrEqual,
+ Greater,
+ NotEqual,
+ GreaterOrEqual,
+ Always
+ };
+
+ enum StencilOp {
+ StencilZero,
+ Keep,
+ Replace,
+ IncrementAndClamp,
+ DecrementAndClamp,
+ Invert,
+ IncrementAndWrap,
+ DecrementAndWrap
+ };
+
+ struct StencilOpState {
+ StencilOp failOp = Keep;
+ StencilOp depthFailOp = Keep;
+ StencilOp passOp = Keep;
+ CompareOp compareOp = Always;
+ };
+
+ enum PolygonMode {
+ Fill,
+ Line
+ };
+
+ QRhiResource::Type resourceType() const override;
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ Topology topology() const { return m_topology; }
+ void setTopology(Topology t) { m_topology = t; }
+
+ CullMode cullMode() const { return m_cullMode; }
+ void setCullMode(CullMode mode) { m_cullMode = mode; }
+
+ FrontFace frontFace() const { return m_frontFace; }
+ void setFrontFace(FrontFace f) { m_frontFace = f; }
+
+ void setTargetBlends(std::initializer_list<TargetBlend> list) { m_targetBlends = list; }
+ template<typename InputIterator>
+ void setTargetBlends(InputIterator first, InputIterator last)
+ {
+ m_targetBlends.clear();
+ std::copy(first, last, std::back_inserter(m_targetBlends));
+ }
+ const TargetBlend *cbeginTargetBlends() const { return m_targetBlends.cbegin(); }
+ const TargetBlend *cendTargetBlends() const { return m_targetBlends.cend(); }
+ const TargetBlend *targetBlendAt(qsizetype index) const { return &m_targetBlends.at(index); }
+ qsizetype targetBlendCount() const { return m_targetBlends.count(); }
+
+ bool hasDepthTest() const { return m_depthTest; }
+ void setDepthTest(bool enable) { m_depthTest = enable; }
+
+ bool hasDepthWrite() const { return m_depthWrite; }
+ void setDepthWrite(bool enable) { m_depthWrite = enable; }
+
+ CompareOp depthOp() const { return m_depthOp; }
+ void setDepthOp(CompareOp op) { m_depthOp = op; }
+
+ bool hasStencilTest() const { return m_stencilTest; }
+ void setStencilTest(bool enable) { m_stencilTest = enable; }
+
+ StencilOpState stencilFront() const { return m_stencilFront; }
+ void setStencilFront(const StencilOpState &state) { m_stencilFront = state; }
+
+ StencilOpState stencilBack() const { return m_stencilBack; }
+ void setStencilBack(const StencilOpState &state) { m_stencilBack = state; }
+
+ quint32 stencilReadMask() const { return m_stencilReadMask; }
+ void setStencilReadMask(quint32 mask) { m_stencilReadMask = mask; }
+
+ quint32 stencilWriteMask() const { return m_stencilWriteMask; }
+ void setStencilWriteMask(quint32 mask) { m_stencilWriteMask = mask; }
+
+ int sampleCount() const { return m_sampleCount; }
+ void setSampleCount(int s) { m_sampleCount = s; }
+
+ float lineWidth() const { return m_lineWidth; }
+ void setLineWidth(float width) { m_lineWidth = width; }
+
+ int depthBias() const { return m_depthBias; }
+ void setDepthBias(int bias) { m_depthBias = bias; }
+
+ float slopeScaledDepthBias() const { return m_slopeScaledDepthBias; }
+ void setSlopeScaledDepthBias(float bias) { m_slopeScaledDepthBias = bias; }
+
+ void setShaderStages(std::initializer_list<QRhiShaderStage> list) { m_shaderStages = list; }
+ template<typename InputIterator>
+ void setShaderStages(InputIterator first, InputIterator last)
+ {
+ m_shaderStages.clear();
+ std::copy(first, last, std::back_inserter(m_shaderStages));
+ }
+ const QRhiShaderStage *cbeginShaderStages() const { return m_shaderStages.cbegin(); }
+ const QRhiShaderStage *cendShaderStages() const { return m_shaderStages.cend(); }
+ const QRhiShaderStage *shaderStageAt(qsizetype index) const { return &m_shaderStages.at(index); }
+ qsizetype shaderStageCount() const { return m_shaderStages.count(); }
+
+ QRhiVertexInputLayout vertexInputLayout() const { return m_vertexInputLayout; }
+ void setVertexInputLayout(const QRhiVertexInputLayout &layout) { m_vertexInputLayout = layout; }
+
+ QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; }
+ void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; }
+
+ QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
+ void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
+
+ int patchControlPointCount() const { return m_patchControlPointCount; }
+ void setPatchControlPointCount(int count) { m_patchControlPointCount = count; }
+
+ PolygonMode polygonMode() const {return m_polygonMode; }
+ void setPolygonMode(PolygonMode mode) {m_polygonMode = mode; }
+
+ int multiViewCount() const { return m_multiViewCount; }
+ void setMultiViewCount(int count) { m_multiViewCount = count; }
+
+ virtual bool create() = 0;
+
+protected:
+ QRhiGraphicsPipeline(QRhiImplementation *rhi);
+ Flags m_flags;
+ Topology m_topology = Triangles;
+ CullMode m_cullMode = None;
+ FrontFace m_frontFace = CCW;
+ QVarLengthArray<TargetBlend, 8> m_targetBlends;
+ bool m_depthTest = false;
+ bool m_depthWrite = false;
+ CompareOp m_depthOp = Less;
+ bool m_stencilTest = false;
+ StencilOpState m_stencilFront;
+ StencilOpState m_stencilBack;
+ quint32 m_stencilReadMask = 0xFF;
+ quint32 m_stencilWriteMask = 0xFF;
+ int m_sampleCount = 1;
+ float m_lineWidth = 1.0f;
+ int m_depthBias = 0;
+ float m_slopeScaledDepthBias = 0.0f;
+ int m_patchControlPointCount = 3;
+ PolygonMode m_polygonMode = Fill;
+ int m_multiViewCount = 0;
+ QVarLengthArray<QRhiShaderStage, 4> m_shaderStages;
+ QRhiVertexInputLayout m_vertexInputLayout;
+ QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
+ QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::Flags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::ColorMask)
+Q_DECLARE_TYPEINFO(QRhiGraphicsPipeline::TargetBlend, Q_RELOCATABLE_TYPE);
+
+struct QRhiSwapChainHdrInfo
+{
+ enum LimitsType {
+ LuminanceInNits,
+ ColorComponentValue
+ };
+
+ enum LuminanceBehavior {
+ SceneReferred,
+ DisplayReferred
+ };
+
+ LimitsType limitsType;
+ union {
+ struct {
+ float minLuminance;
+ float maxLuminance;
+ } luminanceInNits;
+ struct {
+ float maxColorComponentValue;
+ float maxPotentialColorComponentValue;
+ } colorComponentValue;
+ } limits;
+ LuminanceBehavior luminanceBehavior;
+ float sdrWhiteLevel;
+};
+
+Q_DECLARE_TYPEINFO(QRhiSwapChainHdrInfo, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiSwapChainHdrInfo &);
+#endif
+
+struct QRhiSwapChainProxyData
+{
+ void *reserved[2] = {};
+};
+
+class Q_GUI_EXPORT QRhiSwapChain : public QRhiResource
+{
+public:
+ enum Flag {
+ SurfaceHasPreMulAlpha = 1 << 0,
+ SurfaceHasNonPreMulAlpha = 1 << 1,
+ sRGB = 1 << 2,
+ UsedAsTransferSource = 1 << 3,
+ NoVSync = 1 << 4,
+ MinimalBufferCount = 1 << 5
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ enum Format {
+ SDR,
+ HDRExtendedSrgbLinear,
+ HDR10,
+ HDRExtendedDisplayP3Linear
+ };
+
+ enum StereoTargetBuffer {
+ LeftBuffer,
+ RightBuffer
+ };
+
+ QRhiResource::Type resourceType() const override;
+
+ QWindow *window() const { return m_window; }
+ void setWindow(QWindow *window) { m_window = window; }
+
+ QRhiSwapChainProxyData proxyData() const { return m_proxyData; }
+ void setProxyData(const QRhiSwapChainProxyData &d) { m_proxyData = d; }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ Format format() const { return m_format; }
+ void setFormat(Format f) { m_format = f; }
+
+ QRhiRenderBuffer *depthStencil() const { return m_depthStencil; }
+ void setDepthStencil(QRhiRenderBuffer *ds) { m_depthStencil = ds; }
+
+ int sampleCount() const { return m_sampleCount; }
+ void setSampleCount(int samples) { m_sampleCount = samples; }
+
+ QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
+ void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
+
+ QSize currentPixelSize() const { return m_currentPixelSize; }
+
+ virtual QRhiCommandBuffer *currentFrameCommandBuffer() = 0;
+ virtual QRhiRenderTarget *currentFrameRenderTarget() = 0;
+ virtual QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer);
+ virtual QSize surfacePixelSize() = 0;
+ virtual bool isFormatSupported(Format f) = 0;
+ virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0;
+ virtual bool createOrResize() = 0;
+ virtual QRhiSwapChainHdrInfo hdrInfo();
+
+protected:
+ QRhiSwapChain(QRhiImplementation *rhi);
+ QWindow *m_window = nullptr;
+ Flags m_flags;
+ Format m_format = SDR;
+ QRhiRenderBuffer *m_depthStencil = nullptr;
+ int m_sampleCount = 1;
+ QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
+ QSize m_currentPixelSize;
+ QRhiSwapChainProxyData m_proxyData;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags)
+
+class Q_GUI_EXPORT QRhiComputePipeline : public QRhiResource
+{
+public:
+ enum Flag {
+ CompileShadersWithDebugInfo = 1 << 0
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QRhiResource::Type resourceType() const override;
+ virtual bool create() = 0;
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+ QRhiShaderStage shaderStage() const { return m_shaderStage; }
+ void setShaderStage(const QRhiShaderStage &stage) { m_shaderStage = stage; }
+
+ QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; }
+ void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; }
+
+protected:
+ QRhiComputePipeline(QRhiImplementation *rhi);
+ Flags m_flags;
+ QRhiShaderStage m_shaderStage;
+ QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiComputePipeline::Flags)
+
+class Q_GUI_EXPORT QRhiCommandBuffer : public QRhiResource
+{
+public:
+ enum IndexFormat {
+ IndexUInt16,
+ IndexUInt32
+ };
+
+ enum BeginPassFlag {
+ ExternalContent = 0x01,
+ DoNotTrackResourcesForCompute = 0x02
+ };
+ Q_DECLARE_FLAGS(BeginPassFlags, BeginPassFlag)
+
+ QRhiResource::Type resourceType() const override;
+
+ void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates);
+
+ void beginPass(QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates = nullptr,
+ BeginPassFlags flags = {});
+ void endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
+
+ void setGraphicsPipeline(QRhiGraphicsPipeline *ps);
+ using DynamicOffset = QPair<int, quint32>; // binding, offset
+ void setShaderResources(QRhiShaderResourceBindings *srb = nullptr,
+ int dynamicOffsetCount = 0,
+ const DynamicOffset *dynamicOffsets = nullptr);
+ using VertexInput = QPair<QRhiBuffer *, quint32>; // buffer, offset
+ void setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
+ QRhiBuffer *indexBuf = nullptr, quint32 indexOffset = 0,
+ IndexFormat indexFormat = IndexUInt16);
+
+ void setViewport(const QRhiViewport &viewport);
+ void setScissor(const QRhiScissor &scissor);
+ void setBlendConstants(const QColor &c);
+ void setStencilRef(quint32 refValue);
+
+ void draw(quint32 vertexCount,
+ quint32 instanceCount = 1,
+ quint32 firstVertex = 0,
+ quint32 firstInstance = 0);
+
+ void drawIndexed(quint32 indexCount,
+ quint32 instanceCount = 1,
+ quint32 firstIndex = 0,
+ qint32 vertexOffset = 0,
+ quint32 firstInstance = 0);
+
+ void debugMarkBegin(const QByteArray &name);
+ void debugMarkEnd();
+ void debugMarkMsg(const QByteArray &msg);
+
+ void beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr, BeginPassFlags flags = {});
+ void endComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
+ void setComputePipeline(QRhiComputePipeline *ps);
+ void dispatch(int x, int y, int z);
+
+ const QRhiNativeHandles *nativeHandles();
+ void beginExternal();
+ void endExternal();
+
+ double lastCompletedGpuTime();
+
+protected:
+ QRhiCommandBuffer(QRhiImplementation *rhi);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiCommandBuffer::BeginPassFlags)
+
+struct Q_GUI_EXPORT QRhiReadbackResult
+{
+ std::function<void()> completed = nullptr;
+ QRhiTexture::Format format;
+ QSize pixelSize;
+ QByteArray data;
+};
+
+class Q_GUI_EXPORT QRhiResourceUpdateBatch
+{
+public:
+ ~QRhiResourceUpdateBatch();
+
+ void release();
+
+ void merge(QRhiResourceUpdateBatch *other);
+ bool hasOptimalCapacity() const;
+
+ void updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data);
+ void uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data);
+ void uploadStaticBuffer(QRhiBuffer *buf, const void *data);
+ void readBackBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result);
+ void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc);
+ void uploadTexture(QRhiTexture *tex, const QImage &image);
+ void copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc = QRhiTextureCopyDescription());
+ void readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result);
+ void generateMips(QRhiTexture *tex);
+
+private:
+ QRhiResourceUpdateBatch(QRhiImplementation *rhi);
+ Q_DISABLE_COPY(QRhiResourceUpdateBatch)
+ QRhiResourceUpdateBatchPrivate *d;
+ friend class QRhiResourceUpdateBatchPrivate;
+ friend class QRhi;
+};
+
+struct Q_GUI_EXPORT QRhiDriverInfo
+{
+ enum DeviceType {
+ UnknownDevice,
+ IntegratedDevice,
+ DiscreteDevice,
+ ExternalDevice,
+ VirtualDevice,
+ CpuDevice
+ };
+
+ QByteArray deviceName;
+ quint64 deviceId = 0;
+ quint64 vendorId = 0;
+ DeviceType deviceType = UnknownDevice;
+};
+
+Q_DECLARE_TYPEINFO(QRhiDriverInfo, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiDriverInfo &);
+#endif
+
+struct Q_GUI_EXPORT QRhiStats
+{
+ qint64 totalPipelineCreationTime = 0;
+ // Vulkan or D3D12 memory allocator statistics
+ quint32 blockCount = 0;
+ quint32 allocCount = 0;
+ quint64 usedBytes = 0;
+ quint64 unusedBytes = 0;
+ // D3D12 only, from IDXGIAdapter3::QueryVideoMemoryInfo(), incl. all resources
+ quint64 totalUsageBytes = 0;
+};
+
+Q_DECLARE_TYPEINFO(QRhiStats, Q_RELOCATABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiStats &);
+#endif
+
+struct Q_GUI_EXPORT QRhiInitParams
+{
+};
+
+class Q_GUI_EXPORT QRhi
+{
+public:
+ enum Implementation {
+ Null,
+ Vulkan,
+ OpenGLES2,
+ D3D11,
+ Metal,
+ D3D12
+ };
+
+ enum Flag {
+ EnableDebugMarkers = 1 << 0,
+ PreferSoftwareRenderer = 1 << 1,
+ EnablePipelineCacheDataSave = 1 << 2,
+ EnableTimestamps = 1 << 3,
+ SuppressSmokeTestWarnings = 1 << 4
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ enum FrameOpResult {
+ FrameOpSuccess = 0,
+ FrameOpError,
+ FrameOpSwapChainOutOfDate,
+ FrameOpDeviceLost
+ };
+
+ enum Feature {
+ MultisampleTexture = 1,
+ MultisampleRenderBuffer,
+ DebugMarkers,
+ Timestamps,
+ Instancing,
+ CustomInstanceStepRate,
+ PrimitiveRestart,
+ NonDynamicUniformBuffers,
+ NonFourAlignedEffectiveIndexBufferOffset,
+ NPOTTextureRepeat,
+ RedOrAlpha8IsRed,
+ ElementIndexUint,
+ Compute,
+ WideLines,
+ VertexShaderPointSize,
+ BaseVertex,
+ BaseInstance,
+ TriangleFanTopology,
+ ReadBackNonUniformBuffer,
+ ReadBackNonBaseMipLevel,
+ TexelFetch,
+ RenderToNonBaseMipLevel,
+ IntAttributes,
+ ScreenSpaceDerivatives,
+ ReadBackAnyTextureFormat,
+ PipelineCacheDataLoadSave,
+ ImageDataStride,
+ RenderBufferImport,
+ ThreeDimensionalTextures,
+ RenderTo3DTextureSlice,
+ TextureArrays,
+ Tessellation,
+ GeometryShader,
+ TextureArrayRange,
+ NonFillPolygonMode,
+ OneDimensionalTextures,
+ OneDimensionalTextureMipmaps,
+ HalfAttributes,
+ RenderToOneDimensionalTexture,
+ ThreeDimensionalTextureMipmaps,
+ MultiView,
+ TextureViewFormat,
+ ResolveDepthStencil
+ };
+
+ enum BeginFrameFlag {
+ };
+ Q_DECLARE_FLAGS(BeginFrameFlags, BeginFrameFlag)
+
+ enum EndFrameFlag {
+ SkipPresent = 1 << 0
+ };
+ Q_DECLARE_FLAGS(EndFrameFlags, EndFrameFlag)
+
+ enum ResourceLimit {
+ TextureSizeMin = 1,
+ TextureSizeMax,
+ MaxColorAttachments,
+ FramesInFlight,
+ MaxAsyncReadbackFrames,
+ MaxThreadGroupsPerDimension,
+ MaxThreadsPerThreadGroup,
+ MaxThreadGroupX,
+ MaxThreadGroupY,
+ MaxThreadGroupZ,
+ TextureArraySizeMax,
+ MaxUniformBufferRange,
+ MaxVertexInputs,
+ MaxVertexOutputs
+ };
+
+ ~QRhi();
+
+ static QRhi *create(Implementation impl,
+ QRhiInitParams *params,
+ Flags flags = {},
+ QRhiNativeHandles *importDevice = nullptr);
+ static bool probe(Implementation impl, QRhiInitParams *params);
+
+ Implementation backend() const;
+ const char *backendName() const;
+ static const char *backendName(Implementation impl);
+ QRhiDriverInfo driverInfo() const;
+ QThread *thread() const;
+
+ using CleanupCallback = std::function<void(QRhi *)>;
+ void addCleanupCallback(const CleanupCallback &callback);
+ void addCleanupCallback(const void *key, const CleanupCallback &callback);
+ void removeCleanupCallback(const void *key);
+ void runCleanup();
+
+ QRhiGraphicsPipeline *newGraphicsPipeline();
+ QRhiComputePipeline *newComputePipeline();
+ QRhiShaderResourceBindings *newShaderResourceBindings();
+
+ QRhiBuffer *newBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ quint32 size);
+
+ QRhiRenderBuffer *newRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount = 1,
+ QRhiRenderBuffer::Flags flags = {},
+ QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat);
+
+ QRhiTexture *newTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int sampleCount = 1,
+ QRhiTexture::Flags flags = {});
+
+ QRhiTexture *newTexture(QRhiTexture::Format format,
+ int width, int height, int depth,
+ int sampleCount = 1,
+ QRhiTexture::Flags flags = {});
+
+ QRhiTexture *newTextureArray(QRhiTexture::Format format,
+ int arraySize,
+ const QSize &pixelSize,
+ int sampleCount = 1,
+ QRhiTexture::Flags flags = {});
+
+ QRhiSampler *newSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler::AddressMode addressU,
+ QRhiSampler::AddressMode addressV,
+ QRhiSampler::AddressMode addressW = QRhiSampler::Repeat);
+
+ QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags = {});
+
+ QRhiSwapChain *newSwapChain();
+ FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags = {});
+ FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags = {});
+ bool isRecordingFrame() const;
+ int currentFrameSlot() const;
+
+ FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags = {});
+ FrameOpResult endOffscreenFrame(EndFrameFlags flags = {});
+
+ QRhi::FrameOpResult finish();
+
+ QRhiResourceUpdateBatch *nextResourceUpdateBatch();
+
+ QList<int> supportedSampleCounts() const;
+
+ int ubufAlignment() const;
+ int ubufAligned(int v) const;
+
+ static int mipLevelsForSize(const QSize &size);
+ static QSize sizeForMipLevel(int mipLevel, const QSize &baseLevelSize);
+
+ bool isYUpInFramebuffer() const;
+ bool isYUpInNDC() const;
+ bool isClipDepthZeroToOne() const;
+
+ QMatrix4x4 clipSpaceCorrMatrix() const;
+
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = {}) const;
+ bool isFeatureSupported(QRhi::Feature feature) const;
+ int resourceLimit(ResourceLimit limit) const;
+
+ const QRhiNativeHandles *nativeHandles();
+ bool makeThreadLocalNativeContextCurrent();
+
+ static constexpr int MAX_MIP_LEVELS = 16; // -> max width or height is 65536
+
+ void releaseCachedResources();
+
+ bool isDeviceLost() const;
+
+ QByteArray pipelineCacheData();
+ void setPipelineCacheData(const QByteArray &data);
+
+ QRhiStats statistics() const;
+
+ static QRhiSwapChainProxyData updateSwapChainProxyData(Implementation impl, QWindow *window);
+
+protected:
+ QRhi();
+
+private:
+ Q_DISABLE_COPY(QRhi)
+ QRhiImplementation *d = nullptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::Flags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::BeginFrameFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::EndFrameFlags)
+
+QT_END_NAMESPACE
+
+#include <rhi/qrhi_platform.h>
+
+#endif
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index c2a09b7edf..b5429372a8 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHI_H
-#define QRHI_H
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHI_P_H
+#define QRHI_P_H
//
// W A R N I N G
@@ -51,1633 +15,803 @@
// We mean it.
//
-#include <QtGui/qtguiglobal.h>
-#include <QSize>
-#include <QMatrix4x4>
-#include <QList>
-#include <QVarLengthArray>
-#include <QThread>
-#include <QColor>
-#include <QImage>
-#include <functional>
-#include <array>
-#include <private/qshader_p.h>
+#include <rhi/qrhi.h>
+#include <QBitArray>
+#include <QAtomicInt>
+#include <QElapsedTimer>
+#include <QLoggingCategory>
+#include <QtCore/qset.h>
+#include <QtCore/qvarlengtharray.h>
QT_BEGIN_NAMESPACE
-class QWindow;
-class QRhiImplementation;
-class QRhiBuffer;
-class QRhiRenderBuffer;
-class QRhiTexture;
-class QRhiSampler;
-class QRhiCommandBuffer;
-class QRhiResourceUpdateBatch;
-class QRhiResourceUpdateBatchPrivate;
-class QRhiProfiler;
-
-class Q_GUI_EXPORT QRhiDepthStencilClearValue
-{
-public:
- QRhiDepthStencilClearValue() = default;
- QRhiDepthStencilClearValue(float d, quint32 s);
-
- float depthClearValue() const { return m_d; }
- void setDepthClearValue(float d) { m_d = d; }
-
- quint32 stencilClearValue() const { return m_s; }
- void setStencilClearValue(quint32 s) { m_s = s; }
-
-private:
- float m_d = 1.0f;
- quint32 m_s = 0;
-};
-
-Q_DECLARE_TYPEINFO(QRhiDepthStencilClearValue, Q_RELOCATABLE_TYPE);
+#define QRHI_RES(t, x) static_cast<t *>(x)
+#define QRHI_RES_RHI(t) t *rhiD = static_cast<t *>(m_rhi)
-Q_GUI_EXPORT bool operator==(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept;
-Q_GUI_EXPORT bool operator!=(const QRhiDepthStencilClearValue &a, const QRhiDepthStencilClearValue &b) noexcept;
-Q_GUI_EXPORT size_t qHash(const QRhiDepthStencilClearValue &v, size_t seed = 0) noexcept;
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiDepthStencilClearValue &);
-#endif
+Q_DECLARE_LOGGING_CATEGORY(QRHI_LOG_INFO)
-class Q_GUI_EXPORT QRhiViewport
+class QRhiImplementation
{
public:
- QRhiViewport() = default;
- QRhiViewport(float x, float y, float w, float h, float minDepth = 0.0f, float maxDepth = 1.0f);
-
- std::array<float, 4> viewport() const { return m_rect; }
- void setViewport(float x, float y, float w, float h) {
- m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h;
- }
-
- float minDepth() const { return m_minDepth; }
- void setMinDepth(float minDepth) { m_minDepth = minDepth; }
-
- float maxDepth() const { return m_maxDepth; }
- void setMaxDepth(float maxDepth) { m_maxDepth = maxDepth; }
+ virtual ~QRhiImplementation();
-private:
- std::array<float, 4> m_rect { { 0.0f, 0.0f, 0.0f, 0.0f } };
- float m_minDepth = 0.0f;
- float m_maxDepth = 1.0f;
-};
-
-Q_DECLARE_TYPEINFO(QRhiViewport, Q_RELOCATABLE_TYPE);
-
-Q_GUI_EXPORT bool operator==(const QRhiViewport &a, const QRhiViewport &b) noexcept;
-Q_GUI_EXPORT bool operator!=(const QRhiViewport &a, const QRhiViewport &b) noexcept;
-Q_GUI_EXPORT size_t qHash(const QRhiViewport &v, size_t seed = 0) noexcept;
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiViewport &);
-#endif
-
-class Q_GUI_EXPORT QRhiScissor
-{
-public:
- QRhiScissor() = default;
- QRhiScissor(int x, int y, int w, int h);
+ virtual bool create(QRhi::Flags flags) = 0;
+ virtual void destroy() = 0;
- std::array<int, 4> scissor() const { return m_rect; }
- void setScissor(int x, int y, int w, int h) {
- m_rect[0] = x; m_rect[1] = y; m_rect[2] = w; m_rect[3] = h;
+ virtual QRhiGraphicsPipeline *createGraphicsPipeline() = 0;
+ virtual QRhiComputePipeline *createComputePipeline() = 0;
+ virtual QRhiShaderResourceBindings *createShaderResourceBindings() = 0;
+ virtual QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ quint32 size) = 0;
+ virtual QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint) = 0;
+ virtual QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int depth,
+ int arraySize,
+ int sampleCount,
+ QRhiTexture::Flags flags) = 0;
+ virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) = 0;
+
+ virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) = 0;
+
+ virtual QRhiSwapChain *createSwapChain() = 0;
+ virtual QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) = 0;
+ virtual QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) = 0;
+ virtual QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) = 0;
+ virtual QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) = 0;
+ virtual QRhi::FrameOpResult finish() = 0;
+
+ virtual void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
+
+ virtual void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) = 0;
+ virtual void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
+
+ virtual void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) = 0;
+
+ virtual void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) = 0;
+
+ virtual void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) = 0;
+
+ virtual void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) = 0;
+ virtual void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) = 0;
+ virtual void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) = 0;
+ virtual void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) = 0;
+
+ virtual void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) = 0;
+ virtual void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) = 0;
+
+ virtual void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) = 0;
+ virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0;
+ virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0;
+
+ virtual void beginComputePass(QRhiCommandBuffer *cb,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) = 0;
+ virtual void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
+ virtual void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) = 0;
+ virtual void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) = 0;
+
+ virtual const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) = 0;
+ virtual void beginExternal(QRhiCommandBuffer *cb) = 0;
+ virtual void endExternal(QRhiCommandBuffer *cb) = 0;
+ virtual double lastCompletedGpuTime(QRhiCommandBuffer *cb) = 0;
+
+ virtual QList<int> supportedSampleCounts() const = 0;
+ virtual int ubufAlignment() const = 0;
+ virtual bool isYUpInFramebuffer() const = 0;
+ virtual bool isYUpInNDC() const = 0;
+ virtual bool isClipDepthZeroToOne() const = 0;
+ virtual QMatrix4x4 clipSpaceCorrMatrix() const = 0;
+ virtual bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const = 0;
+ virtual bool isFeatureSupported(QRhi::Feature feature) const = 0;
+ virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
+ virtual const QRhiNativeHandles *nativeHandles() = 0;
+ virtual QRhiDriverInfo driverInfo() const = 0;
+ virtual QRhiStats statistics() = 0;
+ virtual bool makeThreadLocalNativeContextCurrent() = 0;
+ virtual void releaseCachedResources() = 0;
+ virtual bool isDeviceLost() const = 0;
+
+ virtual QByteArray pipelineCacheData() = 0;
+ virtual void setPipelineCacheData(const QByteArray &data) = 0;
+
+ void prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags);
+
+ bool isCompressedFormat(QRhiTexture::Format format) const;
+ void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
+ quint32 *bpl, quint32 *byteSize,
+ QSize *blockDim) const;
+ void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
+ quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const;
+ bool isStencilSupportingFormat(QRhiTexture::Format format) const;
+
+ void registerResource(QRhiResource *res, bool ownsNativeResources = true)
+ {
+ // The ownsNativeResources is relevant for the (graphics resource) leak
+ // check in ~QRhiImplementation; when false, the registration's sole
+ // purpose is to automatically null out the resource's m_rhi pointer in
+ // case the rhi goes away first. (which should not happen in
+ // well-written applications but we try to be graceful)
+ resources.insert(res, ownsNativeResources);
}
-private:
- std::array<int, 4> m_rect { { 0, 0, 0, 0 } };
-};
-
-Q_DECLARE_TYPEINFO(QRhiScissor, Q_RELOCATABLE_TYPE);
-
-Q_GUI_EXPORT bool operator==(const QRhiScissor &a, const QRhiScissor &b) noexcept;
-Q_GUI_EXPORT bool operator!=(const QRhiScissor &a, const QRhiScissor &b) noexcept;
-Q_GUI_EXPORT size_t qHash(const QRhiScissor &v, size_t seed = 0) noexcept;
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiScissor &);
-#endif
-
-class Q_GUI_EXPORT QRhiVertexInputBinding
-{
-public:
- enum Classification {
- PerVertex,
- PerInstance
- };
-
- QRhiVertexInputBinding() = default;
- QRhiVertexInputBinding(quint32 stride, Classification cls = PerVertex, int stepRate = 1);
-
- quint32 stride() const { return m_stride; }
- void setStride(quint32 s) { m_stride = s; }
-
- Classification classification() const { return m_classification; }
- void setClassification(Classification c) { m_classification = c; }
-
- int instanceStepRate() const { return m_instanceStepRate; }
- void setInstanceStepRate(int rate) { m_instanceStepRate = rate; }
-
-private:
- quint32 m_stride = 0;
- Classification m_classification = PerVertex;
- int m_instanceStepRate = 1;
-};
-
-Q_DECLARE_TYPEINFO(QRhiVertexInputBinding, Q_RELOCATABLE_TYPE);
-
-Q_GUI_EXPORT bool operator==(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept;
-Q_GUI_EXPORT bool operator!=(const QRhiVertexInputBinding &a, const QRhiVertexInputBinding &b) noexcept;
-Q_GUI_EXPORT size_t qHash(const QRhiVertexInputBinding &v, size_t seed = 0) noexcept;
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputBinding &);
-#endif
-
-class Q_GUI_EXPORT QRhiVertexInputAttribute
-{
-public:
- enum Format {
- Float4,
- Float3,
- Float2,
- Float,
- UNormByte4,
- UNormByte2,
- UNormByte,
- UInt4,
- UInt3,
- UInt2,
- UInt,
- SInt4,
- SInt3,
- SInt2,
- SInt
- };
-
- QRhiVertexInputAttribute() = default;
- QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice = -1);
-
- int binding() const { return m_binding; }
- void setBinding(int b) { m_binding = b; }
-
- int location() const { return m_location; }
- void setLocation(int loc) { m_location = loc; }
-
- Format format() const { return m_format; }
- void setFormat(Format f) { m_format = f; }
-
- quint32 offset() const { return m_offset; }
- void setOffset(quint32 ofs) { m_offset = ofs; }
-
- int matrixSlice() const { return m_matrixSlice; }
- void setMatrixSlice(int slice) { m_matrixSlice = slice; }
-
-private:
- int m_binding = 0;
- int m_location = 0;
- Format m_format = Float4;
- quint32 m_offset = 0;
- int m_matrixSlice = -1;
-};
-
-Q_DECLARE_TYPEINFO(QRhiVertexInputAttribute, Q_RELOCATABLE_TYPE);
-
-Q_GUI_EXPORT bool operator==(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept;
-Q_GUI_EXPORT bool operator!=(const QRhiVertexInputAttribute &a, const QRhiVertexInputAttribute &b) noexcept;
-Q_GUI_EXPORT size_t qHash(const QRhiVertexInputAttribute &v, size_t seed = 0) noexcept;
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputAttribute &);
-#endif
-
-class Q_GUI_EXPORT QRhiVertexInputLayout
-{
-public:
- QRhiVertexInputLayout() = default;
-
- void setBindings(std::initializer_list<QRhiVertexInputBinding> list) { m_bindings = list; }
- template<typename InputIterator>
- void setBindings(InputIterator first, InputIterator last)
+ void unregisterResource(QRhiResource *res)
{
- m_bindings.clear();
- std::copy(first, last, std::back_inserter(m_bindings));
+ resources.remove(res);
}
- const QRhiVertexInputBinding *cbeginBindings() const { return m_bindings.cbegin(); }
- const QRhiVertexInputBinding *cendBindings() const { return m_bindings.cend(); }
- const QRhiVertexInputBinding *bindingAt(int index) const { return &m_bindings.at(index); }
- void setAttributes(std::initializer_list<QRhiVertexInputAttribute> list) { m_attributes = list; }
- template<typename InputIterator>
- void setAttributes(InputIterator first, InputIterator last)
+ void addDeleteLater(QRhiResource *res)
{
- m_attributes.clear();
- std::copy(first, last, std::back_inserter(m_attributes));
+ if (inFrame)
+ pendingDeleteResources.insert(res);
+ else
+ delete res;
}
- const QRhiVertexInputAttribute *cbeginAttributes() const { return m_attributes.cbegin(); }
- const QRhiVertexInputAttribute *cendAttributes() const { return m_attributes.cend(); }
-
-private:
- QVarLengthArray<QRhiVertexInputBinding, 8> m_bindings;
- QVarLengthArray<QRhiVertexInputAttribute, 8> m_attributes;
-
- friend Q_GUI_EXPORT bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept;
- friend Q_GUI_EXPORT size_t qHash(const QRhiVertexInputLayout &v, size_t seed) noexcept;
- friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &);
-};
-
-Q_DECLARE_TYPEINFO(QRhiVertexInputLayout, Q_RELOCATABLE_TYPE);
-
-Q_GUI_EXPORT bool operator==(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept;
-Q_GUI_EXPORT bool operator!=(const QRhiVertexInputLayout &a, const QRhiVertexInputLayout &b) noexcept;
-Q_GUI_EXPORT size_t qHash(const QRhiVertexInputLayout &v, size_t seed = 0) noexcept;
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiVertexInputLayout &);
-#endif
-
-class Q_GUI_EXPORT QRhiShaderStage
-{
-public:
- enum Type {
- Vertex,
- Fragment,
- Compute
- };
-
- QRhiShaderStage() = default;
- QRhiShaderStage(Type type, const QShader &shader,
- QShader::Variant v = QShader::StandardShader);
-
- Type type() const { return m_type; }
- void setType(Type t) { m_type = t; }
-
- QShader shader() const { return m_shader; }
- void setShader(const QShader &s) { m_shader = s; }
-
- QShader::Variant shaderVariant() const { return m_shaderVariant; }
- void setShaderVariant(QShader::Variant v) { m_shaderVariant = v; }
-
-private:
- Type m_type = Vertex;
- QShader m_shader;
- QShader::Variant m_shaderVariant = QShader::StandardShader;
-};
-Q_DECLARE_TYPEINFO(QRhiShaderStage, Q_RELOCATABLE_TYPE);
-
-Q_GUI_EXPORT bool operator==(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept;
-Q_GUI_EXPORT bool operator!=(const QRhiShaderStage &a, const QRhiShaderStage &b) noexcept;
-Q_GUI_EXPORT size_t qHash(const QRhiShaderStage &s, size_t seed = 0) noexcept;
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderStage &);
-#endif
-
-using QRhiGraphicsShaderStage = QRhiShaderStage;
-
-class Q_GUI_EXPORT QRhiShaderResourceBinding
-{
-public:
- enum Type {
- UniformBuffer,
- SampledTexture,
- ImageLoad,
- ImageStore,
- ImageLoadStore,
- BufferLoad,
- BufferStore,
- BufferLoadStore
- };
-
- enum StageFlag {
- VertexStage = 1 << 0,
- FragmentStage = 1 << 1,
- ComputeStage = 1 << 2
- };
- Q_DECLARE_FLAGS(StageFlags, StageFlag)
-
- QRhiShaderResourceBinding() = default;
-
- bool isLayoutCompatible(const QRhiShaderResourceBinding &other) const;
-
- static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf);
- static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size);
- static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, int size);
-
- static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler);
-
- struct TextureAndSampler {
- QRhiTexture *tex;
- QRhiSampler *sampler;
- };
- static QRhiShaderResourceBinding sampledTextures(int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers);
-
- static QRhiShaderResourceBinding imageLoad(int binding, StageFlags stage, QRhiTexture *tex, int level);
- static QRhiShaderResourceBinding imageStore(int binding, StageFlags stage, QRhiTexture *tex, int level);
- static QRhiShaderResourceBinding imageLoadStore(int binding, StageFlags stage, QRhiTexture *tex, int level);
-
- static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf);
- static QRhiShaderResourceBinding bufferLoad(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size);
- static QRhiShaderResourceBinding bufferStore(int binding, StageFlags stage, QRhiBuffer *buf);
- static QRhiShaderResourceBinding bufferStore(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size);
- static QRhiShaderResourceBinding bufferLoadStore(int binding, StageFlags stage, QRhiBuffer *buf);
- static QRhiShaderResourceBinding bufferLoadStore(int binding, StageFlags stage, QRhiBuffer *buf, int offset, int size);
-
- struct Data
+ void addCleanupCallback(const QRhi::CleanupCallback &callback)
{
- int binding;
- QRhiShaderResourceBinding::StageFlags stage;
- QRhiShaderResourceBinding::Type type;
- struct UniformBufferData {
- QRhiBuffer *buf;
- int offset;
- int maybeSize;
- bool hasDynamicOffset;
- };
- static const int MAX_TEX_SAMPLER_ARRAY_SIZE = 16;
- struct SampledTextureData {
- int count;
- TextureAndSampler texSamplers[MAX_TEX_SAMPLER_ARRAY_SIZE];
- };
- struct StorageImageData {
- QRhiTexture *tex;
- int level;
- };
- struct StorageBufferData {
- QRhiBuffer *buf;
- int offset;
- int maybeSize;
- };
- union {
- UniformBufferData ubuf;
- SampledTextureData stex;
- StorageImageData simage;
- StorageBufferData sbuf;
- } u;
- };
-
- Data *data() { return &d; }
- const Data *data() const { return &d; }
-
-private:
- Data d;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiShaderResourceBinding::StageFlags)
-
-Q_DECLARE_TYPEINFO(QRhiShaderResourceBinding, Q_PRIMITIVE_TYPE);
-
-Q_GUI_EXPORT bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept;
-Q_GUI_EXPORT bool operator!=(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b) noexcept;
-Q_GUI_EXPORT size_t qHash(const QRhiShaderResourceBinding &b, size_t seed = 0) noexcept;
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBinding &);
-#endif
-
-class Q_GUI_EXPORT QRhiColorAttachment
-{
-public:
- QRhiColorAttachment() = default;
- QRhiColorAttachment(QRhiTexture *texture);
- QRhiColorAttachment(QRhiRenderBuffer *renderBuffer);
-
- QRhiTexture *texture() const { return m_texture; }
- void setTexture(QRhiTexture *tex) { m_texture = tex; }
-
- QRhiRenderBuffer *renderBuffer() const { return m_renderBuffer; }
- void setRenderBuffer(QRhiRenderBuffer *rb) { m_renderBuffer = rb; }
-
- int layer() const { return m_layer; }
- void setLayer(int layer) { m_layer = layer; }
-
- int level() const { return m_level; }
- void setLevel(int level) { m_level = level; }
-
- QRhiTexture *resolveTexture() const { return m_resolveTexture; }
- void setResolveTexture(QRhiTexture *tex) { m_resolveTexture = tex; }
-
- int resolveLayer() const { return m_resolveLayer; }
- void setResolveLayer(int layer) { m_resolveLayer = layer; }
-
- int resolveLevel() const { return m_resolveLevel; }
- void setResolveLevel(int level) { m_resolveLevel = level; }
-
-private:
- QRhiTexture *m_texture = nullptr;
- QRhiRenderBuffer *m_renderBuffer = nullptr;
- int m_layer = 0;
- int m_level = 0;
- QRhiTexture *m_resolveTexture = nullptr;
- int m_resolveLayer = 0;
- int m_resolveLevel = 0;
-};
-
-Q_DECLARE_TYPEINFO(QRhiColorAttachment, Q_RELOCATABLE_TYPE);
+ cleanupCallbacks.append(callback);
+ }
-class Q_GUI_EXPORT QRhiTextureRenderTargetDescription
-{
-public:
- QRhiTextureRenderTargetDescription() = default;
- QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment);
- QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiRenderBuffer *depthStencilBuffer);
- QRhiTextureRenderTargetDescription(const QRhiColorAttachment &colorAttachment, QRhiTexture *depthTexture);
-
- void setColorAttachments(std::initializer_list<QRhiColorAttachment> list) { m_colorAttachments = list; }
- template<typename InputIterator>
- void setColorAttachments(InputIterator first, InputIterator last)
+ void addCleanupCallback(const void *key, const QRhi::CleanupCallback &callback)
{
- m_colorAttachments.clear();
- std::copy(first, last, std::back_inserter(m_colorAttachments));
+ keyedCleanupCallbacks[key] = callback;
}
- const QRhiColorAttachment *cbeginColorAttachments() const { return m_colorAttachments.cbegin(); }
- const QRhiColorAttachment *cendColorAttachments() const { return m_colorAttachments.cend(); }
- const QRhiColorAttachment *colorAttachmentAt(int index) const { return &m_colorAttachments.at(index); }
-
- QRhiRenderBuffer *depthStencilBuffer() const { return m_depthStencilBuffer; }
- void setDepthStencilBuffer(QRhiRenderBuffer *renderBuffer) { m_depthStencilBuffer = renderBuffer; }
-
- QRhiTexture *depthTexture() const { return m_depthTexture; }
- void setDepthTexture(QRhiTexture *texture) { m_depthTexture = texture; }
-
-private:
- QVarLengthArray<QRhiColorAttachment, 8> m_colorAttachments;
- QRhiRenderBuffer *m_depthStencilBuffer = nullptr;
- QRhiTexture *m_depthTexture = nullptr;
-};
-
-Q_DECLARE_TYPEINFO(QRhiTextureRenderTargetDescription, Q_RELOCATABLE_TYPE);
-class Q_GUI_EXPORT QRhiTextureSubresourceUploadDescription
-{
-public:
- QRhiTextureSubresourceUploadDescription() = default;
- explicit QRhiTextureSubresourceUploadDescription(const QImage &image);
- QRhiTextureSubresourceUploadDescription(const void *data, int size);
- explicit QRhiTextureSubresourceUploadDescription(const QByteArray &data);
-
- QImage image() const { return m_image; }
- void setImage(const QImage &image) { m_image = image; }
-
- QByteArray data() const { return m_data; }
- void setData(const QByteArray &data) { m_data = data; }
-
- quint32 dataStride() const { return m_dataStride; }
- void setDataStride(quint32 stride) { m_dataStride = stride; }
-
- QPoint destinationTopLeft() const { return m_destinationTopLeft; }
- void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
-
- QSize sourceSize() const { return m_sourceSize; }
- void setSourceSize(const QSize &size) { m_sourceSize = size; }
-
- QPoint sourceTopLeft() const { return m_sourceTopLeft; }
- void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
-
-private:
- QImage m_image;
- QByteArray m_data;
- quint32 m_dataStride = 0;
- QPoint m_destinationTopLeft;
- QSize m_sourceSize;
- QPoint m_sourceTopLeft;
-};
-
-Q_DECLARE_TYPEINFO(QRhiTextureSubresourceUploadDescription, Q_RELOCATABLE_TYPE);
-
-class Q_GUI_EXPORT QRhiTextureUploadEntry
-{
-public:
- QRhiTextureUploadEntry() = default;
- QRhiTextureUploadEntry(int layer, int level, const QRhiTextureSubresourceUploadDescription &desc);
-
- int layer() const { return m_layer; }
- void setLayer(int layer) { m_layer = layer; }
-
- int level() const { return m_level; }
- void setLevel(int level) { m_level = level; }
-
- QRhiTextureSubresourceUploadDescription description() const { return m_desc; }
- void setDescription(const QRhiTextureSubresourceUploadDescription &desc) { m_desc = desc; }
-
-private:
- int m_layer = 0;
- int m_level = 0;
- QRhiTextureSubresourceUploadDescription m_desc;
-};
+ void removeCleanupCallback(const void *key)
+ {
+ keyedCleanupCallbacks.remove(key);
+ }
-Q_DECLARE_TYPEINFO(QRhiTextureUploadEntry, Q_RELOCATABLE_TYPE);
+ bool sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps);
+ bool sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb);
+ void updateLayoutDesc(QRhiShaderResourceBindings *srb);
-class Q_GUI_EXPORT QRhiTextureUploadDescription
-{
-public:
- QRhiTextureUploadDescription() = default;
- QRhiTextureUploadDescription(const QRhiTextureUploadEntry &entry);
- QRhiTextureUploadDescription(std::initializer_list<QRhiTextureUploadEntry> list);
+ quint32 pipelineCacheRhiId() const
+ {
+ const quint32 ver = (QT_VERSION_MAJOR << 16) | (QT_VERSION_MINOR << 8) | (QT_VERSION_PATCH);
+ return (quint32(implType) << 24) | ver;
+ }
- void setEntries(std::initializer_list<QRhiTextureUploadEntry> list) { m_entries = list; }
- template<typename InputIterator>
- void setEntries(InputIterator first, InputIterator last)
+ void pipelineCreationStart()
{
- m_entries.clear();
- std::copy(first, last, std::back_inserter(m_entries));
+ pipelineCreationTimer.start();
}
- const QRhiTextureUploadEntry *cbeginEntries() const { return m_entries.cbegin(); }
- const QRhiTextureUploadEntry *cendEntries() const { return m_entries.cend(); }
-private:
- QVarLengthArray<QRhiTextureUploadEntry, 16> m_entries;
-};
+ void pipelineCreationEnd()
+ {
+ accumulatedPipelineCreationTime += pipelineCreationTimer.elapsed();
+ }
-Q_DECLARE_TYPEINFO(QRhiTextureUploadDescription, Q_RELOCATABLE_TYPE);
+ qint64 totalPipelineCreationTime() const
+ {
+ return accumulatedPipelineCreationTime;
+ }
-class Q_GUI_EXPORT QRhiTextureCopyDescription
-{
-public:
- QRhiTextureCopyDescription() = default;
+ QRhiVertexInputAttribute::Format shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const;
+ quint32 byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const;
- QSize pixelSize() const { return m_pixelSize; }
- void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
+ static const QRhiShaderResourceBinding::Data *shaderResourceBindingData(const QRhiShaderResourceBinding &binding)
+ {
+ return &binding.d;
+ }
- int sourceLayer() const { return m_sourceLayer; }
- void setSourceLayer(int layer) { m_sourceLayer = layer; }
+ static QRhiShaderResourceBinding::Data *shaderResourceBindingData(QRhiShaderResourceBinding &binding)
+ {
+ return &binding.d;
+ }
- int sourceLevel() const { return m_sourceLevel; }
- void setSourceLevel(int level) { m_sourceLevel = level; }
+ static bool sortedBindingLessThan(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
+ {
+ return a.d.binding < b.d.binding;
+ }
- QPoint sourceTopLeft() const { return m_sourceTopLeft; }
- void setSourceTopLeft(const QPoint &p) { m_sourceTopLeft = p; }
+ int effectiveSampleCount(int sampleCount) const;
- int destinationLayer() const { return m_destinationLayer; }
- void setDestinationLayer(int layer) { m_destinationLayer = layer; }
+ QRhi *q;
- int destinationLevel() const { return m_destinationLevel; }
- void setDestinationLevel(int level) { m_destinationLevel = level; }
+ static const int MAX_SHADER_CACHE_ENTRIES = 128;
- QPoint destinationTopLeft() const { return m_destinationTopLeft; }
- void setDestinationTopLeft(const QPoint &p) { m_destinationTopLeft = p; }
+ bool debugMarkers = false;
+ int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
+ bool inFrame = false;
private:
- QSize m_pixelSize;
- int m_sourceLayer = 0;
- int m_sourceLevel = 0;
- QPoint m_sourceTopLeft;
- int m_destinationLayer = 0;
- int m_destinationLevel = 0;
- QPoint m_destinationTopLeft;
-};
-
-Q_DECLARE_TYPEINFO(QRhiTextureCopyDescription, Q_RELOCATABLE_TYPE);
-
-class Q_GUI_EXPORT QRhiReadbackDescription
-{
-public:
- QRhiReadbackDescription() = default;
- QRhiReadbackDescription(QRhiTexture *texture);
-
- QRhiTexture *texture() const { return m_texture; }
- void setTexture(QRhiTexture *tex) { m_texture = tex; }
-
- int layer() const { return m_layer; }
- void setLayer(int layer) { m_layer = layer; }
+ QRhi::Implementation implType;
+ QThread *implThread;
+ QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
+ quint64 resUpdPoolMap = 0;
+ int lastResUpdIdx = -1;
+ QHash<QRhiResource *, bool> resources;
+ QSet<QRhiResource *> pendingDeleteResources;
+ QVarLengthArray<QRhi::CleanupCallback, 4> cleanupCallbacks;
+ QHash<const void *, QRhi::CleanupCallback> keyedCleanupCallbacks;
+ QElapsedTimer pipelineCreationTimer;
+ qint64 accumulatedPipelineCreationTime = 0;
- int level() const { return m_level; }
- void setLevel(int level) { m_level = level; }
-
-private:
- QRhiTexture *m_texture = nullptr;
- int m_layer = 0;
- int m_level = 0;
+ friend class QRhi;
+ friend class QRhiResourceUpdateBatchPrivate;
};
-Q_DECLARE_TYPEINFO(QRhiReadbackDescription, Q_RELOCATABLE_TYPE);
-
-struct Q_GUI_EXPORT QRhiNativeHandles
+enum QRhiTargetRectBoundMode
{
+ UnBounded,
+ Bounded
};
-class Q_GUI_EXPORT QRhiResource
+template<QRhiTargetRectBoundMode boundingMode, typename T, size_t N>
+bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, N> &r,
+ T *x, T *y, T *w, T *h)
{
-public:
- enum Type {
- Buffer,
- Texture,
- Sampler,
- RenderBuffer,
- RenderPassDescriptor,
- RenderTarget,
- TextureRenderTarget,
- ShaderResourceBindings,
- GraphicsPipeline,
- SwapChain,
- ComputePipeline,
- CommandBuffer
- };
-
- virtual ~QRhiResource();
+ // x,y are bottom-left in QRhiScissor and QRhiViewport but top-left in
+ // Vulkan/Metal/D3D. Our input is an OpenGL-style scissor rect where both
+ // negative x or y, and partly or completely out of bounds rects are
+ // allowed. The only thing the input here cannot have is a negative width
+ // or height. We must handle all other input gracefully, clamping to a zero
+ // width or height rect in the worst case, and ensuring the resulting rect
+ // is inside the rendertarget's bounds because some APIs' validation/debug
+ // layers are allergic to out of bounds scissor rects.
- virtual Type resourceType() const = 0;
+ const T outputWidth = outputSize.width();
+ const T outputHeight = outputSize.height();
+ const T inputWidth = r[2];
+ const T inputHeight = r[3];
- virtual void destroy() = 0;
+ if (inputWidth < 0 || inputHeight < 0)
+ return false;
- void deleteLater();
+ *x = r[0];
+ *y = outputHeight - (r[1] + inputHeight);
+ *w = inputWidth;
+ *h = inputHeight;
- QByteArray name() const;
- void setName(const QByteArray &name);
+ if (boundingMode == Bounded) {
+ const T widthOffset = *x < 0 ? -*x : 0;
+ const T heightOffset = *y < 0 ? -*y : 0;
+ *w = *x < outputWidth ? qMax<T>(0, inputWidth - widthOffset) : 0;
+ *h = *y < outputHeight ? qMax<T>(0, inputHeight - heightOffset) : 0;
- quint64 globalResourceId() const;
+ if (outputWidth > 0)
+ *x = qBound<T>(0, *x, outputWidth - 1);
+ if (outputHeight > 0)
+ *y = qBound<T>(0, *y, outputHeight - 1);
-protected:
- QRhiResource(QRhiImplementation *rhi);
- Q_DISABLE_COPY(QRhiResource)
- friend class QRhiImplementation;
- QRhiImplementation *m_rhi = nullptr;
- quint64 m_id;
- QByteArray m_objectName;
-};
+ if (*x + *w > outputWidth)
+ *w = qMax<T>(0, outputWidth - *x);
+ if (*y + *h > outputHeight)
+ *h = qMax<T>(0, outputHeight - *y);
+ }
+ return true;
+}
-class Q_GUI_EXPORT QRhiBuffer : public QRhiResource
+struct QRhiBufferDataPrivate
{
-public:
- enum Type {
- Immutable,
- Static,
- Dynamic
- };
-
- enum UsageFlag {
- VertexBuffer = 1 << 0,
- IndexBuffer = 1 << 1,
- UniformBuffer = 1 << 2,
- StorageBuffer = 1 << 3
- };
- Q_DECLARE_FLAGS(UsageFlags, UsageFlag)
-
- struct NativeBuffer {
- const void *objects[3];
- int slotCount;
- };
-
- QRhiResource::Type resourceType() const override;
-
- Type type() const { return m_type; }
- void setType(Type t) { m_type = t; }
-
- UsageFlags usage() const { return m_usage; }
- void setUsage(UsageFlags u) { m_usage = u; }
-
- int size() const { return m_size; }
- void setSize(int sz) { m_size = sz; }
-
- virtual bool create() = 0;
-
- virtual NativeBuffer nativeBuffer();
-
- virtual char *beginFullDynamicBufferUpdateForCurrentFrame();
- virtual void endFullDynamicBufferUpdateForCurrentFrame();
-
-protected:
- QRhiBuffer(QRhiImplementation *rhi, Type type_, UsageFlags usage_, int size_);
- Type m_type;
- UsageFlags m_usage;
- int m_size;
+ Q_DISABLE_COPY_MOVE(QRhiBufferDataPrivate)
+ QRhiBufferDataPrivate() { }
+ ~QRhiBufferDataPrivate() { delete[] largeData; }
+ int ref = 1;
+ quint32 size = 0;
+ quint32 largeAlloc = 0;
+ char *largeData = nullptr;
+ static constexpr quint32 SMALL_DATA_SIZE = 1024;
+ char data[SMALL_DATA_SIZE];
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiBuffer::UsageFlags)
-
-class Q_GUI_EXPORT QRhiTexture : public QRhiResource
+// no detach-with-contents, no atomic refcount, no shrink
+class QRhiBufferData
{
public:
- enum Flag {
- RenderTarget = 1 << 0,
- CubeMap = 1 << 2,
- MipMapped = 1 << 3,
- sRGB = 1 << 4,
- UsedAsTransferSource = 1 << 5,
- UsedWithGenerateMips = 1 << 6,
- UsedWithLoadStore = 1 << 7,
- UsedAsCompressedAtlas = 1 << 8,
- ExternalOES = 1 << 9,
- ThreeDimensional = 1 << 10
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- enum Format {
- UnknownFormat,
-
- RGBA8,
- BGRA8,
- R8,
- RG8,
- R16,
- RG16,
- RED_OR_ALPHA8,
-
- RGBA16F,
- RGBA32F,
- R16F,
- R32F,
-
- D16,
- D24,
- D24S8,
- D32F,
-
- BC1,
- BC2,
- BC3,
- BC4,
- BC5,
- BC6H,
- BC7,
-
- ETC2_RGB8,
- ETC2_RGB8A1,
- ETC2_RGBA8,
-
- ASTC_4x4,
- ASTC_5x4,
- ASTC_5x5,
- ASTC_6x5,
- ASTC_6x6,
- ASTC_8x5,
- ASTC_8x6,
- ASTC_8x8,
- ASTC_10x5,
- ASTC_10x6,
- ASTC_10x8,
- ASTC_10x10,
- ASTC_12x10,
- ASTC_12x12
- };
-
- struct NativeTexture {
- quint64 object;
- int layout;
- };
-
- QRhiResource::Type resourceType() const override;
-
- Format format() const { return m_format; }
- void setFormat(Format fmt) { m_format = fmt; }
-
- QSize pixelSize() const { return m_pixelSize; }
- void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
-
- int depth() const { return m_depth; }
- void setDepth(int depth) { m_depth = depth; }
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
- int sampleCount() const { return m_sampleCount; }
- void setSampleCount(int s) { m_sampleCount = s; }
-
- virtual bool create() = 0;
- virtual NativeTexture nativeTexture();
- virtual bool createFrom(NativeTexture src);
- virtual void setNativeLayout(int layout);
-
-protected:
- QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, int depth_,
- int sampleCount_, Flags flags_);
- Format m_format;
- QSize m_pixelSize;
- int m_depth;
- int m_sampleCount;
- Flags m_flags;
+ QRhiBufferData() = default;
+ ~QRhiBufferData()
+ {
+ if (d && !--d->ref)
+ delete d;
+ }
+ QRhiBufferData(const QRhiBufferData &other)
+ : d(other.d)
+ {
+ if (d)
+ d->ref += 1;
+ }
+ QRhiBufferData &operator=(const QRhiBufferData &other)
+ {
+ if (d == other.d)
+ return *this;
+ if (other.d)
+ other.d->ref += 1;
+ if (d && !--d->ref)
+ delete d;
+ d = other.d;
+ return *this;
+ }
+ const char *constData() const
+ {
+ return d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE ? d->data : d->largeData;
+ }
+ quint32 size() const
+ {
+ return d->size;
+ }
+ void assign(const char *s, quint32 size)
+ {
+ if (!d) {
+ d = new QRhiBufferDataPrivate;
+ } else if (d->ref != 1) {
+ d->ref -= 1;
+ d = new QRhiBufferDataPrivate;
+ }
+ d->size = size;
+ if (size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
+ memcpy(d->data, s, size);
+ } else {
+ if (d->largeAlloc < size) {
+ delete[] d->largeData;
+ d->largeAlloc = size;
+ d->largeData = new char[size];
+ }
+ memcpy(d->largeData, s, size);
+ }
+ }
+private:
+ QRhiBufferDataPrivate *d = nullptr;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTexture::Flags)
-
-class Q_GUI_EXPORT QRhiSampler : public QRhiResource
-{
-public:
- enum Filter {
- None,
- Nearest,
- Linear
- };
-
- enum AddressMode {
- Repeat,
- ClampToEdge,
- Mirror,
- };
-
- enum CompareOp {
- Never,
- Less,
- Equal,
- LessOrEqual,
- Greater,
- NotEqual,
- GreaterOrEqual,
- Always
- };
-
- QRhiResource::Type resourceType() const override;
-
- Filter magFilter() const { return m_magFilter; }
- void setMagFilter(Filter f) { m_magFilter = f; }
-
- Filter minFilter() const { return m_minFilter; }
- void setMinFilter(Filter f) { m_minFilter = f; }
-
- Filter mipmapMode() const { return m_mipmapMode; }
- void setMipmapMode(Filter f) { m_mipmapMode = f; }
-
- AddressMode addressU() const { return m_addressU; }
- void setAddressU(AddressMode mode) { m_addressU = mode; }
-
- AddressMode addressV() const { return m_addressV; }
- void setAddressV(AddressMode mode) { m_addressV = mode; }
-
- AddressMode addressW() const { return m_addressW; }
- void setAddressW(AddressMode mode) { m_addressW = mode; }
+Q_DECLARE_TYPEINFO(QRhiBufferData, Q_RELOCATABLE_TYPE);
- CompareOp textureCompareOp() const { return m_compareOp; }
- void setTextureCompareOp(CompareOp op) { m_compareOp = op; }
-
- virtual bool create() = 0;
-
-protected:
- QRhiSampler(QRhiImplementation *rhi,
- Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
- AddressMode u_, AddressMode v_, AddressMode w_);
- Filter m_magFilter;
- Filter m_minFilter;
- Filter m_mipmapMode;
- AddressMode m_addressU;
- AddressMode m_addressV;
- AddressMode m_addressW;
- CompareOp m_compareOp;
-};
-
-class Q_GUI_EXPORT QRhiRenderBuffer : public QRhiResource
+class QRhiResourceUpdateBatchPrivate
{
public:
- enum Type {
- DepthStencil,
- Color
- };
-
- enum Flag {
- UsedWithSwapChainOnly = 1 << 0
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- struct NativeRenderBuffer {
- quint64 object;
- };
-
- QRhiResource::Type resourceType() const override;
-
- Type type() const { return m_type; }
- void setType(Type t) { m_type = t; }
-
- QSize pixelSize() const { return m_pixelSize; }
- void setPixelSize(const QSize &sz) { m_pixelSize = sz; }
-
- int sampleCount() const { return m_sampleCount; }
- void setSampleCount(int s) { m_sampleCount = s; }
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags h) { m_flags = h; }
-
- virtual bool create() = 0;
- virtual bool createFrom(NativeRenderBuffer src);
-
- virtual QRhiTexture::Format backingFormat() const = 0;
+ struct BufferOp {
+ enum Type {
+ DynamicUpdate,
+ StaticUpload,
+ Read
+ };
+ Type type;
+ QRhiBuffer *buf;
+ quint32 offset;
+ QRhiBufferData data;
+ quint32 readSize;
+ QRhiReadbackResult *result;
+
+ static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
+ {
+ BufferOp op = {};
+ op.type = DynamicUpdate;
+ op.buf = buf;
+ op.offset = offset;
+ const int effectiveSize = size ? size : buf->size();
+ op.data.assign(reinterpret_cast<const char *>(data), effectiveSize);
+ return op;
+ }
+
+ static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
+ {
+ op->type = DynamicUpdate;
+ op->buf = buf;
+ op->offset = offset;
+ const int effectiveSize = size ? size : buf->size();
+ op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
+ }
+
+ static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
+ {
+ BufferOp op = {};
+ op.type = StaticUpload;
+ op.buf = buf;
+ op.offset = offset;
+ const int effectiveSize = size ? size : buf->size();
+ op.data.assign(reinterpret_cast<const char *>(data), effectiveSize);
+ return op;
+ }
+
+ static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
+ {
+ op->type = StaticUpload;
+ op->buf = buf;
+ op->offset = offset;
+ const int effectiveSize = size ? size : buf->size();
+ op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
+ }
+
+ static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
+ {
+ BufferOp op = {};
+ op.type = Read;
+ op.buf = buf;
+ op.offset = offset;
+ op.readSize = size;
+ op.result = result;
+ return op;
+ }
+ };
+
+ struct TextureOp {
+ enum Type {
+ Upload,
+ Copy,
+ Read,
+ GenMips
+ };
+ Type type;
+ QRhiTexture *dst;
+ // Specifying multiple uploads for a subresource must be supported.
+ // In the backend this can then end up, where applicable, as a
+ // single, batched copy operation with only one set of barriers.
+ // This helps when doing for example glyph cache fills.
+ using MipLevelUploadList = std::array<QVector<QRhiTextureSubresourceUploadDescription>, QRhi::MAX_MIP_LEVELS>;
+ QVarLengthArray<MipLevelUploadList, 6> subresDesc;
+ QRhiTexture *src;
+ QRhiTextureCopyDescription desc;
+ QRhiReadbackDescription rb;
+ QRhiReadbackResult *result;
+
+ static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
+ {
+ TextureOp op = {};
+ op.type = Upload;
+ op.dst = tex;
+ int maxLayer = -1;
+ for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it) {
+ if (it->layer() > maxLayer)
+ maxLayer = it->layer();
+ }
+ op.subresDesc.resize(maxLayer + 1);
+ for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it)
+ op.subresDesc[it->layer()][it->level()].append(it->description());
+ return op;
+ }
+
+ static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
+ {
+ TextureOp op = {};
+ op.type = Copy;
+ op.dst = dst;
+ op.src = src;
+ op.desc = desc;
+ return op;
+ }
+
+ static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
+ {
+ TextureOp op = {};
+ op.type = Read;
+ op.rb = rb;
+ op.result = result;
+ return op;
+ }
+
+ static TextureOp genMips(QRhiTexture *tex)
+ {
+ TextureOp op = {};
+ op.type = GenMips;
+ op.dst = tex;
+ return op;
+ }
+ };
+
+ int activeBufferOpCount = 0; // this is the real number of used elements in bufferOps, not bufferOps.count()
+ static const int BUFFER_OPS_STATIC_ALLOC = 1024;
+ QVarLengthArray<BufferOp, BUFFER_OPS_STATIC_ALLOC> bufferOps;
+
+ int activeTextureOpCount = 0; // this is the real number of used elements in textureOps, not textureOps.count()
+ static const int TEXTURE_OPS_STATIC_ALLOC = 256;
+ QVarLengthArray<TextureOp, TEXTURE_OPS_STATIC_ALLOC> textureOps;
+
+ QRhiResourceUpdateBatch *q = nullptr;
+ QRhiImplementation *rhi = nullptr;
+ int poolIndex = -1;
+
+ void free();
+ void merge(QRhiResourceUpdateBatchPrivate *other);
+ bool hasOptimalCapacity() const;
+ void trimOpLists();
-protected:
- QRhiRenderBuffer(QRhiImplementation *rhi, Type type_, const QSize &pixelSize_,
- int sampleCount_, Flags flags_, QRhiTexture::Format backingFormatHint_);
- Type m_type;
- QSize m_pixelSize;
- int m_sampleCount;
- Flags m_flags;
- QRhiTexture::Format m_backingFormatHint;
+ static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiRenderBuffer::Flags)
-
-class Q_GUI_EXPORT QRhiRenderPassDescriptor : public QRhiResource
+template<typename T>
+struct QRhiBatchedBindings
{
-public:
- QRhiResource::Type resourceType() const override;
-
- virtual bool isCompatible(const QRhiRenderPassDescriptor *other) const = 0;
- virtual const QRhiNativeHandles *nativeHandles();
-
- virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const = 0;
-
-protected:
- QRhiRenderPassDescriptor(QRhiImplementation *rhi);
-};
+ void feed(int binding, T resource) { // binding must be strictly increasing
+ if (curBinding == -1 || binding > curBinding + 1) {
+ finish();
+ curBatch.startBinding = binding;
+ curBatch.resources.clear();
+ curBatch.resources.append(resource);
+ } else {
+ Q_ASSERT(binding == curBinding + 1);
+ curBatch.resources.append(resource);
+ }
+ curBinding = binding;
+ }
-class Q_GUI_EXPORT QRhiRenderTarget : public QRhiResource
-{
-public:
- QRhiResource::Type resourceType() const override;
+ bool finish() {
+ if (!curBatch.resources.isEmpty())
+ batches.append(curBatch);
+ return !batches.isEmpty();
+ }
- virtual QSize pixelSize() const = 0;
- virtual float devicePixelRatio() const = 0;
- virtual int sampleCount() const = 0;
+ void clear() {
+ batches.clear();
+ curBatch.resources.clear();
+ curBinding = -1;
+ }
- QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
- void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
+ struct Batch {
+ uint startBinding;
+ QVarLengthArray<T, 4> resources;
-protected:
- QRhiRenderTarget(QRhiImplementation *rhi);
- QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
-};
+ bool operator==(const Batch &other) const
+ {
+ return startBinding == other.startBinding && resources == other.resources;
+ }
-class Q_GUI_EXPORT QRhiTextureRenderTarget : public QRhiRenderTarget
-{
-public:
- enum Flag {
- PreserveColorContents = 1 << 0,
- PreserveDepthStencilContents = 1 << 1
+ bool operator!=(const Batch &other) const
+ {
+ return !operator==(other);
+ }
};
- Q_DECLARE_FLAGS(Flags, Flag)
-
- QRhiResource::Type resourceType() const override;
- QRhiTextureRenderTargetDescription description() const { return m_desc; }
- void setDescription(const QRhiTextureRenderTargetDescription &desc) { m_desc = desc; }
+ QVarLengthArray<Batch, 4> batches; // sorted by startBinding
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
- virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0;
+ bool operator==(const QRhiBatchedBindings<T> &other) const
+ {
+ return batches == other.batches;
+ }
- virtual bool create() = 0;
+ bool operator!=(const QRhiBatchedBindings<T> &other) const
+ {
+ return !operator==(other);
+ }
-protected:
- QRhiTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc_, Flags flags_);
- QRhiTextureRenderTargetDescription m_desc;
- Flags m_flags;
+private:
+ Batch curBatch;
+ int curBinding = -1;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiTextureRenderTarget::Flags)
-
-class Q_GUI_EXPORT QRhiShaderResourceBindings : public QRhiResource
+class QRhiGlobalObjectIdGenerator
{
public:
- QRhiResource::Type resourceType() const override;
-
- void setBindings(std::initializer_list<QRhiShaderResourceBinding> list) { m_bindings = list; }
-
- template<typename InputIterator>
- void setBindings(InputIterator first, InputIterator last)
- {
- m_bindings.clear();
- std::copy(first, last, std::back_inserter(m_bindings));
- }
-
- const QRhiShaderResourceBinding *cbeginBindings() const { return m_bindings.cbegin(); }
- const QRhiShaderResourceBinding *cendBindings() const { return m_bindings.cend(); }
-
- bool isLayoutCompatible(const QRhiShaderResourceBindings *other) const;
-
- virtual bool create() = 0;
-
-protected:
- QRhiShaderResourceBindings(QRhiImplementation *rhi);
- QVarLengthArray<QRhiShaderResourceBinding, 16> m_bindings;
- uint m_layoutDescHash = 0;
- QVarLengthArray<uint, 16 * 3> m_layoutDesc;
- friend class QRhiImplementation;
-#ifndef QT_NO_DEBUG_STREAM
- friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
+#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
+ using Type = quint64;
+#else
+ using Type = quint32;
#endif
+ static Type newId();
};
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
-#endif
-
-class Q_GUI_EXPORT QRhiGraphicsPipeline : public QRhiResource
+class QRhiPassResourceTracker
{
public:
- enum Flag {
- UsesBlendConstants = 1 << 0,
- UsesStencilRef = 1 << 1,
- UsesScissor = 1 << 2,
- CompileShadersWithDebugInfo = 1 << 3
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- enum Topology {
- Triangles,
- TriangleStrip,
- TriangleFan,
- Lines,
- LineStrip,
- Points
- };
+ bool isEmpty() const;
+ void reset();
- enum CullMode {
- None,
- Front,
- Back
+ struct UsageState {
+ int layout;
+ int access;
+ int stage;
};
- enum FrontFace {
- CCW,
- CW
+ enum BufferStage {
+ BufVertexInputStage,
+ BufVertexStage,
+ BufTCStage,
+ BufTEStage,
+ BufFragmentStage,
+ BufComputeStage,
+ BufGeometryStage
};
- enum ColorMaskComponent {
- R = 1 << 0,
- G = 1 << 1,
- B = 1 << 2,
- A = 1 << 3
- };
- Q_DECLARE_FLAGS(ColorMask, ColorMaskComponent)
-
- enum BlendFactor {
- Zero,
- One,
- SrcColor,
- OneMinusSrcColor,
- DstColor,
- OneMinusDstColor,
- SrcAlpha,
- OneMinusSrcAlpha,
- DstAlpha,
- OneMinusDstAlpha,
- ConstantColor,
- OneMinusConstantColor,
- ConstantAlpha,
- OneMinusConstantAlpha,
- SrcAlphaSaturate,
- Src1Color,
- OneMinusSrc1Color,
- Src1Alpha,
- OneMinusSrc1Alpha
+ enum BufferAccess {
+ BufVertexInput,
+ BufIndexRead,
+ BufUniformRead,
+ BufStorageLoad,
+ BufStorageStore,
+ BufStorageLoadStore
};
- enum BlendOp {
- Add,
- Subtract,
- ReverseSubtract,
- Min,
- Max
- };
+ void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
+ const UsageState &state);
- struct TargetBlend {
- ColorMask colorWrite = ColorMask(0xF); // R | G | B | A
- bool enable = false;
- BlendFactor srcColor = One;
- BlendFactor dstColor = OneMinusSrcAlpha;
- BlendOp opColor = Add;
- BlendFactor srcAlpha = One;
- BlendFactor dstAlpha = OneMinusSrcAlpha;
- BlendOp opAlpha = Add;
+ enum TextureStage {
+ TexVertexStage,
+ TexTCStage,
+ TexTEStage,
+ TexFragmentStage,
+ TexColorOutputStage,
+ TexDepthOutputStage,
+ TexComputeStage,
+ TexGeometryStage
};
- enum CompareOp {
- Never,
- Less,
- Equal,
- LessOrEqual,
- Greater,
- NotEqual,
- GreaterOrEqual,
- Always
+ enum TextureAccess {
+ TexSample,
+ TexColorOutput,
+ TexDepthOutput,
+ TexStorageLoad,
+ TexStorageStore,
+ TexStorageLoadStore
};
- enum StencilOp {
- StencilZero,
- Keep,
- Replace,
- IncrementAndClamp,
- DecrementAndClamp,
- Invert,
- IncrementAndWrap,
- DecrementAndWrap
- };
+ void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
+ const UsageState &state);
- struct StencilOpState {
- StencilOp failOp = Keep;
- StencilOp depthFailOp = Keep;
- StencilOp passOp = Keep;
- CompareOp compareOp = Always;
+ struct Buffer {
+ int slot;
+ BufferAccess access;
+ BufferStage stage;
+ UsageState stateAtPassBegin;
};
- QRhiResource::Type resourceType() const override;
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
- Topology topology() const { return m_topology; }
- void setTopology(Topology t) { m_topology = t; }
-
- CullMode cullMode() const { return m_cullMode; }
- void setCullMode(CullMode mode) { m_cullMode = mode; }
-
- FrontFace frontFace() const { return m_frontFace; }
- void setFrontFace(FrontFace f) { m_frontFace = f; }
-
- void setTargetBlends(std::initializer_list<TargetBlend> list) { m_targetBlends = list; }
- template<typename InputIterator>
- void setTargetBlends(InputIterator first, InputIterator last)
- {
- m_targetBlends.clear();
- std::copy(first, last, std::back_inserter(m_targetBlends));
- }
- const TargetBlend *cbeginTargetBlends() const { return m_targetBlends.cbegin(); }
- const TargetBlend *cendTargetBlends() const { return m_targetBlends.cend(); }
-
- bool hasDepthTest() const { return m_depthTest; }
- void setDepthTest(bool enable) { m_depthTest = enable; }
-
- bool hasDepthWrite() const { return m_depthWrite; }
- void setDepthWrite(bool enable) { m_depthWrite = enable; }
-
- CompareOp depthOp() const { return m_depthOp; }
- void setDepthOp(CompareOp op) { m_depthOp = op; }
-
- bool hasStencilTest() const { return m_stencilTest; }
- void setStencilTest(bool enable) { m_stencilTest = enable; }
-
- StencilOpState stencilFront() const { return m_stencilFront; }
- void setStencilFront(const StencilOpState &state) { m_stencilFront = state; }
-
- StencilOpState stencilBack() const { return m_stencilBack; }
- void setStencilBack(const StencilOpState &state) { m_stencilBack = state; }
-
- quint32 stencilReadMask() const { return m_stencilReadMask; }
- void setStencilReadMask(quint32 mask) { m_stencilReadMask = mask; }
-
- quint32 stencilWriteMask() const { return m_stencilWriteMask; }
- void setStencilWriteMask(quint32 mask) { m_stencilWriteMask = mask; }
-
- int sampleCount() const { return m_sampleCount; }
- void setSampleCount(int s) { m_sampleCount = s; }
-
- float lineWidth() const { return m_lineWidth; }
- void setLineWidth(float width) { m_lineWidth = width; }
+ using BufferIterator = QHash<QRhiBuffer *, Buffer>::const_iterator;
+ BufferIterator cbeginBuffers() const { return m_buffers.cbegin(); }
+ BufferIterator cendBuffers() const { return m_buffers.cend(); }
- int depthBias() const { return m_depthBias; }
- void setDepthBias(int bias) { m_depthBias = bias; }
-
- float slopeScaledDepthBias() const { return m_slopeScaledDepthBias; }
- void setSlopeScaledDepthBias(float bias) { m_slopeScaledDepthBias = bias; }
-
- void setShaderStages(std::initializer_list<QRhiShaderStage> list) { m_shaderStages = list; }
- template<typename InputIterator>
- void setShaderStages(InputIterator first, InputIterator last)
- {
- m_shaderStages.clear();
- std::copy(first, last, std::back_inserter(m_shaderStages));
- }
- const QRhiShaderStage *cbeginShaderStages() const { return m_shaderStages.cbegin(); }
- const QRhiShaderStage *cendShaderStages() const { return m_shaderStages.cend(); }
-
- QRhiVertexInputLayout vertexInputLayout() const { return m_vertexInputLayout; }
- void setVertexInputLayout(const QRhiVertexInputLayout &layout) { m_vertexInputLayout = layout; }
-
- QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; }
- void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; }
-
- QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
- void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
-
- virtual bool create() = 0;
-
-protected:
- QRhiGraphicsPipeline(QRhiImplementation *rhi);
- Flags m_flags;
- Topology m_topology = Triangles;
- CullMode m_cullMode = None;
- FrontFace m_frontFace = CCW;
- QVarLengthArray<TargetBlend, 8> m_targetBlends;
- bool m_depthTest = false;
- bool m_depthWrite = false;
- CompareOp m_depthOp = Less;
- bool m_stencilTest = false;
- StencilOpState m_stencilFront;
- StencilOpState m_stencilBack;
- quint32 m_stencilReadMask = 0xFF;
- quint32 m_stencilWriteMask = 0xFF;
- int m_sampleCount = 1;
- float m_lineWidth = 1.0f;
- int m_depthBias = 0;
- float m_slopeScaledDepthBias = 0.0f;
- QVarLengthArray<QRhiShaderStage, 4> m_shaderStages;
- QRhiVertexInputLayout m_vertexInputLayout;
- QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
- QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::Flags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiGraphicsPipeline::ColorMask)
-Q_DECLARE_TYPEINFO(QRhiGraphicsPipeline::TargetBlend, Q_RELOCATABLE_TYPE);
-
-class Q_GUI_EXPORT QRhiSwapChain : public QRhiResource
-{
-public:
- enum Flag {
- SurfaceHasPreMulAlpha = 1 << 0,
- SurfaceHasNonPreMulAlpha = 1 << 1,
- sRGB = 1 << 2,
- UsedAsTransferSource = 1 << 3,
- NoVSync = 1 << 4,
- MinimalBufferCount = 1 << 5
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- QRhiResource::Type resourceType() const override;
-
- QWindow *window() const { return m_window; }
- void setWindow(QWindow *window) { m_window = window; }
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
- QRhiRenderBuffer *depthStencil() const { return m_depthStencil; }
- void setDepthStencil(QRhiRenderBuffer *ds) { m_depthStencil = ds; }
-
- int sampleCount() const { return m_sampleCount; }
- void setSampleCount(int samples) { m_sampleCount = samples; }
-
- QRhiRenderPassDescriptor *renderPassDescriptor() const { return m_renderPassDesc; }
- void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc) { m_renderPassDesc = desc; }
-
- QSize currentPixelSize() const { return m_currentPixelSize; }
-
- virtual QRhiCommandBuffer *currentFrameCommandBuffer() = 0;
- virtual QRhiRenderTarget *currentFrameRenderTarget() = 0;
- virtual QSize surfacePixelSize() = 0;
- virtual QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() = 0;
- virtual bool createOrResize() = 0;
-
-protected:
- QRhiSwapChain(QRhiImplementation *rhi);
- QWindow *m_window = nullptr;
- Flags m_flags;
- QRhiRenderBuffer *m_depthStencil = nullptr;
- int m_sampleCount = 1;
- QRhiRenderPassDescriptor *m_renderPassDesc = nullptr;
- QSize m_currentPixelSize;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiSwapChain::Flags)
-
-class Q_GUI_EXPORT QRhiComputePipeline : public QRhiResource
-{
-public:
- enum Flag {
- CompileShadersWithDebugInfo = 1 << 0
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- QRhiResource::Type resourceType() const override;
- virtual bool create() = 0;
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
- QRhiShaderStage shaderStage() const { return m_shaderStage; }
- void setShaderStage(const QRhiShaderStage &stage) { m_shaderStage = stage; }
-
- QRhiShaderResourceBindings *shaderResourceBindings() const { return m_shaderResourceBindings; }
- void setShaderResourceBindings(QRhiShaderResourceBindings *srb) { m_shaderResourceBindings = srb; }
-
-protected:
- QRhiComputePipeline(QRhiImplementation *rhi);
- Flags m_flags;
- QRhiShaderStage m_shaderStage;
- QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiComputePipeline::Flags)
-
-class Q_GUI_EXPORT QRhiCommandBuffer : public QRhiResource
-{
-public:
- enum IndexFormat {
- IndexUInt16,
- IndexUInt32
+ struct Texture {
+ TextureAccess access;
+ TextureStage stage;
+ UsageState stateAtPassBegin;
};
- enum BeginPassFlag {
- ExternalContent = 0x01,
- DoNotTrackResourcesForCompute = 0x02
- };
- Q_DECLARE_FLAGS(BeginPassFlags, BeginPassFlag)
-
- QRhiResource::Type resourceType() const override;
-
- void resourceUpdate(QRhiResourceUpdateBatch *resourceUpdates);
-
- void beginPass(QRhiRenderTarget *rt,
- const QColor &colorClearValue,
- const QRhiDepthStencilClearValue &depthStencilClearValue,
- QRhiResourceUpdateBatch *resourceUpdates = nullptr,
- BeginPassFlags flags = {});
- void endPass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
-
- void setGraphicsPipeline(QRhiGraphicsPipeline *ps);
- using DynamicOffset = QPair<int, quint32>; // binding, offset
- void setShaderResources(QRhiShaderResourceBindings *srb = nullptr,
- int dynamicOffsetCount = 0,
- const DynamicOffset *dynamicOffsets = nullptr);
- using VertexInput = QPair<QRhiBuffer *, quint32>; // buffer, offset
- void setVertexInput(int startBinding, int bindingCount, const VertexInput *bindings,
- QRhiBuffer *indexBuf = nullptr, quint32 indexOffset = 0,
- IndexFormat indexFormat = IndexUInt16);
-
- void setViewport(const QRhiViewport &viewport);
- void setScissor(const QRhiScissor &scissor);
- void setBlendConstants(const QColor &c);
- void setStencilRef(quint32 refValue);
-
- void draw(quint32 vertexCount,
- quint32 instanceCount = 1,
- quint32 firstVertex = 0,
- quint32 firstInstance = 0);
-
- void drawIndexed(quint32 indexCount,
- quint32 instanceCount = 1,
- quint32 firstIndex = 0,
- qint32 vertexOffset = 0,
- quint32 firstInstance = 0);
-
- void debugMarkBegin(const QByteArray &name);
- void debugMarkEnd();
- void debugMarkMsg(const QByteArray &msg);
-
- void beginComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr, BeginPassFlags flags = {});
- void endComputePass(QRhiResourceUpdateBatch *resourceUpdates = nullptr);
- void setComputePipeline(QRhiComputePipeline *ps);
- void dispatch(int x, int y, int z);
-
- const QRhiNativeHandles *nativeHandles();
- void beginExternal();
- void endExternal();
-
-protected:
- QRhiCommandBuffer(QRhiImplementation *rhi);
-};
+ using TextureIterator = QHash<QRhiTexture *, Texture>::const_iterator;
+ TextureIterator cbeginTextures() const { return m_textures.cbegin(); }
+ TextureIterator cendTextures() const { return m_textures.cend(); }
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhiCommandBuffer::BeginPassFlags)
-
-struct Q_GUI_EXPORT QRhiReadbackResult
-{
- std::function<void()> completed = nullptr;
- QRhiTexture::Format format;
- QSize pixelSize;
- QByteArray data;
-}; // non-movable due to the std::function
-
-struct Q_GUI_EXPORT QRhiBufferReadbackResult
-{
- std::function<void()> completed = nullptr;
- QByteArray data;
-};
-
-class Q_GUI_EXPORT QRhiResourceUpdateBatch
-{
-public:
- ~QRhiResourceUpdateBatch();
-
- void release();
-
- void merge(QRhiResourceUpdateBatch *other);
- bool hasOptimalCapacity() const;
-
- void updateDynamicBuffer(QRhiBuffer *buf, int offset, int size, const void *data);
- void uploadStaticBuffer(QRhiBuffer *buf, int offset, int size, const void *data);
- void uploadStaticBuffer(QRhiBuffer *buf, const void *data);
- void readBackBuffer(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result);
- void uploadTexture(QRhiTexture *tex, const QRhiTextureUploadDescription &desc);
- void uploadTexture(QRhiTexture *tex, const QImage &image);
- void copyTexture(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc = QRhiTextureCopyDescription());
- void readBackTexture(const QRhiReadbackDescription &rb, QRhiReadbackResult *result);
- void generateMips(QRhiTexture *tex);
+ static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
+ static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
private:
- QRhiResourceUpdateBatch(QRhiImplementation *rhi);
- Q_DISABLE_COPY(QRhiResourceUpdateBatch)
- QRhiResourceUpdateBatchPrivate *d;
- friend class QRhiResourceUpdateBatchPrivate;
- friend class QRhi;
+ QHash<QRhiBuffer *, Buffer> m_buffers;
+ QHash<QRhiTexture *, Texture> m_textures;
};
-struct Q_GUI_EXPORT QRhiDriverInfo
-{
- enum DeviceType {
- UnknownDevice,
- IntegratedDevice,
- DiscreteDevice,
- ExternalDevice,
- VirtualDevice,
- CpuDevice
- };
+Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Texture, Q_RELOCATABLE_TYPE);
- QByteArray deviceName;
- quint64 deviceId = 0;
- quint64 vendorId = 0;
- DeviceType deviceType = UnknownDevice;
-};
-
-Q_DECLARE_TYPEINFO(QRhiDriverInfo, Q_RELOCATABLE_TYPE);
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiDriverInfo &);
-#endif
-
-struct Q_GUI_EXPORT QRhiInitParams
-{
-};
-
-class Q_GUI_EXPORT QRhi
+template<typename T, int GROW = 1024>
+class QRhiBackendCommandList
{
public:
- enum Implementation {
- Null,
- Vulkan,
- OpenGLES2,
- D3D11,
- Metal
- };
-
- enum Flag {
- EnableProfiling = 1 << 0,
- EnableDebugMarkers = 1 << 1,
- PreferSoftwareRenderer = 1 << 2,
- EnablePipelineCacheDataSave = 1 << 3
- };
- Q_DECLARE_FLAGS(Flags, Flag)
-
- enum FrameOpResult {
- FrameOpSuccess = 0,
- FrameOpError,
- FrameOpSwapChainOutOfDate,
- FrameOpDeviceLost
- };
-
- enum Feature {
- MultisampleTexture = 1,
- MultisampleRenderBuffer,
- DebugMarkers,
- Timestamps,
- Instancing,
- CustomInstanceStepRate,
- PrimitiveRestart,
- NonDynamicUniformBuffers,
- NonFourAlignedEffectiveIndexBufferOffset,
- NPOTTextureRepeat,
- RedOrAlpha8IsRed,
- ElementIndexUint,
- Compute,
- WideLines,
- VertexShaderPointSize,
- BaseVertex,
- BaseInstance,
- TriangleFanTopology,
- ReadBackNonUniformBuffer,
- ReadBackNonBaseMipLevel,
- TexelFetch,
- RenderToNonBaseMipLevel,
- IntAttributes,
- ScreenSpaceDerivatives,
- ReadBackAnyTextureFormat,
- PipelineCacheDataLoadSave,
- ImageDataStride,
- RenderBufferImport,
- ThreeDimensionalTextures,
- RenderTo3DTextureSlice
- };
-
- enum BeginFrameFlag {
- };
- Q_DECLARE_FLAGS(BeginFrameFlags, BeginFrameFlag)
-
- enum EndFrameFlag {
- SkipPresent = 1 << 0
- };
- Q_DECLARE_FLAGS(EndFrameFlags, EndFrameFlag)
-
- enum ResourceLimit {
- TextureSizeMin = 1,
- TextureSizeMax,
- MaxColorAttachments,
- FramesInFlight,
- MaxAsyncReadbackFrames,
- MaxThreadGroupsPerDimension,
- MaxThreadsPerThreadGroup,
- MaxThreadGroupX,
- MaxThreadGroupY,
- MaxThreadGroupZ
- };
-
- ~QRhi();
-
- static QRhi *create(Implementation impl,
- QRhiInitParams *params,
- Flags flags = {},
- QRhiNativeHandles *importDevice = nullptr);
-
- Implementation backend() const;
- const char *backendName() const;
- QRhiDriverInfo driverInfo() const;
- QThread *thread() const;
-
- using CleanupCallback = std::function<void(QRhi *)>;
- void addCleanupCallback(const CleanupCallback &callback);
- void runCleanup();
-
- QRhiGraphicsPipeline *newGraphicsPipeline();
- QRhiComputePipeline *newComputePipeline();
- QRhiShaderResourceBindings *newShaderResourceBindings();
-
- QRhiBuffer *newBuffer(QRhiBuffer::Type type,
- QRhiBuffer::UsageFlags usage,
- int size);
-
- QRhiRenderBuffer *newRenderBuffer(QRhiRenderBuffer::Type type,
- const QSize &pixelSize,
- int sampleCount = 1,
- QRhiRenderBuffer::Flags flags = {},
- QRhiTexture::Format backingFormatHint = QRhiTexture::UnknownFormat);
-
- QRhiTexture *newTexture(QRhiTexture::Format format,
- const QSize &pixelSize,
- int sampleCount = 1,
- QRhiTexture::Flags flags = {});
-
- QRhiTexture *newTexture(QRhiTexture::Format format,
- int width, int height, int depth,
- int sampleCount = 1,
- QRhiTexture::Flags flags = {});
-
- QRhiSampler *newSampler(QRhiSampler::Filter magFilter,
- QRhiSampler::Filter minFilter,
- QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode addressU,
- QRhiSampler::AddressMode addressV,
- QRhiSampler::AddressMode addressW = QRhiSampler::Repeat);
-
- QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
- QRhiTextureRenderTarget::Flags flags = {});
-
- QRhiSwapChain *newSwapChain();
- FrameOpResult beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags = {});
- FrameOpResult endFrame(QRhiSwapChain *swapChain, EndFrameFlags flags = {});
- bool isRecordingFrame() const;
- int currentFrameSlot() const;
-
- FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags = {});
- FrameOpResult endOffscreenFrame(EndFrameFlags flags = {});
-
- QRhi::FrameOpResult finish();
-
- QRhiResourceUpdateBatch *nextResourceUpdateBatch();
-
- QList<int> supportedSampleCounts() const;
-
- int ubufAlignment() const;
- int ubufAligned(int v) const;
-
- int mipLevelsForSize(const QSize &size) const;
- QSize sizeForMipLevel(int mipLevel, const QSize &baseLevelSize) const;
-
- bool isYUpInFramebuffer() const;
- bool isYUpInNDC() const;
- bool isClipDepthZeroToOne() const;
-
- QMatrix4x4 clipSpaceCorrMatrix() const;
-
- bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = {}) const;
- bool isFeatureSupported(QRhi::Feature feature) const;
- int resourceLimit(ResourceLimit limit) const;
-
- const QRhiNativeHandles *nativeHandles();
- bool makeThreadLocalNativeContextCurrent();
-
- QRhiProfiler *profiler();
-
- static const int MAX_MIP_LEVELS = 16; // a width and/or height of 65536 should be enough for everyone
-
- void releaseCachedResources();
-
- bool isDeviceLost() const;
-
- QByteArray pipelineCacheData();
- void setPipelineCacheData(const QByteArray &data);
-
-protected:
- QRhi();
-
+ QRhiBackendCommandList() = default;
+ ~QRhiBackendCommandList() { delete[] v; }
+ inline void reset() { p = 0; }
+ inline bool isEmpty() const { return p == 0; }
+ inline T &get() {
+ if (p == a) {
+ a += GROW;
+ T *nv = new T[a];
+ if (v) {
+ memcpy(nv, v, p * sizeof(T));
+ delete[] v;
+ }
+ v = nv;
+ }
+ return v[p++];
+ }
+ inline void unget() { --p; }
+ inline T *cbegin() const { return v; }
+ inline T *cend() const { return v + p; }
+ inline T *begin() { return v; }
+ inline T *end() { return v + p; }
private:
- Q_DISABLE_COPY(QRhi)
- QRhiImplementation *d = nullptr;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::Flags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::BeginFrameFlags)
-Q_DECLARE_OPERATORS_FOR_FLAGS(QRhi::EndFrameFlags)
+ Q_DISABLE_COPY(QRhiBackendCommandList)
+ T *v = nullptr;
+ int a = 0;
+ int p = 0;
+};
+
+struct QRhiRenderTargetAttachmentTracker
+{
+ struct ResId { quint64 id; uint generation; };
+ using ResIdList = QVarLengthArray<ResId, 8 * 2 + 1>; // color, resolve, ds
+
+ template<typename TexType, typename RenderBufferType>
+ static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst);
+
+ template<typename TexType, typename RenderBufferType>
+ static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList);
+};
+
+inline bool operator==(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
+{
+ return a.id == b.id && a.generation == b.generation;
+}
+
+inline bool operator!=(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
+{
+ return !(a == b);
+}
+
+template<typename TexType, typename RenderBufferType>
+void QRhiRenderTargetAttachmentTracker::updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
+{
+ const bool hasDepthStencil = desc.depthStencilBuffer() || desc.depthTexture();
+ dst->resize(desc.colorAttachmentCount() * 2 + (hasDepthStencil ? 1 : 0));
+ int n = 0;
+ for (auto it = desc.cbeginColorAttachments(), itEnd = desc.cendColorAttachments(); it != itEnd; ++it, ++n) {
+ const QRhiColorAttachment &colorAtt(*it);
+ if (colorAtt.texture()) {
+ TexType *texD = QRHI_RES(TexType, colorAtt.texture());
+ (*dst)[n] = { texD->globalResourceId(), texD->generation };
+ } else if (colorAtt.renderBuffer()) {
+ RenderBufferType *rbD = QRHI_RES(RenderBufferType, colorAtt.renderBuffer());
+ (*dst)[n] = { rbD->globalResourceId(), rbD->generation };
+ } else {
+ (*dst)[n] = { 0, 0 };
+ }
+ ++n;
+ if (colorAtt.resolveTexture()) {
+ TexType *texD = QRHI_RES(TexType, colorAtt.resolveTexture());
+ (*dst)[n] = { texD->globalResourceId(), texD->generation };
+ } else {
+ (*dst)[n] = { 0, 0 };
+ }
+ }
+ if (hasDepthStencil) {
+ if (desc.depthTexture()) {
+ TexType *depthTexD = QRHI_RES(TexType, desc.depthTexture());
+ (*dst)[n] = { depthTexD->globalResourceId(), depthTexD->generation };
+ } else if (desc.depthStencilBuffer()) {
+ RenderBufferType *depthRbD = QRHI_RES(RenderBufferType, desc.depthStencilBuffer());
+ (*dst)[n] = { depthRbD->globalResourceId(), depthRbD->generation };
+ } else {
+ (*dst)[n] = { 0, 0 };
+ }
+ }
+}
+
+template<typename TexType, typename RenderBufferType>
+bool QRhiRenderTargetAttachmentTracker::isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList &currentResIdList)
+{
+ // Just as setShaderResources() recognizes if an srb's referenced
+ // resources have been rebuilt (got a create() since the srb's
+ // create()), we should do the same for the textures and renderbuffers
+ // referenced from the rendertarget. It is not uncommon that a texture
+ // or ds buffer gets resized due to following a window size in some
+ // form, which involves a create() on them. It is then nice if the
+ // render target auto-rebuilds in beginPass().
+
+ ResIdList resIdList;
+ updateResIdList<TexType, RenderBufferType>(desc, &resIdList);
+ return resIdList == currentResIdList;
+}
+
+template<typename T>
+inline T *qrhi_objectFromProxyData(QRhiSwapChainProxyData *pd, QWindow *window, QRhi::Implementation impl, uint objectIndex)
+{
+ Q_ASSERT(objectIndex < std::size(pd->reserved));
+ if (!pd->reserved[objectIndex]) // // was not set, no other choice, do it here, whatever thread this is
+ *pd = QRhi::updateSwapChainProxyData(impl, window);
+ return static_cast<T *>(pd->reserved[objectIndex]);
+}
QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
deleted file mode 100644
index 89dd7b8e44..0000000000
--- a/src/gui/rhi/qrhi_p_p.h
+++ /dev/null
@@ -1,713 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHI_P_H
-#define QRHI_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qrhi_p.h"
-#include "qrhiprofiler_p_p.h"
-#include <QBitArray>
-#include <QAtomicInt>
-#include <QLoggingCategory>
-
-QT_BEGIN_NAMESPACE
-
-#define QRHI_RES(t, x) static_cast<t *>(x)
-#define QRHI_RES_RHI(t) t *rhiD = static_cast<t *>(m_rhi)
-#define QRHI_PROF QRhiProfilerPrivate *rhiP = m_rhi->profilerPrivateOrNull()
-#define QRHI_PROF_F(f) for (bool qrhip_enabled = rhiP != nullptr; qrhip_enabled; qrhip_enabled = false) rhiP->f
-
-Q_DECLARE_LOGGING_CATEGORY(QRHI_LOG_INFO)
-
-class QRhiImplementation
-{
-public:
- virtual ~QRhiImplementation();
-
- virtual bool create(QRhi::Flags flags) = 0;
- virtual void destroy() = 0;
-
- virtual QRhiGraphicsPipeline *createGraphicsPipeline() = 0;
- virtual QRhiComputePipeline *createComputePipeline() = 0;
- virtual QRhiShaderResourceBindings *createShaderResourceBindings() = 0;
- virtual QRhiBuffer *createBuffer(QRhiBuffer::Type type,
- QRhiBuffer::UsageFlags usage,
- int size) = 0;
- virtual QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
- const QSize &pixelSize,
- int sampleCount,
- QRhiRenderBuffer::Flags flags,
- QRhiTexture::Format backingFormatHint) = 0;
- virtual QRhiTexture *createTexture(QRhiTexture::Format format,
- const QSize &pixelSize,
- int depth,
- int sampleCount,
- QRhiTexture::Flags flags) = 0;
- virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
- QRhiSampler::Filter minFilter,
- QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u,
- QRhiSampler::AddressMode v,
- QRhiSampler::AddressMode w) = 0;
-
- virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
- QRhiTextureRenderTarget::Flags flags) = 0;
-
- virtual QRhiSwapChain *createSwapChain() = 0;
- virtual QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) = 0;
- virtual QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) = 0;
- virtual QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) = 0;
- virtual QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) = 0;
- virtual QRhi::FrameOpResult finish() = 0;
-
- virtual void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
-
- virtual void beginPass(QRhiCommandBuffer *cb,
- QRhiRenderTarget *rt,
- const QColor &colorClearValue,
- const QRhiDepthStencilClearValue &depthStencilClearValue,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) = 0;
- virtual void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
-
- virtual void setGraphicsPipeline(QRhiCommandBuffer *cb,
- QRhiGraphicsPipeline *ps) = 0;
-
- virtual void setShaderResources(QRhiCommandBuffer *cb,
- QRhiShaderResourceBindings *srb,
- int dynamicOffsetCount,
- const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) = 0;
-
- virtual void setVertexInput(QRhiCommandBuffer *cb,
- int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
- QRhiBuffer *indexBuf, quint32 indexOffset,
- QRhiCommandBuffer::IndexFormat indexFormat) = 0;
-
- virtual void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) = 0;
- virtual void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) = 0;
- virtual void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) = 0;
- virtual void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) = 0;
-
- virtual void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
- quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) = 0;
- virtual void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
- quint32 instanceCount, quint32 firstIndex,
- qint32 vertexOffset, quint32 firstInstance) = 0;
-
- virtual void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) = 0;
- virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0;
- virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0;
-
- virtual void beginComputePass(QRhiCommandBuffer *cb,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) = 0;
- virtual void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
- virtual void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) = 0;
- virtual void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) = 0;
-
- virtual const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) = 0;
- virtual void beginExternal(QRhiCommandBuffer *cb) = 0;
- virtual void endExternal(QRhiCommandBuffer *cb) = 0;
-
- virtual QList<int> supportedSampleCounts() const = 0;
- virtual int ubufAlignment() const = 0;
- virtual bool isYUpInFramebuffer() const = 0;
- virtual bool isYUpInNDC() const = 0;
- virtual bool isClipDepthZeroToOne() const = 0;
- virtual QMatrix4x4 clipSpaceCorrMatrix() const = 0;
- virtual bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const = 0;
- virtual bool isFeatureSupported(QRhi::Feature feature) const = 0;
- virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0;
- virtual const QRhiNativeHandles *nativeHandles() = 0;
- virtual QRhiDriverInfo driverInfo() const = 0;
- virtual void sendVMemStatsToProfiler() = 0;
- virtual bool makeThreadLocalNativeContextCurrent() = 0;
- virtual void releaseCachedResources() = 0;
- virtual bool isDeviceLost() const = 0;
-
- virtual QByteArray pipelineCacheData() = 0;
- virtual void setPipelineCacheData(const QByteArray &data) = 0;
-
- bool isCompressedFormat(QRhiTexture::Format format) const;
- void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
- quint32 *bpl, quint32 *byteSize,
- QSize *blockDim) const;
- void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
- quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const;
- quint32 approxByteSizeForTexture(QRhiTexture::Format format, const QSize &baseSize, int depth,
- int mipCount, int layerCount);
-
- QRhiProfilerPrivate *profilerPrivateOrNull()
- {
- // return null when QRhi::EnableProfiling was not set
- QRhiProfilerPrivate *p = QRhiProfilerPrivate::get(&profiler);
- return p->rhiDWhenEnabled ? p : nullptr;
- }
-
- // only really care about resources that own native graphics resources underneath
- void registerResource(QRhiResource *res)
- {
- resources.insert(res);
- }
-
- void unregisterResource(QRhiResource *res)
- {
- resources.remove(res);
- }
-
- QSet<QRhiResource *> activeResources() const
- {
- return resources;
- }
-
- void addDeleteLater(QRhiResource *res)
- {
- if (inFrame)
- pendingDeleteResources.insert(res);
- else
- delete res;
- }
-
- void addCleanupCallback(const QRhi::CleanupCallback &callback)
- {
- cleanupCallbacks.append(callback);
- }
-
- bool sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps);
- bool sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb);
- void updateLayoutDesc(QRhiShaderResourceBindings *srb);
-
- quint32 pipelineCacheRhiId() const
- {
- const quint32 ver = (QT_VERSION_MAJOR << 16) | (QT_VERSION_MINOR << 8) | (QT_VERSION_PATCH);
- return (quint32(implType) << 24) | ver;
- }
-
- QRhi *q;
-
- static const int MAX_SHADER_CACHE_ENTRIES = 128;
-
- bool debugMarkers = false;
- int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
- bool inFrame = false;
-
-private:
- QRhi::Implementation implType;
- QThread *implThread;
- QRhiProfiler profiler;
- QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
- quint64 resUpdPoolMap = 0;
- int lastResUpdIdx = -1;
- QSet<QRhiResource *> resources;
- QSet<QRhiResource *> pendingDeleteResources;
- QVarLengthArray<QRhi::CleanupCallback, 4> cleanupCallbacks;
-
- friend class QRhi;
- friend class QRhiResourceUpdateBatchPrivate;
-};
-
-template<typename T, size_t N>
-bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, N> &r,
- T *x, T *y, T *w, T *h)
-{
- // x,y are bottom-left in QRhiScissor and QRhiViewport but top-left in
- // Vulkan/Metal/D3D. Our input is an OpenGL-style scissor rect where both
- // negative x or y, and partly or completely out of bounds rects are
- // allowed. The only thing the input here cannot have is a negative width
- // or height. We must handle all other input gracefully, clamping to a zero
- // width or height rect in the worst case, and ensuring the resulting rect
- // is inside the rendertarget's bounds because some APIs' validation/debug
- // layers are allergic to out of bounds scissor or viewport rects.
-
- const T outputWidth = outputSize.width();
- const T outputHeight = outputSize.height();
- const T inputWidth = r[2];
- const T inputHeight = r[3];
-
- if (inputWidth < 0 || inputHeight < 0)
- return false;
-
- *x = r[0];
- *y = outputHeight - (r[1] + inputHeight);
-
- const T widthOffset = *x < 0 ? -*x : 0;
- const T heightOffset = *y < 0 ? -*y : 0;
- *w = *x < outputWidth ? qMax<T>(0, inputWidth - widthOffset) : 0;
- *h = *y < outputHeight ? qMax<T>(0, inputHeight - heightOffset) : 0;
-
- *x = qBound<T>(0, *x, outputWidth - 1);
- *y = qBound<T>(0, *y, outputHeight - 1);
-
- if (*x + *w > outputWidth)
- *w = qMax<T>(0, outputWidth - *x);
- if (*y + *h > outputHeight)
- *h = qMax<T>(0, outputHeight - *y);
-
- return true;
-}
-
-struct QRhiBufferDataPrivate
-{
- Q_DISABLE_COPY_MOVE(QRhiBufferDataPrivate)
- QRhiBufferDataPrivate() { }
- ~QRhiBufferDataPrivate() { delete[] largeData; }
- int ref = 1;
- int size = 0;
- int largeAlloc = 0;
- char *largeData = nullptr;
- static constexpr int SMALL_DATA_SIZE = 1024;
- char data[SMALL_DATA_SIZE];
-};
-
-// no detach-with-contents, no atomic refcount, no shrink
-class QRhiBufferData
-{
-public:
- QRhiBufferData() = default;
- ~QRhiBufferData()
- {
- if (d && !--d->ref)
- delete d;
- }
- QRhiBufferData(const QRhiBufferData &other)
- : d(other.d)
- {
- if (d)
- d->ref += 1;
- }
- QRhiBufferData &operator=(const QRhiBufferData &other)
- {
- if (d == other.d)
- return *this;
- if (other.d)
- other.d->ref += 1;
- if (d && !--d->ref)
- delete d;
- d = other.d;
- return *this;
- }
- const char *constData() const
- {
- return d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE ? d->data : d->largeData;
- }
- int size() const
- {
- return d->size;
- }
- void assign(const char *s, int size)
- {
- if (!d) {
- d = new QRhiBufferDataPrivate;
- } else if (d->ref != 1) {
- d->ref -= 1;
- d = new QRhiBufferDataPrivate;
- }
- d->size = size;
- if (size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
- memcpy(d->data, s, size);
- } else {
- if (d->largeAlloc < size) {
- delete[] d->largeData;
- d->largeAlloc = size;
- d->largeData = new char[size];
- }
- memcpy(d->largeData, s, size);
- }
- }
-private:
- QRhiBufferDataPrivate *d = nullptr;
-};
-
-Q_DECLARE_TYPEINFO(QRhiBufferData, Q_RELOCATABLE_TYPE);
-
-class QRhiResourceUpdateBatchPrivate
-{
-public:
- struct BufferOp {
- enum Type {
- DynamicUpdate,
- StaticUpload,
- Read
- };
- Type type;
- QRhiBuffer *buf;
- int offset;
- QRhiBufferData data;
- int readSize;
- QRhiBufferReadbackResult *result;
-
- static BufferOp dynamicUpdate(QRhiBuffer *buf, int offset, int size, const void *data)
- {
- BufferOp op = {};
- op.type = DynamicUpdate;
- op.buf = buf;
- op.offset = offset;
- const int effectiveSize = size ? size : buf->size();
- op.data.assign(reinterpret_cast<const char *>(data), effectiveSize);
- return op;
- }
-
- static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, int offset, int size, const void *data)
- {
- op->type = DynamicUpdate;
- op->buf = buf;
- op->offset = offset;
- const int effectiveSize = size ? size : buf->size();
- op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
- }
-
- static BufferOp staticUpload(QRhiBuffer *buf, int offset, int size, const void *data)
- {
- BufferOp op = {};
- op.type = StaticUpload;
- op.buf = buf;
- op.offset = offset;
- const int effectiveSize = size ? size : buf->size();
- op.data.assign(reinterpret_cast<const char *>(data), effectiveSize);
- return op;
- }
-
- static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, int offset, int size, const void *data)
- {
- op->type = StaticUpload;
- op->buf = buf;
- op->offset = offset;
- const int effectiveSize = size ? size : buf->size();
- op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
- }
-
- static BufferOp read(QRhiBuffer *buf, int offset, int size, QRhiBufferReadbackResult *result)
- {
- BufferOp op = {};
- op.type = Read;
- op.buf = buf;
- op.offset = offset;
- op.readSize = size;
- op.result = result;
- return op;
- }
- };
-
- struct TextureOp {
- enum Type {
- Upload,
- Copy,
- Read,
- GenMips
- };
- Type type;
- QRhiTexture *dst;
- // Specifying multiple uploads for a subresource must be supported.
- // In the backend this can then end up, where applicable, as a
- // single, batched copy operation with only one set of barriers.
- // This helps when doing for example glyph cache fills.
- using MipLevelUploadList = std::array<QVector<QRhiTextureSubresourceUploadDescription>, QRhi::MAX_MIP_LEVELS>;
- QVarLengthArray<MipLevelUploadList, 6> subresDesc;
- QRhiTexture *src;
- QRhiTextureCopyDescription desc;
- QRhiReadbackDescription rb;
- QRhiReadbackResult *result;
-
- static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
- {
- TextureOp op = {};
- op.type = Upload;
- op.dst = tex;
- int maxLayer = -1;
- for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it) {
- if (it->layer() > maxLayer)
- maxLayer = it->layer();
- }
- op.subresDesc.resize(maxLayer + 1);
- for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it)
- op.subresDesc[it->layer()][it->level()].append(it->description());
- return op;
- }
-
- static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
- {
- TextureOp op = {};
- op.type = Copy;
- op.dst = dst;
- op.src = src;
- op.desc = desc;
- return op;
- }
-
- static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
- {
- TextureOp op = {};
- op.type = Read;
- op.rb = rb;
- op.result = result;
- return op;
- }
-
- static TextureOp genMips(QRhiTexture *tex)
- {
- TextureOp op = {};
- op.type = GenMips;
- op.dst = tex;
- return op;
- }
- };
-
- int activeBufferOpCount = 0; // this is the real number of used elements in bufferOps, not bufferOps.count()
- static const int BUFFER_OPS_STATIC_ALLOC = 1024;
- QVarLengthArray<BufferOp, BUFFER_OPS_STATIC_ALLOC> bufferOps;
-
- int activeTextureOpCount = 0; // this is the real number of used elements in textureOps, not textureOps.count()
- static const int TEXTURE_OPS_STATIC_ALLOC = 256;
- QVarLengthArray<TextureOp, TEXTURE_OPS_STATIC_ALLOC> textureOps;
-
- QRhiResourceUpdateBatch *q = nullptr;
- QRhiImplementation *rhi = nullptr;
- int poolIndex = -1;
-
- void free();
- void merge(QRhiResourceUpdateBatchPrivate *other);
- bool hasOptimalCapacity() const;
- void trimOpLists();
-
- static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
-};
-
-Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::BufferOp, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QRhiResourceUpdateBatchPrivate::TextureOp, Q_RELOCATABLE_TYPE);
-
-template<typename T>
-struct QRhiBatchedBindings
-{
- void feed(int binding, T resource) { // binding must be strictly increasing
- if (curBinding == -1 || binding > curBinding + 1) {
- finish();
- curBatch.startBinding = binding;
- curBatch.resources.clear();
- curBatch.resources.append(resource);
- } else {
- Q_ASSERT(binding == curBinding + 1);
- curBatch.resources.append(resource);
- }
- curBinding = binding;
- }
-
- bool finish() {
- if (!curBatch.resources.isEmpty())
- batches.append(curBatch);
- return !batches.isEmpty();
- }
-
- void clear() {
- batches.clear();
- curBatch.resources.clear();
- curBinding = -1;
- }
-
- struct Batch {
- uint startBinding;
- QVarLengthArray<T, 4> resources;
-
- bool operator==(const Batch &other) const
- {
- return startBinding == other.startBinding && resources == other.resources;
- }
-
- bool operator!=(const Batch &other) const
- {
- return !operator==(other);
- }
- };
-
- QVarLengthArray<Batch, 4> batches; // sorted by startBinding
-
- bool operator==(const QRhiBatchedBindings<T> &other) const
- {
- return batches == other.batches;
- }
-
- bool operator!=(const QRhiBatchedBindings<T> &other) const
- {
- return !operator==(other);
- }
-
-private:
- Batch curBatch;
- int curBinding = -1;
-};
-
-class QRhiGlobalObjectIdGenerator
-{
-public:
-#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
- using Type = quint64;
-#else
- using Type = quint32;
-#endif
- static Type newId();
-};
-
-class QRhiPassResourceTracker
-{
-public:
- bool isEmpty() const;
- void reset();
-
- struct UsageState {
- int layout;
- int access;
- int stage;
- };
-
- enum BufferStage {
- BufVertexInputStage,
- BufVertexStage,
- BufFragmentStage,
- BufComputeStage
- };
-
- enum BufferAccess {
- BufVertexInput,
- BufIndexRead,
- BufUniformRead,
- BufStorageLoad,
- BufStorageStore,
- BufStorageLoadStore
- };
-
- void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
- const UsageState &state);
-
- enum TextureStage {
- TexVertexStage,
- TexFragmentStage,
- TexColorOutputStage,
- TexDepthOutputStage,
- TexComputeStage
- };
-
- enum TextureAccess {
- TexSample,
- TexColorOutput,
- TexDepthOutput,
- TexStorageLoad,
- TexStorageStore,
- TexStorageLoadStore
- };
-
- void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
- const UsageState &state);
-
- struct Buffer {
- int slot;
- BufferAccess access;
- BufferStage stage;
- UsageState stateAtPassBegin;
- };
-
- using BufferIterator = QHash<QRhiBuffer *, Buffer>::const_iterator;
- BufferIterator cbeginBuffers() const { return m_buffers.cbegin(); }
- BufferIterator cendBuffers() const { return m_buffers.cend(); }
-
- struct Texture {
- TextureAccess access;
- TextureStage stage;
- UsageState stateAtPassBegin;
- };
-
- using TextureIterator = QHash<QRhiTexture *, Texture>::const_iterator;
- TextureIterator cbeginTextures() const { return m_textures.cbegin(); }
- TextureIterator cendTextures() const { return m_textures.cend(); }
-
- static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
- static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
-
-private:
- QHash<QRhiBuffer *, Buffer> m_buffers;
- QHash<QRhiTexture *, Texture> m_textures;
-};
-
-Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Texture, Q_RELOCATABLE_TYPE);
-
-template<typename T, int GROW = 1024>
-class QRhiBackendCommandList
-{
-public:
- QRhiBackendCommandList() = default;
- ~QRhiBackendCommandList() { delete[] v; }
- inline void reset() { p = 0; }
- inline bool isEmpty() const { return p == 0; }
- inline T &get() {
- if (p == a) {
- a += GROW;
- T *nv = new T[a];
- if (v) {
- memcpy(nv, v, p * sizeof(T));
- delete[] v;
- }
- v = nv;
- }
- return v[p++];
- }
- inline void unget() { --p; }
- inline T *cbegin() const { return v; }
- inline T *cend() const { return v + p; }
- inline T *begin() { return v; }
- inline T *end() { return v + p; }
-private:
- Q_DISABLE_COPY(QRhiBackendCommandList)
- T *v = nullptr;
- int a = 0;
- int p = 0;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qrhi_platform.h b/src/gui/rhi/qrhi_platform.h
new file mode 100644
index 0000000000..e7be522c52
--- /dev/null
+++ b/src/gui/rhi/qrhi_platform.h
@@ -0,0 +1,175 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHIPLATFORM_H
+#define QRHIPLATFORM_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the RHI API, with limited compatibility guarantees.
+// Usage of this API may make your code source and binary incompatible with
+// future versions of Qt.
+//
+
+#include <rhi/qrhi.h>
+
+#if QT_CONFIG(opengl)
+#include <QtGui/qsurfaceformat.h>
+#endif
+
+#if QT_CONFIG(vulkan)
+#include <QtGui/qvulkaninstance.h>
+#endif
+
+#if QT_CONFIG(metal) || defined(Q_QDOC)
+Q_FORWARD_DECLARE_OBJC_CLASS(MTLDevice);
+Q_FORWARD_DECLARE_OBJC_CLASS(MTLCommandQueue);
+Q_FORWARD_DECLARE_OBJC_CLASS(MTLCommandBuffer);
+Q_FORWARD_DECLARE_OBJC_CLASS(MTLRenderCommandEncoder);
+#endif
+
+QT_BEGIN_NAMESPACE
+
+struct Q_GUI_EXPORT QRhiNullInitParams : public QRhiInitParams
+{
+};
+
+struct Q_GUI_EXPORT QRhiNullNativeHandles : public QRhiNativeHandles
+{
+};
+
+#if QT_CONFIG(opengl) || defined(Q_QDOC)
+
+class QOpenGLContext;
+class QOffscreenSurface;
+class QSurface;
+class QWindow;
+
+struct Q_GUI_EXPORT QRhiGles2InitParams : public QRhiInitParams
+{
+ QRhiGles2InitParams();
+
+ QSurfaceFormat format;
+ QSurface *fallbackSurface = nullptr;
+ QWindow *window = nullptr;
+ QOpenGLContext *shareContext = nullptr;
+
+ static QOffscreenSurface *newFallbackSurface(const QSurfaceFormat &format = QSurfaceFormat::defaultFormat());
+};
+
+struct Q_GUI_EXPORT QRhiGles2NativeHandles : public QRhiNativeHandles
+{
+ QOpenGLContext *context = nullptr;
+};
+
+#endif // opengl/qdoc
+
+#if (QT_CONFIG(vulkan) && __has_include(<vulkan/vulkan.h>)) || defined(Q_QDOC)
+
+struct Q_GUI_EXPORT QRhiVulkanInitParams : public QRhiInitParams
+{
+ QVulkanInstance *inst = nullptr;
+ QWindow *window = nullptr;
+ QByteArrayList deviceExtensions;
+
+ static QByteArrayList preferredInstanceExtensions();
+ static QByteArrayList preferredExtensionsForImportedDevice();
+};
+
+struct Q_GUI_EXPORT QRhiVulkanNativeHandles : public QRhiNativeHandles
+{
+ // to import a physical device (always required)
+ VkPhysicalDevice physDev = VK_NULL_HANDLE;
+ // to import a device and queue
+ VkDevice dev = VK_NULL_HANDLE;
+ quint32 gfxQueueFamilyIdx = 0;
+ quint32 gfxQueueIdx = 0;
+ // and optionally, the mem allocator
+ void *vmemAllocator = nullptr;
+
+ // only for querying (rhi->nativeHandles())
+ VkQueue gfxQueue = VK_NULL_HANDLE;
+ QVulkanInstance *inst = nullptr;
+};
+
+struct Q_GUI_EXPORT QRhiVulkanCommandBufferNativeHandles : public QRhiNativeHandles
+{
+ VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
+};
+
+struct Q_GUI_EXPORT QRhiVulkanRenderPassNativeHandles : public QRhiNativeHandles
+{
+ VkRenderPass renderPass = VK_NULL_HANDLE;
+};
+
+#endif // vulkan/qdoc
+
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+
+// no d3d includes here, to prevent precompiled header mess due to COM, hence the void pointers
+
+struct Q_GUI_EXPORT QRhiD3D11InitParams : public QRhiInitParams
+{
+ bool enableDebugLayer = false;
+};
+
+struct Q_GUI_EXPORT QRhiD3D11NativeHandles : public QRhiNativeHandles
+{
+ // to import a device and a context
+ void *dev = nullptr;
+ void *context = nullptr;
+ // alternatively, to specify the device feature level and/or the adapter to use
+ int featureLevel = 0;
+ quint32 adapterLuidLow = 0;
+ qint32 adapterLuidHigh = 0;
+};
+
+struct Q_GUI_EXPORT QRhiD3D12InitParams : public QRhiInitParams
+{
+ bool enableDebugLayer = false;
+};
+
+struct Q_GUI_EXPORT QRhiD3D12NativeHandles : public QRhiNativeHandles
+{
+ // to import a device
+ void *dev = nullptr;
+ int minimumFeatureLevel = 0;
+ // to just specify the adapter to use, set these and leave dev set to null
+ quint32 adapterLuidLow = 0;
+ qint32 adapterLuidHigh = 0;
+ // in addition, can specify the command queue to use
+ void *commandQueue = nullptr;
+};
+
+struct Q_GUI_EXPORT QRhiD3D12CommandBufferNativeHandles : public QRhiNativeHandles
+{
+ void *commandList = nullptr; // ID3D12GraphicsCommandList1
+};
+
+#endif // WIN/QDOC
+
+#if QT_CONFIG(metal) || defined(Q_QDOC)
+
+struct Q_GUI_EXPORT QRhiMetalInitParams : public QRhiInitParams
+{
+};
+
+struct Q_GUI_EXPORT QRhiMetalNativeHandles : public QRhiNativeHandles
+{
+ MTLDevice *dev = nullptr;
+ MTLCommandQueue *cmdQueue = nullptr;
+};
+
+struct Q_GUI_EXPORT QRhiMetalCommandBufferNativeHandles : public QRhiNativeHandles
+{
+ MTLCommandBuffer *commandBuffer = nullptr;
+ MTLRenderCommandEncoder *encoder = nullptr;
+};
+
+#endif // MACOS/IOS/QDOC
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 6b4be76fef..b09baf57b2 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -1,58 +1,22 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qrhid3d11_p_p.h"
-#include "qshader_p.h"
-#include "cs_tdr_p.h"
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhid3d11_p.h"
+#include "qshader.h"
+#include "vs_test_p.h"
#include <QWindow>
-#include <QOperatingSystemVersion>
#include <qmath.h>
-#include <private/qsystemlibrary_p.h>
-
-#include <d3dcompiler.h>
-#include <comdef.h>
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/private/qsystemerror_p.h>
+#include "qrhid3dhelpers_p.h"
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*
- Direct3D 11 backend. Provides a double-buffered flip model (FLIP_DISCARD)
- swapchain. Textures and "static" buffers are USAGE_DEFAULT, leaving it to
+ Direct3D 11 backend. Provides a double-buffered flip model swapchain.
+ Textures and "static" buffers are USAGE_DEFAULT, leaving it to
UpdateSubResource to upload the data in any way it sees fit. "Dynamic"
buffers are USAGE_DYNAMIC and updating is done by mapping with WRITE_DISCARD.
(so here QRhiBuffer keeps a copy of the buffer contents and all of it is
@@ -62,10 +26,13 @@ QT_BEGIN_NAMESPACE
/*!
\class QRhiD3D11InitParams
- \internal
\inmodule QtGui
+ \since 6.6
\brief Direct3D 11 specific initialization parameters.
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
A D3D11-based QRhi needs no special parameters for initialization. If
desired, enableDebugLayer can be set to \c true to enable the Direct3D
debug layer. This can be useful during development, but should be avoided
@@ -78,9 +45,7 @@ QT_BEGIN_NAMESPACE
\endcode
\note QRhiSwapChain should only be used in combination with QWindow
- instances that have their surface type set to QSurface::OpenGLSurface.
- There are currently no Direct3D specifics in the Windows platform support
- of Qt and therefore there is no separate QSurface type available.
+ instances that have their surface type set to QSurface::Direct3DSurface.
\section2 Working with existing Direct3D 11 devices
@@ -106,16 +71,71 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \variable QRhiD3D11InitParams::enableDebugLayer
+
+ When set to true, a debug device is created, assuming the debug layer is
+ available. The default value is false.
+*/
+
+/*!
\class QRhiD3D11NativeHandles
- \internal
\inmodule QtGui
+ \since 6.6
\brief Holds the D3D device and device context used by the QRhi.
\note The class uses \c{void *} as the type since including the COM-based
\c{d3d11.h} headers is not acceptable here. The actual types are
\c{ID3D11Device *} and \c{ID3D11DeviceContext *}.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
+/*!
+ \variable QRhiD3D11NativeHandles::dev
+
+ Points to a
+ \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nn-d3d11-id3d11device}{ID3D11Device}
+ or left set to \nullptr if no existing device is to be imported.
+
+ \note When importing a device, both the device and the device context must be set to valid objects.
+*/
+
+/*!
+ \variable QRhiD3D11NativeHandles::context
+
+ Points to a \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nn-d3d11-id3d11devicecontext}{ID3D11DeviceContext}
+ or left set to \nullptr if no existing device context is to be imported.
+
+ \note When importing a device, both the device and the device context must be set to valid objects.
+*/
+
+/*!
+ \variable QRhiD3D11NativeHandles::featureLevel
+
+ Specifies the feature level passed to
+ \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-d3d11createdevice}{D3D11CreateDevice()}.
+ Relevant only when QRhi creates the device, ignored when importing a device
+ and device context. When not set, the default rules outlined in the D3D
+ documentation apply.
+*/
+
+/*!
+ \variable QRhiD3D11NativeHandles::adapterLuidLow
+
+ The low part of the local identifier (LUID) of the DXGI adapter to use.
+ Relevant only when QRhi creates the device, ignored when importing a device
+ and device context.
+*/
+
+/*!
+ \variable QRhiD3D11NativeHandles::adapterLuidHigh
+
+ The high part of the local identifier (LUID) of the DXGI adapter to use.
+ Relevant only when QRhi creates the device, ignored when importing a device
+ and device context.
+*/
+
// help mingw with its ancient sdk headers
#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
#define DXGI_ADAPTER_FLAG_SOFTWARE 2
@@ -125,20 +145,20 @@ QT_BEGIN_NAMESPACE
#define D3D11_1_UAV_SLOT_COUNT 64
#endif
+#ifndef D3D11_VS_INPUT_REGISTER_COUNT
+#define D3D11_VS_INPUT_REGISTER_COUNT 32
+#endif
+
QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importParams)
- : ofr(this),
- deviceCurse(this)
+ : ofr(this)
{
debugLayer = params->enableDebugLayer;
- deviceCurse.framesToActivate = params->framesUntilKillingDeviceViaTdr;
- deviceCurse.permanent = params->repeatDeviceKill;
-
if (importParams) {
if (importParams->dev && importParams->context) {
dev = reinterpret_cast<ID3D11Device *>(importParams->dev);
ID3D11DeviceContext *ctx = reinterpret_cast<ID3D11DeviceContext *>(importParams->context);
- if (SUCCEEDED(ctx->QueryInterface(IID_ID3D11DeviceContext1, reinterpret_cast<void **>(&context)))) {
+ if (SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void **>(&context)))) {
// get rid of the ref added by QueryInterface
ctx->Release();
importedDeviceAndContext = true;
@@ -152,15 +172,6 @@ QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *import
}
}
-static QString comErrorMessage(HRESULT hr)
-{
- const _com_error comError(hr);
- QString result = QLatin1String("Error 0x") + QString::number(ulong(hr), 16);
- if (const wchar_t *msg = comError.ErrorMessage())
- result += QLatin1String(": ") + QString::fromWCharArray(msg);
- return result;
-}
-
template <class Int>
inline Int aligned(Int v, Int byteAlign)
{
@@ -170,28 +181,10 @@ inline Int aligned(Int v, Int byteAlign)
static IDXGIFactory1 *createDXGIFactory2()
{
IDXGIFactory1 *result = nullptr;
- if (QOperatingSystemVersion::current() > QOperatingSystemVersion::Windows7) {
- using PtrCreateDXGIFactory2 = HRESULT (WINAPI *)(UINT, REFIID, void **);
- QSystemLibrary dxgilib(QStringLiteral("dxgi"));
- if (auto createDXGIFactory2 = reinterpret_cast<PtrCreateDXGIFactory2>(dxgilib.resolve("CreateDXGIFactory2"))) {
- const HRESULT hr = createDXGIFactory2(0, IID_IDXGIFactory2, reinterpret_cast<void **>(&result));
- if (FAILED(hr)) {
- qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s", qPrintable(comErrorMessage(hr)));
- result = nullptr;
- }
- } else {
- qWarning("Unable to resolve CreateDXGIFactory2()");
- }
- }
- return result;
-}
-
-static IDXGIFactory1 *createDXGIFactory1()
-{
- IDXGIFactory1 *result = nullptr;
- const HRESULT hr = CreateDXGIFactory1(IID_IDXGIFactory1, reinterpret_cast<void **>(&result));
+ const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&result));
if (FAILED(hr)) {
- qWarning("CreateDXGIFactory1() failed to create DXGI factory: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
result = nullptr;
}
return result;
@@ -199,28 +192,39 @@ static IDXGIFactory1 *createDXGIFactory1()
bool QRhiD3D11::create(QRhi::Flags flags)
{
- Q_UNUSED(flags);
+ rhiFlags = flags;
uint devFlags = 0;
if (debugLayer)
devFlags |= D3D11_CREATE_DEVICE_DEBUG;
dxgiFactory = createDXGIFactory2();
- if (dxgiFactory != nullptr) {
- hasDxgi2 = true;
- supportsFlipDiscardSwapchain = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10
- && !qEnvironmentVariableIntValue("QT_D3D_NO_FLIP");
- } else {
- dxgiFactory = createDXGIFactory1();
- hasDxgi2 = false;
- supportsFlipDiscardSwapchain = false;
+ if (!dxgiFactory)
+ return false;
+
+ // For a FLIP_* swapchain Present(0, 0) is not necessarily
+ // sufficient to get non-blocking behavior, try using ALLOW_TEARING
+ // when available.
+ supportsAllowTearing = false;
+ IDXGIFactory5 *factory5 = nullptr;
+ if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5), reinterpret_cast<void **>(&factory5)))) {
+ BOOL allowTearing = false;
+ if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))))
+ supportsAllowTearing = allowTearing;
+ factory5->Release();
}
- if (dxgiFactory == nullptr)
- return false;
+ if (qEnvironmentVariableIntValue("QT_D3D_FLIP_DISCARD"))
+ qWarning("The default swap effect is FLIP_DISCARD, QT_D3D_FLIP_DISCARD is now ignored");
- qCDebug(QRHI_LOG_INFO, "DXGI 1.2 = %s, FLIP_DISCARD swapchain supported = %s",
- hasDxgi2 ? "true" : "false", supportsFlipDiscardSwapchain ? "true" : "false");
+ // Support for flip model swapchains is required now (since we are
+ // targeting Windows 10+), but the option for using the old model is still
+ // there. (some features are not supported then, however)
+ useLegacySwapchainModel = qEnvironmentVariableIntValue("QT_D3D_NO_FLIP");
+
+ qCDebug(QRHI_LOG_INFO, "FLIP_* swapchain supported = true, ALLOW_TEARING supported = %s, use legacy (non-FLIP) model = %s",
+ supportsAllowTearing ? "true" : "false",
+ useLegacySwapchainModel ? "true" : "false");
if (!importedDeviceAndContext) {
IDXGIAdapter1 *adapter;
@@ -255,7 +259,7 @@ bool QRhiD3D11::create(QRhi::Flags flags)
}
}
- IDXGIAdapter1 *adapterToUse = nullptr;
+ activeAdapter = nullptr;
for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
@@ -266,18 +270,16 @@ bool QRhiD3D11::create(QRhi::Flags flags)
desc.VendorId,
desc.DeviceId,
desc.Flags);
- if (!adapterToUse && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
- adapterToUse = adapter;
+ if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
+ activeAdapter = adapter;
adapterLuid = desc.AdapterLuid;
- driverInfoStruct.deviceName = name.toUtf8();
- driverInfoStruct.deviceId = desc.DeviceId;
- driverInfoStruct.vendorId = desc.VendorId;
+ QRhiD3D::fillDriverInfo(&driverInfoStruct, desc);
qCDebug(QRHI_LOG_INFO, " using this adapter");
} else {
adapter->Release();
}
}
- if (!adapterToUse) {
+ if (!activeAdapter) {
qWarning("No adapter");
return false;
}
@@ -292,7 +294,7 @@ bool QRhiD3D11::create(QRhi::Flags flags)
}
ID3D11DeviceContext *ctx = nullptr;
- HRESULT hr = D3D11CreateDevice(adapterToUse, D3D_DRIVER_TYPE_UNKNOWN, nullptr, devFlags,
+ HRESULT hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, devFlags,
requestFeatureLevels ? requestedFeatureLevels.constData() : nullptr,
requestFeatureLevels ? requestedFeatureLevels.count() : 0,
D3D11_SDK_VERSION,
@@ -302,36 +304,75 @@ bool QRhiD3D11::create(QRhi::Flags flags)
qCDebug(QRHI_LOG_INFO, "Debug layer was requested but is not available. "
"Attempting to create D3D11 device without it.");
devFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
- hr = D3D11CreateDevice(adapterToUse, D3D_DRIVER_TYPE_UNKNOWN, nullptr, devFlags,
+ hr = D3D11CreateDevice(activeAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, devFlags,
requestFeatureLevels ? requestedFeatureLevels.constData() : nullptr,
requestFeatureLevels ? requestedFeatureLevels.count() : 0,
D3D11_SDK_VERSION,
&dev, &featureLevel, &ctx);
}
- adapterToUse->Release();
if (FAILED(hr)) {
- qWarning("Failed to create D3D11 device and context: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create D3D11 device and context: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
- if (SUCCEEDED(ctx->QueryInterface(IID_ID3D11DeviceContext1, reinterpret_cast<void **>(&context)))) {
- ctx->Release();
- } else {
+
+ const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void **>(&context)));
+ ctx->Release();
+ if (!supports11_1) {
qWarning("ID3D11DeviceContext1 not supported");
return false;
}
+
+ // Test if creating a Shader Model 5.0 vertex shader works; we want to
+ // fail already in create() if that's not the case.
+ ID3D11VertexShader *testShader = nullptr;
+ if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader, sizeof(g_testVertexShader), nullptr, &testShader))) {
+ testShader->Release();
+ } else {
+ static const char *msg = "D3D11 smoke test: Failed to create vertex shader";
+ if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
+ qCDebug(QRHI_LOG_INFO, "%s", msg);
+ else
+ qWarning("%s", msg);
+ return false;
+ }
+
+ D3D11_FEATURE_DATA_D3D11_OPTIONS features = {};
+ if (SUCCEEDED(dev->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features, sizeof(features)))) {
+ // The D3D _runtime_ may be 11.1, but the underlying _driver_ may
+ // still not support this D3D_FEATURE_LEVEL_11_1 feature. (e.g.
+ // because it only does 11_0)
+ if (!features.ConstantBufferOffsetting) {
+ static const char *msg = "D3D11 smoke test: Constant buffer offsetting is not supported by the driver";
+ if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
+ qCDebug(QRHI_LOG_INFO, "%s", msg);
+ else
+ qWarning("%s", msg);
+ return false;
+ }
+ } else {
+ static const char *msg = "D3D11 smoke test: Failed to query D3D11_FEATURE_D3D11_OPTIONS";
+ if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
+ qCDebug(QRHI_LOG_INFO, "%s", msg);
+ else
+ qWarning("%s", msg);
+ return false;
+ }
} else {
Q_ASSERT(dev && context);
featureLevel = dev->GetFeatureLevel();
IDXGIDevice *dxgiDev = nullptr;
- if (SUCCEEDED(dev->QueryInterface(IID_IDXGIDevice, reinterpret_cast<void **>(&dxgiDev)))) {
+ if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(&dxgiDev)))) {
IDXGIAdapter *adapter = nullptr;
if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
- DXGI_ADAPTER_DESC desc;
- adapter->GetDesc(&desc);
- adapterLuid = desc.AdapterLuid;
- driverInfoStruct.deviceName = QString::fromUtf16(reinterpret_cast<char16_t *>(desc.Description)).toUtf8();
- driverInfoStruct.deviceId = desc.DeviceId;
- driverInfoStruct.vendorId = desc.VendorId;
+ IDXGIAdapter1 *adapter1 = nullptr;
+ if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1), reinterpret_cast<void **>(&adapter1)))) {
+ DXGI_ADAPTER_DESC1 desc;
+ adapter1->GetDesc1(&desc);
+ adapterLuid = desc.AdapterLuid;
+ QRhiD3D::fillDriverInfo(&driverInfoStruct, desc);
+ adapter1->Release();
+ }
adapter->Release();
}
dxgiDev->Release();
@@ -339,7 +380,7 @@ bool QRhiD3D11::create(QRhi::Flags flags)
qCDebug(QRHI_LOG_INFO, "Using imported device %p", dev);
}
- if (FAILED(context->QueryInterface(IID_ID3DUserDefinedAnnotation, reinterpret_cast<void **>(&annotations))))
+ if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation), reinterpret_cast<void **>(&annotations))))
annotations = nullptr;
deviceLost = false;
@@ -350,9 +391,6 @@ bool QRhiD3D11::create(QRhi::Flags flags)
nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
- if (deviceCurse.framesToActivate > 0)
- deviceCurse.initResources();
-
return true;
}
@@ -370,7 +408,16 @@ void QRhiD3D11::destroy()
clearShaderCache();
- deviceCurse.releaseResources();
+ if (ofr.tsDisjointQuery) {
+ ofr.tsDisjointQuery->Release();
+ ofr.tsDisjointQuery = nullptr;
+ }
+ for (int i = 0; i < 2; ++i) {
+ if (ofr.tsQueries[i]) {
+ ofr.tsQueries[i]->Release();
+ ofr.tsQueries[i] = nullptr;
+ }
+ }
if (annotations) {
annotations->Release();
@@ -388,6 +435,16 @@ void QRhiD3D11::destroy()
}
}
+ if (dcompDevice) {
+ dcompDevice->Release();
+ dcompDevice = nullptr;
+ }
+
+ if (activeAdapter) {
+ activeAdapter->Release();
+ activeAdapter = nullptr;
+ }
+
if (dxgiFactory) {
dxgiFactory->Release();
dxgiFactory = nullptr;
@@ -398,7 +455,7 @@ void QRhiD3D11::reportLiveObjects(ID3D11Device *device)
{
// this works only when params.enableDebugLayer was true
ID3D11Debug *debug;
- if (SUCCEEDED(device->QueryInterface(IID_ID3D11Debug, reinterpret_cast<void **>(&debug)))) {
+ if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<void **>(&debug)))) {
debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
debug->Release();
}
@@ -409,19 +466,13 @@ QList<int> QRhiD3D11::supportedSampleCounts() const
return { 1, 2, 4, 8 };
}
-DXGI_SAMPLE_DESC QRhiD3D11::effectiveSampleCount(int sampleCount) const
+DXGI_SAMPLE_DESC QRhiD3D11::effectiveSampleDesc(int sampleCount) const
{
DXGI_SAMPLE_DESC desc;
desc.Count = 1;
desc.Quality = 0;
- // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
- int s = qBound(1, sampleCount, 64);
-
- if (!supportedSampleCounts().contains(s)) {
- qWarning("Attempted to set unsupported sample count %d", sampleCount);
- return desc;
- }
+ const int s = effectiveSampleCount(sampleCount);
desc.Count = UINT(s);
if (s > 1)
@@ -437,7 +488,7 @@ QRhiSwapChain *QRhiD3D11::createSwapChain()
return new QD3D11SwapChain(this);
}
-QRhiBuffer *QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+QRhiBuffer *QRhiD3D11::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
{
return new QD3D11Buffer(this, type, usage, size);
}
@@ -541,7 +592,7 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
case QRhi::ReadBackAnyTextureFormat:
return true;
case QRhi::PipelineCacheDataLoadSave:
- return false;
+ return true;
case QRhi::ImageDataStride:
return true;
case QRhi::RenderBufferImport:
@@ -550,6 +601,32 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::RenderTo3DTextureSlice:
return true;
+ case QRhi::TextureArrays:
+ return true;
+ case QRhi::Tessellation:
+ return true;
+ case QRhi::GeometryShader:
+ return true;
+ case QRhi::TextureArrayRange:
+ return true;
+ case QRhi::NonFillPolygonMode:
+ return true;
+ case QRhi::OneDimensionalTextures:
+ return true;
+ case QRhi::OneDimensionalTextureMipmaps:
+ return true;
+ case QRhi::HalfAttributes:
+ return true;
+ case QRhi::RenderToOneDimensionalTexture:
+ return true;
+ case QRhi::ThreeDimensionalTextureMipmaps:
+ return true;
+ case QRhi::MultiView:
+ return false;
+ case QRhi::TextureViewFormat:
+ return false; // because we use fully typed formats for textures and relaxed casting is a D3D12 thing
+ case QRhi::ResolveDepthStencil:
+ return false;
default:
Q_UNREACHABLE();
return false;
@@ -583,6 +660,14 @@ int QRhiD3D11::resourceLimit(QRhi::ResourceLimit limit) const
return D3D11_CS_THREAD_GROUP_MAX_Y;
case QRhi::MaxThreadGroupZ:
return D3D11_CS_THREAD_GROUP_MAX_Z;
+ case QRhi::TextureArraySizeMax:
+ return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+ case QRhi::MaxUniformBufferRange:
+ return 65536;
+ case QRhi::MaxVertexInputs:
+ return D3D11_VS_INPUT_REGISTER_COUNT;
+ case QRhi::MaxVertexOutputs:
+ return D3D11_VS_OUTPUT_REGISTER_COUNT;
default:
Q_UNREACHABLE();
return 0;
@@ -599,9 +684,11 @@ QRhiDriverInfo QRhiD3D11::driverInfo() const
return driverInfoStruct;
}
-void QRhiD3D11::sendVMemStatsToProfiler()
+QRhiStats QRhiD3D11::statistics()
{
- // nothing to do here
+ QRhiStats result;
+ result.totalPipelineCreationTime = totalPipelineCreationTime();
+ return result;
}
bool QRhiD3D11::makeThreadLocalNativeContextCurrent()
@@ -613,6 +700,7 @@ bool QRhiD3D11::makeThreadLocalNativeContextCurrent()
void QRhiD3D11::releaseCachedResources()
{
clearShaderCache();
+ m_bytecodeCache.clear();
}
bool QRhiD3D11::isDeviceLost() const
@@ -620,14 +708,159 @@ bool QRhiD3D11::isDeviceLost() const
return deviceLost;
}
+struct QD3D11PipelineCacheDataHeader
+{
+ quint32 rhiId;
+ quint32 arch;
+ // no need for driver specifics
+ quint32 count;
+ quint32 dataSize;
+};
+
QByteArray QRhiD3D11::pipelineCacheData()
{
- return QByteArray();
+ QByteArray data;
+ if (m_bytecodeCache.isEmpty())
+ return data;
+
+ QD3D11PipelineCacheDataHeader header;
+ memset(&header, 0, sizeof(header));
+ header.rhiId = pipelineCacheRhiId();
+ header.arch = quint32(sizeof(void*));
+ header.count = m_bytecodeCache.count();
+
+ const size_t dataOffset = sizeof(header);
+ size_t dataSize = 0;
+ for (auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
+ BytecodeCacheKey key = it.key();
+ QByteArray bytecode = it.value();
+ dataSize +=
+ sizeof(quint32) + key.sourceHash.size()
+ + sizeof(quint32) + key.target.size()
+ + sizeof(quint32) + key.entryPoint.size()
+ + sizeof(quint32) // compileFlags
+ + sizeof(quint32) + bytecode.size();
+ }
+
+ QByteArray buf(dataOffset + dataSize, Qt::Uninitialized);
+ char *p = buf.data() + dataOffset;
+ for (auto it = m_bytecodeCache.cbegin(), end = m_bytecodeCache.cend(); it != end; ++it) {
+ BytecodeCacheKey key = it.key();
+ QByteArray bytecode = it.value();
+
+ quint32 i = key.sourceHash.size();
+ memcpy(p, &i, 4);
+ p += 4;
+ memcpy(p, key.sourceHash.constData(), key.sourceHash.size());
+ p += key.sourceHash.size();
+
+ i = key.target.size();
+ memcpy(p, &i, 4);
+ p += 4;
+ memcpy(p, key.target.constData(), key.target.size());
+ p += key.target.size();
+
+ i = key.entryPoint.size();
+ memcpy(p, &i, 4);
+ p += 4;
+ memcpy(p, key.entryPoint.constData(), key.entryPoint.size());
+ p += key.entryPoint.size();
+
+ quint32 f = key.compileFlags;
+ memcpy(p, &f, 4);
+ p += 4;
+
+ i = bytecode.size();
+ memcpy(p, &i, 4);
+ p += 4;
+ memcpy(p, bytecode.constData(), bytecode.size());
+ p += bytecode.size();
+ }
+ Q_ASSERT(p == buf.data() + dataOffset + dataSize);
+
+ header.dataSize = quint32(dataSize);
+ memcpy(buf.data(), &header, sizeof(header));
+
+ return buf;
}
void QRhiD3D11::setPipelineCacheData(const QByteArray &data)
{
- Q_UNUSED(data);
+ if (data.isEmpty())
+ return;
+
+ const size_t headerSize = sizeof(QD3D11PipelineCacheDataHeader);
+ if (data.size() < qsizetype(headerSize)) {
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Invalid blob size (header incomplete)");
+ return;
+ }
+ const size_t dataOffset = headerSize;
+ QD3D11PipelineCacheDataHeader header;
+ memcpy(&header, data.constData(), headerSize);
+
+ const quint32 rhiId = pipelineCacheRhiId();
+ if (header.rhiId != rhiId) {
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
+ rhiId, header.rhiId);
+ return;
+ }
+ const quint32 arch = quint32(sizeof(void*));
+ if (header.arch != arch) {
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Architecture does not match (%u, %u)",
+ arch, header.arch);
+ return;
+ }
+ if (header.count == 0)
+ return;
+
+ if (data.size() < qsizetype(dataOffset + header.dataSize)) {
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Invalid blob size (data incomplete)");
+ return;
+ }
+
+ m_bytecodeCache.clear();
+
+ const char *p = data.constData() + dataOffset;
+ for (quint32 i = 0; i < header.count; ++i) {
+ quint32 len = 0;
+ memcpy(&len, p, 4);
+ p += 4;
+ QByteArray sourceHash(len, Qt::Uninitialized);
+ memcpy(sourceHash.data(), p, len);
+ p += len;
+
+ memcpy(&len, p, 4);
+ p += 4;
+ QByteArray target(len, Qt::Uninitialized);
+ memcpy(target.data(), p, len);
+ p += len;
+
+ memcpy(&len, p, 4);
+ p += 4;
+ QByteArray entryPoint(len, Qt::Uninitialized);
+ memcpy(entryPoint.data(), p, len);
+ p += len;
+
+ quint32 flags;
+ memcpy(&flags, p, 4);
+ p += 4;
+
+ memcpy(&len, p, 4);
+ p += 4;
+ QByteArray bytecode(len, Qt::Uninitialized);
+ memcpy(bytecode.data(), p, len);
+ p += len;
+
+ BytecodeCacheKey cacheKey;
+ cacheKey.sourceHash = sourceHash;
+ cacheKey.target = target;
+ cacheKey.entryPoint = entryPoint;
+ cacheKey.compileFlags = flags;
+
+ m_bytecodeCache.insert(cacheKey, bytecode);
+ }
+
+ qCDebug(QRHI_LOG_INFO, "Seeded bytecode cache with %d shaders", int(m_bytecodeCache.count()));
}
QRhiRenderBuffer *QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
@@ -638,10 +871,10 @@ QRhiRenderBuffer *QRhiD3D11::createRenderBuffer(QRhiRenderBuffer::Type type, con
}
QRhiTexture *QRhiD3D11::createTexture(QRhiTexture::Format format,
- const QSize &pixelSize, int depth,
+ const QSize &pixelSize, int depth, int arraySize,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QD3D11Texture(this, format, pixelSize, depth, sampleCount, flags);
+ return new QD3D11Texture(this, format, pixelSize, depth, arraySize, sampleCount, flags);
}
QRhiSampler *QRhiD3D11::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -690,10 +923,13 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
}
}
-static const int RBM_SUPPORTED_STAGES = 3;
+static const int RBM_SUPPORTED_STAGES = 6;
static const int RBM_VERTEX = 0;
-static const int RBM_FRAGMENT = 1;
-static const int RBM_COMPUTE = 2;
+static const int RBM_HULL = 1;
+static const int RBM_DOMAIN = 2;
+static const int RBM_GEOMETRY = 3;
+static const int RBM_FRAGMENT = 4;
+static const int RBM_COMPUTE = 5;
void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
int dynamicOffsetCount,
@@ -715,7 +951,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
bool srbUpdate = false;
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
- const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data();
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
@@ -734,8 +970,10 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
}
break;
case QRhiShaderResourceBinding::SampledTexture:
+ case QRhiShaderResourceBinding::Texture:
+ case QRhiShaderResourceBinding::Sampler:
{
- const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
+ const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
if (bd.stex.count != data->count) {
bd.stex.count = data->count;
srbUpdate = true;
@@ -743,16 +981,24 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
for (int elem = 0; elem < data->count; ++elem) {
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, data->texSamplers[elem].tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, data->texSamplers[elem].sampler);
- if (texD->generation != bd.stex.d[elem].texGeneration
- || texD->m_id != bd.stex.d[elem].texId
- || samplerD->generation != bd.stex.d[elem].samplerGeneration
- || samplerD->m_id != bd.stex.d[elem].samplerId)
+ // We use the same code path for both combined and separate
+ // images and samplers, so tex or sampler (but not both) can be
+ // null here.
+ Q_ASSERT(texD || samplerD);
+ const quint64 texId = texD ? texD->m_id : 0;
+ const uint texGen = texD ? texD->generation : 0;
+ const quint64 samplerId = samplerD ? samplerD->m_id : 0;
+ const uint samplerGen = samplerD ? samplerD->generation : 0;
+ if (texGen != bd.stex.d[elem].texGeneration
+ || texId != bd.stex.d[elem].texId
+ || samplerGen != bd.stex.d[elem].samplerGeneration
+ || samplerId != bd.stex.d[elem].samplerId)
{
srbUpdate = true;
- bd.stex.d[elem].texId = texD->m_id;
- bd.stex.d[elem].texGeneration = texD->generation;
- bd.stex.d[elem].samplerId = samplerD->m_id;
- bd.stex.d[elem].samplerGeneration = samplerD->generation;
+ bd.stex.d[elem].texId = texId;
+ bd.stex.d[elem].texGeneration = texGen;
+ bd.stex.d[elem].samplerId = samplerId;
+ bd.stex.d[elem].samplerGeneration = samplerGen;
}
}
}
@@ -792,6 +1038,9 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
memset(resBindMaps, 0, sizeof(resBindMaps));
if (gfxPsD) {
resBindMaps[RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
+ resBindMaps[RBM_HULL] = &gfxPsD->hs.nativeResourceBindingMap;
+ resBindMaps[RBM_DOMAIN] = &gfxPsD->ds.nativeResourceBindingMap;
+ resBindMaps[RBM_GEOMETRY] = &gfxPsD->gs.nativeResourceBindingMap;
resBindMaps[RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
} else {
resBindMaps[RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
@@ -826,8 +1075,8 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
for (int i = 0; i < dynamicOffsetCount; ++i) {
const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
const uint binding = uint(dynOfs.first);
- Q_ASSERT(aligned(dynOfs.second, quint32(256)) == dynOfs.second);
- const uint offsetInConstants = dynOfs.second / 16;
+ Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
+ const quint32 offsetInConstants = dynOfs.second / 16;
*p++ = binding;
*p++ = offsetInConstants;
}
@@ -918,7 +1167,7 @@ void QRhiD3D11::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
// d3d expects top-left, QRhiViewport is bottom-left
float x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
return;
QD3D11CommandBuffer::Command &cmd(cbD->commands.get());
@@ -940,7 +1189,7 @@ void QRhiD3D11::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
// d3d expects top-left, QRhiScissor is bottom-left
int x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
return;
QD3D11CommandBuffer::Command &cmd(cbD->commands.get());
@@ -1048,7 +1297,6 @@ const QRhiNativeHandles *QRhiD3D11::nativeHandles(QRhiCommandBuffer *cb)
void QRhiD3D11::beginExternal(QRhiCommandBuffer *cb)
{
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
- // no timestampSwapChain, in order to avoid timestamp mess
executeCommandBuffer(cbD);
cbD->resetCommands();
}
@@ -1065,6 +1313,25 @@ void QRhiD3D11::endExternal(QRhiCommandBuffer *cb)
}
}
+double QRhiD3D11::lastCompletedGpuTime(QRhiCommandBuffer *cb)
+{
+ QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
+ return cbD->lastGpuTime;
+}
+
+static inline QD3D11RenderTargetData *rtData(QRhiRenderTarget *rt)
+{
+ switch (rt->resourceType()) {
+ case QRhiResource::SwapChainRenderTarget:
+ return &QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
+ case QRhiResource::TextureRenderTarget:
+ return &QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
+ default:
+ Q_UNREACHABLE();
+ return nullptr;
+ }
+}
+
QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
{
Q_UNUSED(flags);
@@ -1072,32 +1339,6 @@ QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginF
QD3D11SwapChain *swapChainD = QRHI_RES(QD3D11SwapChain, swapChain);
contextState.currentSwapChain = swapChainD;
const int currentFrameSlot = swapChainD->currentFrameSlot;
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
-
- if (swapChainD->timestampActive[currentFrameSlot]) {
- ID3D11Query *tsDisjoint = swapChainD->timestampDisjointQuery[currentFrameSlot];
- const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
- ID3D11Query *tsStart = swapChainD->timestampQuery[tsIdx];
- ID3D11Query *tsEnd = swapChainD->timestampQuery[tsIdx + 1];
- quint64 timestamps[2];
- D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
- bool ok = true;
- ok &= context->GetData(tsDisjoint, &dj, sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
- ok &= context->GetData(tsEnd, &timestamps[1], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
- // this above is often not ready, not even in frame_where_recorded+2,
- // not clear why. so make the whole thing async and do not touch the
- // queries until they are finally all available in frame this+2 or
- // this+4 or ...
- ok &= context->GetData(tsStart, &timestamps[0], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
- if (ok) {
- if (!dj.Disjoint && dj.Frequency) {
- const float elapsedMs = (timestamps[1] - timestamps[0]) / float(dj.Frequency) * 1000.0f;
- // finally got a value, just report it, the profiler cares about min/max/avg anyway
- QRHI_PROF_F(swapChainFrameGpuTime(swapChain, elapsedMs));
- }
- swapChainD->timestampActive[currentFrameSlot] = false;
- } // else leave timestampActive set to true, will retry in a subsequent beginFrame
- }
swapChainD->cb.resetState();
@@ -1105,10 +1346,24 @@ QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginF
swapChainD->msaaRtv[currentFrameSlot] : swapChainD->backBufferRtv;
swapChainD->rt.d.dsv = swapChainD->ds ? swapChainD->ds->dsv : nullptr;
- QRHI_PROF_F(beginSwapChainFrame(swapChain));
-
finishActiveReadbacks();
+ if (swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex]) {
+ double elapsedSec = 0;
+ if (swapChainD->timestamps.tryQueryTimestamps(swapChainD->currentTimestampPairIndex, context, &elapsedSec))
+ swapChainD->cb.lastGpuTime = elapsedSec;
+ }
+
+ ID3D11Query *tsStart = swapChainD->timestamps.query[swapChainD->currentTimestampPairIndex * 2];
+ ID3D11Query *tsDisjoint = swapChainD->timestamps.disjointQuery[swapChainD->currentTimestampPairIndex];
+ const bool recordTimestamps = tsStart && tsDisjoint && !swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex];
+
+ QD3D11CommandBuffer::Command &cmd(swapChainD->cb.commands.get());
+ cmd.cmd = QD3D11CommandBuffer::Command::BeginFrame;
+ cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart : nullptr;
+ cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint : nullptr;
+ cmd.args.beginFrame.swapchainData = rtData(&swapChainD->rt);
+
return QRhi::FrameOpSuccess;
}
@@ -1118,17 +1373,13 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
Q_ASSERT(contextState.currentSwapChain = swapChainD);
const int currentFrameSlot = swapChainD->currentFrameSlot;
- ID3D11Query *tsDisjoint = swapChainD->timestampDisjointQuery[currentFrameSlot];
- const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
- ID3D11Query *tsStart = swapChainD->timestampQuery[tsIdx];
- ID3D11Query *tsEnd = swapChainD->timestampQuery[tsIdx + 1];
- const bool recordTimestamps = tsDisjoint && tsStart && tsEnd && !swapChainD->timestampActive[currentFrameSlot];
+ QD3D11CommandBuffer::Command &cmd(swapChainD->cb.commands.get());
+ cmd.cmd = QD3D11CommandBuffer::Command::EndFrame;
+ cmd.args.endFrame.tsQuery = nullptr; // done later manually, see below
+ cmd.args.endFrame.tsDisjointQuery = nullptr;
// send all commands to the context
- if (recordTimestamps)
- executeCommandBuffer(&swapChainD->cb, swapChainD);
- else
- executeCommandBuffer(&swapChainD->cb);
+ executeCommandBuffer(&swapChainD->cb);
if (swapChainD->sampleDesc.Count > 1) {
context->ResolveSubresource(swapChainD->backBufferTex, 0,
@@ -1136,29 +1387,39 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
swapChainD->colorFormat);
}
- // this is here because we want to include the time spent on the resolve as well
+ // this is here because we want to include the time spent on the ResolveSubresource as well
+ ID3D11Query *tsEnd = swapChainD->timestamps.query[swapChainD->currentTimestampPairIndex * 2 + 1];
+ ID3D11Query *tsDisjoint = swapChainD->timestamps.disjointQuery[swapChainD->currentTimestampPairIndex];
+ const bool recordTimestamps = tsEnd && tsDisjoint && !swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex];
if (recordTimestamps) {
context->End(tsEnd);
context->End(tsDisjoint);
- swapChainD->timestampActive[currentFrameSlot] = true;
+ swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex] = true;
+ swapChainD->currentTimestampPairIndex = (swapChainD->currentTimestampPairIndex + 1) % QD3D11SwapChainTimestamps::TIMESTAMP_PAIRS;
}
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- // this must be done before the Present
- QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
-
if (!flags.testFlag(QRhi::SkipPresent)) {
- const UINT presentFlags = 0;
+ UINT presentFlags = 0;
+ if (swapChainD->swapInterval == 0 && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
+ presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
+ if (!swapChainD->swapChain) {
+ qWarning("Failed to present: IDXGISwapChain is unavailable");
+ return QRhi::FrameOpError;
+ }
HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
qWarning("Device loss detected in Present()");
deviceLost = true;
return QRhi::FrameOpDeviceLost;
} else if (FAILED(hr)) {
- qWarning("Failed to present: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to present: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return QRhi::FrameOpError;
}
+ if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
+ dcompDevice->Commit();
+
// move on to the next buffer
swapChainD->currentFrameSlot = (swapChainD->currentFrameSlot + 1) % QD3D11SwapChain::BUFFER_COUNT;
} else {
@@ -1168,19 +1429,6 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
swapChainD->frameCount += 1;
contextState.currentSwapChain = nullptr;
- if (deviceCurse.framesToActivate > 0) {
- deviceCurse.framesLeft -= 1;
- if (deviceCurse.framesLeft == 0) {
- deviceCurse.framesLeft = deviceCurse.framesToActivate;
- if (!deviceCurse.permanent)
- deviceCurse.framesToActivate = -1;
-
- deviceCurse.activate();
- } else if (deviceCurse.framesLeft % 100 == 0) {
- qDebug("Impending doom: %d frames left", deviceCurse.framesLeft);
- }
- }
-
return QRhi::FrameOpSuccess;
}
@@ -1192,6 +1440,36 @@ QRhi::FrameOpResult QRhiD3D11::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi:
ofr.cbWrapper.resetState();
*cb = &ofr.cbWrapper;
+ if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
+ D3D11_QUERY_DESC queryDesc = {};
+ if (!ofr.tsDisjointQuery) {
+ queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
+ HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
+ if (FAILED(hr)) {
+ qWarning("Failed to create timestamp disjoint query: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return QRhi::FrameOpError;
+ }
+ }
+ queryDesc.Query = D3D11_QUERY_TIMESTAMP;
+ for (int i = 0; i < 2; ++i) {
+ if (!ofr.tsQueries[i]) {
+ HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
+ if (FAILED(hr)) {
+ qWarning("Failed to create timestamp query: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return QRhi::FrameOpError;
+ }
+ }
+ }
+ }
+
+ QD3D11CommandBuffer::Command &cmd(ofr.cbWrapper.commands.get());
+ cmd.cmd = QD3D11CommandBuffer::Command::BeginFrame;
+ cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] : nullptr;
+ cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery : nullptr;
+ cmd.args.beginFrame.swapchainData = nullptr;
+
return QRhi::FrameOpSuccess;
}
@@ -1200,10 +1478,41 @@ QRhi::FrameOpResult QRhiD3D11::endOffscreenFrame(QRhi::EndFrameFlags flags)
Q_UNUSED(flags);
ofr.active = false;
+ QD3D11CommandBuffer::Command &cmd(ofr.cbWrapper.commands.get());
+ cmd.cmd = QD3D11CommandBuffer::Command::EndFrame;
+ cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] : nullptr;
+ cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery : nullptr;
+
executeCommandBuffer(&ofr.cbWrapper);
+ context->Flush();
finishActiveReadbacks();
+ if (ofr.tsQueries[0]) {
+ quint64 timestamps[2];
+ D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
+ HRESULT hr;
+ bool ok = true;
+ do {
+ hr = context->GetData(ofr.tsDisjointQuery, &dj, sizeof(dj), 0);
+ } while (hr == S_FALSE);
+ ok &= hr == S_OK;
+ do {
+ hr = context->GetData(ofr.tsQueries[1], &timestamps[1], sizeof(quint64), 0);
+ } while (hr == S_FALSE);
+ ok &= hr == S_OK;
+ do {
+ hr = context->GetData(ofr.tsQueries[0], &timestamps[0], sizeof(quint64), 0);
+ } while (hr == S_FALSE);
+ ok &= hr == S_OK;
+ if (ok) {
+ if (!dj.Disjoint && dj.Frequency) {
+ const float elapsedMs = (timestamps[1] - timestamps[0]) / float(dj.Frequency) * 1000.0f;
+ ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
+ }
+ }
+ }
+
return QRhi::FrameOpSuccess;
}
@@ -1235,12 +1544,15 @@ static inline DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format, QRhiTex
case QRhiTexture::R32F:
return DXGI_FORMAT_R32_FLOAT;
+ case QRhiTexture::RGB10A2:
+ return DXGI_FORMAT_R10G10B10A2_UNORM;
+
case QRhiTexture::D16:
return DXGI_FORMAT_R16_TYPELESS;
case QRhiTexture::D24:
- return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
+ return DXGI_FORMAT_R24G8_TYPELESS;
case QRhiTexture::D24S8:
- return DXGI_FORMAT_D24_UNORM_S8_UINT;
+ return DXGI_FORMAT_R24G8_TYPELESS;
case QRhiTexture::D32F:
return DXGI_FORMAT_R32_TYPELESS;
@@ -1288,7 +1600,7 @@ static inline DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format, QRhiTex
}
}
-static inline QRhiTexture::Format colorTextureFormatFromDxgiFormat(DXGI_FORMAT format, QRhiTexture::Flags *flags)
+static inline QRhiTexture::Format swapchainReadbackTextureFormat(DXGI_FORMAT format, QRhiTexture::Flags *flags)
{
switch (format) {
case DXGI_FORMAT_R8G8B8A8_UNORM:
@@ -1303,16 +1615,14 @@ static inline QRhiTexture::Format colorTextureFormatFromDxgiFormat(DXGI_FORMAT f
if (flags)
(*flags) |= QRhiTexture::sRGB;
return QRhiTexture::BGRA8;
- case DXGI_FORMAT_R8_UNORM:
- return QRhiTexture::R8;
- case DXGI_FORMAT_R8G8_UNORM:
- return QRhiTexture::RG8;
- case DXGI_FORMAT_R16_UNORM:
- return QRhiTexture::R16;
- case DXGI_FORMAT_R16G16_UNORM:
- return QRhiTexture::RG16;
- default: // this cannot assert, must warn and return unknown
- qWarning("DXGI_FORMAT %d is not a recognized uncompressed color format", format);
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ return QRhiTexture::RGBA16F;
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ return QRhiTexture::RGBA32F;
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ return QRhiTexture::RGB10A2;
+ default:
+ qWarning("DXGI_FORMAT %d cannot be read back", format);
break;
}
return QRhiTexture::UnknownFormat;
@@ -1343,7 +1653,7 @@ QRhi::FrameOpResult QRhiD3D11::finish()
} else {
Q_ASSERT(contextState.currentSwapChain);
Q_ASSERT(contextState.currentSwapChain->cb.recordingPass == QD3D11CommandBuffer::NoPass);
- executeCommandBuffer(&contextState.currentSwapChain->cb); // no timestampSwapChain, in order to avoid timestamp mess
+ executeCommandBuffer(&contextState.currentSwapChain->cb);
contextState.currentSwapChain->cb.resetCommands();
}
}
@@ -1437,7 +1747,6 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
{
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
for (int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
const QRhiResourceUpdateBatchPrivate::BufferOp &u(ud->bufferOps[opIdx]);
@@ -1460,10 +1769,10 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
// since the ID3D11Buffer's size is rounded up to be a multiple of 256
// while the data we have has the original size.
D3D11_BOX box;
- box.left = UINT(u.offset);
+ box.left = u.offset;
box.top = box.front = 0;
box.back = box.bottom = 1;
- box.right = UINT(u.offset + u.data.size()); // no -1: right, bottom, back are exclusive, see D3D11_BOX doc
+ box.right = u.offset + u.data.size(); // no -1: right, bottom, back are exclusive, see D3D11_BOX doc
cmd.args.updateSubRes.hasDstBox = true;
cmd.args.updateSubRes.dstBox = box;
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
@@ -1471,22 +1780,23 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
if (bufD->m_type == QRhiBuffer::Dynamic) {
u.result->data.resize(u.readSize);
memcpy(u.result->data.data(), bufD->dynBuf + u.offset, size_t(u.readSize));
+ if (u.result->completed)
+ u.result->completed();
} else {
BufferReadback readback;
readback.result = u.result;
readback.byteSize = u.readSize;
- D3D11_BUFFER_DESC desc;
- memset(&desc, 0, sizeof(desc));
+ D3D11_BUFFER_DESC desc = {};
desc.ByteWidth = readback.byteSize;
desc.Usage = D3D11_USAGE_STAGING;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
HRESULT hr = dev->CreateBuffer(&desc, nullptr, &readback.stagingBuf);
if (FAILED(hr)) {
- qWarning("Failed to create buffer: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create buffer: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
continue;
}
- QRHI_PROF_F(newReadbackBuffer(qint64(qintptr(readback.stagingBuf)), bufD, readback.byteSize));
QD3D11CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes;
@@ -1499,16 +1809,14 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd.args.copySubRes.srcSubRes = 0;
cmd.args.copySubRes.hasSrcBox = true;
D3D11_BOX box;
- box.left = UINT(u.offset);
+ box.left = u.offset;
box.top = box.front = 0;
box.back = box.bottom = 1;
- box.right = UINT(u.offset + u.readSize);
+ box.right = u.offset + u.readSize;
cmd.args.copySubRes.srcBox = box;
activeBufferReadbacks.append(readback);
}
- if (u.result->completed)
- u.result->completed();
}
}
for (int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
@@ -1517,7 +1825,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, u.dst);
for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
- for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level]))
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
}
}
@@ -1594,7 +1902,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
src = swapChainD->backBufferTex;
dxgiFormat = swapChainD->colorFormat;
pixelSize = swapChainD->pixelSize;
- format = colorTextureFormatFromDxgiFormat(dxgiFormat, nullptr);
+ format = swapchainReadbackTextureFormat(dxgiFormat, nullptr);
if (format == QRhiTexture::UnknownFormat)
continue;
}
@@ -1602,8 +1910,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
quint32 bpl = 0;
textureFormatInfo(format, pixelSize, &bpl, &byteSize, nullptr);
- D3D11_TEXTURE2D_DESC desc;
- memset(&desc, 0, sizeof(desc));
+ D3D11_TEXTURE2D_DESC desc = {};
desc.Width = UINT(pixelSize.width());
desc.Height = UINT(pixelSize.height());
desc.MipLevels = 1;
@@ -1615,12 +1922,10 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
ID3D11Texture2D *stagingTex;
HRESULT hr = dev->CreateTexture2D(&desc, nullptr, &stagingTex);
if (FAILED(hr)) {
- qWarning("Failed to create readback staging texture: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create readback staging texture: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return;
}
- QRHI_PROF_F(newReadbackBuffer(qint64(qintptr(stagingTex)),
- texD ? static_cast<QRhiResource *>(texD) : static_cast<QRhiResource *>(swapChainD),
- byteSize));
QD3D11CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QD3D11CommandBuffer::Command::CopySubRes;
@@ -1632,8 +1937,7 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd.args.copySubRes.src = src;
cmd.args.copySubRes.srcSubRes = subres;
if (is3D) {
- D3D11_BOX srcBox;
- memset(&srcBox, 0, sizeof(srcBox));
+ D3D11_BOX srcBox = {};
srcBox.front = UINT(u.rb.layer());
srcBox.right = desc.Width; // exclusive
srcBox.bottom = desc.Height;
@@ -1665,7 +1969,6 @@ void QRhiD3D11::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
void QRhiD3D11::finishActiveReadbacks()
{
QVarLengthArray<std::function<void()>, 4> completedCallbacks;
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
for (int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
const QRhiD3D11::TextureReadback &readback(activeTextureReadbacks[i]);
@@ -1687,11 +1990,11 @@ void QRhiD3D11::finishActiveReadbacks()
}
context->Unmap(readback.stagingTex, 0);
} else {
- qWarning("Failed to map readback staging texture: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to map readback staging texture: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
}
readback.stagingTex->Release();
- QRHI_PROF_F(releaseReadbackBuffer(qint64(qintptr(readback.stagingTex))));
if (readback.result->completed)
completedCallbacks.append(readback.result->completed);
@@ -1709,11 +2012,11 @@ void QRhiD3D11::finishActiveReadbacks()
memcpy(readback.result->data.data(), mp.pData, readback.byteSize);
context->Unmap(readback.stagingBuf, 0);
} else {
- qWarning("Failed to map readback staging texture: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to map readback staging texture: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
}
readback.stagingBuf->Release();
- QRHI_PROF_F(releaseReadbackBuffer(qint64(qintptr(readback.stagingBuf))));
if (readback.result->completed)
completedCallbacks.append(readback.result->completed);
@@ -1725,19 +2028,6 @@ void QRhiD3D11::finishActiveReadbacks()
f();
}
-static inline QD3D11RenderTargetData *rtData(QRhiRenderTarget *rt)
-{
- switch (rt->resourceType()) {
- case QRhiResource::RenderTarget:
- return &QRHI_RES(QD3D11ReferenceRenderTarget, rt)->d;
- case QRhiResource::TextureRenderTarget:
- return &QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
- default:
- Q_UNREACHABLE();
- return nullptr;
- }
-}
-
void QRhiD3D11::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
{
Q_ASSERT(QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
@@ -1765,6 +2055,8 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb,
QD3D11TextureRenderTarget *rtTex = QRHI_RES(QD3D11TextureRenderTarget, rt);
wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(rtTex->description(), rtD->currentResIdList))
+ rtTex->create();
}
cbD->commands.get().cmd = QD3D11CommandBuffer::Command::ResetShaderResources;
@@ -1792,7 +2084,7 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb,
cbD->recordingPass = QD3D11CommandBuffer::RenderPass;
cbD->currentTarget = rt;
- cbD->resetCachedShaderResourceState();
+ cbD->resetCachedState();
}
void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@@ -1854,6 +2146,8 @@ void QRhiD3D11::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
cmd.args.resolveSubRes.srcSubRes = D3D11CalcSubresource(0, UINT(colorAtt.layer()), 1);
cmd.args.resolveSubRes.format = dstTexD->dxgiFormat;
}
+ if (rtTex->m_desc.depthResolveTexture())
+ qWarning("Resolving multisample depth-stencil buffers is not supported with D3D");
}
cbD->recordingPass = QD3D11CommandBuffer::NoPass;
@@ -1878,7 +2172,7 @@ void QRhiD3D11::beginComputePass(QRhiCommandBuffer *cb,
cbD->recordingPass = QD3D11CommandBuffer::ComputePass;
- cbD->resetCachedShaderResourceState();
+ cbD->resetCachedState();
}
void QRhiD3D11::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@@ -1928,7 +2222,7 @@ static inline QPair<int, int> mapBinding(int binding,
{
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
+ return { binding, binding }; // assume 1:1 mapping
auto it = map->constFind(binding);
if (it != map->cend())
@@ -1943,31 +2237,21 @@ static inline QPair<int, int> mapBinding(int binding,
void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
{
- srbD->vsubufs.clear();
- srbD->vsubuforigbindings.clear();
- srbD->vsubufoffsets.clear();
- srbD->vsubufsizes.clear();
-
- srbD->fsubufs.clear();
- srbD->fsubuforigbindings.clear();
- srbD->fsubufoffsets.clear();
- srbD->fsubufsizes.clear();
+ srbD->vsUniformBufferBatches.clear();
+ srbD->hsUniformBufferBatches.clear();
+ srbD->dsUniformBufferBatches.clear();
+ srbD->gsUniformBufferBatches.clear();
+ srbD->fsUniformBufferBatches.clear();
+ srbD->csUniformBufferBatches.clear();
- srbD->csubufs.clear();
- srbD->csubuforigbindings.clear();
- srbD->csubufoffsets.clear();
- srbD->csubufsizes.clear();
+ srbD->vsSamplerBatches.clear();
+ srbD->hsSamplerBatches.clear();
+ srbD->dsSamplerBatches.clear();
+ srbD->gsSamplerBatches.clear();
+ srbD->fsSamplerBatches.clear();
+ srbD->csSamplerBatches.clear();
- srbD->vssamplers.clear();
- srbD->vsshaderresources.clear();
-
- srbD->fssamplers.clear();
- srbD->fsshaderresources.clear();
-
- srbD->cssamplers.clear();
- srbD->csshaderresources.clear();
-
- srbD->csUAVs.clear();
+ srbD->csUavBatches.clear();
struct Stage {
struct Buffer {
@@ -1993,16 +2277,40 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
QVarLengthArray<Texture, 8> textures;
QVarLengthArray<Sampler, 8> samplers;
QVarLengthArray<Uav, 8> uavs;
+ void buildBufferBatches(QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches) const
+ {
+ for (const Buffer &buf : buffers) {
+ batches.ubufs.feed(buf.breg, buf.buffer);
+ batches.ubuforigbindings.feed(buf.breg, UINT(buf.binding));
+ batches.ubufoffsets.feed(buf.breg, buf.offsetInConstants);
+ batches.ubufsizes.feed(buf.breg, buf.sizeInConstants);
+ }
+ batches.finish();
+ }
+ void buildSamplerBatches(QD3D11ShaderResourceBindings::StageSamplerBatches &batches) const
+ {
+ for (const Texture &t : textures)
+ batches.shaderresources.feed(t.treg, t.srv);
+ for (const Sampler &s : samplers)
+ batches.samplers.feed(s.sreg, s.sampler);
+ batches.finish();
+ }
+ void buildUavBatches(QD3D11ShaderResourceBindings::StageUavBatches &batches) const
+ {
+ for (const Stage::Uav &u : uavs)
+ batches.uavs.feed(u.ureg, u.uav);
+ batches.finish();
+ }
} res[RBM_SUPPORTED_STAGES];
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
- const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data();
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf);
- Q_ASSERT(aligned(b->u.ubuf.offset, 256) == b->u.ubuf.offset);
+ Q_ASSERT(aligned(b->u.ubuf.offset, 256u) == b->u.ubuf.offset);
bd.ubuf.id = bufD->m_id;
bd.ubuf.generation = bufD->generation;
// Dynamic ubuf offsets are not considered here, those are baked in
@@ -2011,16 +2319,31 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
// Metal) are different in this respect since those do not store
// per-srb vsubufoffsets etc. data so life's a bit easier for them.
// But here we have to defer baking in the dynamic offset.
- const uint offsetInConstants = uint(b->u.ubuf.offset) / 16;
+ const quint32 offsetInConstants = b->u.ubuf.offset / 16;
// size must be 16 mult. (in constants, i.e. multiple of 256 bytes).
// We can round up if needed since the buffers's actual size
// (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 quint32 sizeInConstants = aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256u) / 16;
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
if (nativeBinding.first >= 0)
res[RBM_VERTEX].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
+ if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_HULL].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_DOMAIN].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
+ QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
+ if (nativeBinding.first >= 0)
+ res[RBM_GEOMETRY].buffers.append({ b->binding, nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
+ }
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
if (nativeBinding.first >= 0)
@@ -2034,10 +2357,15 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
}
break;
case QRhiShaderResourceBinding::SampledTexture:
+ case QRhiShaderResourceBinding::Texture:
+ case QRhiShaderResourceBinding::Sampler:
{
- const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
+ const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
bd.stex.count = data->count;
const QPair<int, int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
+ const QPair<int, int> nativeBindingHull = mapBinding(b->binding, RBM_HULL, nativeResourceBindingMaps);
+ const QPair<int, int> nativeBindingDomain = mapBinding(b->binding, RBM_DOMAIN, nativeResourceBindingMaps);
+ const QPair<int, int> nativeBindingGeom = mapBinding(b->binding, RBM_GEOMETRY, nativeResourceBindingMaps);
const QPair<int, int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
const QPair<int, int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
// if SPIR-V binding b is mapped to tN and sN in HLSL, and it
@@ -2046,27 +2374,61 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
for (int elem = 0; elem < data->count; ++elem) {
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, data->texSamplers[elem].tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, data->texSamplers[elem].sampler);
- bd.stex.d[elem].texId = texD->m_id;
- bd.stex.d[elem].texGeneration = texD->generation;
- bd.stex.d[elem].samplerId = samplerD->m_id;
- bd.stex.d[elem].samplerGeneration = samplerD->generation;
+ bd.stex.d[elem].texId = texD ? texD->m_id : 0;
+ bd.stex.d[elem].texGeneration = texD ? texD->generation : 0;
+ bd.stex.d[elem].samplerId = samplerD ? samplerD->m_id : 0;
+ bd.stex.d[elem].samplerGeneration = samplerD ? samplerD->generation : 0;
+ // Must handle all three cases (combined, separate, separate):
+ // first = texture binding, second = sampler binding
+ // first = texture binding
+ // first = sampler binding
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- if (nativeBindingVert.first >= 0 && nativeBindingVert.second >= 0) {
+ const int samplerBinding = texD && samplerD ? nativeBindingVert.second
+ : (samplerD ? nativeBindingVert.first : -1);
+ if (nativeBindingVert.first >= 0 && texD)
res[RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
- res[RBM_VERTEX].samplers.append({ nativeBindingVert.second + elem, samplerD->samplerState });
- }
+ if (samplerBinding >= 0)
+ res[RBM_VERTEX].samplers.append({ samplerBinding + elem, samplerD->samplerState });
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage)) {
+ const int samplerBinding = texD && samplerD ? nativeBindingHull.second
+ : (samplerD ? nativeBindingHull.first : -1);
+ if (nativeBindingHull.first >= 0 && texD)
+ res[RBM_HULL].textures.append({ nativeBindingHull.first + elem, texD->srv });
+ if (samplerBinding >= 0)
+ res[RBM_HULL].samplers.append({ samplerBinding + elem, samplerD->samplerState });
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage)) {
+ const int samplerBinding = texD && samplerD ? nativeBindingDomain.second
+ : (samplerD ? nativeBindingDomain.first : -1);
+ if (nativeBindingDomain.first >= 0 && texD)
+ res[RBM_DOMAIN].textures.append({ nativeBindingDomain.first + elem, texD->srv });
+ if (samplerBinding >= 0)
+ res[RBM_DOMAIN].samplers.append({ samplerBinding + elem, samplerD->samplerState });
+ }
+ if (b->stage.testFlag(QRhiShaderResourceBinding::GeometryStage)) {
+ const int samplerBinding = texD && samplerD ? nativeBindingGeom.second
+ : (samplerD ? nativeBindingGeom.first : -1);
+ if (nativeBindingGeom.first >= 0 && texD)
+ res[RBM_GEOMETRY].textures.append({ nativeBindingGeom.first + elem, texD->srv });
+ if (samplerBinding >= 0)
+ res[RBM_GEOMETRY].samplers.append({ samplerBinding + elem, samplerD->samplerState });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- if (nativeBindingFrag.first >= 0 && nativeBindingFrag.second >= 0) {
+ const int samplerBinding = texD && samplerD ? nativeBindingFrag.second
+ : (samplerD ? nativeBindingFrag.first : -1);
+ if (nativeBindingFrag.first >= 0 && texD)
res[RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
- res[RBM_FRAGMENT].samplers.append({ nativeBindingFrag.second + elem, samplerD->samplerState });
- }
+ if (samplerBinding >= 0)
+ res[RBM_FRAGMENT].samplers.append({ samplerBinding + elem, samplerD->samplerState });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- if (nativeBindingComp.first >= 0 && nativeBindingComp.second >= 0) {
+ const int samplerBinding = texD && samplerD ? nativeBindingComp.second
+ : (samplerD ? nativeBindingComp.first : -1);
+ if (nativeBindingComp.first >= 0 && texD)
res[RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
- res[RBM_COMPUTE].samplers.append({ nativeBindingComp.second + elem, samplerD->samplerState });
- }
+ if (samplerBinding >= 0)
+ res[RBM_COMPUTE].samplers.append({ samplerBinding + elem, samplerD->samplerState });
}
}
}
@@ -2100,7 +2462,7 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
if (nativeBinding.first >= 0) {
- ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView();
+ ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(b->u.sbuf.offset);
if (uav)
res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
}
@@ -2134,63 +2496,21 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
});
}
- for (const Stage::Buffer &buf : qAsConst(res[RBM_VERTEX].buffers)) {
- srbD->vsubufs.feed(buf.breg, buf.buffer);
- srbD->vsubuforigbindings.feed(buf.breg, UINT(buf.binding));
- srbD->vsubufoffsets.feed(buf.breg, buf.offsetInConstants);
- srbD->vsubufsizes.feed(buf.breg, buf.sizeInConstants);
- }
- srbD->vsubufsPresent = srbD->vsubufs.finish();
- srbD->vsubuforigbindings.finish();
- srbD->vsubufoffsets.finish();
- srbD->vsubufsizes.finish();
-
- for (const Stage::Buffer &buf : qAsConst(res[RBM_FRAGMENT].buffers)) {
- srbD->fsubufs.feed(buf.breg, buf.buffer);
- srbD->fsubuforigbindings.feed(buf.breg, UINT(buf.binding));
- srbD->fsubufoffsets.feed(buf.breg, buf.offsetInConstants);
- srbD->fsubufsizes.feed(buf.breg, buf.sizeInConstants);
- }
- srbD->fsubufsPresent = srbD->fsubufs.finish();
- srbD->fsubuforigbindings.finish();
- srbD->fsubufoffsets.finish();
- srbD->fsubufsizes.finish();
-
- for (const Stage::Buffer &buf : qAsConst(res[RBM_COMPUTE].buffers)) {
- srbD->csubufs.feed(buf.breg, buf.buffer);
- srbD->csubuforigbindings.feed(buf.breg, UINT(buf.binding));
- srbD->csubufoffsets.feed(buf.breg, buf.offsetInConstants);
- srbD->csubufsizes.feed(buf.breg, buf.sizeInConstants);
- }
- srbD->csubufsPresent = srbD->csubufs.finish();
- srbD->csubuforigbindings.finish();
- srbD->csubufoffsets.finish();
- srbD->csubufsizes.finish();
-
- for (const Stage::Texture &t : qAsConst(res[RBM_VERTEX].textures))
- srbD->vsshaderresources.feed(t.treg, t.srv);
- for (const Stage::Sampler &s : qAsConst(res[RBM_VERTEX].samplers))
- srbD->vssamplers.feed(s.sreg, s.sampler);
- srbD->vssamplersPresent = srbD->vssamplers.finish();
- srbD->vsshaderresources.finish();
-
- for (const Stage::Texture &t : qAsConst(res[RBM_FRAGMENT].textures))
- srbD->fsshaderresources.feed(t.treg, t.srv);
- for (const Stage::Sampler &s : qAsConst(res[RBM_FRAGMENT].samplers))
- srbD->fssamplers.feed(s.sreg, s.sampler);
- srbD->fssamplersPresent = srbD->fssamplers.finish();
- srbD->fsshaderresources.finish();
-
- for (const Stage::Texture &t : qAsConst(res[RBM_COMPUTE].textures))
- srbD->csshaderresources.feed(t.treg, t.srv);
- for (const Stage::Sampler &s : qAsConst(res[RBM_COMPUTE].samplers))
- srbD->cssamplers.feed(s.sreg, s.sampler);
- srbD->cssamplersPresent = srbD->cssamplers.finish();
- srbD->csshaderresources.finish();
-
- for (const Stage::Uav &u : qAsConst(res[RBM_COMPUTE].uavs))
- srbD->csUAVs.feed(u.ureg, u.uav);
- srbD->csUAVsPresent = srbD->csUAVs.finish();
+ res[RBM_VERTEX].buildBufferBatches(srbD->vsUniformBufferBatches);
+ res[RBM_HULL].buildBufferBatches(srbD->hsUniformBufferBatches);
+ res[RBM_DOMAIN].buildBufferBatches(srbD->dsUniformBufferBatches);
+ res[RBM_GEOMETRY].buildBufferBatches(srbD->gsUniformBufferBatches);
+ res[RBM_FRAGMENT].buildBufferBatches(srbD->fsUniformBufferBatches);
+ res[RBM_COMPUTE].buildBufferBatches(srbD->csUniformBufferBatches);
+
+ res[RBM_VERTEX].buildSamplerBatches(srbD->vsSamplerBatches);
+ res[RBM_HULL].buildSamplerBatches(srbD->hsSamplerBatches);
+ res[RBM_DOMAIN].buildSamplerBatches(srbD->dsSamplerBatches);
+ res[RBM_GEOMETRY].buildSamplerBatches(srbD->gsSamplerBatches);
+ res[RBM_FRAGMENT].buildSamplerBatches(srbD->fsSamplerBatches);
+ res[RBM_COMPUTE].buildSamplerBatches(srbD->csSamplerBatches);
+
+ res[RBM_COMPUTE].buildUavBatches(srbD->csUavBatches);
}
void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD)
@@ -2203,17 +2523,18 @@ void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD)
D3D11_MAPPED_SUBRESOURCE mp;
HRESULT hr = context->Map(bufD->buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
if (SUCCEEDED(hr)) {
- memcpy(mp.pData, bufD->dynBuf, size_t(bufD->m_size));
+ memcpy(mp.pData, bufD->dynBuf, bufD->m_size);
context->Unmap(bufD->buffer, 0);
} else {
- qWarning("Failed to map buffer: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to map buffer: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
}
}
static void applyDynamicOffsets(UINT *offsets,
int batchIndex,
- QRhiBatchedBindings<UINT> *originalBindings,
- QRhiBatchedBindings<UINT> *staticOffsets,
+ const QRhiBatchedBindings<UINT> *originalBindings,
+ const QRhiBatchedBindings<UINT> *staticOffsets,
const uint *dynOfsPairs, int dynOfsPairCount)
{
const int count = staticOffsets->batches[batchIndex].resources.count();
@@ -2244,162 +2565,92 @@ static inline uint clampedResourceCount(uint startSlot, int countSlots, uint max
return countSlots;
}
+#define SETUBUFBATCH(stagePrefixL, stagePrefixU) \
+ if (srbD->stagePrefixL##UniformBufferBatches.present) { \
+ const QD3D11ShaderResourceBindings::StageUniformBufferBatches &batches(srbD->stagePrefixL##UniformBufferBatches); \
+ for (int i = 0, ie = batches.ubufs.batches.count(); i != ie; ++i) { \
+ const uint count = clampedResourceCount(batches.ubufs.batches[i].startBinding, \
+ batches.ubufs.batches[i].resources.count(), \
+ D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, \
+ #stagePrefixU " cbuf"); \
+ if (count) { \
+ if (!dynOfsPairCount) { \
+ context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding, \
+ count, \
+ batches.ubufs.batches[i].resources.constData(), \
+ batches.ubufoffsets.batches[i].resources.constData(), \
+ batches.ubufsizes.batches[i].resources.constData()); \
+ } else { \
+ applyDynamicOffsets(offsets, i, \
+ &batches.ubuforigbindings, &batches.ubufoffsets, \
+ dynOfsPairs, dynOfsPairCount); \
+ context->stagePrefixU##SetConstantBuffers1(batches.ubufs.batches[i].startBinding, \
+ count, \
+ batches.ubufs.batches[i].resources.constData(), \
+ offsets, \
+ batches.ubufsizes.batches[i].resources.constData()); \
+ } \
+ } \
+ } \
+ }
+
+#define SETSAMPLERBATCH(stagePrefixL, stagePrefixU) \
+ if (srbD->stagePrefixL##SamplerBatches.present) { \
+ for (const auto &batch : srbD->stagePrefixL##SamplerBatches.samplers.batches) { \
+ const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(), \
+ D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, #stagePrefixU " sampler"); \
+ if (count) \
+ context->stagePrefixU##SetSamplers(batch.startBinding, count, batch.resources.constData()); \
+ } \
+ for (const auto &batch : srbD->stagePrefixL##SamplerBatches.shaderresources.batches) { \
+ const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(), \
+ D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, #stagePrefixU " SRV"); \
+ if (count) { \
+ context->stagePrefixU##SetShaderResources(batch.startBinding, count, batch.resources.constData()); \
+ contextState.stagePrefixL##HighestActiveSrvBinding = qMax(contextState.stagePrefixL##HighestActiveSrvBinding, \
+ int(batch.startBinding + count) - 1); \
+ } \
+ } \
+ }
+
+#define SETUAVBATCH(stagePrefixL, stagePrefixU) \
+ if (srbD->stagePrefixL##UavBatches.present) { \
+ for (const auto &batch : srbD->stagePrefixL##UavBatches.uavs.batches) { \
+ const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(), \
+ D3D11_1_UAV_SLOT_COUNT, #stagePrefixU " UAV"); \
+ if (count) { \
+ context->stagePrefixU##SetUnorderedAccessViews(batch.startBinding, \
+ count, \
+ batch.resources.constData(), \
+ nullptr); \
+ contextState.stagePrefixL##HighestActiveUavBinding = qMax(contextState.stagePrefixL##HighestActiveUavBinding, \
+ int(batch.startBinding + count) - 1); \
+ } \
+ } \
+ }
+
void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
const uint *dynOfsPairs, int dynOfsPairCount,
bool offsetOnlyChange)
{
UINT offsets[QD3D11CommandBuffer::MAX_DYNAMIC_OFFSET_COUNT];
- if (srbD->vsubufsPresent) {
- for (int i = 0, ie = srbD->vsubufs.batches.count(); i != ie; ++i) {
- const uint count = clampedResourceCount(srbD->vsubufs.batches[i].startBinding,
- srbD->vsubufs.batches[i].resources.count(),
- D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
- "VS cbuf");
- if (count) {
- if (!dynOfsPairCount) {
- context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
- count,
- srbD->vsubufs.batches[i].resources.constData(),
- srbD->vsubufoffsets.batches[i].resources.constData(),
- srbD->vsubufsizes.batches[i].resources.constData());
- } else {
- applyDynamicOffsets(offsets, i, &srbD->vsubuforigbindings, &srbD->vsubufoffsets,
- dynOfsPairs, dynOfsPairCount);
- context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
- count,
- srbD->vsubufs.batches[i].resources.constData(),
- offsets,
- srbD->vsubufsizes.batches[i].resources.constData());
- }
- }
- }
- }
-
- if (srbD->fsubufsPresent) {
- for (int i = 0, ie = srbD->fsubufs.batches.count(); i != ie; ++i) {
- const uint count = clampedResourceCount(srbD->fsubufs.batches[i].startBinding,
- srbD->fsubufs.batches[i].resources.count(),
- D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
- "PS cbuf");
- if (count) {
- if (!dynOfsPairCount) {
- context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
- count,
- srbD->fsubufs.batches[i].resources.constData(),
- srbD->fsubufoffsets.batches[i].resources.constData(),
- srbD->fsubufsizes.batches[i].resources.constData());
- } else {
- applyDynamicOffsets(offsets, i, &srbD->fsubuforigbindings, &srbD->fsubufoffsets,
- dynOfsPairs, dynOfsPairCount);
- context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
- count,
- srbD->fsubufs.batches[i].resources.constData(),
- offsets,
- srbD->fsubufsizes.batches[i].resources.constData());
- }
- }
- }
- }
-
- if (srbD->csubufsPresent) {
- for (int i = 0, ie = srbD->csubufs.batches.count(); i != ie; ++i) {
- const uint count = clampedResourceCount(srbD->csubufs.batches[i].startBinding,
- srbD->csubufs.batches[i].resources.count(),
- D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
- "CS cbuf");
- if (count) {
- if (!dynOfsPairCount) {
- context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
- count,
- srbD->csubufs.batches[i].resources.constData(),
- srbD->csubufoffsets.batches[i].resources.constData(),
- srbD->csubufsizes.batches[i].resources.constData());
- } else {
- applyDynamicOffsets(offsets, i, &srbD->csubuforigbindings, &srbD->csubufoffsets,
- dynOfsPairs, dynOfsPairCount);
- context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
- count,
- srbD->csubufs.batches[i].resources.constData(),
- offsets,
- srbD->csubufsizes.batches[i].resources.constData());
- }
- }
- }
- }
+ SETUBUFBATCH(vs, VS)
+ SETUBUFBATCH(hs, HS)
+ SETUBUFBATCH(ds, DS)
+ SETUBUFBATCH(gs, GS)
+ SETUBUFBATCH(fs, PS)
+ SETUBUFBATCH(cs, CS)
if (!offsetOnlyChange) {
- if (srbD->vssamplersPresent) {
- for (const auto &batch : srbD->vssamplers.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, "VS sampler");
- if (count)
- context->VSSetSamplers(batch.startBinding, count, batch.resources.constData());
- }
-
- for (const auto &batch : srbD->vsshaderresources.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "VS SRV");
- if (count) {
- context->VSSetShaderResources(batch.startBinding, count, batch.resources.constData());
- contextState.vsHighestActiveSrvBinding = qMax(contextState.vsHighestActiveSrvBinding,
- int(batch.startBinding + count) - 1);
- }
- }
- }
-
- if (srbD->fssamplersPresent) {
- for (const auto &batch : srbD->fssamplers.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, "PS sampler");
- if (count)
- context->PSSetSamplers(batch.startBinding, count, batch.resources.constData());
- }
-
- for (const auto &batch : srbD->fsshaderresources.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "PS SRV");
- if (count) {
- context->PSSetShaderResources(batch.startBinding, count, batch.resources.constData());
- contextState.fsHighestActiveSrvBinding = qMax(contextState.fsHighestActiveSrvBinding,
- int(batch.startBinding + count) - 1);
- }
- }
- }
-
- if (srbD->cssamplersPresent) {
- for (const auto &batch : srbD->cssamplers.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, "CS sampler");
- if (count)
- context->CSSetSamplers(batch.startBinding, count, batch.resources.constData());
- }
-
- for (const auto &batch : srbD->csshaderresources.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "CS SRV");
- if (count) {
- context->CSSetShaderResources(batch.startBinding, count, batch.resources.constData());
- contextState.csHighestActiveSrvBinding = qMax(contextState.csHighestActiveSrvBinding,
- int(batch.startBinding + count) - 1);
- }
- }
- }
+ SETSAMPLERBATCH(vs, VS)
+ SETSAMPLERBATCH(hs, HS)
+ SETSAMPLERBATCH(ds, DS)
+ SETSAMPLERBATCH(gs, GS)
+ SETSAMPLERBATCH(fs, PS)
+ SETSAMPLERBATCH(cs, CS)
- if (srbD->csUAVsPresent) {
- for (const auto &batch : srbD->csUAVs.batches) {
- const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
- D3D11_1_UAV_SLOT_COUNT, "CS UAV");
- if (count) {
- context->CSSetUnorderedAccessViews(batch.startBinding,
- count,
- batch.resources.constData(),
- nullptr);
- contextState.csHighestActiveUavBinding = qMax(contextState.csHighestActiveUavBinding,
- int(batch.startBinding + count) - 1);
- }
- }
- }
+ SETUAVBATCH(cs, CS)
}
}
@@ -2428,6 +2679,9 @@ void QRhiD3D11::resetShaderResources()
}
int nullsrvCount = qMax(contextState.vsHighestActiveSrvBinding, contextState.fsHighestActiveSrvBinding);
+ nullsrvCount = qMax(nullsrvCount, contextState.hsHighestActiveSrvBinding);
+ nullsrvCount = qMax(nullsrvCount, contextState.dsHighestActiveSrvBinding);
+ nullsrvCount = qMax(nullsrvCount, contextState.gsHighestActiveSrvBinding);
nullsrvCount = qMax(nullsrvCount, contextState.csHighestActiveSrvBinding);
nullsrvCount += 1;
if (nullsrvCount > 0) {
@@ -2439,6 +2693,18 @@ void QRhiD3D11::resetShaderResources()
context->VSSetShaderResources(0, UINT(contextState.vsHighestActiveSrvBinding + 1), nullsrvs.constData());
contextState.vsHighestActiveSrvBinding = -1;
}
+ if (contextState.hsHighestActiveSrvBinding >= 0) {
+ context->HSSetShaderResources(0, UINT(contextState.hsHighestActiveSrvBinding + 1), nullsrvs.constData());
+ contextState.hsHighestActiveSrvBinding = -1;
+ }
+ if (contextState.dsHighestActiveSrvBinding >= 0) {
+ context->DSSetShaderResources(0, UINT(contextState.dsHighestActiveSrvBinding + 1), nullsrvs.constData());
+ contextState.dsHighestActiveSrvBinding = -1;
+ }
+ if (contextState.gsHighestActiveSrvBinding >= 0) {
+ context->GSSetShaderResources(0, UINT(contextState.gsHighestActiveSrvBinding + 1), nullsrvs.constData());
+ contextState.gsHighestActiveSrvBinding = -1;
+ }
if (contextState.fsHighestActiveSrvBinding >= 0) {
context->PSSetShaderResources(0, UINT(contextState.fsHighestActiveSrvBinding + 1), nullsrvs.constData());
contextState.fsHighestActiveSrvBinding = -1;
@@ -2460,31 +2726,52 @@ void QRhiD3D11::resetShaderResources()
}
}
-void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain)
+#define SETSHADER(StageL, StageU) \
+ if (psD->StageL.shader) { \
+ context->StageU##SetShader(psD->StageL.shader, nullptr, 0); \
+ currentShaderMask |= StageU##MaskBit; \
+ } else if (currentShaderMask & StageU##MaskBit) { \
+ context->StageU##SetShader(nullptr, nullptr, 0); \
+ currentShaderMask &= ~StageU##MaskBit; \
+ }
+
+void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
{
quint32 stencilRef = 0;
float blendConstants[] = { 1, 1, 1, 1 };
-
- if (timestampSwapChain) {
- const int currentFrameSlot = timestampSwapChain->currentFrameSlot;
- ID3D11Query *tsDisjoint = timestampSwapChain->timestampDisjointQuery[currentFrameSlot];
- const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
- ID3D11Query *tsStart = timestampSwapChain->timestampQuery[tsIdx];
- if (tsDisjoint && tsStart && !timestampSwapChain->timestampActive[currentFrameSlot]) {
- // The timestamps seem to include vsync time with Present(1), except
- // when running on a non-primary gpu. This is not ideal. So try working
- // it around by issuing a semi-fake OMSetRenderTargets early and
- // writing the first timestamp only afterwards.
- context->Begin(tsDisjoint);
- QD3D11RenderTargetData *rtD = rtData(&timestampSwapChain->rt);
- context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
- context->End(tsStart); // just record a timestamp, no Begin needed
- }
- }
+ enum ActiveShaderMask {
+ VSMaskBit = 0x01,
+ HSMaskBit = 0x02,
+ DSMaskBit = 0x04,
+ GSMaskBit = 0x08,
+ PSMaskBit = 0x10
+ };
+ int currentShaderMask = 0xFF;
for (auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
const QD3D11CommandBuffer::Command &cmd(*it);
switch (cmd.cmd) {
+ case QD3D11CommandBuffer::Command::BeginFrame:
+ if (cmd.args.beginFrame.tsDisjointQuery)
+ context->Begin(cmd.args.beginFrame.tsDisjointQuery);
+ if (cmd.args.beginFrame.tsQuery) {
+ if (cmd.args.beginFrame.swapchainData) {
+ // The timestamps seem to include vsync time with Present(1), except
+ // when running on a non-primary gpu. This is not ideal. So try working
+ // it around by issuing a semi-fake OMSetRenderTargets early and
+ // writing the first timestamp only afterwards.
+ QD3D11RenderTargetData *rtD = cmd.args.beginFrame.swapchainData;
+ context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
+ }
+ context->End(cmd.args.beginFrame.tsQuery); // no Begin() for D3D11_QUERY_TIMESTAMP
+ }
+ break;
+ case QD3D11CommandBuffer::Command::EndFrame:
+ if (cmd.args.endFrame.tsQuery)
+ context->End(cmd.args.endFrame.tsQuery);
+ if (cmd.args.endFrame.tsDisjointQuery)
+ context->End(cmd.args.endFrame.tsDisjointQuery);
+ break;
case QD3D11CommandBuffer::Command::ResetShaderResources:
resetShaderResources();
break;
@@ -2552,8 +2839,11 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
case QD3D11CommandBuffer::Command::BindGraphicsPipeline:
{
QD3D11GraphicsPipeline *psD = cmd.args.bindGraphicsPipeline.ps;
- context->VSSetShader(psD->vs.shader, nullptr, 0);
- context->PSSetShader(psD->fs.shader, nullptr, 0);
+ SETSHADER(vs, VS)
+ SETSHADER(hs, HS)
+ SETSHADER(ds, DS)
+ SETSHADER(gs, GS)
+ SETSHADER(fs, PS)
context->IASetPrimitiveTopology(psD->d3dTopology);
context->IASetInputLayout(psD->inputLayout); // may be null, that's ok
context->OMSetDepthStencilState(psD->dsState, stencilRef);
@@ -2639,7 +2929,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
}
}
-QD3D11Buffer::QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+QD3D11Buffer::QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
: QRhiBuffer(rhi, type, usage, size)
{
}
@@ -2660,15 +2950,13 @@ void QD3D11Buffer::destroy()
delete[] dynBuf;
dynBuf = nullptr;
- if (uav) {
- uav->Release();
- uav = nullptr;
- }
+ for (auto it = uavs.begin(), end = uavs.end(); it != end; ++it)
+ it.value()->Release();
+ uavs.clear();
QRHI_RES_RHI(QRhiD3D11);
- QRHI_PROF;
- QRHI_PROF_F(releaseBuffer(this));
- rhiD->unregisterResource(this);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
static inline uint toD3DBufferUsage(QRhiBuffer::UsageFlags usage)
@@ -2700,12 +2988,11 @@ bool QD3D11Buffer::create()
return false;
}
- const int nonZeroSize = m_size <= 0 ? 256 : m_size;
- const int roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256 : 4);
+ const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
+ const quint32 roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
- D3D11_BUFFER_DESC desc;
- memset(&desc, 0, sizeof(desc));
- desc.ByteWidth = UINT(roundedSize);
+ D3D11_BUFFER_DESC desc = {};
+ desc.ByteWidth = roundedSize;
desc.Usage = m_type == Dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
desc.BindFlags = toD3DBufferUsage(m_usage);
desc.CPUAccessFlags = m_type == Dynamic ? D3D11_CPU_ACCESS_WRITE : 0;
@@ -2714,7 +3001,8 @@ bool QD3D11Buffer::create()
QRHI_RES_RHI(QRhiD3D11);
HRESULT hr = rhiD->dev->CreateBuffer(&desc, nullptr, &buffer);
if (FAILED(hr)) {
- qWarning("Failed to create buffer: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create buffer: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
@@ -2726,9 +3014,6 @@ bool QD3D11Buffer::create()
if (!m_objectName.isEmpty())
buffer->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
- QRHI_PROF;
- QRHI_PROF_F(newBuffer(this, quint32(roundedSize), m_type == Dynamic ? 2 : 1, m_type == Dynamic ? 1 : 0));
-
generation += 1;
rhiD->registerResource(this);
return true;
@@ -2756,7 +3041,8 @@ char *QD3D11Buffer::beginFullDynamicBufferUpdateForCurrentFrame()
QRHI_RES_RHI(QRhiD3D11);
HRESULT hr = rhiD->context->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mp);
if (FAILED(hr)) {
- qWarning("Failed to map buffer: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to map buffer: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return nullptr;
}
return static_cast<char *>(mp.pData);
@@ -2768,27 +3054,30 @@ void QD3D11Buffer::endFullDynamicBufferUpdateForCurrentFrame()
rhiD->context->Unmap(buffer, 0);
}
-ID3D11UnorderedAccessView *QD3D11Buffer::unorderedAccessView()
+ID3D11UnorderedAccessView *QD3D11Buffer::unorderedAccessView(quint32 offset)
{
- if (uav)
- return uav;
+ auto it = uavs.find(offset);
+ if (it != uavs.end())
+ return it.value();
// SPIRV-Cross generated HLSL uses RWByteAddressBuffer
- D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
- memset(&desc, 0, sizeof(desc));
+ D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
desc.Format = DXGI_FORMAT_R32_TYPELESS;
desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
- desc.Buffer.FirstElement = 0;
- desc.Buffer.NumElements = UINT(aligned(m_size, 4) / 4);
+ desc.Buffer.FirstElement = offset / 4u;
+ desc.Buffer.NumElements = aligned(m_size - offset, 4u) / 4u;
desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
QRHI_RES_RHI(QRhiD3D11);
+ ID3D11UnorderedAccessView *uav = nullptr;
HRESULT hr = rhiD->dev->CreateUnorderedAccessView(buffer, &desc, &uav);
if (FAILED(hr)) {
- qWarning("Failed to create UAV: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create UAV: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return nullptr;
}
+ uavs[offset] = uav;
return uav;
}
@@ -2823,9 +3112,8 @@ void QD3D11RenderBuffer::destroy()
tex = nullptr;
QRHI_RES_RHI(QRhiD3D11);
- QRHI_PROF;
- QRHI_PROF_F(releaseRenderBuffer(this));
- rhiD->unregisterResource(this);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QD3D11RenderBuffer::create()
@@ -2837,10 +3125,9 @@ bool QD3D11RenderBuffer::create()
return false;
QRHI_RES_RHI(QRhiD3D11);
- sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
+ sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
- D3D11_TEXTURE2D_DESC desc;
- memset(&desc, 0, sizeof(desc));
+ D3D11_TEXTURE2D_DESC desc = {};
desc.Width = UINT(m_pixelSize.width());
desc.Height = UINT(m_pixelSize.height());
desc.MipLevels = 1;
@@ -2855,17 +3142,18 @@ bool QD3D11RenderBuffer::create()
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex);
if (FAILED(hr)) {
- qWarning("Failed to create color renderbuffer: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create color renderbuffer: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- memset(&rtvDesc, 0, sizeof(rtvDesc));
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
rtvDesc.Format = dxgiFormat;
rtvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS
: D3D11_RTV_DIMENSION_TEXTURE2D;
hr = rhiD->dev->CreateRenderTargetView(tex, &rtvDesc, &rtv);
if (FAILED(hr)) {
- qWarning("Failed to create rtv: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create rtv: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
} else if (m_type == DepthStencil) {
@@ -2874,17 +3162,18 @@ bool QD3D11RenderBuffer::create()
desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex);
if (FAILED(hr)) {
- qWarning("Failed to create depth-stencil buffer: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create depth-stencil buffer: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
- D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- memset(&dsvDesc, 0, sizeof(dsvDesc));
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
dsvDesc.Format = dxgiFormat;
dsvDesc.ViewDimension = desc.SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
: D3D11_DSV_DIMENSION_TEXTURE2D;
hr = rhiD->dev->CreateDepthStencilView(tex, &dsvDesc, &dsv);
if (FAILED(hr)) {
- qWarning("Failed to create dsv: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create dsv: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
} else {
@@ -2894,9 +3183,7 @@ bool QD3D11RenderBuffer::create()
if (!m_objectName.isEmpty())
tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
- QRHI_PROF;
- QRHI_PROF_F(newRenderBuffer(this, false, false, int(sampleDesc.Count)));
-
+ generation += 1;
rhiD->registerResource(this);
return true;
}
@@ -2910,8 +3197,8 @@ QRhiTexture::Format QD3D11RenderBuffer::backingFormat() const
}
QD3D11Texture::QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags)
+ int arraySize, int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, arraySize, sampleCount, flags)
{
for (int i = 0; i < QRhi::MAX_MIP_LEVELS; ++i)
perLevelViews[i] = nullptr;
@@ -2924,7 +3211,7 @@ QD3D11Texture::~QD3D11Texture()
void QD3D11Texture::destroy()
{
- if (!tex && !tex3D)
+ if (!tex && !tex3D && !tex1D)
return;
if (srv) {
@@ -2944,15 +3231,17 @@ void QD3D11Texture::destroy()
tex->Release();
if (tex3D)
tex3D->Release();
+ if (tex1D)
+ tex1D->Release();
}
tex = nullptr;
tex3D = nullptr;
+ tex1D = nullptr;
QRHI_RES_RHI(QRhiD3D11);
- QRHI_PROF;
- QRHI_PROF_F(releaseTexture(this));
- rhiD->unregisterResource(this);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
static inline DXGI_FORMAT toD3DDepthTextureSRVFormat(QRhiTexture::Format format)
@@ -2978,7 +3267,7 @@ static inline DXGI_FORMAT toD3DDepthTextureDSVFormat(QRhiTexture::Format format)
case QRhiTexture::Format::D16:
return DXGI_FORMAT_D16_UNORM;
case QRhiTexture::Format::D24:
- return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
+ return DXGI_FORMAT_D24_UNORM_S8_UINT;
case QRhiTexture::Format::D24S8:
return DXGI_FORMAT_D24_UNORM_S8_UINT;
case QRhiTexture::Format::D32F:
@@ -2991,19 +3280,23 @@ static inline DXGI_FORMAT toD3DDepthTextureDSVFormat(QRhiTexture::Format format)
bool QD3D11Texture::prepareCreate(QSize *adjustedSize)
{
- if (tex || tex3D)
+ if (tex || tex3D || tex1D)
destroy();
- const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
const bool isDepth = isDepthTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool isArray = m_flags.testFlag(TextureArray);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
+ const bool is1D = m_flags.testFlag(OneDimensional);
+
+ const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
+ : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
QRHI_RES_RHI(QRhiD3D11);
dxgiFormat = toD3DTextureFormat(m_format, m_flags);
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
- sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
+ sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
if (sampleDesc.Count > 1) {
if (isCube) {
qWarning("Cubemap texture cannot be multisample");
@@ -3026,11 +3319,30 @@ bool QD3D11Texture::prepareCreate(QSize *adjustedSize)
qWarning("Texture cannot be both cube and 3D");
return false;
}
- m_depth = qMax(1, m_depth);
+ if (isArray && is3D) {
+ qWarning("Texture cannot be both array and 3D");
+ return false;
+ }
+ if (isCube && is1D) {
+ qWarning("Texture cannot be both cube and 1D");
+ return false;
+ }
+ if (is1D && is3D) {
+ qWarning("Texture cannot be both 1D and 3D");
+ return false;
+ }
if (m_depth > 1 && !is3D) {
qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
return false;
}
+ if (m_arraySize > 0 && !isArray) {
+ qWarning("Texture cannot have an array size of %d when it is not an array", m_arraySize);
+ return false;
+ }
+ if (m_arraySize < 1 && isArray) {
+ qWarning("Texture is an array but array size is %d", m_arraySize);
+ return false;
+ }
if (adjustedSize)
*adjustedSize = size;
@@ -3044,28 +3356,68 @@ bool QD3D11Texture::finishCreate()
const bool isDepth = isDepthTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool isArray = m_flags.testFlag(TextureArray);
+ const bool is1D = m_flags.testFlag(OneDimensional);
- D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
- memset(&srvDesc, 0, sizeof(srvDesc));
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = isDepth ? toD3DDepthTextureSRVFormat(m_format) : dxgiFormat;
if (isCube) {
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
srvDesc.TextureCube.MipLevels = mipLevelCount;
} else {
- if (sampleDesc.Count > 1) {
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
- } else if (is3D) {
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
- srvDesc.Texture3D.MipLevels = mipLevelCount;
+ if (is1D) {
+ if (isArray) {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
+ srvDesc.Texture1DArray.MipLevels = mipLevelCount;
+ if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
+ srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
+ srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
+ } else {
+ srvDesc.Texture1DArray.FirstArraySlice = 0;
+ srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
+ }
+ } else {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
+ srvDesc.Texture1D.MipLevels = mipLevelCount;
+ }
+ } else if (isArray) {
+ if (sampleDesc.Count > 1) {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
+ if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
+ srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
+ srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
+ } else {
+ srvDesc.Texture2DMSArray.FirstArraySlice = 0;
+ srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
+ }
+ } else {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MipLevels = mipLevelCount;
+ if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
+ srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
+ srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
+ } else {
+ srvDesc.Texture2DArray.FirstArraySlice = 0;
+ srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
+ }
+ }
} else {
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- srvDesc.Texture2D.MipLevels = mipLevelCount;
+ if (sampleDesc.Count > 1) {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ } else if (is3D) {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+ srvDesc.Texture3D.MipLevels = mipLevelCount;
+ } else {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MipLevels = mipLevelCount;
+ }
}
}
HRESULT hr = rhiD->dev->CreateShaderResourceView(textureResource(), &srvDesc, &srv);
if (FAILED(hr)) {
- qWarning("Failed to create srv: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create srv: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
@@ -3082,6 +3434,8 @@ bool QD3D11Texture::create()
const bool isDepth = isDepthTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool isArray = m_flags.testFlag(TextureArray);
+ const bool is1D = m_flags.testFlag(OneDimensional);
uint bindFlags = D3D11_BIND_SHADER_RESOURCE;
uint miscFlags = isCube ? D3D11_RESOURCE_MISC_TEXTURECUBE : 0;
@@ -3103,13 +3457,31 @@ bool QD3D11Texture::create()
bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
QRHI_RES_RHI(QRhiD3D11);
- if (!is3D) {
- D3D11_TEXTURE2D_DESC desc;
- memset(&desc, 0, sizeof(desc));
+ if (is1D) {
+ D3D11_TEXTURE1D_DESC desc = {};
+ desc.Width = UINT(size.width());
+ desc.MipLevels = mipLevelCount;
+ desc.ArraySize = isArray ? UINT(qMax(0, m_arraySize)) : 1;
+ desc.Format = dxgiFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = bindFlags;
+ desc.MiscFlags = miscFlags;
+
+ HRESULT hr = rhiD->dev->CreateTexture1D(&desc, nullptr, &tex1D);
+ if (FAILED(hr)) {
+ qWarning("Failed to create 1D texture: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ if (!m_objectName.isEmpty())
+ tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()),
+ m_objectName.constData());
+ } else if (!is3D) {
+ D3D11_TEXTURE2D_DESC desc = {};
desc.Width = UINT(size.width());
desc.Height = UINT(size.height());
desc.MipLevels = mipLevelCount;
- desc.ArraySize = isCube ? 6 : 1;
+ desc.ArraySize = isCube ? 6 : (isArray ? UINT(qMax(0, m_arraySize)) : 1);
desc.Format = dxgiFormat;
desc.SampleDesc = sampleDesc;
desc.Usage = D3D11_USAGE_DEFAULT;
@@ -3118,17 +3490,17 @@ bool QD3D11Texture::create()
HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, &tex);
if (FAILED(hr)) {
- qWarning("Failed to create 2D texture: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create 2D texture: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
if (!m_objectName.isEmpty())
tex->SetPrivateData(WKPDID_D3DDebugObjectName, UINT(m_objectName.size()), m_objectName.constData());
} else {
- D3D11_TEXTURE3D_DESC desc;
- memset(&desc, 0, sizeof(desc));
+ D3D11_TEXTURE3D_DESC desc = {};
desc.Width = UINT(size.width());
desc.Height = UINT(size.height());
- desc.Depth = UINT(m_depth);
+ desc.Depth = UINT(qMax(1, m_depth));
desc.MipLevels = mipLevelCount;
desc.Format = dxgiFormat;
desc.Usage = D3D11_USAGE_DEFAULT;
@@ -3137,7 +3509,8 @@ bool QD3D11Texture::create()
HRESULT hr = rhiD->dev->CreateTexture3D(&desc, nullptr, &tex3D);
if (FAILED(hr)) {
- qWarning("Failed to create 3D texture: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create 3D texture: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
if (!m_objectName.isEmpty())
@@ -3147,9 +3520,6 @@ bool QD3D11Texture::create()
if (!finishCreate())
return false;
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, true, int(mipLevelCount), isCube ? 6 : 1, int(sampleDesc.Count)));
-
owns = true;
rhiD->registerResource(this);
return true;
@@ -3165,15 +3535,14 @@ bool QD3D11Texture::createFrom(QRhiTexture::NativeTexture src)
if (m_flags.testFlag(ThreeDimensional))
tex3D = reinterpret_cast<ID3D11Texture3D *>(src.object);
+ else if (m_flags.testFlags(OneDimensional))
+ tex1D = reinterpret_cast<ID3D11Texture1D *>(src.object);
else
tex = reinterpret_cast<ID3D11Texture2D *>(src.object);
if (!finishCreate())
return false;
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, false, int(mipLevelCount), m_flags.testFlag(CubeMap) ? 6 : 1, int(sampleDesc.Count)));
-
owns = false;
QRHI_RES_RHI(QRhiD3D11);
rhiD->registerResource(this);
@@ -3191,15 +3560,20 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
return perLevelViews[level];
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool isArray = m_flags.testFlag(TextureArray);
const bool is3D = m_flags.testFlag(ThreeDimensional);
- D3D11_UNORDERED_ACCESS_VIEW_DESC desc;
- memset(&desc, 0, sizeof(desc));
+ D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
desc.Format = dxgiFormat;
if (isCube) {
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
desc.Texture2DArray.MipSlice = UINT(level);
desc.Texture2DArray.FirstArraySlice = 0;
desc.Texture2DArray.ArraySize = 6;
+ } else if (isArray) {
+ desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+ desc.Texture2DArray.MipSlice = UINT(level);
+ desc.Texture2DArray.FirstArraySlice = 0;
+ desc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
} else if (is3D) {
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
desc.Texture3D.MipSlice = UINT(level);
@@ -3212,7 +3586,8 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
ID3D11UnorderedAccessView *uav = nullptr;
HRESULT hr = rhiD->dev->CreateUnorderedAccessView(textureResource(), &desc, &uav);
if (FAILED(hr)) {
- qWarning("Failed to create UAV: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create UAV: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return nullptr;
}
@@ -3240,7 +3615,8 @@ void QD3D11Sampler::destroy()
samplerState = nullptr;
QRHI_RES_RHI(QRhiD3D11);
- rhiD->unregisterResource(this);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
static inline D3D11_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
@@ -3320,8 +3696,7 @@ bool QD3D11Sampler::create()
if (samplerState)
destroy();
- D3D11_SAMPLER_DESC desc;
- memset(&desc, 0, sizeof(desc));
+ D3D11_SAMPLER_DESC desc = {};
desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
if (m_compareOp != Never)
desc.Filter = D3D11_FILTER(desc.Filter | 0x80);
@@ -3335,7 +3710,8 @@ bool QD3D11Sampler::create()
QRHI_RES_RHI(QRhiD3D11);
HRESULT hr = rhiD->dev->CreateSamplerState(&desc, &samplerState);
if (FAILED(hr)) {
- qWarning("Failed to create sampler state: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create sampler state: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
@@ -3357,7 +3733,9 @@ QD3D11RenderPassDescriptor::~QD3D11RenderPassDescriptor()
void QD3D11RenderPassDescriptor::destroy()
{
- // nothing to do here
+ QRHI_RES_RHI(QRhiD3D11);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QD3D11RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
@@ -3368,36 +3746,44 @@ bool QD3D11RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot
QRhiRenderPassDescriptor *QD3D11RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
{
- return new QD3D11RenderPassDescriptor(m_rhi);
+ QD3D11RenderPassDescriptor *rpD = new QD3D11RenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiD3D11);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
-QD3D11ReferenceRenderTarget::QD3D11ReferenceRenderTarget(QRhiImplementation *rhi)
- : QRhiRenderTarget(rhi),
+QVector<quint32> QD3D11RenderPassDescriptor::serializedFormat() const
+{
+ return {};
+}
+
+QD3D11SwapChainRenderTarget::QD3D11SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
+ : QRhiSwapChainRenderTarget(rhi, swapchain),
d(rhi)
{
}
-QD3D11ReferenceRenderTarget::~QD3D11ReferenceRenderTarget()
+QD3D11SwapChainRenderTarget::~QD3D11SwapChainRenderTarget()
{
destroy();
}
-void QD3D11ReferenceRenderTarget::destroy()
+void QD3D11SwapChainRenderTarget::destroy()
{
// nothing to do here
}
-QSize QD3D11ReferenceRenderTarget::pixelSize() const
+QSize QD3D11SwapChainRenderTarget::pixelSize() const
{
return d.pixelSize;
}
-float QD3D11ReferenceRenderTarget::devicePixelRatio() const
+float QD3D11SwapChainRenderTarget::devicePixelRatio() const
{
return d.dpr;
}
-int QD3D11ReferenceRenderTarget::sampleCount() const
+int QD3D11SwapChainRenderTarget::sampleCount() const
{
return d.sampleCount;
}
@@ -3421,8 +3807,6 @@ QD3D11TextureRenderTarget::~QD3D11TextureRenderTarget()
void QD3D11TextureRenderTarget::destroy()
{
- QRHI_RES_RHI(QRhiD3D11);
-
if (!rtv[0] && !dsv)
return;
@@ -3440,12 +3824,17 @@ void QD3D11TextureRenderTarget::destroy()
}
}
- rhiD->unregisterResource(this);
+ QRHI_RES_RHI(QRhiD3D11);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
QRhiRenderPassDescriptor *QD3D11TextureRenderTarget::newCompatibleRenderPassDescriptor()
{
- return new QD3D11RenderPassDescriptor(m_rhi);
+ QD3D11RenderPassDescriptor *rpD = new QD3D11RenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiD3D11);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
bool QD3D11TextureRenderTarget::create()
@@ -3453,8 +3842,7 @@ bool QD3D11TextureRenderTarget::create()
if (rtv[0] || dsv)
destroy();
- const bool hasColorAttachments = m_desc.cbeginColorAttachments() != m_desc.cendColorAttachments();
- Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
+ Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
@@ -3470,14 +3858,34 @@ bool QD3D11TextureRenderTarget::create()
Q_ASSERT(texture || rb);
if (texture) {
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, texture);
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- memset(&rtvDesc, 0, sizeof(rtvDesc));
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
rtvDesc.Format = toD3DTextureFormat(texD->format(), texD->flags());
if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
rtvDesc.Texture2DArray.ArraySize = 1;
+ } else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
+ if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
+ rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
+ rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
+ rtvDesc.Texture1DArray.ArraySize = 1;
+ } else {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
+ rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
+ }
+ } else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
+ if (texD->sampleDesc.Count > 1) {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
+ rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
+ rtvDesc.Texture2DMSArray.ArraySize = 1;
+ } else {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
+ rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
+ rtvDesc.Texture2DArray.ArraySize = 1;
+ }
} else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
@@ -3493,7 +3901,8 @@ bool QD3D11TextureRenderTarget::create()
}
HRESULT hr = rhiD->dev->CreateRenderTargetView(texD->textureResource(), &rtvDesc, &rtv[attIndex]);
if (FAILED(hr)) {
- qWarning("Failed to create rtv: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create rtv: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
ownsRtv[attIndex] = true;
@@ -3517,14 +3926,35 @@ bool QD3D11TextureRenderTarget::create()
if (m_desc.depthTexture()) {
ownsDsv = true;
QD3D11Texture *depthTexD = QRHI_RES(QD3D11Texture, m_desc.depthTexture());
- D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
- memset(&dsvDesc, 0, sizeof(dsvDesc));
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
dsvDesc.Format = toD3DDepthTextureDSVFormat(depthTexD->format());
dsvDesc.ViewDimension = depthTexD->sampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS
: D3D11_DSV_DIMENSION_TEXTURE2D;
+ if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
+ if (depthTexD->sampleDesc.Count > 1) {
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
+ if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
+ dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
+ dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
+ } else {
+ dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
+ dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
+ }
+ } else {
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+ if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
+ dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
+ dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
+ } else {
+ dsvDesc.Texture2DArray.FirstArraySlice = 0;
+ dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
+ }
+ }
+ }
HRESULT hr = rhiD->dev->CreateDepthStencilView(depthTexD->tex, &dsvDesc, &dsv);
if (FAILED(hr)) {
- qWarning("Failed to create dsv: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create dsv: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
if (d.colorAttCount == 0) {
@@ -3551,12 +3981,17 @@ bool QD3D11TextureRenderTarget::create()
d.dsv = dsv;
d.rp = QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
+ QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D11Texture, QD3D11RenderBuffer>(m_desc, &d.currentResIdList);
+
rhiD->registerResource(this);
return true;
}
QSize QD3D11TextureRenderTarget::pixelSize() const
{
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D11Texture, QD3D11RenderBuffer>(m_desc, d.currentResIdList))
+ const_cast<QD3D11TextureRenderTarget *>(this)->create();
+
return d.pixelSize;
}
@@ -3584,6 +4019,10 @@ void QD3D11ShaderResourceBindings::destroy()
{
sortedBindings.clear();
boundResourceData.clear();
+
+ QRHI_RES_RHI(QRhiD3D11);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QD3D11ShaderResourceBindings::create()
@@ -3598,11 +4037,7 @@ bool QD3D11ShaderResourceBindings::create()
rhiD->updateLayoutDesc(this);
std::copy(m_bindings.cbegin(), m_bindings.cend(), std::back_inserter(sortedBindings));
- std::sort(sortedBindings.begin(), sortedBindings.end(),
- [](const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
- {
- return a.data()->binding < b.data()->binding;
- });
+ std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
boundResourceData.resize(sortedBindings.count());
@@ -3611,7 +4046,7 @@ bool QD3D11ShaderResourceBindings::create()
hasDynamicOffset = false;
for (const QRhiShaderResourceBinding &b : sortedBindings) {
- const QRhiShaderResourceBinding::Data *bd = b.data();
+ const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
hasDynamicOffset = true;
break;
@@ -3619,9 +4054,24 @@ bool QD3D11ShaderResourceBindings::create()
}
generation += 1;
+ rhiD->registerResource(this, false);
return true;
}
+void QD3D11ShaderResourceBindings::updateResources(UpdateFlags flags)
+{
+ sortedBindings.clear();
+ std::copy(m_bindings.cbegin(), m_bindings.cend(), std::back_inserter(sortedBindings));
+ if (!flags.testFlag(BindingsAreSorted))
+ std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
+
+ Q_ASSERT(boundResourceData.count() == sortedBindings.count());
+ for (BoundResourceData &bd : boundResourceData)
+ memset(&bd, 0, sizeof(BoundResourceData));
+
+ generation += 1;
+}
+
QD3D11GraphicsPipeline::QD3D11GraphicsPipeline(QRhiImplementation *rhi)
: QRhiGraphicsPipeline(rhi)
{
@@ -3632,10 +4082,18 @@ QD3D11GraphicsPipeline::~QD3D11GraphicsPipeline()
destroy();
}
-void QD3D11GraphicsPipeline::destroy()
+template<typename T>
+inline void releasePipelineShader(T &s)
{
- QRHI_RES_RHI(QRhiD3D11);
+ if (s.shader) {
+ s.shader->Release();
+ s.shader = nullptr;
+ }
+ s.nativeResourceBindingMap.clear();
+}
+void QD3D11GraphicsPipeline::destroy()
+{
if (!dsState)
return;
@@ -3657,19 +4115,15 @@ void QD3D11GraphicsPipeline::destroy()
rastState = nullptr;
}
- if (vs.shader) {
- vs.shader->Release();
- vs.shader = nullptr;
- }
- vs.nativeResourceBindingMap.clear();
+ releasePipelineShader(vs);
+ releasePipelineShader(hs);
+ releasePipelineShader(ds);
+ releasePipelineShader(gs);
+ releasePipelineShader(fs);
- if (fs.shader) {
- fs.shader->Release();
- fs.shader = nullptr;
- }
- fs.nativeResourceBindingMap.clear();
-
- rhiD->unregisterResource(this);
+ QRHI_RES_RHI(QRhiD3D11);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
static inline D3D11_CULL_MODE toD3DCullMode(QRhiGraphicsPipeline::CullMode c)
@@ -3687,6 +4141,19 @@ static inline D3D11_CULL_MODE toD3DCullMode(QRhiGraphicsPipeline::CullMode c)
}
}
+static inline D3D11_FILL_MODE toD3DFillMode(QRhiGraphicsPipeline::PolygonMode mode)
+{
+ switch (mode) {
+ case QRhiGraphicsPipeline::Fill:
+ return D3D11_FILL_SOLID;
+ case QRhiGraphicsPipeline::Line:
+ return D3D11_FILL_WIREFRAME;
+ default:
+ Q_UNREACHABLE();
+ return D3D11_FILL_SOLID;
+ }
+}
+
static inline D3D11_COMPARISON_FUNC toD3DCompareOp(QRhiGraphicsPipeline::CompareOp op)
{
switch (op) {
@@ -3770,13 +4237,37 @@ static inline DXGI_FORMAT toD3DAttributeFormat(QRhiVertexInputAttribute::Format
return DXGI_FORMAT_R32G32_SINT;
case QRhiVertexInputAttribute::SInt:
return DXGI_FORMAT_R32_SINT;
+ case QRhiVertexInputAttribute::Half4:
+ // Note: D3D does not support half3. Pass through half3 as half4.
+ case QRhiVertexInputAttribute::Half3:
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+ case QRhiVertexInputAttribute::Half2:
+ return DXGI_FORMAT_R16G16_FLOAT;
+ case QRhiVertexInputAttribute::Half:
+ return DXGI_FORMAT_R16_FLOAT;
+ case QRhiVertexInputAttribute::UShort4:
+ // Note: D3D does not support UShort3. Pass through UShort3 as UShort4.
+ case QRhiVertexInputAttribute::UShort3:
+ return DXGI_FORMAT_R16G16B16A16_UINT;
+ case QRhiVertexInputAttribute::UShort2:
+ return DXGI_FORMAT_R16G16_UINT;
+ case QRhiVertexInputAttribute::UShort:
+ return DXGI_FORMAT_R16_UINT;
+ case QRhiVertexInputAttribute::SShort4:
+ // Note: D3D does not support SShort3. Pass through SShort3 as SShort4.
+ case QRhiVertexInputAttribute::SShort3:
+ return DXGI_FORMAT_R16G16B16A16_SINT;
+ case QRhiVertexInputAttribute::SShort2:
+ return DXGI_FORMAT_R16G16_SINT;
+ case QRhiVertexInputAttribute::SShort:
+ return DXGI_FORMAT_R16_SINT;
default:
Q_UNREACHABLE();
return DXGI_FORMAT_R32G32B32A32_FLOAT;
}
}
-static inline D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topology t)
+static inline D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topology t, int patchControlPointCount)
{
switch (t) {
case QRhiGraphicsPipeline::Triangles:
@@ -3789,6 +4280,9 @@ static inline D3D11_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topol
return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
case QRhiGraphicsPipeline::Points:
return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
+ case QRhiGraphicsPipeline::Patches:
+ Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
+ return D3D11_PRIMITIVE_TOPOLOGY(D3D11_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
default:
Q_UNREACHABLE();
return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
@@ -3879,20 +4373,16 @@ static inline D3D11_BLEND_OP toD3DBlendOp(QRhiGraphicsPipeline::BlendOp op)
}
}
-static pD3DCompile resolveD3DCompile()
+static inline QByteArray sourceHash(const QByteArray &source)
{
- for (const wchar_t *libraryName : {L"D3DCompiler_47", L"D3DCompiler_43"}) {
- QSystemLibrary library(libraryName);
- if (library.load()) {
- if (auto symbol = library.resolve("D3DCompile"))
- return reinterpret_cast<pD3DCompile>(symbol);
- }
- }
- return nullptr;
+ // taken from the GL backend, use the same mechanism to get a key
+ QCryptographicHash keyBuilder(QCryptographicHash::Sha1);
+ keyBuilder.addData(source);
+ return keyBuilder.result().toHex();
}
-static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, UINT flags,
- QString *error, QShaderKey *usedShaderKey)
+QByteArray QRhiD3D11::compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, uint flags,
+ QString *error, QShaderKey *usedShaderKey)
{
QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
QShaderCode dxbc = shader.shader(key);
@@ -3909,6 +4399,9 @@ static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Varian
return QByteArray();
}
+ if (usedShaderKey)
+ *usedShaderKey = key;
+
const char *target;
switch (shader.stage()) {
case QShader::VertexStage:
@@ -3934,7 +4427,18 @@ static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Varian
return QByteArray();
}
- static const pD3DCompile d3dCompile = resolveD3DCompile();
+ BytecodeCacheKey cacheKey;
+ if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave)) {
+ cacheKey.sourceHash = sourceHash(hlslSource.shader());
+ cacheKey.target = target;
+ cacheKey.entryPoint = hlslSource.entryPoint();
+ cacheKey.compileFlags = flags;
+ auto cacheIt = m_bytecodeCache.constFind(cacheKey);
+ if (cacheIt != m_bytecodeCache.constEnd())
+ return cacheIt.value();
+ }
+
+ static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
if (d3dCompile == nullptr) {
qWarning("Unable to resolve function D3DCompile()");
return QByteArray();
@@ -3955,13 +4459,14 @@ static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Varian
return QByteArray();
}
- if (usedShaderKey)
- *usedShaderKey = key;
-
QByteArray result;
result.resize(int(bytecode->GetBufferSize()));
memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
bytecode->Release();
+
+ if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
+ m_bytecodeCache.insert(cacheKey, result);
+
return result;
}
@@ -3971,27 +4476,27 @@ bool QD3D11GraphicsPipeline::create()
destroy();
QRHI_RES_RHI(QRhiD3D11);
+ rhiD->pipelineCreationStart();
if (!rhiD->sanityCheckGraphicsPipeline(this))
return false;
- D3D11_RASTERIZER_DESC rastDesc;
- memset(&rastDesc, 0, sizeof(rastDesc));
- rastDesc.FillMode = D3D11_FILL_SOLID;
+ D3D11_RASTERIZER_DESC rastDesc = {};
+ rastDesc.FillMode = toD3DFillMode(m_polygonMode);
rastDesc.CullMode = toD3DCullMode(m_cullMode);
rastDesc.FrontCounterClockwise = m_frontFace == CCW;
rastDesc.DepthBias = m_depthBias;
rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
rastDesc.DepthClipEnable = true;
rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
- rastDesc.MultisampleEnable = rhiD->effectiveSampleCount(m_sampleCount).Count > 1;
+ rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
if (FAILED(hr)) {
- qWarning("Failed to create rasterizer state: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create rasterizer state: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
- D3D11_DEPTH_STENCIL_DESC dsDesc;
- memset(&dsDesc, 0, sizeof(dsDesc));
+ D3D11_DEPTH_STENCIL_DESC dsDesc = {};
dsDesc.DepthEnable = m_depthTest;
dsDesc.DepthWriteMask = m_depthWrite ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
dsDesc.DepthFunc = toD3DCompareOp(m_depthOp);
@@ -4010,17 +4515,16 @@ bool QD3D11GraphicsPipeline::create()
}
hr = rhiD->dev->CreateDepthStencilState(&dsDesc, &dsState);
if (FAILED(hr)) {
- qWarning("Failed to create depth-stencil state: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create depth-stencil state: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
- D3D11_BLEND_DESC blendDesc;
- memset(&blendDesc, 0, sizeof(blendDesc));
+ D3D11_BLEND_DESC blendDesc = {};
blendDesc.IndependentBlendEnable = m_targetBlends.count() > 1;
for (int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
- D3D11_RENDER_TARGET_BLEND_DESC blend;
- memset(&blend, 0, sizeof(blend));
+ D3D11_RENDER_TARGET_BLEND_DESC blend = {};
blend.BlendEnable = b.enable;
blend.SrcBlend = toD3DBlendFactor(b.srcColor, true);
blend.DestBlend = toD3DBlendFactor(b.dstColor, true);
@@ -4032,19 +4536,19 @@ bool QD3D11GraphicsPipeline::create()
blendDesc.RenderTarget[i] = blend;
}
if (m_targetBlends.isEmpty()) {
- D3D11_RENDER_TARGET_BLEND_DESC blend;
- memset(&blend, 0, sizeof(blend));
+ D3D11_RENDER_TARGET_BLEND_DESC blend = {};
blend.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
blendDesc.RenderTarget[0] = blend;
}
hr = rhiD->dev->CreateBlendState(&blendDesc, &blendState);
if (FAILED(hr)) {
- qWarning("Failed to create blend state: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create blend state: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
QByteArray vsByteCode;
- for (const QRhiShaderStage &shaderStage : qAsConst(m_shaderStages)) {
+ for (const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
auto cacheIt = rhiD->m_shaderCache.constFind(shaderStage);
if (cacheIt != rhiD->m_shaderCache.constEnd()) {
switch (shaderStage.type()) {
@@ -4054,6 +4558,21 @@ bool QD3D11GraphicsPipeline::create()
vsByteCode = cacheIt->bytecode;
vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break;
+ case QRhiShaderStage::TessellationControl:
+ hs.shader = static_cast<ID3D11HullShader *>(cacheIt->s);
+ hs.shader->AddRef();
+ hs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
+ break;
+ case QRhiShaderStage::TessellationEvaluation:
+ ds.shader = static_cast<ID3D11DomainShader *>(cacheIt->s);
+ ds.shader->AddRef();
+ ds.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
+ break;
+ case QRhiShaderStage::Geometry:
+ gs.shader = static_cast<ID3D11GeometryShader *>(cacheIt->s);
+ gs.shader->AddRef();
+ gs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
+ break;
case QRhiShaderStage::Fragment:
fs.shader = static_cast<ID3D11PixelShader *>(cacheIt->s);
fs.shader->AddRef();
@@ -4069,8 +4588,8 @@ bool QD3D11GraphicsPipeline::create()
if (m_flags.testFlag(CompileShadersWithDebugInfo))
compileFlags |= D3DCOMPILE_DEBUG;
- const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
- &error, &shaderKey);
+ const QByteArray bytecode = rhiD->compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), compileFlags,
+ &error, &shaderKey);
if (bytecode.isEmpty()) {
qWarning("HLSL shader compilation failed: %s", qPrintable(error));
return false;
@@ -4085,23 +4604,56 @@ bool QD3D11GraphicsPipeline::create()
case QRhiShaderStage::Vertex:
hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs.shader);
if (FAILED(hr)) {
- qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create vertex shader: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
vsByteCode = bytecode;
- if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
- vs.nativeResourceBindingMap = *map;
+ vs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
vs.shader->AddRef();
break;
+ case QRhiShaderStage::TessellationControl:
+ hr = rhiD->dev->CreateHullShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &hs.shader);
+ if (FAILED(hr)) {
+ qWarning("Failed to create hull shader: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ hs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(hs.shader, bytecode, hs.nativeResourceBindingMap));
+ hs.shader->AddRef();
+ break;
+ case QRhiShaderStage::TessellationEvaluation:
+ hr = rhiD->dev->CreateDomainShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &ds.shader);
+ if (FAILED(hr)) {
+ qWarning("Failed to create domain shader: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ ds.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(ds.shader, bytecode, ds.nativeResourceBindingMap));
+ ds.shader->AddRef();
+ break;
+ case QRhiShaderStage::Geometry:
+ hr = rhiD->dev->CreateGeometryShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &gs.shader);
+ if (FAILED(hr)) {
+ qWarning("Failed to create geometry shader: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ gs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
+ rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(gs.shader, bytecode, gs.nativeResourceBindingMap));
+ gs.shader->AddRef();
+ break;
case QRhiShaderStage::Fragment:
hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs.shader);
if (FAILED(hr)) {
- qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create pixel shader: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
- if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
- fs.nativeResourceBindingMap = *map;
+ fs.nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
fs.shader->AddRef();
break;
@@ -4111,7 +4663,7 @@ bool QD3D11GraphicsPipeline::create()
}
}
- d3dTopology = toD3DTopology(m_topology);
+ d3dTopology = toD3DTopology(m_topology, m_patchControlPointCount);
if (!vsByteCode.isEmpty()) {
QByteArrayList matrixSliceSemantics;
@@ -4119,8 +4671,7 @@ bool QD3D11GraphicsPipeline::create()
for (auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
it != itEnd; ++it)
{
- D3D11_INPUT_ELEMENT_DESC desc;
- memset(&desc, 0, sizeof(desc));
+ D3D11_INPUT_ELEMENT_DESC desc = {};
// The output from SPIRV-Cross uses TEXCOORD<location> as the
// semantic, except for matrices that are unrolled into consecutive
// vec2/3/4s attributes and need TEXCOORD<location>_ as
@@ -4143,7 +4694,7 @@ bool QD3D11GraphicsPipeline::create()
const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
desc.InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
- desc.InstanceDataStepRate = UINT(inputBinding->instanceStepRate());
+ desc.InstanceDataStepRate = inputBinding->instanceStepRate();
} else {
desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
}
@@ -4153,12 +4704,14 @@ bool QD3D11GraphicsPipeline::create()
hr = rhiD->dev->CreateInputLayout(inputDescs.constData(), UINT(inputDescs.count()),
vsByteCode, SIZE_T(vsByteCode.size()), &inputLayout);
if (FAILED(hr)) {
- qWarning("Failed to create input layout: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create input layout: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
} // else leave inputLayout set to nullptr; that's valid and it avoids a debug layer warning about an input layout with 0 elements
}
+ rhiD->pipelineCreationEnd();
generation += 1;
rhiD->registerResource(this);
return true;
@@ -4176,8 +4729,6 @@ QD3D11ComputePipeline::~QD3D11ComputePipeline()
void QD3D11ComputePipeline::destroy()
{
- QRHI_RES_RHI(QRhiD3D11);
-
if (!cs.shader)
return;
@@ -4185,7 +4736,9 @@ void QD3D11ComputePipeline::destroy()
cs.shader = nullptr;
cs.nativeResourceBindingMap.clear();
- rhiD->unregisterResource(this);
+ QRHI_RES_RHI(QRhiD3D11);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QD3D11ComputePipeline::create()
@@ -4194,6 +4747,7 @@ bool QD3D11ComputePipeline::create()
destroy();
QRHI_RES_RHI(QRhiD3D11);
+ rhiD->pipelineCreationStart();
auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
if (cacheIt != rhiD->m_shaderCache.constEnd()) {
@@ -4206,8 +4760,8 @@ bool QD3D11ComputePipeline::create()
if (m_flags.testFlag(CompileShadersWithDebugInfo))
compileFlags |= D3DCOMPILE_DEBUG;
- const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
- &error, &shaderKey);
+ const QByteArray bytecode = rhiD->compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), compileFlags,
+ &error, &shaderKey);
if (bytecode.isEmpty()) {
qWarning("HLSL compute shader compilation failed: %s", qPrintable(error));
return false;
@@ -4215,12 +4769,12 @@ bool QD3D11ComputePipeline::create()
HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs.shader);
if (FAILED(hr)) {
- qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create compute shader: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
- if (const QShader::NativeResourceBindingMap *map = m_shaderStage.shader().nativeResourceBindingMap(shaderKey))
- cs.nativeResourceBindingMap = *map;
+ cs.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
rhiD->clearShaderCache();
@@ -4230,6 +4784,7 @@ bool QD3D11ComputePipeline::create()
cs.shader->AddRef();
+ rhiD->pipelineCreationEnd();
generation += 1;
rhiD->registerResource(this);
return true;
@@ -4251,20 +4806,93 @@ void QD3D11CommandBuffer::destroy()
// nothing to do here
}
+bool QD3D11SwapChainTimestamps::prepare(QRhiD3D11 *rhiD)
+{
+ // Creates the query objects if not yet done, but otherwise calling this
+ // function is expected to be a no-op.
+
+ D3D11_QUERY_DESC queryDesc = {};
+ for (int i = 0; i < TIMESTAMP_PAIRS; ++i) {
+ if (!disjointQuery[i]) {
+ queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
+ HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
+ if (FAILED(hr)) {
+ qWarning("Failed to create timestamp disjoint query: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ }
+ queryDesc.Query = D3D11_QUERY_TIMESTAMP;
+ for (int j = 0; j < 2; ++j) {
+ const int idx = 2 * i + j;
+ if (!query[idx]) {
+ HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
+ if (FAILED(hr)) {
+ qWarning("Failed to create timestamp query: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+void QD3D11SwapChainTimestamps::destroy()
+{
+ for (int i = 0; i < TIMESTAMP_PAIRS; ++i) {
+ active[i] = false;
+ if (disjointQuery[i]) {
+ disjointQuery[i]->Release();
+ disjointQuery[i] = nullptr;
+ }
+ for (int j = 0; j < 2; ++j) {
+ const int idx = TIMESTAMP_PAIRS * i + j;
+ if (query[idx]) {
+ query[idx]->Release();
+ query[idx] = nullptr;
+ }
+ }
+ }
+}
+
+bool QD3D11SwapChainTimestamps::tryQueryTimestamps(int pairIndex, ID3D11DeviceContext *context, double *elapsedSec)
+{
+ bool result = false;
+ if (!active[pairIndex])
+ return result;
+
+ ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
+ ID3D11Query *tsStart = query[pairIndex * 2];
+ ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
+ quint64 timestamps[2];
+ D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
+
+ bool ok = true;
+ ok &= context->GetData(tsDisjoint, &dj, sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
+ ok &= context->GetData(tsEnd, &timestamps[1], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
+ ok &= context->GetData(tsStart, &timestamps[0], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
+
+ if (ok) {
+ if (!dj.Disjoint && dj.Frequency) {
+ const float elapsedMs = (timestamps[1] - timestamps[0]) / float(dj.Frequency) * 1000.0f;
+ *elapsedSec = elapsedMs / 1000.0;
+ result = true;
+ }
+ active[pairIndex] = false;
+ } // else leave active set, will retry in a subsequent beginFrame
+
+ return result;
+}
+
QD3D11SwapChain::QD3D11SwapChain(QRhiImplementation *rhi)
- : QRhiSwapChain(rhi),
- rt(rhi),
- cb(rhi)
+ : QRhiSwapChain(rhi), rt(rhi, this), rtRight(rhi, this), cb(rhi)
{
backBufferTex = nullptr;
backBufferRtv = nullptr;
for (int i = 0; i < BUFFER_COUNT; ++i) {
msaaTex[i] = nullptr;
msaaRtv[i] = nullptr;
- timestampActive[i] = false;
- timestampDisjointQuery[i] = nullptr;
- timestampQuery[2 * i] = nullptr;
- timestampQuery[2 * i + 1] = nullptr;
}
}
@@ -4279,6 +4907,10 @@ void QD3D11SwapChain::releaseBuffers()
backBufferRtv->Release();
backBufferRtv = nullptr;
}
+ if (backBufferRtvRight) {
+ backBufferRtvRight->Release();
+ backBufferRtvRight = nullptr;
+ }
if (backBufferTex) {
backBufferTex->Release();
backBufferTex = nullptr;
@@ -4302,28 +4934,28 @@ void QD3D11SwapChain::destroy()
releaseBuffers();
- for (int i = 0; i < BUFFER_COUNT; ++i) {
- if (timestampDisjointQuery[i]) {
- timestampDisjointQuery[i]->Release();
- timestampDisjointQuery[i] = nullptr;
- }
- for (int j = 0; j < 2; ++j) {
- const int idx = BUFFER_COUNT * i + j;
- if (timestampQuery[idx]) {
- timestampQuery[idx]->Release();
- timestampQuery[idx] = nullptr;
- }
- }
- }
+ timestamps.destroy();
swapChain->Release();
swapChain = nullptr;
- QRHI_PROF;
- QRHI_PROF_F(releaseSwapChain(this));
+ if (dcompVisual) {
+ dcompVisual->Release();
+ dcompVisual = nullptr;
+ }
+
+ if (dcompTarget) {
+ dcompTarget->Release();
+ dcompTarget = nullptr;
+ }
QRHI_RES_RHI(QRhiD3D11);
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->unregisterResource(this);
+ // See Deferred Destruction Issues with Flip Presentation Swap Chains in
+ // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-flush
+ rhiD->context->Flush();
+ }
}
QRhiCommandBuffer *QD3D11SwapChain::currentFrameCommandBuffer()
@@ -4336,22 +4968,67 @@ QRhiRenderTarget *QD3D11SwapChain::currentFrameRenderTarget()
return &rt;
}
+QRhiRenderTarget *QD3D11SwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
+{
+ return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
+}
+
QSize QD3D11SwapChain::surfacePixelSize()
{
Q_ASSERT(m_window);
return m_window->size() * m_window->devicePixelRatio();
}
+bool QD3D11SwapChain::isFormatSupported(Format f)
+{
+ if (f == SDR)
+ return true;
+
+ if (!m_window) {
+ qWarning("Attempted to call isFormatSupported() without a window set");
+ return false;
+ }
+
+ QRHI_RES_RHI(QRhiD3D11);
+ DXGI_OUTPUT_DESC1 desc1;
+ if (QRhiD3D::outputDesc1ForWindow(m_window, rhiD->activeAdapter, &desc1)) {
+ if (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)
+ return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
+ }
+
+ return false;
+}
+
+QRhiSwapChainHdrInfo QD3D11SwapChain::hdrInfo()
+{
+ QRhiSwapChainHdrInfo info = QRhiSwapChain::hdrInfo();
+ // Must use m_window, not window, given this may be called before createOrResize().
+ if (m_window) {
+ QRHI_RES_RHI(QRhiD3D11);
+ DXGI_OUTPUT_DESC1 hdrOutputDesc;
+ if (QRhiD3D::outputDesc1ForWindow(m_window, rhiD->activeAdapter, &hdrOutputDesc)) {
+ info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
+ info.limits.luminanceInNits.minLuminance = hdrOutputDesc.MinLuminance;
+ info.limits.luminanceInNits.maxLuminance = hdrOutputDesc.MaxLuminance;
+ info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred; // 1.0 = 80 nits
+ info.sdrWhiteLevel = QRhiD3D::sdrWhiteLevelInNits(hdrOutputDesc);
+ }
+ }
+ return info;
+}
+
QRhiRenderPassDescriptor *QD3D11SwapChain::newCompatibleRenderPassDescriptor()
{
- return new QD3D11RenderPassDescriptor(m_rhi);
+ QD3D11RenderPassDescriptor *rpD = new QD3D11RenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiD3D11);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
bool QD3D11SwapChain::newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const
{
- D3D11_TEXTURE2D_DESC desc;
- memset(&desc, 0, sizeof(desc));
+ D3D11_TEXTURE2D_DESC desc = {};
desc.Width = UINT(size.width());
desc.Height = UINT(size.height());
desc.MipLevels = 1;
@@ -4364,17 +5041,18 @@ bool QD3D11SwapChain::newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI
QRHI_RES_RHI(QRhiD3D11);
HRESULT hr = rhiD->dev->CreateTexture2D(&desc, nullptr, tex);
if (FAILED(hr)) {
- qWarning("Failed to create color buffer texture: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create color buffer texture: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- memset(&rtvDesc, 0, sizeof(rtvDesc));
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
rtvDesc.Format = format;
rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
hr = rhiD->dev->CreateRenderTargetView(*tex, &rtvDesc, rtv);
if (FAILED(hr)) {
- qWarning("Failed to create color buffer rtv: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create color buffer rtv: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
(*tex)->Release();
*tex = nullptr;
return false;
@@ -4383,6 +5061,19 @@ bool QD3D11SwapChain::newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI
return true;
}
+bool QRhiD3D11::ensureDirectCompositionDevice()
+{
+ if (dcompDevice)
+ return true;
+
+ qCDebug(QRHI_LOG_INFO, "Creating Direct Composition device (needed for semi-transparent windows)");
+ dcompDevice = QRhiD3D::createDirectCompositionDevice();
+ return dcompDevice ? true : false;
+}
+
+static const DXGI_FORMAT DEFAULT_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM;
+static const DXGI_FORMAT DEFAULT_SRGB_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+
bool QD3D11SwapChain::createOrResize()
{
// Can be called multiple times due to window resizes - that is not the
@@ -4390,6 +5081,7 @@ bool QD3D11SwapChain::createOrResize()
// resize the buffers then.
const bool needsRegistration = !window || window != m_window;
+ const bool stereo = m_window->format().stereo();
// except if the window actually changes
if (window && window != m_window)
@@ -4402,101 +5094,183 @@ bool QD3D11SwapChain::createOrResize()
if (pixelSize.isEmpty())
return false;
- colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
- const DXGI_FORMAT srgbAdjustedFormat = m_flags.testFlag(sRGB) ?
- DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
-
- const UINT swapChainFlags = 0;
+ HWND hwnd = reinterpret_cast<HWND>(window->winId());
+ HRESULT hr;
QRHI_RES_RHI(QRhiD3D11);
- bool useFlipDiscard = rhiD->hasDxgi2 && rhiD->supportsFlipDiscardSwapchain;
+
+ if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
+ if (!rhiD->useLegacySwapchainModel && rhiD->ensureDirectCompositionDevice()) {
+ if (!dcompTarget) {
+ hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd, false, &dcompTarget);
+ if (FAILED(hr)) {
+ qWarning("Failed to create Direct Compsition target for the window: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ }
+ }
+ if (dcompTarget && !dcompVisual) {
+ hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
+ if (FAILED(hr)) {
+ qWarning("Failed to create DirectComposition visual: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ }
+ }
+ }
+ // simple consistency check
+ if (window->requestedFormat().alphaBufferSize() <= 0)
+ qWarning("Swapchain says surface has alpha but the window has no alphaBufferSize set. "
+ "This may lead to problems.");
+ }
+
+ swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
+ swapChainFlags = 0;
+
+ // A non-flip swapchain can do Present(0) as expected without
+ // ALLOW_TEARING, and ALLOW_TEARING is not compatible with it at all so the
+ // flag must not be set then. Whereas for flip we should use it, if
+ // supported, to get better results for 'unthrottled' presentation.
+ if (swapInterval == 0 && rhiD->supportsAllowTearing)
+ swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
+
if (!swapChain) {
- HWND hwnd = reinterpret_cast<HWND>(window->winId());
- sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
-
- // Take a shortcut for alpha: our QWindow is OpenGLSurface so whatever
- // the platform plugin does to enable transparency for OpenGL window
- // will be sufficient for us too on the legacy (DISCARD) path. For
- // FLIP_DISCARD we'd need to use DirectComposition (create a
- // IDCompositionDevice/Target/Visual), avoid that for now.
- if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
- useFlipDiscard = false;
- if (window->requestedFormat().alphaBufferSize() <= 0)
- qWarning("Swapchain says surface has alpha but the window has no alphaBufferSize set. "
- "This may lead to problems.");
+ sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
+ colorFormat = DEFAULT_FORMAT;
+ srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
+
+ DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; // SDR
+ DXGI_OUTPUT_DESC1 hdrOutputDesc;
+ if (QRhiD3D::outputDesc1ForWindow(m_window, rhiD->activeAdapter, &hdrOutputDesc) && m_format != SDR) {
+ // https://docs.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range
+ if (hdrOutputDesc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
+ switch (m_format) {
+ case HDRExtendedSrgbLinear:
+ colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
+ hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
+ srgbAdjustedColorFormat = colorFormat;
+ break;
+ case HDR10:
+ colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
+ hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
+ srgbAdjustedColorFormat = colorFormat;
+ break;
+ default:
+ break;
+ }
+ } else {
+ // This happens also when Use HDR is set to Off in the Windows
+ // Display settings. Show a helpful warning, but continue with the
+ // default non-HDR format.
+ qWarning("The output associated with the window is not HDR capable "
+ "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
+ }
}
- HRESULT hr;
- if (useFlipDiscard) {
- // We use FLIP_DISCARD which implies a buffer count of 2 (as opposed to the
- // old DISCARD with back buffer count == 1). This makes no difference for
- // the rest of the stuff except that automatic MSAA is unsupported and
- // needs to be implemented via a custom multisample render target and an
- // explicit resolve.
-
- DXGI_SWAP_CHAIN_DESC1 desc;
- memset(&desc, 0, sizeof(desc));
- desc.Width = UINT(pixelSize.width());
- desc.Height = UINT(pixelSize.height());
- desc.Format = colorFormat;
- desc.SampleDesc.Count = 1;
- desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- desc.BufferCount = BUFFER_COUNT;
+ // We use a FLIP model swapchain which implies a buffer count of 2
+ // (as opposed to the old DISCARD with back buffer count == 1).
+ // This makes no difference for the rest of the stuff except that
+ // automatic MSAA is unsupported and needs to be implemented via a
+ // custom multisample render target and an explicit resolve.
+
+ DXGI_SWAP_CHAIN_DESC1 desc = {};
+ desc.Width = UINT(pixelSize.width());
+ desc.Height = UINT(pixelSize.height());
+ desc.Format = colorFormat;
+ desc.SampleDesc.Count = 1;
+ desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ desc.BufferCount = BUFFER_COUNT;
+ desc.Flags = swapChainFlags;
+ desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
+ desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ desc.Stereo = stereo;
+
+ if (dcompVisual) {
+ // With DirectComposition setting AlphaMode to STRAIGHT fails the
+ // swapchain creation, whereas the result seems to be identical
+ // with any of the other values, including IGNORE. (?)
+ desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
+
+ // DirectComposition has its own limitations, cannot use
+ // SCALING_NONE. So with semi-transparency requested we are forced
+ // to SCALING_STRETCH.
desc.Scaling = DXGI_SCALING_STRETCH;
- desc.SwapEffect = DXGI_SWAP_EFFECT(4); // DXGI_SWAP_EFFECT_FLIP_DISCARD
- // Do not bother with AlphaMode, if won't work unless we go through
- // DirectComposition. Instead, we just take the other (DISCARD)
- // path for now when alpha is requested.
- desc.Flags = swapChainFlags;
-
- IDXGISwapChain1 *sc1;
- hr = static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory)->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc,
- nullptr, nullptr, &sc1);
- if (SUCCEEDED(hr))
- swapChain = sc1;
- } else {
- // Windows 7 for instance. Use DISCARD mode. Regardless, keep on
- // using our manual resolve for symmetry with the FLIP_DISCARD code
- // path when MSAA is requested.
-
- DXGI_SWAP_CHAIN_DESC desc;
- memset(&desc, 0, sizeof(desc));
- desc.BufferDesc.Width = UINT(pixelSize.width());
- desc.BufferDesc.Height = UINT(pixelSize.height());
- desc.BufferDesc.RefreshRate.Numerator = 60;
- desc.BufferDesc.RefreshRate.Denominator = 1;
- desc.BufferDesc.Format = colorFormat;
- desc.SampleDesc.Count = 1;
- desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- desc.BufferCount = 1;
- desc.OutputWindow = hwnd;
- desc.Windowed = true;
- desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
- desc.Flags = swapChainFlags;
-
- hr = rhiD->dxgiFactory->CreateSwapChain(rhiD->dev, &desc, &swapChain);
+ }
+
+ IDXGIFactory2 *fac = static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
+ IDXGISwapChain1 *sc1;
+
+ if (dcompVisual)
+ hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc, nullptr, &sc1);
+ else
+ hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc, nullptr, nullptr, &sc1);
+
+ // If failed and we tried a HDR format, then try with SDR. This
+ // matches other backends, such as Vulkan where if the format is
+ // not supported, the default one is used instead.
+ if (FAILED(hr) && m_format != SDR) {
+ colorFormat = DEFAULT_FORMAT;
+ desc.Format = DEFAULT_FORMAT;
+ if (dcompVisual)
+ hr = fac->CreateSwapChainForComposition(rhiD->dev, &desc, nullptr, &sc1);
+ else
+ hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc, nullptr, nullptr, &sc1);
+ }
+
+ if (SUCCEEDED(hr)) {
+ swapChain = sc1;
+ if (m_format != SDR) {
+ IDXGISwapChain3 *sc3 = nullptr;
+ if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3), reinterpret_cast<void **>(&sc3)))) {
+ hr = sc3->SetColorSpace1(hdrColorSpace);
+ if (FAILED(hr))
+ qWarning("Failed to set color space on swapchain: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ sc3->Release();
+ } else {
+ qWarning("IDXGISwapChain3 not available, HDR swapchain will not work as expected");
+ }
+ }
+ if (dcompVisual) {
+ hr = dcompVisual->SetContent(sc1);
+ if (SUCCEEDED(hr)) {
+ hr = dcompTarget->SetRoot(dcompVisual);
+ if (FAILED(hr)) {
+ qWarning("Failed to associate Direct Composition visual with the target: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ }
+ } else {
+ qWarning("Failed to set content for Direct Composition visual: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ }
+ } else {
+ // disable Alt+Enter; not relevant when using DirectComposition
+ rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
+ }
}
if (FAILED(hr)) {
- qWarning("Failed to create D3D11 swapchain: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create D3D11 swapchain: %s"
+ " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
+ qPrintable(QSystemError::windowsComString(hr)),
+ desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
+ desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
return false;
}
- rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
} else {
releaseBuffers();
- const UINT count = useFlipDiscard ? BUFFER_COUNT : 1;
- HRESULT hr = swapChain->ResizeBuffers(count, UINT(pixelSize.width()), UINT(pixelSize.height()),
- colorFormat, swapChainFlags);
+ // flip model -> buffer count is the real buffer count, not 1 like with the legacy modes
+ hr = swapChain->ResizeBuffers(UINT(BUFFER_COUNT), UINT(pixelSize.width()), UINT(pixelSize.height()),
+ colorFormat, swapChainFlags);
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
qWarning("Device loss detected in ResizeBuffers()");
rhiD->deviceLost = true;
return false;
} else if (FAILED(hr)) {
- qWarning("Failed to resize D3D11 swapchain: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to resize D3D11 swapchain: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
}
- // This looks odd (for FLIP_DISCARD, esp. compared with backends for Vulkan
+ // This looks odd (for FLIP_*, esp. compared with backends for Vulkan
// & co.) but the backbuffer is always at index 0, with magic underneath.
// Some explanation from
// https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/dxgi-1-4-improvements
@@ -4510,25 +5284,39 @@ bool QD3D11SwapChain::createOrResize()
// swapchain."
// So just query index 0 once (per resize) and be done with it.
- HRESULT hr = swapChain->GetBuffer(0, IID_ID3D11Texture2D, reinterpret_cast<void **>(&backBufferTex));
+ hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&backBufferTex));
if (FAILED(hr)) {
- qWarning("Failed to query swapchain backbuffer: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to query swapchain backbuffer: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
- D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
- memset(&rtvDesc, 0, sizeof(rtvDesc));
- rtvDesc.Format = srgbAdjustedFormat;
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
+ rtvDesc.Format = srgbAdjustedColorFormat;
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
if (FAILED(hr)) {
- qWarning("Failed to create rtv for swapchain backbuffer: %s", qPrintable(comErrorMessage(hr)));
+ qWarning("Failed to create rtv for swapchain backbuffer: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
return false;
}
+ if (stereo) {
+ // Create a second render target view for the right eye
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.FirstArraySlice = 1;
+ rtvDesc.Texture2DArray.ArraySize = 1;
+ hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
+ if (FAILED(hr)) {
+ qWarning("Failed to create rtv for swapchain backbuffer (right eye): %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ }
+
// Try to reduce stalls by having a dedicated MSAA texture per swapchain buffer.
for (int i = 0; i < BUFFER_COUNT; ++i) {
if (sampleDesc.Count > 1) {
- if (!newColorBuffer(pixelSize, srgbAdjustedFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
+ if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
return false;
}
}
@@ -4553,9 +5341,9 @@ bool QD3D11SwapChain::createOrResize()
currentFrameSlot = 0;
frameCount = 0;
ds = m_depthStencil ? QRHI_RES(QD3D11RenderBuffer, m_depthStencil) : nullptr;
- swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
- QD3D11ReferenceRenderTarget *rtD = QRHI_RES(QD3D11ReferenceRenderTarget, &rt);
+ rt.setRenderPassDescriptor(m_renderPassDesc); // for the public getter in QRhiRenderTarget
+ QD3D11SwapChainRenderTarget *rtD = QRHI_RES(QD3D11SwapChainRenderTarget, &rt);
rtD->d.rp = QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
rtD->d.pixelSize = pixelSize;
rtD->d.dpr = float(window->devicePixelRatio());
@@ -4563,32 +5351,20 @@ bool QD3D11SwapChain::createOrResize()
rtD->d.colorAttCount = 1;
rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
- QRHI_PROF;
- QRHI_PROF_F(resizeSwapChain(this, BUFFER_COUNT, sampleDesc.Count > 1 ? BUFFER_COUNT : 0, int(sampleDesc.Count)));
- if (rhiP) {
- D3D11_QUERY_DESC queryDesc;
- memset(&queryDesc, 0, sizeof(queryDesc));
- for (int i = 0; i < BUFFER_COUNT; ++i) {
- if (!timestampDisjointQuery[i]) {
- queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
- HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &timestampDisjointQuery[i]);
- if (FAILED(hr)) {
- qWarning("Failed to create timestamp disjoint query: %s", qPrintable(comErrorMessage(hr)));
- break;
- }
- }
- queryDesc.Query = D3D11_QUERY_TIMESTAMP;
- for (int j = 0; j < 2; ++j) {
- const int idx = BUFFER_COUNT * i + j; // one pair per buffer (frame)
- if (!timestampQuery[idx]) {
- HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &timestampQuery[idx]);
- if (FAILED(hr)) {
- qWarning("Failed to create timestamp query: %s", qPrintable(comErrorMessage(hr)));
- break;
- }
- }
- }
- }
+ if (stereo) {
+ rtD = QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
+ rtD->d.rp = QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
+ rtD->d.pixelSize = pixelSize;
+ rtD->d.dpr = float(window->devicePixelRatio());
+ rtD->d.sampleCount = int(sampleDesc.Count);
+ rtD->d.colorAttCount = 1;
+ rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
+ rtD->d.rtv[0] = backBufferRtvRight;
+ rtD->d.dsv = ds ? ds->dsv : nullptr;
+ }
+
+ if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
+ timestamps.prepare(rhiD);
// timestamp queries are optional so we can go on even if they failed
}
@@ -4598,34 +5374,4 @@ bool QD3D11SwapChain::createOrResize()
return true;
}
-void QRhiD3D11::DeviceCurse::initResources()
-{
- framesLeft = framesToActivate;
-
- HRESULT hr = q->dev->CreateComputeShader(g_killDeviceByTimingOut, sizeof(g_killDeviceByTimingOut), nullptr, &cs);
- if (FAILED(hr)) {
- qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
- return;
- }
-}
-
-void QRhiD3D11::DeviceCurse::releaseResources()
-{
- if (cs) {
- cs->Release();
- cs = nullptr;
- }
-}
-
-void QRhiD3D11::DeviceCurse::activate()
-{
- if (!cs)
- return;
-
- qDebug("Activating Curse. Goodbye Cruel World.");
-
- q->context->CSSetShader(cs, nullptr, 0);
- q->context->Dispatch(256, 1, 1);
-}
-
QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhid3d11_p.h b/src/gui/rhi/qrhid3d11_p.h
index ed26e9af16..7644748407 100644
--- a/src/gui/rhi/qrhid3d11_p.h
+++ b/src/gui/rhi/qrhid3d11_p.h
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHID3D11_H
-#define QRHID3D11_H
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHID3D11_P_H
+#define QRHID3D11_P_H
//
// W A R N I N G
@@ -51,31 +15,852 @@
// We mean it.
//
-#include <private/qrhi_p.h>
+#include "qrhi_p.h"
+#include <rhi/qshaderdescription.h>
+#include <QWindow>
-// no d3d includes here, to prevent precompiled header mess due to COM
+#include <d3d11_1.h>
+#include <dxgi1_6.h>
+#include <dcomp.h>
QT_BEGIN_NAMESPACE
-struct Q_GUI_EXPORT QRhiD3D11InitParams : public QRhiInitParams
+class QRhiD3D11;
+
+struct QD3D11Buffer : public QRhiBuffer
+{
+ QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
+ ~QD3D11Buffer();
+ void destroy() override;
+ bool create() override;
+ QRhiBuffer::NativeBuffer nativeBuffer() override;
+ char *beginFullDynamicBufferUpdateForCurrentFrame() override;
+ void endFullDynamicBufferUpdateForCurrentFrame() override;
+
+ ID3D11UnorderedAccessView *unorderedAccessView(quint32 offset);
+
+ ID3D11Buffer *buffer = nullptr;
+ char *dynBuf = nullptr;
+ bool hasPendingDynamicUpdates = false;
+ QHash<quint32, ID3D11UnorderedAccessView *> uavs;
+ uint generation = 0;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11RenderBuffer : public QRhiRenderBuffer
+{
+ QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint);
+ ~QD3D11RenderBuffer();
+ void destroy() override;
+ bool create() override;
+ QRhiTexture::Format backingFormat() const override;
+
+ ID3D11Texture2D *tex = nullptr;
+ ID3D11DepthStencilView *dsv = nullptr;
+ ID3D11RenderTargetView *rtv = nullptr;
+ DXGI_FORMAT dxgiFormat;
+ DXGI_SAMPLE_DESC sampleDesc;
+ uint generation = 0;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11Texture : public QRhiTexture
+{
+ QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
+ int arraySize, int sampleCount, Flags flags);
+ ~QD3D11Texture();
+ void destroy() override;
+ bool create() override;
+ bool createFrom(NativeTexture src) override;
+ NativeTexture nativeTexture() override;
+
+ bool prepareCreate(QSize *adjustedSize = nullptr);
+ bool finishCreate();
+ ID3D11UnorderedAccessView *unorderedAccessViewForLevel(int level);
+ ID3D11Resource *textureResource() const
+ {
+ if (tex)
+ return tex;
+ else if (tex1D)
+ return tex1D;
+ return tex3D;
+ }
+
+ ID3D11Texture2D *tex = nullptr;
+ ID3D11Texture3D *tex3D = nullptr;
+ ID3D11Texture1D *tex1D = nullptr;
+ bool owns = true;
+ ID3D11ShaderResourceView *srv = nullptr;
+ DXGI_FORMAT dxgiFormat;
+ uint mipLevelCount = 0;
+ DXGI_SAMPLE_DESC sampleDesc;
+ ID3D11UnorderedAccessView *perLevelViews[QRhi::MAX_MIP_LEVELS];
+ uint generation = 0;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11Sampler : public QRhiSampler
+{
+ QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v, AddressMode w);
+ ~QD3D11Sampler();
+ void destroy() override;
+ bool create() override;
+
+ ID3D11SamplerState *samplerState = nullptr;
+ uint generation = 0;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11RenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QD3D11RenderPassDescriptor(QRhiImplementation *rhi);
+ ~QD3D11RenderPassDescriptor();
+ void destroy() override;
+ bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
+ QVector<quint32> serializedFormat() const override;
+};
+
+struct QD3D11RenderTargetData
+{
+ QD3D11RenderTargetData(QRhiImplementation *)
+ {
+ for (int i = 0; i < MAX_COLOR_ATTACHMENTS; ++i)
+ rtv[i] = nullptr;
+ }
+
+ QD3D11RenderPassDescriptor *rp = nullptr;
+ QSize pixelSize;
+ float dpr = 1;
+ int sampleCount = 1;
+ int colorAttCount = 0;
+ int dsAttCount = 0;
+
+ static const int MAX_COLOR_ATTACHMENTS = 8;
+ ID3D11RenderTargetView *rtv[MAX_COLOR_ATTACHMENTS];
+ ID3D11DepthStencilView *dsv = nullptr;
+
+ QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList;
+};
+
+struct QD3D11SwapChainRenderTarget : public QRhiSwapChainRenderTarget
+{
+ QD3D11SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
+ ~QD3D11SwapChainRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QD3D11RenderTargetData d;
+};
+
+struct QD3D11TextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
+ ~QD3D11TextureRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool create() override;
+
+ QD3D11RenderTargetData d;
+ bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
+ ID3D11RenderTargetView *rtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
+ bool ownsDsv = false;
+ ID3D11DepthStencilView *dsv = nullptr;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QD3D11ShaderResourceBindings(QRhiImplementation *rhi);
+ ~QD3D11ShaderResourceBindings();
+ void destroy() override;
+ bool create() override;
+ void updateResources(UpdateFlags flags) override;
+
+ bool hasDynamicOffset = false;
+ QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
+ uint generation = 0;
+
+ // Keep track of the generation number of each referenced QRhi* to be able
+ // to detect that the batched bindings are out of date.
+ struct BoundUniformBufferData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundSampledTextureData {
+ int count;
+ struct {
+ quint64 texId;
+ uint texGeneration;
+ quint64 samplerId;
+ uint samplerGeneration;
+ } d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
+ };
+ struct BoundStorageImageData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundStorageBufferData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundResourceData {
+ union {
+ BoundUniformBufferData ubuf;
+ BoundSampledTextureData stex;
+ BoundStorageImageData simage;
+ BoundStorageBufferData sbuf;
+ };
+ };
+ QVarLengthArray<BoundResourceData, 8> boundResourceData;
+
+ struct StageUniformBufferBatches {
+ bool present = false;
+ QRhiBatchedBindings<ID3D11Buffer *> ubufs;
+ QRhiBatchedBindings<UINT> ubuforigbindings;
+ QRhiBatchedBindings<UINT> ubufoffsets;
+ QRhiBatchedBindings<UINT> ubufsizes;
+ void finish() {
+ present = ubufs.finish();
+ ubuforigbindings.finish();
+ ubufoffsets.finish();
+ ubufsizes.finish();
+ }
+ void clear() {
+ ubufs.clear();
+ ubuforigbindings.clear();
+ ubufoffsets.clear();
+ ubufsizes.clear();
+ }
+ };
+
+ struct StageSamplerBatches {
+ bool present = false;
+ QRhiBatchedBindings<ID3D11SamplerState *> samplers;
+ QRhiBatchedBindings<ID3D11ShaderResourceView *> shaderresources;
+ void finish() {
+ present = samplers.finish();
+ shaderresources.finish();
+ }
+ void clear() {
+ samplers.clear();
+ shaderresources.clear();
+ }
+ };
+
+ struct StageUavBatches {
+ bool present = false;
+ QRhiBatchedBindings<ID3D11UnorderedAccessView *> uavs;
+ void finish() {
+ present = uavs.finish();
+ }
+ void clear() {
+ uavs.clear();
+ }
+ };
+
+ StageUniformBufferBatches vsUniformBufferBatches;
+ StageUniformBufferBatches hsUniformBufferBatches;
+ StageUniformBufferBatches dsUniformBufferBatches;
+ StageUniformBufferBatches gsUniformBufferBatches;
+ StageUniformBufferBatches fsUniformBufferBatches;
+ StageUniformBufferBatches csUniformBufferBatches;
+
+ StageSamplerBatches vsSamplerBatches;
+ StageSamplerBatches hsSamplerBatches;
+ StageSamplerBatches dsSamplerBatches;
+ StageSamplerBatches gsSamplerBatches;
+ StageSamplerBatches fsSamplerBatches;
+ StageSamplerBatches csSamplerBatches;
+
+ StageUavBatches csUavBatches;
+
+ friend class QRhiD3D11;
+};
+
+Q_DECLARE_TYPEINFO(QD3D11ShaderResourceBindings::BoundResourceData, Q_RELOCATABLE_TYPE);
+
+struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QD3D11GraphicsPipeline(QRhiImplementation *rhi);
+ ~QD3D11GraphicsPipeline();
+ void destroy() override;
+ bool create() override;
+
+ ID3D11DepthStencilState *dsState = nullptr;
+ ID3D11BlendState *blendState = nullptr;
+ struct {
+ ID3D11VertexShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } vs;
+ struct {
+ ID3D11HullShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } hs;
+ struct {
+ ID3D11DomainShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } ds;
+ struct {
+ ID3D11GeometryShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } gs;
+ struct {
+ ID3D11PixelShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } fs;
+ ID3D11InputLayout *inputLayout = nullptr;
+ D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ ID3D11RasterizerState *rastState = nullptr;
+ uint generation = 0;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11ComputePipeline : public QRhiComputePipeline
+{
+ QD3D11ComputePipeline(QRhiImplementation *rhi);
+ ~QD3D11ComputePipeline();
+ void destroy() override;
+ bool create() override;
+
+ struct {
+ ID3D11ComputeShader *shader = nullptr;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ } cs;
+ uint generation = 0;
+ friend class QRhiD3D11;
+};
+
+struct QD3D11SwapChain;
+
+struct QD3D11CommandBuffer : public QRhiCommandBuffer
+{
+ QD3D11CommandBuffer(QRhiImplementation *rhi);
+ ~QD3D11CommandBuffer();
+ void destroy() override;
+
+ // these must be kept at a reasonably low value otherwise sizeof Command explodes
+ static const int MAX_DYNAMIC_OFFSET_COUNT = 8;
+ static const int MAX_VERTEX_BUFFER_BINDING_COUNT = 8;
+
+ struct Command {
+ enum Cmd {
+ BeginFrame,
+ EndFrame,
+ ResetShaderResources,
+ SetRenderTarget,
+ Clear,
+ Viewport,
+ Scissor,
+ BindVertexBuffers,
+ BindIndexBuffer,
+ BindGraphicsPipeline,
+ BindShaderResources,
+ StencilRef,
+ BlendConstants,
+ Draw,
+ DrawIndexed,
+ UpdateSubRes,
+ CopySubRes,
+ ResolveSubRes,
+ GenMip,
+ DebugMarkBegin,
+ DebugMarkEnd,
+ DebugMarkMsg,
+ BindComputePipeline,
+ Dispatch
+ };
+ enum ClearFlag { Color = 1, Depth = 2, Stencil = 4 };
+ Cmd cmd;
+
+ // QRhi*/QD3D11* references should be kept at minimum (so no
+ // QRhiTexture/Buffer/etc. pointers).
+ union Args {
+ struct {
+ ID3D11Query *tsQuery;
+ ID3D11Query *tsDisjointQuery;
+ QD3D11RenderTargetData *swapchainData;
+ } beginFrame;
+ struct {
+ ID3D11Query *tsQuery;
+ ID3D11Query *tsDisjointQuery;
+ } endFrame;
+ struct {
+ QRhiRenderTarget *rt;
+ } setRenderTarget;
+ struct {
+ QRhiRenderTarget *rt;
+ int mask;
+ float c[4];
+ float d;
+ quint32 s;
+ } clear;
+ struct {
+ float x, y, w, h;
+ float d0, d1;
+ } viewport;
+ struct {
+ int x, y, w, h;
+ } scissor;
+ struct {
+ int startSlot;
+ int slotCount;
+ ID3D11Buffer *buffers[MAX_VERTEX_BUFFER_BINDING_COUNT];
+ UINT offsets[MAX_VERTEX_BUFFER_BINDING_COUNT];
+ UINT strides[MAX_VERTEX_BUFFER_BINDING_COUNT];
+ } bindVertexBuffers;
+ struct {
+ ID3D11Buffer *buffer;
+ quint32 offset;
+ DXGI_FORMAT format;
+ } bindIndexBuffer;
+ struct {
+ QD3D11GraphicsPipeline *ps;
+ } bindGraphicsPipeline;
+ struct {
+ QD3D11ShaderResourceBindings *srb;
+ bool offsetOnlyChange;
+ int dynamicOffsetCount;
+ uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offsetInConstants
+ } bindShaderResources;
+ struct {
+ QD3D11GraphicsPipeline *ps;
+ quint32 ref;
+ } stencilRef;
+ struct {
+ QD3D11GraphicsPipeline *ps;
+ float c[4];
+ } blendConstants;
+ struct {
+ QD3D11GraphicsPipeline *ps;
+ quint32 vertexCount;
+ quint32 instanceCount;
+ quint32 firstVertex;
+ quint32 firstInstance;
+ } draw;
+ struct {
+ QD3D11GraphicsPipeline *ps;
+ quint32 indexCount;
+ quint32 instanceCount;
+ quint32 firstIndex;
+ qint32 vertexOffset;
+ quint32 firstInstance;
+ } drawIndexed;
+ struct {
+ ID3D11Resource *dst;
+ UINT dstSubRes;
+ bool hasDstBox;
+ D3D11_BOX dstBox;
+ const void *src; // must come from retain*()
+ UINT srcRowPitch;
+ } updateSubRes;
+ struct {
+ ID3D11Resource *dst;
+ UINT dstSubRes;
+ UINT dstX;
+ UINT dstY;
+ UINT dstZ;
+ ID3D11Resource *src;
+ UINT srcSubRes;
+ bool hasSrcBox;
+ D3D11_BOX srcBox;
+ } copySubRes;
+ struct {
+ ID3D11Resource *dst;
+ UINT dstSubRes;
+ ID3D11Resource *src;
+ UINT srcSubRes;
+ DXGI_FORMAT format;
+ } resolveSubRes;
+ struct {
+ ID3D11ShaderResourceView *srv;
+ } genMip;
+ struct {
+ char s[64];
+ } debugMark;
+ struct {
+ QD3D11ComputePipeline *ps;
+ } bindComputePipeline;
+ struct {
+ UINT x;
+ UINT y;
+ UINT z;
+ } dispatch;
+ } args;
+ };
+
+ enum PassType {
+ NoPass,
+ RenderPass,
+ ComputePass
+ };
+
+ QRhiBackendCommandList<Command> commands;
+ PassType recordingPass;
+ double lastGpuTime = 0;
+ QRhiRenderTarget *currentTarget;
+ QRhiGraphicsPipeline *currentGraphicsPipeline;
+ QRhiComputePipeline *currentComputePipeline;
+ uint currentPipelineGeneration;
+ QRhiShaderResourceBindings *currentGraphicsSrb;
+ QRhiShaderResourceBindings *currentComputeSrb;
+ uint currentSrbGeneration;
+ ID3D11Buffer *currentIndexBuffer;
+ quint32 currentIndexOffset;
+ DXGI_FORMAT currentIndexFormat;
+ ID3D11Buffer *currentVertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+
+ QVarLengthArray<QByteArray, 4> dataRetainPool;
+ QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
+ QVarLengthArray<QImage, 4> imageRetainPool;
+
+ // relies heavily on implicit sharing (no copies of the actual data will be made)
+ const uchar *retainData(const QByteArray &data) {
+ dataRetainPool.append(data);
+ return reinterpret_cast<const uchar *>(dataRetainPool.last().constData());
+ }
+ const uchar *retainBufferData(const QRhiBufferData &data) {
+ bufferDataRetainPool.append(data);
+ return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData());
+ }
+ const uchar *retainImage(const QImage &image) {
+ imageRetainPool.append(image);
+ return imageRetainPool.last().constBits();
+ }
+ void resetCommands() {
+ commands.reset();
+ dataRetainPool.clear();
+ bufferDataRetainPool.clear();
+ imageRetainPool.clear();
+ }
+ void resetState() {
+ recordingPass = NoPass;
+ // do not zero lastGpuTime
+ currentTarget = nullptr;
+ resetCommands();
+ resetCachedState();
+ }
+ void resetCachedState() {
+ currentGraphicsPipeline = nullptr;
+ currentComputePipeline = nullptr;
+ currentPipelineGeneration = 0;
+ currentGraphicsSrb = nullptr;
+ currentComputeSrb = nullptr;
+ currentSrbGeneration = 0;
+ currentIndexBuffer = nullptr;
+ currentIndexOffset = 0;
+ currentIndexFormat = DXGI_FORMAT_R16_UINT;
+ memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
+ memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
+ }
+};
+
+struct QD3D11SwapChainTimestamps
+{
+ static const int TIMESTAMP_PAIRS = 2;
+
+ bool active[TIMESTAMP_PAIRS] = {};
+ ID3D11Query *disjointQuery[TIMESTAMP_PAIRS] = {};
+ ID3D11Query *query[TIMESTAMP_PAIRS * 2] = {};
+
+ bool prepare(QRhiD3D11 *rhiD);
+ void destroy();
+ bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec);
+};
+
+struct QD3D11SwapChain : public QRhiSwapChain
{
- bool enableDebugLayer = false;
+ QD3D11SwapChain(QRhiImplementation *rhi);
+ ~QD3D11SwapChain();
+ void destroy() override;
- int framesUntilKillingDeviceViaTdr = -1;
- bool repeatDeviceKill = false;
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+ QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override;
+
+ QSize surfacePixelSize() override;
+ bool isFormatSupported(Format f) override;
+ QRhiSwapChainHdrInfo hdrInfo() override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool createOrResize() override;
+
+ void releaseBuffers();
+ bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
+ ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const;
+
+ QWindow *window = nullptr;
+ QSize pixelSize;
+ QD3D11SwapChainRenderTarget rt;
+ QD3D11SwapChainRenderTarget rtRight;
+ QD3D11CommandBuffer cb;
+ DXGI_FORMAT colorFormat;
+ DXGI_FORMAT srgbAdjustedColorFormat;
+ IDXGISwapChain *swapChain = nullptr;
+ UINT swapChainFlags = 0;
+ ID3D11Texture2D *backBufferTex;
+ ID3D11RenderTargetView *backBufferRtv;
+ ID3D11RenderTargetView *backBufferRtvRight = nullptr;
+ static const int BUFFER_COUNT = 2;
+ ID3D11Texture2D *msaaTex[BUFFER_COUNT];
+ ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
+ DXGI_SAMPLE_DESC sampleDesc;
+ int currentFrameSlot = 0;
+ int frameCount = 0;
+ QD3D11RenderBuffer *ds = nullptr;
+ UINT swapInterval = 1;
+ IDCompositionTarget *dcompTarget = nullptr;
+ IDCompositionVisual *dcompVisual = nullptr;
+ QD3D11SwapChainTimestamps timestamps;
+ int currentTimestampPairIndex = 0;
};
-struct Q_GUI_EXPORT QRhiD3D11NativeHandles : public QRhiNativeHandles
+class QRhiD3D11 : public QRhiImplementation
{
- // to import a device and a context
- void *dev = nullptr;
- void *context = nullptr;
- // alternatively, to specify the device feature level and/or the adapter to use
- int featureLevel = 0;
- quint32 adapterLuidLow = 0;
- qint32 adapterLuidHigh = 0;
+public:
+ QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice = nullptr);
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiComputePipeline *createComputePipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ quint32 size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int depth,
+ int arraySize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ void beginComputePass(QRhiCommandBuffer *cb,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+ void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
+ void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+ double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
+
+ QList<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ QRhiDriverInfo driverInfo() const override;
+ QRhiStats statistics() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
+
+ QByteArray pipelineCacheData() override;
+ void setPipelineCacheData(const QByteArray &data) override;
+
+ void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
+ int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
+ void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
+ void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
+ void executeBufferHostWrites(QD3D11Buffer *bufD);
+ void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
+ const uint *dynOfsPairs, int dynOfsPairCount,
+ bool offsetOnlyChange);
+ void resetShaderResources();
+ void executeCommandBuffer(QD3D11CommandBuffer *cbD);
+ DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const;
+ void finishActiveReadbacks();
+ void reportLiveObjects(ID3D11Device *device);
+ void clearShaderCache();
+ QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, uint flags,
+ QString *error, QShaderKey *usedShaderKey);
+ bool ensureDirectCompositionDevice();
+
+ QRhi::Flags rhiFlags;
+ bool debugLayer = false;
+ bool importedDeviceAndContext = false;
+ ID3D11Device *dev = nullptr;
+ ID3D11DeviceContext1 *context = nullptr;
+ D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL(0);
+ LUID adapterLuid = {};
+ ID3DUserDefinedAnnotation *annotations = nullptr;
+ IDXGIAdapter1 *activeAdapter = nullptr;
+ IDXGIFactory1 *dxgiFactory = nullptr;
+ IDCompositionDevice *dcompDevice = nullptr;
+ bool supportsAllowTearing = false;
+ bool useLegacySwapchainModel = false;
+ bool deviceLost = false;
+ QRhiD3D11NativeHandles nativeHandlesStruct;
+ QRhiDriverInfo driverInfoStruct;
+
+ struct {
+ int vsHighestActiveVertexBufferBinding = -1;
+ bool vsHasIndexBufferBound = false;
+ int vsHighestActiveSrvBinding = -1;
+ int hsHighestActiveSrvBinding = -1;
+ int dsHighestActiveSrvBinding = -1;
+ int gsHighestActiveSrvBinding = -1;
+ int fsHighestActiveSrvBinding = -1;
+ int csHighestActiveSrvBinding = -1;
+ int csHighestActiveUavBinding = -1;
+ QD3D11SwapChain *currentSwapChain = nullptr;
+ } contextState;
+
+ struct OffscreenFrame {
+ OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
+ bool active = false;
+ QD3D11CommandBuffer cbWrapper;
+ ID3D11Query *tsQueries[2] = {};
+ ID3D11Query *tsDisjointQuery = nullptr;
+ } ofr;
+
+ struct TextureReadback {
+ QRhiReadbackDescription desc;
+ QRhiReadbackResult *result;
+ ID3D11Texture2D *stagingTex;
+ quint32 byteSize;
+ quint32 bpl;
+ QSize pixelSize;
+ QRhiTexture::Format format;
+ };
+ QVarLengthArray<TextureReadback, 2> activeTextureReadbacks;
+ struct BufferReadback {
+ QRhiReadbackResult *result;
+ quint32 byteSize;
+ ID3D11Buffer *stagingBuf;
+ };
+ QVarLengthArray<BufferReadback, 2> activeBufferReadbacks;
+
+ struct Shader {
+ Shader() = default;
+ Shader(IUnknown *s, const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm)
+ : s(s), bytecode(bytecode), nativeResourceBindingMap(rbm) { }
+ IUnknown *s;
+ QByteArray bytecode;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ };
+ QHash<QRhiShaderStage, Shader> m_shaderCache;
+
+ // This is what gets exposed as the "pipeline cache", not that that concept
+ // applies anyway. Here we are just storing the DX bytecode for a shader so
+ // we can skip the HLSL->DXBC compilation when the QShader has HLSL source
+ // code and the same shader source has already been compiled before.
+ // m_shaderCache seemingly does the same, but this here does not care about
+ // the ID3D11*Shader, this is just about the bytecode and about allowing
+ // the data to be serialized to persistent storage and then reloaded in
+ // future runs of the app, or when creating another QRhi, etc.
+ struct BytecodeCacheKey {
+ QByteArray sourceHash;
+ QByteArray target;
+ QByteArray entryPoint;
+ uint compileFlags;
+ };
+ QHash<BytecodeCacheKey, QByteArray> m_bytecodeCache;
};
+Q_DECLARE_TYPEINFO(QRhiD3D11::TextureReadback, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiD3D11::BufferReadback, Q_RELOCATABLE_TYPE);
+
+inline bool operator==(const QRhiD3D11::BytecodeCacheKey &a, const QRhiD3D11::BytecodeCacheKey &b) noexcept
+{
+ return a.sourceHash == b.sourceHash
+ && a.target == b.target
+ && a.entryPoint == b.entryPoint
+ && a.compileFlags == b.compileFlags;
+}
+
+inline bool operator!=(const QRhiD3D11::BytecodeCacheKey &a, const QRhiD3D11::BytecodeCacheKey &b) noexcept
+{
+ return !(a == b);
+}
+
+inline size_t qHash(const QRhiD3D11::BytecodeCacheKey &k, size_t seed = 0) noexcept
+{
+ return qHash(k.sourceHash, seed) ^ qHash(k.target) ^ qHash(k.entryPoint) ^ k.compileFlags;
+}
+
QT_END_NAMESPACE
#endif
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
deleted file mode 100644
index 0695259612..0000000000
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ /dev/null
@@ -1,788 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHID3D11_P_H
-#define QRHID3D11_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qrhid3d11_p.h"
-#include "qrhi_p_p.h"
-#include "qshaderdescription_p.h"
-#include <QWindow>
-
-#include <d3d11_1.h>
-#include <dxgi1_3.h>
-
-QT_BEGIN_NAMESPACE
-
-struct QD3D11Buffer : public QRhiBuffer
-{
- QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
- ~QD3D11Buffer();
- void destroy() override;
- bool create() override;
- QRhiBuffer::NativeBuffer nativeBuffer() override;
- char *beginFullDynamicBufferUpdateForCurrentFrame() override;
- void endFullDynamicBufferUpdateForCurrentFrame() override;
-
- ID3D11UnorderedAccessView *unorderedAccessView();
-
- ID3D11Buffer *buffer = nullptr;
- char *dynBuf = nullptr;
- bool hasPendingDynamicUpdates = false;
- ID3D11UnorderedAccessView *uav = nullptr;
- uint generation = 0;
- friend class QRhiD3D11;
-};
-
-struct QD3D11RenderBuffer : public QRhiRenderBuffer
-{
- QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
- int sampleCount, QRhiRenderBuffer::Flags flags,
- QRhiTexture::Format backingFormatHint);
- ~QD3D11RenderBuffer();
- void destroy() override;
- bool create() override;
- QRhiTexture::Format backingFormat() const override;
-
- ID3D11Texture2D *tex = nullptr;
- ID3D11DepthStencilView *dsv = nullptr;
- ID3D11RenderTargetView *rtv = nullptr;
- DXGI_FORMAT dxgiFormat;
- DXGI_SAMPLE_DESC sampleDesc;
- friend class QRhiD3D11;
-};
-
-struct QD3D11Texture : public QRhiTexture
-{
- QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags);
- ~QD3D11Texture();
- void destroy() override;
- bool create() override;
- bool createFrom(NativeTexture src) override;
- NativeTexture nativeTexture() override;
-
- bool prepareCreate(QSize *adjustedSize = nullptr);
- bool finishCreate();
- ID3D11UnorderedAccessView *unorderedAccessViewForLevel(int level);
- ID3D11Resource *textureResource() const
- {
- if (tex)
- return tex;
- return tex3D;
- }
-
- ID3D11Texture2D *tex = nullptr;
- ID3D11Texture3D *tex3D = nullptr;
- bool owns = true;
- ID3D11ShaderResourceView *srv = nullptr;
- DXGI_FORMAT dxgiFormat;
- uint mipLevelCount = 0;
- DXGI_SAMPLE_DESC sampleDesc;
- ID3D11UnorderedAccessView *perLevelViews[QRhi::MAX_MIP_LEVELS];
- uint generation = 0;
- friend class QRhiD3D11;
-};
-
-struct QD3D11Sampler : public QRhiSampler
-{
- QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v, AddressMode w);
- ~QD3D11Sampler();
- void destroy() override;
- bool create() override;
-
- ID3D11SamplerState *samplerState = nullptr;
- uint generation = 0;
- friend class QRhiD3D11;
-};
-
-struct QD3D11RenderPassDescriptor : public QRhiRenderPassDescriptor
-{
- QD3D11RenderPassDescriptor(QRhiImplementation *rhi);
- ~QD3D11RenderPassDescriptor();
- void destroy() override;
- bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
-};
-
-struct QD3D11RenderTargetData
-{
- QD3D11RenderTargetData(QRhiImplementation *)
- {
- for (int i = 0; i < MAX_COLOR_ATTACHMENTS; ++i)
- rtv[i] = nullptr;
- }
-
- QD3D11RenderPassDescriptor *rp = nullptr;
- QSize pixelSize;
- float dpr = 1;
- int sampleCount = 1;
- int colorAttCount = 0;
- int dsAttCount = 0;
-
- static const int MAX_COLOR_ATTACHMENTS = 8;
- ID3D11RenderTargetView *rtv[MAX_COLOR_ATTACHMENTS];
- ID3D11DepthStencilView *dsv = nullptr;
-};
-
-struct QD3D11ReferenceRenderTarget : public QRhiRenderTarget
-{
- QD3D11ReferenceRenderTarget(QRhiImplementation *rhi);
- ~QD3D11ReferenceRenderTarget();
- void destroy() override;
-
- QSize pixelSize() const override;
- float devicePixelRatio() const override;
- int sampleCount() const override;
-
- QD3D11RenderTargetData d;
-};
-
-struct QD3D11TextureRenderTarget : public QRhiTextureRenderTarget
-{
- QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
- ~QD3D11TextureRenderTarget();
- void destroy() override;
-
- QSize pixelSize() const override;
- float devicePixelRatio() const override;
- int sampleCount() const override;
-
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
- bool create() override;
-
- QD3D11RenderTargetData d;
- bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
- ID3D11RenderTargetView *rtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
- bool ownsDsv = false;
- ID3D11DepthStencilView *dsv = nullptr;
- friend class QRhiD3D11;
-};
-
-struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
-{
- QD3D11ShaderResourceBindings(QRhiImplementation *rhi);
- ~QD3D11ShaderResourceBindings();
- void destroy() override;
- bool create() override;
-
- bool hasDynamicOffset = false;
- QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
- uint generation = 0;
-
- // Keep track of the generation number of each referenced QRhi* to be able
- // to detect that the batched bindings are out of date.
- struct BoundUniformBufferData {
- quint64 id;
- uint generation;
- };
- struct BoundSampledTextureData {
- int count;
- struct {
- quint64 texId;
- uint texGeneration;
- quint64 samplerId;
- uint samplerGeneration;
- } d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
- };
- struct BoundStorageImageData {
- quint64 id;
- uint generation;
- };
- struct BoundStorageBufferData {
- quint64 id;
- uint generation;
- };
- struct BoundResourceData {
- union {
- BoundUniformBufferData ubuf;
- BoundSampledTextureData stex;
- BoundStorageImageData simage;
- BoundStorageBufferData sbuf;
- };
- };
- QVarLengthArray<BoundResourceData, 8> boundResourceData;
-
- bool vsubufsPresent = false;
- bool fsubufsPresent = false;
- bool csubufsPresent = false;
- bool vssamplersPresent = false;
- bool fssamplersPresent = false;
- bool cssamplersPresent = false;
- bool csUAVsPresent = false;
-
- QRhiBatchedBindings<ID3D11Buffer *> vsubufs;
- QRhiBatchedBindings<UINT> vsubuforigbindings;
- QRhiBatchedBindings<UINT> vsubufoffsets;
- QRhiBatchedBindings<UINT> vsubufsizes;
-
- QRhiBatchedBindings<ID3D11Buffer *> fsubufs;
- QRhiBatchedBindings<UINT> fsubuforigbindings;
- QRhiBatchedBindings<UINT> fsubufoffsets;
- QRhiBatchedBindings<UINT> fsubufsizes;
-
- QRhiBatchedBindings<ID3D11Buffer *> csubufs;
- QRhiBatchedBindings<UINT> csubuforigbindings;
- QRhiBatchedBindings<UINT> csubufoffsets;
- QRhiBatchedBindings<UINT> csubufsizes;
-
- QRhiBatchedBindings<ID3D11SamplerState *> vssamplers;
- QRhiBatchedBindings<ID3D11ShaderResourceView *> vsshaderresources;
-
- QRhiBatchedBindings<ID3D11SamplerState *> fssamplers;
- QRhiBatchedBindings<ID3D11ShaderResourceView *> fsshaderresources;
-
- QRhiBatchedBindings<ID3D11SamplerState *> cssamplers;
- QRhiBatchedBindings<ID3D11ShaderResourceView *> csshaderresources;
-
- QRhiBatchedBindings<ID3D11UnorderedAccessView *> csUAVs;
-
- friend class QRhiD3D11;
-};
-
-Q_DECLARE_TYPEINFO(QD3D11ShaderResourceBindings::BoundResourceData, Q_RELOCATABLE_TYPE);
-
-struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
-{
- QD3D11GraphicsPipeline(QRhiImplementation *rhi);
- ~QD3D11GraphicsPipeline();
- void destroy() override;
- bool create() override;
-
- ID3D11DepthStencilState *dsState = nullptr;
- ID3D11BlendState *blendState = nullptr;
- struct {
- ID3D11VertexShader *shader = nullptr;
- QShader::NativeResourceBindingMap nativeResourceBindingMap;
- } vs;
- struct {
- ID3D11PixelShader *shader = nullptr;
- QShader::NativeResourceBindingMap nativeResourceBindingMap;
- } fs;
- ID3D11InputLayout *inputLayout = nullptr;
- D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
- ID3D11RasterizerState *rastState = nullptr;
- uint generation = 0;
- friend class QRhiD3D11;
-};
-
-struct QD3D11ComputePipeline : public QRhiComputePipeline
-{
- QD3D11ComputePipeline(QRhiImplementation *rhi);
- ~QD3D11ComputePipeline();
- void destroy() override;
- bool create() override;
-
- struct {
- ID3D11ComputeShader *shader = nullptr;
- QShader::NativeResourceBindingMap nativeResourceBindingMap;
- } cs;
- uint generation = 0;
- friend class QRhiD3D11;
-};
-
-struct QD3D11SwapChain;
-
-struct QD3D11CommandBuffer : public QRhiCommandBuffer
-{
- QD3D11CommandBuffer(QRhiImplementation *rhi);
- ~QD3D11CommandBuffer();
- void destroy() override;
-
- // these must be kept at a reasonably low value otherwise sizeof Command explodes
- static const int MAX_DYNAMIC_OFFSET_COUNT = 8;
- static const int MAX_VERTEX_BUFFER_BINDING_COUNT = 8;
-
- struct Command {
- enum Cmd {
- ResetShaderResources,
- SetRenderTarget,
- Clear,
- Viewport,
- Scissor,
- BindVertexBuffers,
- BindIndexBuffer,
- BindGraphicsPipeline,
- BindShaderResources,
- StencilRef,
- BlendConstants,
- Draw,
- DrawIndexed,
- UpdateSubRes,
- CopySubRes,
- ResolveSubRes,
- GenMip,
- DebugMarkBegin,
- DebugMarkEnd,
- DebugMarkMsg,
- BindComputePipeline,
- Dispatch
- };
- enum ClearFlag { Color = 1, Depth = 2, Stencil = 4 };
- Cmd cmd;
-
- // QRhi*/QD3D11* references should be kept at minimum (so no
- // QRhiTexture/Buffer/etc. pointers).
- union Args {
- struct {
- QRhiRenderTarget *rt;
- } setRenderTarget;
- struct {
- QRhiRenderTarget *rt;
- int mask;
- float c[4];
- float d;
- quint32 s;
- } clear;
- struct {
- float x, y, w, h;
- float d0, d1;
- } viewport;
- struct {
- int x, y, w, h;
- } scissor;
- struct {
- int startSlot;
- int slotCount;
- ID3D11Buffer *buffers[MAX_VERTEX_BUFFER_BINDING_COUNT];
- UINT offsets[MAX_VERTEX_BUFFER_BINDING_COUNT];
- UINT strides[MAX_VERTEX_BUFFER_BINDING_COUNT];
- } bindVertexBuffers;
- struct {
- ID3D11Buffer *buffer;
- quint32 offset;
- DXGI_FORMAT format;
- } bindIndexBuffer;
- struct {
- QD3D11GraphicsPipeline *ps;
- } bindGraphicsPipeline;
- struct {
- QD3D11ShaderResourceBindings *srb;
- bool offsetOnlyChange;
- int dynamicOffsetCount;
- uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offsetInConstants
- } bindShaderResources;
- struct {
- QD3D11GraphicsPipeline *ps;
- quint32 ref;
- } stencilRef;
- struct {
- QD3D11GraphicsPipeline *ps;
- float c[4];
- } blendConstants;
- struct {
- QD3D11GraphicsPipeline *ps;
- quint32 vertexCount;
- quint32 instanceCount;
- quint32 firstVertex;
- quint32 firstInstance;
- } draw;
- struct {
- QD3D11GraphicsPipeline *ps;
- quint32 indexCount;
- quint32 instanceCount;
- quint32 firstIndex;
- qint32 vertexOffset;
- quint32 firstInstance;
- } drawIndexed;
- struct {
- ID3D11Resource *dst;
- UINT dstSubRes;
- bool hasDstBox;
- D3D11_BOX dstBox;
- const void *src; // must come from retain*()
- UINT srcRowPitch;
- } updateSubRes;
- struct {
- ID3D11Resource *dst;
- UINT dstSubRes;
- UINT dstX;
- UINT dstY;
- UINT dstZ;
- ID3D11Resource *src;
- UINT srcSubRes;
- bool hasSrcBox;
- D3D11_BOX srcBox;
- } copySubRes;
- struct {
- ID3D11Resource *dst;
- UINT dstSubRes;
- ID3D11Resource *src;
- UINT srcSubRes;
- DXGI_FORMAT format;
- } resolveSubRes;
- struct {
- ID3D11ShaderResourceView *srv;
- } genMip;
- struct {
- char s[64];
- } debugMark;
- struct {
- QD3D11ComputePipeline *ps;
- } bindComputePipeline;
- struct {
- UINT x;
- UINT y;
- UINT z;
- } dispatch;
- } args;
- };
-
- enum PassType {
- NoPass,
- RenderPass,
- ComputePass
- };
-
- QRhiBackendCommandList<Command> commands;
- PassType recordingPass;
- QRhiRenderTarget *currentTarget;
- QRhiGraphicsPipeline *currentGraphicsPipeline;
- QRhiComputePipeline *currentComputePipeline;
- uint currentPipelineGeneration;
- QRhiShaderResourceBindings *currentGraphicsSrb;
- QRhiShaderResourceBindings *currentComputeSrb;
- uint currentSrbGeneration;
- ID3D11Buffer *currentIndexBuffer;
- quint32 currentIndexOffset;
- DXGI_FORMAT currentIndexFormat;
- ID3D11Buffer *currentVertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
- quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
-
- QVarLengthArray<QByteArray, 4> dataRetainPool;
- QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
- QVarLengthArray<QImage, 4> imageRetainPool;
-
- // relies heavily on implicit sharing (no copies of the actual data will be made)
- const uchar *retainData(const QByteArray &data) {
- dataRetainPool.append(data);
- return reinterpret_cast<const uchar *>(dataRetainPool.last().constData());
- }
- const uchar *retainBufferData(const QRhiBufferData &data) {
- bufferDataRetainPool.append(data);
- return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData());
- }
- const uchar *retainImage(const QImage &image) {
- imageRetainPool.append(image);
- return imageRetainPool.last().constBits();
- }
- void resetCommands() {
- commands.reset();
- dataRetainPool.clear();
- bufferDataRetainPool.clear();
- imageRetainPool.clear();
- }
- void resetState() {
- recordingPass = NoPass;
- currentTarget = nullptr;
- resetCommands();
- resetCachedState();
- }
- void resetCachedState() {
- currentGraphicsPipeline = nullptr;
- currentComputePipeline = nullptr;
- currentPipelineGeneration = 0;
- resetCachedShaderResourceState();
- }
- void resetCachedShaderResourceState() {
- currentGraphicsSrb = nullptr;
- currentComputeSrb = nullptr;
- currentSrbGeneration = 0;
- currentIndexBuffer = nullptr;
- currentIndexOffset = 0;
- currentIndexFormat = DXGI_FORMAT_R16_UINT;
- memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
- memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
- }
-};
-
-struct QD3D11SwapChain : public QRhiSwapChain
-{
- QD3D11SwapChain(QRhiImplementation *rhi);
- ~QD3D11SwapChain();
- void destroy() override;
-
- QRhiCommandBuffer *currentFrameCommandBuffer() override;
- QRhiRenderTarget *currentFrameRenderTarget() override;
-
- QSize surfacePixelSize() override;
-
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
- bool createOrResize() override;
-
- void releaseBuffers();
- bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
- ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const;
-
- QWindow *window = nullptr;
- QSize pixelSize;
- QD3D11ReferenceRenderTarget rt;
- QD3D11CommandBuffer cb;
- DXGI_FORMAT colorFormat;
- IDXGISwapChain *swapChain = nullptr;
- static const int BUFFER_COUNT = 2;
- ID3D11Texture2D *backBufferTex;
- ID3D11RenderTargetView *backBufferRtv;
- ID3D11Texture2D *msaaTex[BUFFER_COUNT];
- ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
- DXGI_SAMPLE_DESC sampleDesc;
- int currentFrameSlot = 0;
- int frameCount = 0;
- QD3D11RenderBuffer *ds = nullptr;
- bool timestampActive[BUFFER_COUNT];
- ID3D11Query *timestampDisjointQuery[BUFFER_COUNT];
- ID3D11Query *timestampQuery[BUFFER_COUNT * 2];
- UINT swapInterval = 1;
-};
-
-class QRhiD3D11 : public QRhiImplementation
-{
-public:
- QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice = nullptr);
-
- bool create(QRhi::Flags flags) override;
- void destroy() override;
-
- QRhiGraphicsPipeline *createGraphicsPipeline() override;
- QRhiComputePipeline *createComputePipeline() override;
- QRhiShaderResourceBindings *createShaderResourceBindings() override;
- QRhiBuffer *createBuffer(QRhiBuffer::Type type,
- QRhiBuffer::UsageFlags usage,
- int size) override;
- QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
- const QSize &pixelSize,
- int sampleCount,
- QRhiRenderBuffer::Flags flags,
- QRhiTexture::Format backingFormatHint) override;
- QRhiTexture *createTexture(QRhiTexture::Format format,
- const QSize &pixelSize,
- int depth,
- int sampleCount,
- QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
- QRhiSampler::Filter minFilter,
- QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u,
- QRhiSampler::AddressMode v,
- QRhiSampler::AddressMode w) override;
-
- QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
- QRhiTextureRenderTarget::Flags flags) override;
-
- QRhiSwapChain *createSwapChain() override;
- QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
- QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
- QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
- QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
- QRhi::FrameOpResult finish() override;
-
- void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
-
- void beginPass(QRhiCommandBuffer *cb,
- QRhiRenderTarget *rt,
- const QColor &colorClearValue,
- const QRhiDepthStencilClearValue &depthStencilClearValue,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) override;
- void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
-
- void setGraphicsPipeline(QRhiCommandBuffer *cb,
- QRhiGraphicsPipeline *ps) override;
-
- void setShaderResources(QRhiCommandBuffer *cb,
- QRhiShaderResourceBindings *srb,
- int dynamicOffsetCount,
- const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
-
- void setVertexInput(QRhiCommandBuffer *cb,
- int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
- QRhiBuffer *indexBuf, quint32 indexOffset,
- QRhiCommandBuffer::IndexFormat indexFormat) override;
-
- void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
- void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
- void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
- void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
-
- void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
- quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
-
- void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
- quint32 instanceCount, quint32 firstIndex,
- qint32 vertexOffset, quint32 firstInstance) override;
-
- void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
- void debugMarkEnd(QRhiCommandBuffer *cb) override;
- void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
-
- void beginComputePass(QRhiCommandBuffer *cb,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) override;
- void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
- void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
- void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
-
- const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
- void beginExternal(QRhiCommandBuffer *cb) override;
- void endExternal(QRhiCommandBuffer *cb) override;
-
- QList<int> supportedSampleCounts() const override;
- int ubufAlignment() const override;
- bool isYUpInFramebuffer() const override;
- bool isYUpInNDC() const override;
- bool isClipDepthZeroToOne() const override;
- QMatrix4x4 clipSpaceCorrMatrix() const override;
- bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
- bool isFeatureSupported(QRhi::Feature feature) const override;
- int resourceLimit(QRhi::ResourceLimit limit) const override;
- const QRhiNativeHandles *nativeHandles() override;
- QRhiDriverInfo driverInfo() const override;
- void sendVMemStatsToProfiler() override;
- bool makeThreadLocalNativeContextCurrent() override;
- void releaseCachedResources() override;
- bool isDeviceLost() const override;
-
- QByteArray pipelineCacheData() override;
- void setPipelineCacheData(const QByteArray &data) override;
-
- void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
- int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
- void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
- void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
- const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
- void executeBufferHostWrites(QD3D11Buffer *bufD);
- void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
- const uint *dynOfsPairs, int dynOfsPairCount,
- bool offsetOnlyChange);
- void resetShaderResources();
- void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr);
- DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const;
- void finishActiveReadbacks();
- void reportLiveObjects(ID3D11Device *device);
- void clearShaderCache();
-
- bool debugLayer = false;
- bool importedDeviceAndContext = false;
- ID3D11Device *dev = nullptr;
- ID3D11DeviceContext1 *context = nullptr;
- D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL(0);
- LUID adapterLuid = {};
- ID3DUserDefinedAnnotation *annotations = nullptr;
- IDXGIFactory1 *dxgiFactory = nullptr;
- bool hasDxgi2 = false;
- bool supportsFlipDiscardSwapchain = false;
- bool deviceLost = false;
- QRhiD3D11NativeHandles nativeHandlesStruct;
- QRhiDriverInfo driverInfoStruct;
-
- struct {
- int vsHighestActiveVertexBufferBinding = -1;
- bool vsHasIndexBufferBound = false;
- int vsHighestActiveSrvBinding = -1;
- int fsHighestActiveSrvBinding = -1;
- int csHighestActiveSrvBinding = -1;
- int csHighestActiveUavBinding = -1;
- QD3D11SwapChain *currentSwapChain = nullptr;
- } contextState;
-
- struct OffscreenFrame {
- OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
- bool active = false;
- QD3D11CommandBuffer cbWrapper;
- } ofr;
-
- struct TextureReadback {
- QRhiReadbackDescription desc;
- QRhiReadbackResult *result;
- ID3D11Texture2D *stagingTex;
- quint32 byteSize;
- quint32 bpl;
- QSize pixelSize;
- QRhiTexture::Format format;
- };
- QVarLengthArray<TextureReadback, 2> activeTextureReadbacks;
- struct BufferReadback {
- QRhiBufferReadbackResult *result;
- quint32 byteSize;
- ID3D11Buffer *stagingBuf;
- };
- QVarLengthArray<BufferReadback, 2> activeBufferReadbacks;
-
- struct Shader {
- Shader() = default;
- Shader(IUnknown *s, const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm)
- : s(s), bytecode(bytecode), nativeResourceBindingMap(rbm) { }
- IUnknown *s;
- QByteArray bytecode;
- QShader::NativeResourceBindingMap nativeResourceBindingMap;
- };
- QHash<QRhiShaderStage, Shader> m_shaderCache;
-
- struct DeviceCurse {
- DeviceCurse(QRhiD3D11 *impl) : q(impl) { }
- QRhiD3D11 *q;
- int framesToActivate = -1;
- bool permanent = false;
- int framesLeft = 0;
- ID3D11ComputeShader *cs = nullptr;
-
- void initResources();
- void releaseResources();
- void activate();
- } deviceCurse;
-};
-
-Q_DECLARE_TYPEINFO(QRhiD3D11::TextureReadback, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QRhiD3D11::BufferReadback, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qrhid3d12.cpp b/src/gui/rhi/qrhid3d12.cpp
new file mode 100644
index 0000000000..0f176c683d
--- /dev/null
+++ b/src/gui/rhi/qrhid3d12.cpp
@@ -0,0 +1,6569 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhid3d12_p.h"
+#include <qmath.h>
+#include <QtCore/private/qsystemerror_p.h>
+#include <comdef.h>
+#include "qrhid3dhelpers_p.h"
+#include "cs_mipmap_p.h"
+
+#if __has_include(<pix.h>)
+#include <pix.h>
+#define QRHI_D3D12_HAS_OLD_PIX
+#endif
+
+#ifdef __ID3D12Device2_INTERFACE_DEFINED__
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Direct 3D 12 backend.
+*/
+
+/*!
+ \class QRhiD3D12InitParams
+ \inmodule QtGui
+ \brief Direct3D 12 specific initialization parameters.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ A D3D12-based QRhi needs no special parameters for initialization. If
+ desired, enableDebugLayer can be set to \c true to enable the Direct3D
+ debug layer. This can be useful during development, but should be avoided
+ in production builds.
+
+ \badcode
+ QRhiD3D12InitParams params;
+ params.enableDebugLayer = true;
+ rhi = QRhi::create(QRhi::D3D12, &params);
+ \endcode
+
+ \note QRhiSwapChain should only be used in combination with QWindow
+ instances that have their surface type set to QSurface::Direct3DSurface.
+
+ \section2 Working with existing Direct3D 12 devices
+
+ When interoperating with another graphics engine, it may be necessary to
+ get a QRhi instance that uses the same Direct3D device. This can be
+ achieved by passing a pointer to a QRhiD3D12NativeHandles to
+ QRhi::create(). QRhi does not take ownership of any of the external
+ objects.
+
+ Sometimes, for example when using QRhi in combination with OpenXR, one will
+ want to specify which adapter to use, and optionally, which feature level
+ to request on the device, while leaving the device creation to QRhi. This
+ is achieved by leaving the device pointer set to null, while specifying the
+ adapter LUID and feature level.
+
+ Optionally the ID3D12CommandQueue can be specified as well, by setting \c
+ commandQueue to a non-null value.
+ */
+
+/*!
+ \variable QRhiD3D12InitParams::enableDebugLayer
+
+ When set to true, the debug layer is enabled, if installed and available.
+ The default value is false.
+*/
+
+/*!
+ \class QRhiD3D12NativeHandles
+ \inmodule QtGui
+ \brief Holds the D3D12 device used by the QRhi.
+
+ \note The class uses \c{void *} as the type since including the COM-based
+ \c{d3d12.h} headers is not acceptable here. The actual types are
+ \c{ID3D12Device *} and \c{ID3D12CommandQueue *}.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+ */
+
+/*!
+ \variable QRhiD3D12NativeHandles::dev
+
+ Points to a
+ \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nn-d3d12-id3d12device}{ID3D12Device}
+ or left set to \nullptr if no existing device is to be imported.
+*/
+
+/*!
+ \variable QRhiD3D12NativeHandles::minimumFeatureLevel
+
+ Specifies the \b minimum feature level passed to
+ \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-d3d12createdevice}{D3D12CreateDevice()}.
+ When not set, \c{D3D_FEATURE_LEVEL_11_0} is used. See
+ \l{https://learn.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels}{this
+ page} for details.
+
+ Relevant only when QRhi creates the device, ignored when importing a device
+ and device context.
+*/
+
+/*!
+ \variable QRhiD3D12NativeHandles::adapterLuidLow
+
+ The low part of the local identifier (LUID) of the DXGI adapter to use.
+ Relevant only when QRhi creates the device, ignored when importing a device
+ and device context.
+*/
+
+/*!
+ \variable QRhiD3D12NativeHandles::adapterLuidHigh
+
+ The high part of the local identifier (LUID) of the DXGI adapter to use.
+ Relevant only when QRhi creates the device, ignored when importing a device
+ and device context.
+*/
+
+/*!
+ \variable QRhiD3D12NativeHandles::commandQueue
+
+ When set, must point to a
+ \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nn-d3d12-id3d12commandqueue}{ID3D12CommandQueue}.
+ It allows to optionally import a command queue as well, in addition to a
+ device.
+*/
+
+/*!
+ \class QRhiD3D12CommandBufferNativeHandles
+ \inmodule QtGui
+ \brief Holds the ID3D12GraphicsCommandList1 object that is backing a QRhiCommandBuffer.
+
+ \note The command list object is only guaranteed to be valid, and
+ in recording state, while recording a frame. That is, between a
+ \l{QRhi::beginFrame()}{beginFrame()} - \l{QRhi::endFrame()}{endFrame()} or
+ \l{QRhi::beginOffscreenFrame()}{beginOffscreenFrame()} -
+ \l{QRhi::endOffscreenFrame()}{endOffscreenFrame()} pair.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+ */
+
+/*!
+ \variable QRhiD3D12CommandBufferNativeHandles::commandList
+*/
+
+// https://learn.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels
+static const D3D_FEATURE_LEVEL MIN_FEATURE_LEVEL = D3D_FEATURE_LEVEL_11_0;
+
+QRhiD3D12::QRhiD3D12(QRhiD3D12InitParams *params, QRhiD3D12NativeHandles *importParams)
+{
+ debugLayer = params->enableDebugLayer;
+ if (importParams) {
+ if (importParams->dev) {
+ ID3D12Device *d3d12Device = reinterpret_cast<ID3D12Device *>(importParams->dev);
+ if (SUCCEEDED(d3d12Device->QueryInterface(__uuidof(ID3D12Device2), reinterpret_cast<void **>(&dev)))) {
+ // get rid of the ref added by QueryInterface
+ d3d12Device->Release();
+ importedDevice = true;
+ } else {
+ qWarning("ID3D12Device2 not supported, cannot import device");
+ }
+ }
+ if (importParams->commandQueue) {
+ cmdQueue = reinterpret_cast<ID3D12CommandQueue *>(importParams->commandQueue);
+ importedCommandQueue = true;
+ }
+ minimumFeatureLevel = D3D_FEATURE_LEVEL(importParams->minimumFeatureLevel);
+ adapterLuid.LowPart = importParams->adapterLuidLow;
+ adapterLuid.HighPart = importParams->adapterLuidHigh;
+ }
+}
+
+template <class Int>
+inline Int aligned(Int v, Int byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+static inline UINT calcSubresource(UINT mipSlice, UINT arraySlice, UINT mipLevels)
+{
+ return mipSlice + arraySlice * mipLevels;
+}
+
+static inline QD3D12RenderTargetData *rtData(QRhiRenderTarget *rt)
+{
+ switch (rt->resourceType()) {
+ case QRhiResource::SwapChainRenderTarget:
+ return &QRHI_RES(QD3D12SwapChainRenderTarget, rt)->d;
+ case QRhiResource::TextureRenderTarget:
+ return &QRHI_RES(QD3D12TextureRenderTarget, rt)->d;
+ break;
+ default:
+ break;
+ }
+ Q_UNREACHABLE_RETURN(nullptr);
+}
+
+bool QRhiD3D12::create(QRhi::Flags flags)
+{
+ rhiFlags = flags;
+
+ UINT factoryFlags = 0;
+ if (debugLayer)
+ factoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
+ HRESULT hr = CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
+ if (FAILED(hr)) {
+ // retry without debug, if it was requested (to match D3D11 backend behavior)
+ if (debugLayer) {
+ qCDebug(QRHI_LOG_INFO, "Debug layer was requested but is not available. "
+ "Attempting to create DXGIFactory2 without it.");
+ factoryFlags &= ~DXGI_CREATE_FACTORY_DEBUG;
+ hr = CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
+ }
+ if (SUCCEEDED(hr)) {
+ debugLayer = false;
+ } else {
+ qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ }
+
+ supportsAllowTearing = false;
+ IDXGIFactory5 *factory5 = nullptr;
+ if (SUCCEEDED(dxgiFactory->QueryInterface(__uuidof(IDXGIFactory5), reinterpret_cast<void **>(&factory5)))) {
+ BOOL allowTearing = false;
+ if (SUCCEEDED(factory5->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, &allowTearing, sizeof(allowTearing))))
+ supportsAllowTearing = allowTearing;
+ factory5->Release();
+ }
+
+ if (debugLayer) {
+ ID3D12Debug1 *debug = nullptr;
+ if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(ID3D12Debug1), reinterpret_cast<void **>(&debug)))) {
+ qCDebug(QRHI_LOG_INFO, "Enabling D3D12 debug layer");
+ debug->EnableDebugLayer();
+ debug->Release();
+ }
+ }
+
+ if (!importedDevice) {
+ IDXGIAdapter1 *adapter;
+ int requestedAdapterIndex = -1;
+ if (qEnvironmentVariableIsSet("QT_D3D_ADAPTER_INDEX"))
+ requestedAdapterIndex = qEnvironmentVariableIntValue("QT_D3D_ADAPTER_INDEX");
+
+ // The importParams may specify an adapter by the luid, take that into account.
+ if (requestedAdapterIndex < 0 && (adapterLuid.LowPart || adapterLuid.HighPart)) {
+ for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
+ DXGI_ADAPTER_DESC1 desc;
+ adapter->GetDesc1(&desc);
+ adapter->Release();
+ if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
+ && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
+ {
+ requestedAdapterIndex = adapterIndex;
+ break;
+ }
+ }
+ }
+
+ if (requestedAdapterIndex < 0 && flags.testFlag(QRhi::PreferSoftwareRenderer)) {
+ for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
+ DXGI_ADAPTER_DESC1 desc;
+ adapter->GetDesc1(&desc);
+ adapter->Release();
+ if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
+ requestedAdapterIndex = adapterIndex;
+ break;
+ }
+ }
+ }
+
+ activeAdapter = nullptr;
+ for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
+ DXGI_ADAPTER_DESC1 desc;
+ adapter->GetDesc1(&desc);
+ const QString name = QString::fromUtf16(reinterpret_cast<char16_t *>(desc.Description));
+ qCDebug(QRHI_LOG_INFO, "Adapter %d: '%s' (vendor 0x%X device 0x%X flags 0x%X)",
+ adapterIndex,
+ qPrintable(name),
+ desc.VendorId,
+ desc.DeviceId,
+ desc.Flags);
+ if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
+ activeAdapter = adapter;
+ adapterLuid = desc.AdapterLuid;
+ QRhiD3D::fillDriverInfo(&driverInfoStruct, desc);
+ qCDebug(QRHI_LOG_INFO, " using this adapter");
+ } else {
+ adapter->Release();
+ }
+ }
+ if (!activeAdapter) {
+ qWarning("No adapter");
+ return false;
+ }
+
+ if (minimumFeatureLevel == 0)
+ minimumFeatureLevel = MIN_FEATURE_LEVEL;
+
+ hr = D3D12CreateDevice(activeAdapter,
+ minimumFeatureLevel,
+ __uuidof(ID3D12Device2),
+ reinterpret_cast<void **>(&dev));
+ if (FAILED(hr)) {
+ qWarning("Failed to create D3D12 device: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ } else {
+ Q_ASSERT(dev);
+ // cannot just get a IDXGIDevice from the ID3D12Device anymore, look up the adapter instead
+ adapterLuid = dev->GetAdapterLuid();
+ IDXGIAdapter1 *adapter;
+ for (int adapterIndex = 0; dxgiFactory->EnumAdapters1(UINT(adapterIndex), &adapter) != DXGI_ERROR_NOT_FOUND; ++adapterIndex) {
+ DXGI_ADAPTER_DESC1 desc;
+ adapter->GetDesc1(&desc);
+ if (desc.AdapterLuid.LowPart == adapterLuid.LowPart
+ && desc.AdapterLuid.HighPart == adapterLuid.HighPart)
+ {
+ activeAdapter = adapter;
+ QRhiD3D::fillDriverInfo(&driverInfoStruct, desc);
+ break;
+ } else {
+ adapter->Release();
+ }
+ }
+ if (!activeAdapter) {
+ qWarning("No adapter");
+ return false;
+ }
+ qCDebug(QRHI_LOG_INFO, "Using imported device %p", dev);
+ }
+
+ if (debugLayer) {
+ ID3D12InfoQueue *infoQueue;
+ if (SUCCEEDED(dev->QueryInterface(__uuidof(ID3D12InfoQueue), reinterpret_cast<void **>(&infoQueue)))) {
+ if (qEnvironmentVariableIntValue("QT_D3D_DEBUG_BREAK")) {
+ infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, true);
+ infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, true);
+ infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, true);
+ }
+ D3D12_INFO_QUEUE_FILTER filter = {};
+ D3D12_MESSAGE_ID suppressedMessages[2] = {
+ // there is no way of knowing the clear color upfront
+ D3D12_MESSAGE_ID_CLEARRENDERTARGETVIEW_MISMATCHINGCLEARVALUE,
+ // we have no control over viewport and scissor rects
+ D3D12_MESSAGE_ID_DRAW_EMPTY_SCISSOR_RECTANGLE
+ };
+ filter.DenyList.NumIDs = 2;
+ filter.DenyList.pIDList = suppressedMessages;
+ // Setting the filter would enable Info messages (e.g. about
+ // resource creation) which we don't need.
+ D3D12_MESSAGE_SEVERITY infoSev = D3D12_MESSAGE_SEVERITY_INFO;
+ filter.DenyList.NumSeverities = 1;
+ filter.DenyList.pSeverityList = &infoSev;
+ infoQueue->PushStorageFilter(&filter);
+ infoQueue->Release();
+ }
+ }
+
+ if (!importedCommandQueue) {
+ D3D12_COMMAND_QUEUE_DESC queueDesc = {};
+ queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+ queueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
+ hr = dev->CreateCommandQueue(&queueDesc, __uuidof(ID3D12CommandQueue), reinterpret_cast<void **>(&cmdQueue));
+ if (FAILED(hr)) {
+ qWarning("Failed to create command queue: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ }
+
+ hr = dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), reinterpret_cast<void **>(&fullFence));
+ if (FAILED(hr)) {
+ qWarning("Failed to create fence: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ fullFenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ fullFenceCounter = 0;
+
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ hr = dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
+ __uuidof(ID3D12CommandAllocator),
+ reinterpret_cast<void **>(&cmdAllocators[i]));
+ if (FAILED(hr)) {
+ qWarning("Failed to create command allocator: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ }
+
+ if (!vma.create(dev, activeAdapter)) {
+ qWarning("Failed to initialize graphics memory suballocator");
+ return false;
+ }
+
+ if (!rtvPool.create(dev, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, "main RTV pool")) {
+ qWarning("Could not create RTV pool");
+ return false;
+ }
+
+ if (!dsvPool.create(dev, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, "main DSV pool")) {
+ qWarning("Could not create DSV pool");
+ return false;
+ }
+
+ if (!cbvSrvUavPool.create(dev, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, "main CBV-SRV-UAV pool")) {
+ qWarning("Could not create CBV-SRV-UAV pool");
+ return false;
+ }
+
+ resourcePool.create("main resource pool");
+ pipelinePool.create("main pipeline pool");
+ rootSignaturePool.create("main root signature pool");
+ releaseQueue.create(&resourcePool, &pipelinePool, &rootSignaturePool);
+ barrierGen.create(&resourcePool);
+
+ if (!samplerMgr.create(dev)) {
+ qWarning("Could not create sampler pool and shader-visible sampler heap");
+ return false;
+ }
+
+ if (!mipmapGen.create(this)) {
+ qWarning("Could not initialize mipmap generator");
+ return false;
+ }
+
+ const qint32 smallStagingSize = aligned(SMALL_STAGING_AREA_BYTES_PER_FRAME, QD3D12StagingArea::ALIGNMENT);
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ if (!smallStagingAreas[i].create(this, smallStagingSize, D3D12_HEAP_TYPE_UPLOAD)) {
+ qWarning("Could not create host-visible staging area");
+ return false;
+ }
+ QString decoratedName = QLatin1String("Small staging area buffer/");
+ decoratedName += QString::number(i);
+ smallStagingAreas[i].mem.buffer->SetName(reinterpret_cast<LPCWSTR>(decoratedName.utf16()));
+ }
+
+ if (!shaderVisibleCbvSrvUavHeap.create(dev,
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+ SHADER_VISIBLE_CBV_SRV_UAV_HEAP_PER_FRAME_START_SIZE))
+ {
+ qWarning("Could not create first shader-visible CBV/SRV/UAV heap");
+ return false;
+ }
+
+ if (flags.testFlag(QRhi::EnableTimestamps)) {
+ static bool wantsStablePowerState = qEnvironmentVariableIntValue("QT_D3D_STABLE_POWER_STATE");
+ //
+ // https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-setstablepowerstate
+ //
+ // NB! This is a _global_ setting, affecting other processes (and 3D
+ // APIs such as Vulkan), as long as this application is running. Hence
+ // making it an env.var. for now. Never enable it in production. But
+ // extremely useful for the GPU timings with NVIDIA at least; the
+ // timestamps become stable and smooth, making the number readable and
+ // actually useful e.g. in Quick 3D's DebugView when this is enabled.
+ // (otherwise the number's all over the place)
+ //
+ // See also
+ // https://developer.nvidia.com/blog/advanced-api-performance-setstablepowerstate/
+ // for possible other approaches.
+ //
+ if (wantsStablePowerState)
+ dev->SetStablePowerState(TRUE);
+
+ hr = cmdQueue->GetTimestampFrequency(&timestampTicksPerSecond);
+ if (FAILED(hr)) {
+ qWarning("Failed to query timestamp frequency: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ if (!timestampQueryHeap.create(dev, QD3D12_FRAMES_IN_FLIGHT * 2, D3D12_QUERY_HEAP_TYPE_TIMESTAMP)) {
+ qWarning("Failed to create timestamp query pool");
+ return false;
+ }
+ const quint32 readbackBufSize = QD3D12_FRAMES_IN_FLIGHT * 2 * sizeof(quint64);
+ if (!timestampReadbackArea.create(this, readbackBufSize, D3D12_HEAP_TYPE_READBACK)) {
+ qWarning("Failed to create timestamp readback buffer");
+ return false;
+ }
+ timestampReadbackArea.mem.buffer->SetName(L"Timestamp readback buffer");
+ memset(timestampReadbackArea.mem.p, 0, readbackBufSize);
+ }
+
+ caps = {};
+ D3D12_FEATURE_DATA_D3D12_OPTIONS3 options3 = {};
+ if (SUCCEEDED(dev->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS3, &options3, sizeof(options3)))) {
+ caps.multiView = options3.ViewInstancingTier != D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED;
+ // https://microsoft.github.io/DirectX-Specs/d3d/RelaxedCasting.html
+ caps.textureViewFormat = options3.CastingFullyTypedFormatSupported;
+ }
+
+ deviceLost = false;
+ offscreenActive = false;
+
+ nativeHandlesStruct.dev = dev;
+ nativeHandlesStruct.minimumFeatureLevel = minimumFeatureLevel;
+ nativeHandlesStruct.adapterLuidLow = adapterLuid.LowPart;
+ nativeHandlesStruct.adapterLuidHigh = adapterLuid.HighPart;
+ nativeHandlesStruct.commandQueue = cmdQueue;
+
+ return true;
+}
+
+void QRhiD3D12::destroy()
+{
+ if (!deviceLost && fullFence && fullFenceEvent)
+ waitGpu();
+
+ releaseQueue.releaseAll();
+
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ if (offscreenCb[i]) {
+ if (offscreenCb[i]->cmdList)
+ offscreenCb[i]->cmdList->Release();
+ delete offscreenCb[i];
+ offscreenCb[i] = nullptr;
+ }
+ }
+
+ timestampQueryHeap.destroy();
+ timestampReadbackArea.destroy();
+
+ shaderVisibleCbvSrvUavHeap.destroy();
+
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i)
+ smallStagingAreas[i].destroy();
+
+ mipmapGen.destroy();
+ samplerMgr.destroy();
+ resourcePool.destroy();
+ pipelinePool.destroy();
+ rootSignaturePool.destroy();
+ rtvPool.destroy();
+ dsvPool.destroy();
+ cbvSrvUavPool.destroy();
+
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ if (cmdAllocators[i]) {
+ cmdAllocators[i]->Release();
+ cmdAllocators[i] = nullptr;
+ }
+ }
+
+ if (fullFenceEvent) {
+ CloseHandle(fullFenceEvent);
+ fullFenceEvent = nullptr;
+ }
+
+ if (fullFence) {
+ fullFence->Release();
+ fullFence = nullptr;
+ }
+
+ if (!importedCommandQueue) {
+ if (cmdQueue) {
+ cmdQueue->Release();
+ cmdQueue = nullptr;
+ }
+ }
+
+ vma.destroy();
+
+ if (!importedDevice) {
+ if (dev) {
+ dev->Release();
+ dev = nullptr;
+ }
+ }
+
+ if (dcompDevice) {
+ dcompDevice->Release();
+ dcompDevice = nullptr;
+ }
+
+ if (activeAdapter) {
+ activeAdapter->Release();
+ activeAdapter = nullptr;
+ }
+
+ if (dxgiFactory) {
+ dxgiFactory->Release();
+ dxgiFactory = nullptr;
+ }
+}
+
+QList<int> QRhiD3D12::supportedSampleCounts() const
+{
+ return { 1, 2, 4, 8 };
+}
+
+QRhiSwapChain *QRhiD3D12::createSwapChain()
+{
+ return new QD3D12SwapChain(this);
+}
+
+QRhiBuffer *QRhiD3D12::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
+{
+ return new QD3D12Buffer(this, type, usage, size);
+}
+
+int QRhiD3D12::ubufAlignment() const
+{
+ return D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT; // 256
+}
+
+bool QRhiD3D12::isYUpInFramebuffer() const
+{
+ return false;
+}
+
+bool QRhiD3D12::isYUpInNDC() const
+{
+ return true;
+}
+
+bool QRhiD3D12::isClipDepthZeroToOne() const
+{
+ return true;
+}
+
+QMatrix4x4 QRhiD3D12::clipSpaceCorrMatrix() const
+{
+ // Like with Vulkan, but Y is already good.
+
+ static QMatrix4x4 m;
+ if (m.isIdentity()) {
+ // NB the ctor takes row-major
+ m = QMatrix4x4(1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 0.5f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ return m;
+}
+
+bool QRhiD3D12::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const
+{
+ Q_UNUSED(flags);
+
+ if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ASTC_12x12)
+ return false;
+
+ return true;
+}
+
+bool QRhiD3D12::isFeatureSupported(QRhi::Feature feature) const
+{
+ switch (feature) {
+ case QRhi::MultisampleTexture:
+ return true;
+ case QRhi::MultisampleRenderBuffer:
+ return true;
+ case QRhi::DebugMarkers:
+#ifdef QRHI_D3D12_HAS_OLD_PIX
+ return true;
+#else
+ return false;
+#endif
+ case QRhi::Timestamps:
+ return true;
+ case QRhi::Instancing:
+ return true;
+ case QRhi::CustomInstanceStepRate:
+ return true;
+ case QRhi::PrimitiveRestart:
+ return true;
+ case QRhi::NonDynamicUniformBuffers:
+ return false;
+ case QRhi::NonFourAlignedEffectiveIndexBufferOffset:
+ return true;
+ case QRhi::NPOTTextureRepeat:
+ return true;
+ case QRhi::RedOrAlpha8IsRed:
+ return true;
+ case QRhi::ElementIndexUint:
+ return true;
+ case QRhi::Compute:
+ return true;
+ case QRhi::WideLines:
+ return false;
+ case QRhi::VertexShaderPointSize:
+ return false;
+ case QRhi::BaseVertex:
+ return true;
+ case QRhi::BaseInstance:
+ return true;
+ case QRhi::TriangleFanTopology:
+ return false;
+ case QRhi::ReadBackNonUniformBuffer:
+ return true;
+ case QRhi::ReadBackNonBaseMipLevel:
+ return true;
+ case QRhi::TexelFetch:
+ return true;
+ case QRhi::RenderToNonBaseMipLevel:
+ return true;
+ case QRhi::IntAttributes:
+ return true;
+ case QRhi::ScreenSpaceDerivatives:
+ return true;
+ case QRhi::ReadBackAnyTextureFormat:
+ return true;
+ case QRhi::PipelineCacheDataLoadSave:
+ return false; // ###
+ case QRhi::ImageDataStride:
+ return true;
+ case QRhi::RenderBufferImport:
+ return false;
+ case QRhi::ThreeDimensionalTextures:
+ return true;
+ case QRhi::RenderTo3DTextureSlice:
+ return true;
+ case QRhi::TextureArrays:
+ return true;
+ case QRhi::Tessellation:
+ return true;
+ case QRhi::GeometryShader:
+ return true;
+ case QRhi::TextureArrayRange:
+ return true;
+ case QRhi::NonFillPolygonMode:
+ return true;
+ case QRhi::OneDimensionalTextures:
+ return true;
+ case QRhi::OneDimensionalTextureMipmaps:
+ return false; // we generate mipmaps ourselves with compute and this is not implemented
+ case QRhi::HalfAttributes:
+ return true;
+ case QRhi::RenderToOneDimensionalTexture:
+ return true;
+ case QRhi::ThreeDimensionalTextureMipmaps:
+ return false; // we generate mipmaps ourselves with compute and this is not implemented
+ case QRhi::MultiView:
+ return caps.multiView;
+ case QRhi::TextureViewFormat:
+ return caps.textureViewFormat;
+ case QRhi::ResolveDepthStencil:
+ // there is no Multisample Resolve support for depth/stencil formats
+ // https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/hardware-support-for-direct3d-12-1-formats
+ return false;
+ }
+ return false;
+}
+
+int QRhiD3D12::resourceLimit(QRhi::ResourceLimit limit) const
+{
+ switch (limit) {
+ case QRhi::TextureSizeMin:
+ return 1;
+ case QRhi::TextureSizeMax:
+ return 16384;
+ case QRhi::MaxColorAttachments:
+ return 8;
+ case QRhi::FramesInFlight:
+ return QD3D12_FRAMES_IN_FLIGHT;
+ case QRhi::MaxAsyncReadbackFrames:
+ return QD3D12_FRAMES_IN_FLIGHT;
+ case QRhi::MaxThreadGroupsPerDimension:
+ return 65535;
+ case QRhi::MaxThreadsPerThreadGroup:
+ return 1024;
+ case QRhi::MaxThreadGroupX:
+ return 1024;
+ case QRhi::MaxThreadGroupY:
+ return 1024;
+ case QRhi::MaxThreadGroupZ:
+ return 1024;
+ case QRhi::TextureArraySizeMax:
+ return 2048;
+ case QRhi::MaxUniformBufferRange:
+ return 65536;
+ case QRhi::MaxVertexInputs:
+ return 32;
+ case QRhi::MaxVertexOutputs:
+ return 32;
+ }
+ return 0;
+}
+
+const QRhiNativeHandles *QRhiD3D12::nativeHandles()
+{
+ return &nativeHandlesStruct;
+}
+
+QRhiDriverInfo QRhiD3D12::driverInfo() const
+{
+ return driverInfoStruct;
+}
+
+QRhiStats QRhiD3D12::statistics()
+{
+ QRhiStats result;
+ result.totalPipelineCreationTime = totalPipelineCreationTime();
+
+ D3D12MA::Budget budgets[2]; // [gpu, system] with discreet GPU or [shared, nothing] with UMA
+ vma.getBudget(&budgets[0], &budgets[1]);
+ for (int i = 0; i < 2; ++i) {
+ const D3D12MA::Statistics &stats(budgets[i].Stats);
+ result.blockCount += stats.BlockCount;
+ result.allocCount += stats.AllocationCount;
+ result.usedBytes += stats.AllocationBytes;
+ result.unusedBytes += stats.BlockBytes - stats.AllocationBytes;
+ result.totalUsageBytes += budgets[i].UsageBytes;
+ }
+
+ return result;
+}
+
+bool QRhiD3D12::makeThreadLocalNativeContextCurrent()
+{
+ // not applicable
+ return false;
+}
+
+void QRhiD3D12::releaseCachedResources()
+{
+ shaderBytecodeCache.data.clear();
+}
+
+bool QRhiD3D12::isDeviceLost() const
+{
+ return deviceLost;
+}
+
+QByteArray QRhiD3D12::pipelineCacheData()
+{
+ return {};
+}
+
+void QRhiD3D12::setPipelineCacheData(const QByteArray &data)
+{
+ Q_UNUSED(data);
+}
+
+QRhiRenderBuffer *QRhiD3D12::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint)
+{
+ return new QD3D12RenderBuffer(this, type, pixelSize, sampleCount, flags, backingFormatHint);
+}
+
+QRhiTexture *QRhiD3D12::createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize, int depth, int arraySize,
+ int sampleCount, QRhiTexture::Flags flags)
+{
+ return new QD3D12Texture(this, format, pixelSize, depth, arraySize, sampleCount, flags);
+}
+
+QRhiSampler *QRhiD3D12::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
+{
+ return new QD3D12Sampler(this, magFilter, minFilter, mipmapMode, u, v, w);
+}
+
+QRhiTextureRenderTarget *QRhiD3D12::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags)
+{
+ return new QD3D12TextureRenderTarget(this, desc, flags);
+}
+
+QRhiGraphicsPipeline *QRhiD3D12::createGraphicsPipeline()
+{
+ return new QD3D12GraphicsPipeline(this);
+}
+
+QRhiComputePipeline *QRhiD3D12::createComputePipeline()
+{
+ return new QD3D12ComputePipeline(this);
+}
+
+QRhiShaderResourceBindings *QRhiD3D12::createShaderResourceBindings()
+{
+ return new QD3D12ShaderResourceBindings(this);
+}
+
+void QRhiD3D12::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
+ QD3D12GraphicsPipeline *psD = QRHI_RES(QD3D12GraphicsPipeline, ps);
+ const bool pipelineChanged = cbD->currentGraphicsPipeline != psD || cbD->currentPipelineGeneration != psD->generation;
+
+ if (pipelineChanged) {
+ cbD->currentGraphicsPipeline = psD;
+ cbD->currentComputePipeline = nullptr;
+ cbD->currentPipelineGeneration = psD->generation;
+
+ if (QD3D12Pipeline *pipeline = pipelinePool.lookupRef(psD->handle)) {
+ Q_ASSERT(pipeline->type == QD3D12Pipeline::Graphics);
+ cbD->cmdList->SetPipelineState(pipeline->pso);
+ if (QD3D12RootSignature *rs = rootSignaturePool.lookupRef(psD->rootSigHandle))
+ cbD->cmdList->SetGraphicsRootSignature(rs->rootSig);
+ }
+
+ cbD->cmdList->IASetPrimitiveTopology(psD->topology);
+
+ if (psD->viewInstanceMask)
+ cbD->cmdList->SetViewInstanceMask(psD->viewInstanceMask);
+ }
+}
+
+void QD3D12CommandBuffer::visitUniformBuffer(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::UniformBufferData &d,
+ int,
+ int binding,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
+{
+ QD3D12Buffer *bufD = QRHI_RES(QD3D12Buffer, d.buf);
+ quint32 offset = d.offset;
+ if (d.hasDynamicOffset) {
+ for (int i = 0; i < dynamicOffsetCount; ++i) {
+ const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
+ if (dynOfs.first == binding) {
+ Q_ASSERT(aligned(dynOfs.second, 256u) == dynOfs.second);
+ offset += dynOfs.second;
+ }
+ }
+ }
+ QRHI_RES_RHI(QRhiD3D12);
+ visitorData.cbufs[s].append({ bufD->handles[rhiD->currentFrameSlot], offset });
+}
+
+void QD3D12CommandBuffer::visitTexture(QD3D12Stage s,
+ const QRhiShaderResourceBinding::TextureAndSampler &d,
+ int)
+{
+ QD3D12Texture *texD = QRHI_RES(QD3D12Texture, d.tex);
+ visitorData.srvs[s].append(texD->srv);
+}
+
+void QD3D12CommandBuffer::visitSampler(QD3D12Stage s,
+ const QRhiShaderResourceBinding::TextureAndSampler &d,
+ int)
+{
+ QD3D12Sampler *samplerD = QRHI_RES(QD3D12Sampler, d.sampler);
+ visitorData.samplers[s].append(samplerD->lookupOrCreateShaderVisibleDescriptor());
+}
+
+void QD3D12CommandBuffer::visitStorageBuffer(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::StorageBufferData &d,
+ QD3D12ShaderResourceVisitor::StorageOp,
+ int)
+{
+ QD3D12Buffer *bufD = QRHI_RES(QD3D12Buffer, d.buf);
+ // SPIRV-Cross generated HLSL uses RWByteAddressBuffer
+ D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
+ uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
+ uavDesc.Buffer.FirstElement = d.offset / 4;
+ uavDesc.Buffer.NumElements = aligned(bufD->m_size - d.offset, 4u) / 4;
+ uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
+ visitorData.uavs[s].append({ bufD->handles[0], uavDesc });
+}
+
+void QD3D12CommandBuffer::visitStorageImage(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::StorageImageData &d,
+ QD3D12ShaderResourceVisitor::StorageOp,
+ int)
+{
+ QD3D12Texture *texD = QRHI_RES(QD3D12Texture, d.tex);
+ const bool isCube = texD->m_flags.testFlag(QRhiTexture::CubeMap);
+ const bool isArray = texD->m_flags.testFlag(QRhiTexture::TextureArray);
+ const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
+ uavDesc.Format = texD->rtFormat;
+ if (isCube) {
+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
+ uavDesc.Texture2DArray.MipSlice = UINT(d.level);
+ uavDesc.Texture2DArray.FirstArraySlice = 0;
+ uavDesc.Texture2DArray.ArraySize = 6;
+ } else if (isArray) {
+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
+ uavDesc.Texture2DArray.MipSlice = UINT(d.level);
+ uavDesc.Texture2DArray.FirstArraySlice = 0;
+ uavDesc.Texture2DArray.ArraySize = UINT(qMax(0, texD->m_arraySize));
+ } else if (is3D) {
+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
+ uavDesc.Texture3D.MipSlice = UINT(d.level);
+ } else {
+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
+ uavDesc.Texture2D.MipSlice = UINT(d.level);
+ }
+ visitorData.uavs[s].append({ texD->handle, uavDesc });
+}
+
+void QRhiD3D12::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass != QD3D12CommandBuffer::NoPass);
+ QD3D12GraphicsPipeline *gfxPsD = QRHI_RES(QD3D12GraphicsPipeline, cbD->currentGraphicsPipeline);
+ QD3D12ComputePipeline *compPsD = QRHI_RES(QD3D12ComputePipeline, cbD->currentComputePipeline);
+
+ if (!srb) {
+ if (gfxPsD)
+ srb = gfxPsD->m_shaderResourceBindings;
+ else
+ srb = compPsD->m_shaderResourceBindings;
+ }
+
+ QD3D12ShaderResourceBindings *srbD = QRHI_RES(QD3D12ShaderResourceBindings, srb);
+
+ for (int i = 0, ie = srbD->m_bindings.size(); i != ie; ++i) {
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->m_bindings[i]);
+ switch (b->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ {
+ QD3D12Buffer *bufD = QRHI_RES(QD3D12Buffer, b->u.ubuf.buf);
+ Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
+ Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
+ bufD->executeHostWritesForFrameSlot(currentFrameSlot);
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ case QRhiShaderResourceBinding::Texture:
+ case QRhiShaderResourceBinding::Sampler:
+ {
+ const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
+ for (int elem = 0; elem < data->count; ++elem) {
+ QD3D12Texture *texD = QRHI_RES(QD3D12Texture, data->texSamplers[elem].tex);
+ QD3D12Sampler *samplerD = QRHI_RES(QD3D12Sampler, data->texSamplers[elem].sampler);
+ // We use the same code path for both combined and separate
+ // images and samplers, so tex or sampler (but not both) can be
+ // null here.
+ Q_ASSERT(texD || samplerD);
+ if (texD) {
+ UINT state = 0;
+ if (b->stage == QRhiShaderResourceBinding::FragmentStage) {
+ state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
+ } else if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
+ state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ } else {
+ state = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ }
+ barrierGen.addTransitionBarrier(texD->handle, D3D12_RESOURCE_STATES(state));
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+ }
+ }
+ }
+ break;
+ case QRhiShaderResourceBinding::ImageLoad:
+ case QRhiShaderResourceBinding::ImageStore:
+ case QRhiShaderResourceBinding::ImageLoadStore:
+ {
+ QD3D12Texture *texD = QRHI_RES(QD3D12Texture, b->u.simage.tex);
+ if (QD3D12Resource *res = resourcePool.lookupRef(texD->handle)) {
+ if (res->uavUsage) {
+ if (res->uavUsage & QD3D12Resource::UavUsageWrite) {
+ // RaW or WaW
+ barrierGen.enqueueUavBarrier(cbD, texD->handle);
+ } else {
+ if (b->type == QRhiShaderResourceBinding::ImageStore
+ || b->type == QRhiShaderResourceBinding::ImageLoadStore)
+ {
+ // WaR or WaW
+ barrierGen.enqueueUavBarrier(cbD, texD->handle);
+ }
+ }
+ }
+ res->uavUsage = 0;
+ if (b->type == QRhiShaderResourceBinding::ImageLoad || b->type == QRhiShaderResourceBinding::ImageLoadStore)
+ res->uavUsage |= QD3D12Resource::UavUsageRead;
+ if (b->type == QRhiShaderResourceBinding::ImageStore || b->type == QRhiShaderResourceBinding::ImageLoadStore)
+ res->uavUsage |= QD3D12Resource::UavUsageWrite;
+ barrierGen.addTransitionBarrier(texD->handle, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+ }
+ }
+ break;
+ case QRhiShaderResourceBinding::BufferLoad:
+ case QRhiShaderResourceBinding::BufferStore:
+ case QRhiShaderResourceBinding::BufferLoadStore:
+ {
+ QD3D12Buffer *bufD = QRHI_RES(QD3D12Buffer, b->u.sbuf.buf);
+ Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
+ Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
+ if (QD3D12Resource *res = resourcePool.lookupRef(bufD->handles[0])) {
+ if (res->uavUsage) {
+ if (res->uavUsage & QD3D12Resource::UavUsageWrite) {
+ // RaW or WaW
+ barrierGen.enqueueUavBarrier(cbD, bufD->handles[0]);
+ } else {
+ if (b->type == QRhiShaderResourceBinding::BufferStore
+ || b->type == QRhiShaderResourceBinding::BufferLoadStore)
+ {
+ // WaR or WaW
+ barrierGen.enqueueUavBarrier(cbD, bufD->handles[0]);
+ }
+ }
+ }
+ res->uavUsage = 0;
+ if (b->type == QRhiShaderResourceBinding::BufferLoad || b->type == QRhiShaderResourceBinding::BufferLoadStore)
+ res->uavUsage |= QD3D12Resource::UavUsageRead;
+ if (b->type == QRhiShaderResourceBinding::BufferStore || b->type == QRhiShaderResourceBinding::BufferLoadStore)
+ res->uavUsage |= QD3D12Resource::UavUsageWrite;
+ barrierGen.addTransitionBarrier(bufD->handles[0], D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+ }
+ }
+ break;
+ }
+ }
+
+ const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
+ const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
+
+ if (srbChanged || srbRebuilt || srbD->hasDynamicOffset) {
+ const QD3D12ShaderStageData *stageData = gfxPsD ? gfxPsD->stageData.data() : &compPsD->stageData;
+
+ // The order of root parameters must match
+ // QD3D12ShaderResourceBindings::createRootSignature(), meaning the
+ // logic below must mirror that function (uniform buffers first etc.)
+
+ QD3D12ShaderResourceVisitor visitor(srbD, stageData, gfxPsD ? 5 : 1);
+
+ QD3D12CommandBuffer::VisitorData &visitorData(cbD->visitorData);
+ visitorData = {};
+
+ using namespace std::placeholders;
+ visitor.uniformBuffer = std::bind(&QD3D12CommandBuffer::visitUniformBuffer, cbD, _1, _2, _3, _4, dynamicOffsetCount, dynamicOffsets);
+ visitor.texture = std::bind(&QD3D12CommandBuffer::visitTexture, cbD, _1, _2, _3);
+ visitor.sampler = std::bind(&QD3D12CommandBuffer::visitSampler, cbD, _1, _2, _3);
+ visitor.storageBuffer = std::bind(&QD3D12CommandBuffer::visitStorageBuffer, cbD, _1, _2, _3, _4);
+ visitor.storageImage = std::bind(&QD3D12CommandBuffer::visitStorageImage, cbD, _1, _2, _3, _4);
+
+ visitor.visit();
+
+ quint32 cbvSrvUavCount = 0;
+ for (int s = 0; s < 6; ++s) {
+ // CBs use root constant buffer views, no need to count them here
+ cbvSrvUavCount += visitorData.srvs[s].count();
+ cbvSrvUavCount += visitorData.uavs[s].count();
+ }
+
+ bool gotNewHeap = false;
+ if (!ensureShaderVisibleDescriptorHeapCapacity(&shaderVisibleCbvSrvUavHeap,
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+ currentFrameSlot,
+ cbvSrvUavCount,
+ &gotNewHeap))
+ {
+ return;
+ }
+ if (gotNewHeap) {
+ qCDebug(QRHI_LOG_INFO, "Created new shader-visible CBV/SRV/UAV descriptor heap,"
+ " per-frame slice size is now %u,"
+ " if this happens frequently then that's not great.",
+ shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[0].capacity);
+ bindShaderVisibleHeaps(cbD);
+ }
+
+ int rootParamIndex = 0;
+ for (int s = 0; s < 6; ++s) {
+ if (!visitorData.cbufs[s].isEmpty()) {
+ for (int i = 0, count = visitorData.cbufs[s].count(); i < count; ++i) {
+ const auto &cbuf(visitorData.cbufs[s][i]);
+ if (QD3D12Resource *res = resourcePool.lookupRef(cbuf.first)) {
+ quint32 offset = cbuf.second;
+ D3D12_GPU_VIRTUAL_ADDRESS gpuAddr = res->resource->GetGPUVirtualAddress() + offset;
+ if (cbD->currentGraphicsPipeline)
+ cbD->cmdList->SetGraphicsRootConstantBufferView(rootParamIndex, gpuAddr);
+ else
+ cbD->cmdList->SetComputeRootConstantBufferView(rootParamIndex, gpuAddr);
+ }
+ rootParamIndex += 1;
+ }
+ }
+ }
+ for (int s = 0; s < 6; ++s) {
+ if (!visitorData.srvs[s].isEmpty()) {
+ QD3D12DescriptorHeap &gpuSrvHeap(shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[currentFrameSlot]);
+ QD3D12Descriptor startDesc = gpuSrvHeap.get(visitorData.srvs[s].count());
+ for (int i = 0, count = visitorData.srvs[s].count(); i < count; ++i) {
+ const auto &srv(visitorData.srvs[s][i]);
+ dev->CopyDescriptorsSimple(1, gpuSrvHeap.incremented(startDesc, i).cpuHandle, srv.cpuHandle,
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+ }
+
+ if (cbD->currentGraphicsPipeline)
+ cbD->cmdList->SetGraphicsRootDescriptorTable(rootParamIndex, startDesc.gpuHandle);
+ else if (cbD->currentComputePipeline)
+ cbD->cmdList->SetComputeRootDescriptorTable(rootParamIndex, startDesc.gpuHandle);
+
+ rootParamIndex += 1;
+ }
+ }
+ for (int s = 0; s < 6; ++s) {
+ // Samplers are one parameter / descriptor table each, and the
+ // descriptor is from the shader visible sampler heap already.
+ for (const QD3D12Descriptor &samplerDescriptor : visitorData.samplers[s]) {
+ if (cbD->currentGraphicsPipeline)
+ cbD->cmdList->SetGraphicsRootDescriptorTable(rootParamIndex, samplerDescriptor.gpuHandle);
+ else if (cbD->currentComputePipeline)
+ cbD->cmdList->SetComputeRootDescriptorTable(rootParamIndex, samplerDescriptor.gpuHandle);
+
+ rootParamIndex += 1;
+ }
+ }
+ for (int s = 0; s < 6; ++s) {
+ if (!visitorData.uavs[s].isEmpty()) {
+ QD3D12DescriptorHeap &gpuUavHeap(shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[currentFrameSlot]);
+ QD3D12Descriptor startDesc = gpuUavHeap.get(visitorData.uavs[s].count());
+ for (int i = 0, count = visitorData.uavs[s].count(); i < count; ++i) {
+ const auto &uav(visitorData.uavs[s][i]);
+ if (QD3D12Resource *res = resourcePool.lookupRef(uav.first)) {
+ dev->CreateUnorderedAccessView(res->resource, nullptr, &uav.second,
+ gpuUavHeap.incremented(startDesc, i).cpuHandle);
+ } else {
+ dev->CreateUnorderedAccessView(nullptr, nullptr, nullptr,
+ gpuUavHeap.incremented(startDesc, i).cpuHandle);
+ }
+ }
+
+ if (cbD->currentGraphicsPipeline)
+ cbD->cmdList->SetGraphicsRootDescriptorTable(rootParamIndex, startDesc.gpuHandle);
+ else if (cbD->currentComputePipeline)
+ cbD->cmdList->SetComputeRootDescriptorTable(rootParamIndex, startDesc.gpuHandle);
+
+ rootParamIndex += 1;
+ }
+ }
+
+ if (gfxPsD) {
+ cbD->currentGraphicsSrb = srb;
+ cbD->currentComputeSrb = nullptr;
+ } else {
+ cbD->currentGraphicsSrb = nullptr;
+ cbD->currentComputeSrb = srb;
+ }
+ cbD->currentSrbGeneration = srbD->generation;
+ }
+}
+
+void QRhiD3D12::setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset, QRhiCommandBuffer::IndexFormat indexFormat)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
+
+ bool needsBindVBuf = false;
+ for (int i = 0; i < bindingCount; ++i) {
+ const int inputSlot = startBinding + i;
+ QD3D12Buffer *bufD = QRHI_RES(QD3D12Buffer, bindings[i].first);
+ Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
+ const bool isDynamic = bufD->m_type == QRhiBuffer::Dynamic;
+ if (isDynamic)
+ bufD->executeHostWritesForFrameSlot(currentFrameSlot);
+
+ if (cbD->currentVertexBuffers[inputSlot] != bufD->handles[isDynamic ? currentFrameSlot : 0]
+ || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
+ {
+ needsBindVBuf = true;
+ cbD->currentVertexBuffers[inputSlot] = bufD->handles[isDynamic ? currentFrameSlot : 0];
+ cbD->currentVertexOffsets[inputSlot] = bindings[i].second;
+ }
+ }
+
+ if (needsBindVBuf) {
+ QVarLengthArray<D3D12_VERTEX_BUFFER_VIEW, 4> vbv;
+ vbv.reserve(bindingCount);
+
+ QD3D12GraphicsPipeline *psD = cbD->currentGraphicsPipeline;
+ const QRhiVertexInputLayout &inputLayout(psD->m_vertexInputLayout);
+ const int inputBindingCount = inputLayout.cendBindings() - inputLayout.cbeginBindings();
+
+ for (int i = 0, ie = qMin(bindingCount, inputBindingCount); i != ie; ++i) {
+ QD3D12Buffer *bufD = QRHI_RES(QD3D12Buffer, bindings[i].first);
+ const QD3D12ObjectHandle handle = bufD->handles[bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0];
+ const quint32 offset = bindings[i].second;
+ const quint32 stride = inputLayout.bindingAt(i)->stride();
+
+ if (bufD->m_type != QRhiBuffer::Dynamic) {
+ barrierGen.addTransitionBarrier(handle, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+ }
+
+ if (QD3D12Resource *res = resourcePool.lookupRef(handle)) {
+ vbv.append({
+ res->resource->GetGPUVirtualAddress() + offset,
+ UINT(res->desc.Width - offset),
+ stride
+ });
+ }
+ }
+
+ cbD->cmdList->IASetVertexBuffers(UINT(startBinding), vbv.count(), vbv.constData());
+ }
+
+ if (indexBuf) {
+ QD3D12Buffer *ibufD = QRHI_RES(QD3D12Buffer, indexBuf);
+ Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
+ const bool isDynamic = ibufD->m_type == QRhiBuffer::Dynamic;
+ if (isDynamic)
+ ibufD->executeHostWritesForFrameSlot(currentFrameSlot);
+
+ const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
+ : DXGI_FORMAT_R32_UINT;
+ if (cbD->currentIndexBuffer != ibufD->handles[isDynamic ? currentFrameSlot : 0]
+ || cbD->currentIndexOffset != indexOffset
+ || cbD->currentIndexFormat != dxgiFormat)
+ {
+ cbD->currentIndexBuffer = ibufD->handles[isDynamic ? currentFrameSlot : 0];
+ cbD->currentIndexOffset = indexOffset;
+ cbD->currentIndexFormat = dxgiFormat;
+
+ if (ibufD->m_type != QRhiBuffer::Dynamic) {
+ barrierGen.addTransitionBarrier(cbD->currentIndexBuffer, D3D12_RESOURCE_STATE_INDEX_BUFFER);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+ }
+
+ if (QD3D12Resource *res = resourcePool.lookupRef(cbD->currentIndexBuffer)) {
+ const D3D12_INDEX_BUFFER_VIEW ibv = {
+ res->resource->GetGPUVirtualAddress() + indexOffset,
+ UINT(res->desc.Width - indexOffset),
+ dxgiFormat
+ };
+ cbD->cmdList->IASetIndexBuffer(&ibv);
+ }
+ }
+ }
+}
+
+void QRhiD3D12::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
+ Q_ASSERT(cbD->currentTarget);
+ const QSize outputSize = cbD->currentTarget->pixelSize();
+
+ // D3D expects top-left, QRhiViewport is bottom-left
+ float x, y, w, h;
+ if (!qrhi_toTopLeftRenderTargetRect<UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
+ return;
+
+ D3D12_VIEWPORT v;
+ v.TopLeftX = x;
+ v.TopLeftY = y;
+ v.Width = w;
+ v.Height = h;
+ v.MinDepth = viewport.minDepth();
+ v.MaxDepth = viewport.maxDepth();
+ cbD->cmdList->RSSetViewports(1, &v);
+
+ if (cbD->currentGraphicsPipeline
+ && !cbD->currentGraphicsPipeline->flags().testFlag(QRhiGraphicsPipeline::UsesScissor))
+ {
+ qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, viewport.viewport(), &x, &y, &w, &h);
+ D3D12_RECT r;
+ r.left = x;
+ r.top = y;
+ // right and bottom are exclusive
+ r.right = x + w;
+ r.bottom = y + h;
+ cbD->cmdList->RSSetScissorRects(1, &r);
+ }
+}
+
+void QRhiD3D12::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
+ Q_ASSERT(cbD->currentTarget);
+ const QSize outputSize = cbD->currentTarget->pixelSize();
+
+ // D3D expects top-left, QRhiScissor is bottom-left
+ int x, y, w, h;
+ if (!qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
+ return;
+
+ D3D12_RECT r;
+ r.left = x;
+ r.top = y;
+ // right and bottom are exclusive
+ r.right = x + w;
+ r.bottom = y + h;
+ cbD->cmdList->RSSetScissorRects(1, &r);
+}
+
+void QRhiD3D12::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
+ float v[4] = { c.redF(), c.greenF(), c.blueF(), c.alphaF() };
+ cbD->cmdList->OMSetBlendFactor(v);
+}
+
+void QRhiD3D12::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
+ cbD->cmdList->OMSetStencilRef(refValue);
+}
+
+void QRhiD3D12::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
+ cbD->cmdList->DrawInstanced(vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
+void QRhiD3D12::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
+ cbD->cmdList->DrawIndexedInstanced(indexCount, instanceCount,
+ firstIndex, vertexOffset,
+ firstInstance);
+}
+
+void QRhiD3D12::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
+{
+ if (!debugMarkers)
+ return;
+
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+#ifdef QRHI_D3D12_HAS_OLD_PIX
+ PIXBeginEvent(cbD->cmdList, PIX_COLOR_DEFAULT, reinterpret_cast<LPCWSTR>(QString::fromLatin1(name).utf16()));
+#else
+ Q_UNUSED(cbD);
+ Q_UNUSED(name);
+#endif
+}
+
+void QRhiD3D12::debugMarkEnd(QRhiCommandBuffer *cb)
+{
+ if (!debugMarkers)
+ return;
+
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+#ifdef QRHI_D3D12_HAS_OLD_PIX
+ PIXEndEvent(cbD->cmdList);
+#else
+ Q_UNUSED(cbD);
+#endif
+}
+
+void QRhiD3D12::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
+{
+ if (!debugMarkers)
+ return;
+
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+#ifdef QRHI_D3D12_HAS_OLD_PIX
+ PIXSetMarker(cbD->cmdList, PIX_COLOR_DEFAULT, reinterpret_cast<LPCWSTR>(QString::fromLatin1(msg).utf16()));
+#else
+ Q_UNUSED(cbD);
+ Q_UNUSED(msg);
+#endif
+}
+
+const QRhiNativeHandles *QRhiD3D12::nativeHandles(QRhiCommandBuffer *cb)
+{
+ return QRHI_RES(QD3D12CommandBuffer, cb)->nativeHandles();
+}
+
+void QRhiD3D12::beginExternal(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+}
+
+void QRhiD3D12::endExternal(QRhiCommandBuffer *cb)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ cbD->resetPerPassState();
+ bindShaderVisibleHeaps(cbD);
+ if (cbD->currentTarget) { // could be compute, no rendertarget then
+ QD3D12RenderTargetData *rtD = rtData(cbD->currentTarget);
+ cbD->cmdList->OMSetRenderTargets(UINT(rtD->colorAttCount),
+ rtD->rtv,
+ TRUE,
+ rtD->dsAttCount ? &rtD->dsv : nullptr);
+ }
+}
+
+double QRhiD3D12::lastCompletedGpuTime(QRhiCommandBuffer *cb)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ return cbD->lastGpuTime;
+}
+
+static void calculateGpuTime(QD3D12CommandBuffer *cbD,
+ int timestampPairStartIndex,
+ const quint8 *readbackBufPtr,
+ quint64 timestampTicksPerSecond)
+{
+ const size_t byteOffset = timestampPairStartIndex * sizeof(quint64);
+ const quint64 *p = reinterpret_cast<const quint64 *>(readbackBufPtr + byteOffset);
+ const quint64 startTime = *p++;
+ const quint64 endTime = *p;
+ if (startTime < endTime) {
+ const quint64 ticks = endTime - startTime;
+ const double timeSec = ticks / double(timestampTicksPerSecond);
+ cbD->lastGpuTime = timeSec;
+ }
+}
+
+QRhi::FrameOpResult QRhiD3D12::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
+{
+ Q_UNUSED(flags);
+
+ QD3D12SwapChain *swapChainD = QRHI_RES(QD3D12SwapChain, swapChain);
+ currentSwapChain = swapChainD;
+ currentFrameSlot = swapChainD->currentFrameSlot;
+ QD3D12SwapChain::FrameResources &fr(swapChainD->frameRes[currentFrameSlot]);
+
+ // We could do smarter things but mirror the Vulkan backend for now: Make
+ // sure the previous commands for this same frame slot have finished. Do
+ // this also for any other swapchain's commands with the same frame slot.
+ // While this reduces concurrency in render-to-swapchain-A,
+ // render-to-swapchain-B, repeat kind of scenarios, it keeps resource usage
+ // safe: swapchain A starting its frame 0, followed by swapchain B starting
+ // its own frame 0 will make B wait for A's frame 0 commands. If a resource
+ // is written in B's frame or when B checks for pending resource releases,
+ // that won't mess up A's in-flight commands (as they are guaranteed not to
+ // be in flight anymore). With Qt Quick this situation cannot happen anyway
+ // by design (one QRhi per window).
+ for (QD3D12SwapChain *sc : std::as_const(swapchains))
+ sc->waitCommandCompletionForFrameSlot(currentFrameSlot); // note: swapChainD->currentFrameSlot, not sc's
+
+ HRESULT hr = cmdAllocators[currentFrameSlot]->Reset();
+ if (FAILED(hr)) {
+ qWarning("Failed to reset command allocator: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return QRhi::FrameOpError;
+ }
+
+ if (!startCommandListForCurrentFrameSlot(&fr.cmdList))
+ return QRhi::FrameOpError;
+
+ QD3D12CommandBuffer *cbD = &swapChainD->cbWrapper;
+ cbD->cmdList = fr.cmdList;
+
+ swapChainD->rtWrapper.d.rtv[0] = swapChainD->sampleDesc.Count > 1
+ ? swapChainD->msaaRtvs[swapChainD->currentBackBufferIndex].cpuHandle
+ : swapChainD->rtvs[swapChainD->currentBackBufferIndex].cpuHandle;
+
+ swapChainD->rtWrapper.d.dsv = swapChainD->ds ? swapChainD->ds->dsv.cpuHandle
+ : D3D12_CPU_DESCRIPTOR_HANDLE { 0 };
+
+ if (swapChainD->stereo) {
+ swapChainD->rtWrapperRight.d.rtv[0] = swapChainD->sampleDesc.Count > 1
+ ? swapChainD->msaaRtvs[swapChainD->currentBackBufferIndex].cpuHandle
+ : swapChainD->rtvsRight[swapChainD->currentBackBufferIndex].cpuHandle;
+
+ swapChainD->rtWrapperRight.d.dsv =
+ swapChainD->ds ? swapChainD->ds->dsv.cpuHandle : D3D12_CPU_DESCRIPTOR_HANDLE{ 0 };
+ }
+
+
+ // Time to release things that are marked for currentFrameSlot since due to
+ // the wait above we know that the previous commands on the GPU for this
+ // slot must have finished already.
+ releaseQueue.executeDeferredReleases(currentFrameSlot);
+
+ // Full reset of the command buffer data.
+ cbD->resetState();
+
+ // Move the head back to zero for the per-frame shader-visible descriptor heap work areas.
+ shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[currentFrameSlot].head = 0;
+ // Same for the small staging area.
+ smallStagingAreas[currentFrameSlot].head = 0;
+
+ bindShaderVisibleHeaps(cbD);
+
+ finishActiveReadbacks(); // last, in case the readback-completed callback issues rhi calls
+
+ if (timestampQueryHeap.isValid() && timestampTicksPerSecond) {
+ // Read the timestamps for the previous frame for this slot. (the
+ // ResolveQuery() should have completed by now due to the wait above)
+ const int timestampPairStartIndex = currentFrameSlot * QD3D12_FRAMES_IN_FLIGHT;
+ calculateGpuTime(cbD,
+ timestampPairStartIndex,
+ timestampReadbackArea.mem.p,
+ timestampTicksPerSecond);
+ // Write the start timestamp for this frame for this slot.
+ cbD->cmdList->EndQuery(timestampQueryHeap.heap,
+ D3D12_QUERY_TYPE_TIMESTAMP,
+ timestampPairStartIndex);
+ }
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiD3D12::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags)
+{
+ QD3D12SwapChain *swapChainD = QRHI_RES(QD3D12SwapChain, swapChain);
+ Q_ASSERT(currentSwapChain == swapChainD);
+ QD3D12CommandBuffer *cbD = &swapChainD->cbWrapper;
+
+ QD3D12ObjectHandle backBufferResourceHandle = swapChainD->colorBuffers[swapChainD->currentBackBufferIndex];
+ if (swapChainD->sampleDesc.Count > 1) {
+ QD3D12ObjectHandle msaaBackBufferResourceHandle = swapChainD->msaaBuffers[swapChainD->currentBackBufferIndex];
+ barrierGen.addTransitionBarrier(msaaBackBufferResourceHandle, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
+ barrierGen.addTransitionBarrier(backBufferResourceHandle, D3D12_RESOURCE_STATE_RESOLVE_DEST);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+ const QD3D12Resource *src = resourcePool.lookupRef(msaaBackBufferResourceHandle);
+ const QD3D12Resource *dst = resourcePool.lookupRef(backBufferResourceHandle);
+ if (src && dst)
+ cbD->cmdList->ResolveSubresource(dst->resource, 0, src->resource, 0, swapChainD->colorFormat);
+ }
+
+ barrierGen.addTransitionBarrier(backBufferResourceHandle, D3D12_RESOURCE_STATE_PRESENT);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+
+ if (timestampQueryHeap.isValid()) {
+ const int timestampPairStartIndex = currentFrameSlot * QD3D12_FRAMES_IN_FLIGHT;
+ cbD->cmdList->EndQuery(timestampQueryHeap.heap,
+ D3D12_QUERY_TYPE_TIMESTAMP,
+ timestampPairStartIndex + 1);
+ cbD->cmdList->ResolveQueryData(timestampQueryHeap.heap,
+ D3D12_QUERY_TYPE_TIMESTAMP,
+ timestampPairStartIndex,
+ 2,
+ timestampReadbackArea.mem.buffer,
+ timestampPairStartIndex * sizeof(quint64));
+ }
+
+ ID3D12GraphicsCommandList1 *cmdList = cbD->cmdList;
+ HRESULT hr = cmdList->Close();
+ if (FAILED(hr)) {
+ qWarning("Failed to close command list: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return QRhi::FrameOpError;
+ }
+
+ ID3D12CommandList *execList[] = { cmdList };
+ cmdQueue->ExecuteCommandLists(1, execList);
+
+ if (!flags.testFlag(QRhi::SkipPresent)) {
+ UINT presentFlags = 0;
+ if (swapChainD->swapInterval == 0
+ && (swapChainD->swapChainFlags & DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING))
+ {
+ presentFlags |= DXGI_PRESENT_ALLOW_TEARING;
+ }
+ if (!swapChainD->swapChain) {
+ qWarning("Failed to present, no swapchain");
+ return QRhi::FrameOpError;
+ }
+ HRESULT hr = swapChainD->swapChain->Present(swapChainD->swapInterval, presentFlags);
+ if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
+ qWarning("Device loss detected in Present()");
+ deviceLost = true;
+ return QRhi::FrameOpDeviceLost;
+ } else if (FAILED(hr)) {
+ qWarning("Failed to present: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return QRhi::FrameOpError;
+ }
+
+ if (dcompDevice && swapChainD->dcompTarget && swapChainD->dcompVisual)
+ dcompDevice->Commit();
+ }
+
+ swapChainD->addCommandCompletionSignalForCurrentFrameSlot();
+
+ // NB! The deferred-release mechanism here differs from the older QRhi
+ // backends. There is no lastActiveFrameSlot tracking. Instead,
+ // currentFrameSlot is written to the registered entries now, and so the
+ // resources will get released in the frames_in_flight'th beginFrame()
+ // counting starting from now.
+ releaseQueue.activatePendingDeferredReleaseRequests(currentFrameSlot);
+
+ if (!flags.testFlag(QRhi::SkipPresent)) {
+ // Only move to the next slot if we presented. Otherwise will block and
+ // wait for completion in the next beginFrame already, but SkipPresent
+ // should be infrequent anyway.
+ swapChainD->currentFrameSlot = (swapChainD->currentFrameSlot + 1) % QD3D12_FRAMES_IN_FLIGHT;
+ swapChainD->currentBackBufferIndex = swapChainD->swapChain->GetCurrentBackBufferIndex();
+ }
+
+ currentSwapChain = nullptr;
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiD3D12::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags)
+{
+ Q_UNUSED(flags);
+
+ // Switch to the next slot manually. Swapchains do not know about this
+ // which is good. So for example an onscreen, onscreen, offscreen,
+ // onscreen, onscreen, onscreen sequence of frames leads to 0, 1, 0, 0, 1,
+ // 0. (no strict alternation anymore) But this is not different from what
+ // happens when multiple swapchains are involved. Offscreen frames are
+ // synchronous anyway in the sense that they wait for execution to complete
+ // in endOffscreenFrame, so no resources used in that frame are busy
+ // anymore in the next frame.
+
+ currentFrameSlot = (currentFrameSlot + 1) % QD3D12_FRAMES_IN_FLIGHT;
+
+ for (QD3D12SwapChain *sc : std::as_const(swapchains))
+ sc->waitCommandCompletionForFrameSlot(currentFrameSlot); // note: not sc's currentFrameSlot
+
+ if (!offscreenCb[currentFrameSlot])
+ offscreenCb[currentFrameSlot] = new QD3D12CommandBuffer(this);
+ QD3D12CommandBuffer *cbD = offscreenCb[currentFrameSlot];
+ if (!startCommandListForCurrentFrameSlot(&cbD->cmdList))
+ return QRhi::FrameOpError;
+
+ releaseQueue.executeDeferredReleases(currentFrameSlot);
+ cbD->resetState();
+ shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[currentFrameSlot].head = 0;
+ smallStagingAreas[currentFrameSlot].head = 0;
+
+ bindShaderVisibleHeaps(cbD);
+
+ if (timestampQueryHeap.isValid() && timestampTicksPerSecond) {
+ cbD->cmdList->EndQuery(timestampQueryHeap.heap,
+ D3D12_QUERY_TYPE_TIMESTAMP,
+ currentFrameSlot * QD3D12_FRAMES_IN_FLIGHT);
+ }
+
+ offscreenActive = true;
+ *cb = cbD;
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiD3D12::endOffscreenFrame(QRhi::EndFrameFlags flags)
+{
+ Q_UNUSED(flags);
+ Q_ASSERT(offscreenActive);
+ offscreenActive = false;
+
+ QD3D12CommandBuffer *cbD = offscreenCb[currentFrameSlot];
+ if (timestampQueryHeap.isValid()) {
+ const int timestampPairStartIndex = currentFrameSlot * QD3D12_FRAMES_IN_FLIGHT;
+ cbD->cmdList->EndQuery(timestampQueryHeap.heap,
+ D3D12_QUERY_TYPE_TIMESTAMP,
+ timestampPairStartIndex + 1);
+ cbD->cmdList->ResolveQueryData(timestampQueryHeap.heap,
+ D3D12_QUERY_TYPE_TIMESTAMP,
+ timestampPairStartIndex,
+ 2,
+ timestampReadbackArea.mem.buffer,
+ timestampPairStartIndex * sizeof(quint64));
+ }
+
+ ID3D12GraphicsCommandList1 *cmdList = cbD->cmdList;
+ HRESULT hr = cmdList->Close();
+ if (FAILED(hr)) {
+ qWarning("Failed to close command list: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return QRhi::FrameOpError;
+ }
+
+ ID3D12CommandList *execList[] = { cmdList };
+ cmdQueue->ExecuteCommandLists(1, execList);
+
+ releaseQueue.activatePendingDeferredReleaseRequests(currentFrameSlot);
+
+ // wait for completion
+ waitGpu();
+
+ // Here we know that executing the host-side reads for this (or any
+ // previous) frame is safe since we waited for completion above.
+ finishActiveReadbacks(true);
+
+ // the timestamp query results should be available too, given the wait
+ if (timestampQueryHeap.isValid()) {
+ calculateGpuTime(cbD,
+ currentFrameSlot * QD3D12_FRAMES_IN_FLIGHT,
+ timestampReadbackArea.mem.p,
+ timestampTicksPerSecond);
+ }
+
+ return QRhi::FrameOpSuccess;
+}
+
+QRhi::FrameOpResult QRhiD3D12::finish()
+{
+ if (!inFrame)
+ return QRhi::FrameOpSuccess;
+
+ QD3D12CommandBuffer *cbD = nullptr;
+ if (offscreenActive) {
+ Q_ASSERT(!currentSwapChain);
+ cbD = offscreenCb[currentFrameSlot];
+ } else {
+ Q_ASSERT(currentSwapChain);
+ cbD = &currentSwapChain->cbWrapper;
+ }
+ if (!cbD)
+ return QRhi::FrameOpError;
+
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::NoPass);
+
+ ID3D12GraphicsCommandList1 *cmdList = cbD->cmdList;
+ HRESULT hr = cmdList->Close();
+ if (FAILED(hr)) {
+ qWarning("Failed to close command list: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return QRhi::FrameOpError;
+ }
+
+ ID3D12CommandList *execList[] = { cmdList };
+ cmdQueue->ExecuteCommandLists(1, execList);
+
+ releaseQueue.activatePendingDeferredReleaseRequests(currentFrameSlot);
+
+ // full blocking wait for everything, frame slots do not matter now
+ waitGpu();
+
+ hr = cmdAllocators[currentFrameSlot]->Reset();
+ if (FAILED(hr)) {
+ qWarning("Failed to reset command allocator: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return QRhi::FrameOpError;
+ }
+
+ if (!startCommandListForCurrentFrameSlot(&cmdList))
+ return QRhi::FrameOpError;
+
+ cbD->resetState();
+
+ shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[currentFrameSlot].head = 0;
+ smallStagingAreas[currentFrameSlot].head = 0;
+
+ bindShaderVisibleHeaps(cbD);
+
+ releaseQueue.executeDeferredReleases(currentFrameSlot);
+
+ finishActiveReadbacks(true);
+
+ return QRhi::FrameOpSuccess;
+}
+
+void QRhiD3D12::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::NoPass);
+ enqueueResourceUpdates(cbD, resourceUpdates);
+}
+
+void QRhiD3D12::beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::NoPass);
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cbD, resourceUpdates);
+
+ QD3D12RenderTargetData *rtD = rtData(rt);
+ bool wantsColorClear = true;
+ bool wantsDsClear = true;
+ if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
+ QD3D12TextureRenderTarget *rtTex = QRHI_RES(QD3D12TextureRenderTarget, rt);
+ wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
+ wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D12Texture, QD3D12RenderBuffer>(rtTex->description(), rtD->currentResIdList))
+ rtTex->create();
+
+ for (auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments(); it != itEnd; ++it) {
+ QD3D12Texture *texD = QRHI_RES(QD3D12Texture, it->texture());
+ QD3D12Texture *resolveTexD = QRHI_RES(QD3D12Texture, it->resolveTexture());
+ QD3D12RenderBuffer *rbD = QRHI_RES(QD3D12RenderBuffer, it->renderBuffer());
+ if (texD)
+ barrierGen.addTransitionBarrier(texD->handle, D3D12_RESOURCE_STATE_RENDER_TARGET);
+ else if (rbD)
+ barrierGen.addTransitionBarrier(rbD->handle, D3D12_RESOURCE_STATE_RENDER_TARGET);
+ if (resolveTexD)
+ barrierGen.addTransitionBarrier(resolveTexD->handle, D3D12_RESOURCE_STATE_RENDER_TARGET);
+ }
+ if (rtTex->m_desc.depthStencilBuffer()) {
+ QD3D12RenderBuffer *rbD = QRHI_RES(QD3D12RenderBuffer, rtTex->m_desc.depthStencilBuffer());
+ Q_ASSERT(rbD->m_type == QRhiRenderBuffer::DepthStencil);
+ barrierGen.addTransitionBarrier(rbD->handle, D3D12_RESOURCE_STATE_DEPTH_WRITE);
+ } else if (rtTex->m_desc.depthTexture()) {
+ QD3D12Texture *depthTexD = QRHI_RES(QD3D12Texture, rtTex->m_desc.depthTexture());
+ barrierGen.addTransitionBarrier(depthTexD->handle, D3D12_RESOURCE_STATE_DEPTH_WRITE);
+ }
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+ } else {
+ Q_ASSERT(currentSwapChain);
+ barrierGen.addTransitionBarrier(currentSwapChain->sampleDesc.Count > 1
+ ? currentSwapChain->msaaBuffers[currentSwapChain->currentBackBufferIndex]
+ : currentSwapChain->colorBuffers[currentSwapChain->currentBackBufferIndex],
+ D3D12_RESOURCE_STATE_RENDER_TARGET);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+ }
+
+ cbD->cmdList->OMSetRenderTargets(UINT(rtD->colorAttCount),
+ rtD->rtv,
+ TRUE,
+ rtD->dsAttCount ? &rtD->dsv : nullptr);
+
+ if (rtD->colorAttCount && wantsColorClear) {
+ float clearColor[4] = {
+ colorClearValue.redF(),
+ colorClearValue.greenF(),
+ colorClearValue.blueF(),
+ colorClearValue.alphaF()
+ };
+ for (int i = 0; i < rtD->colorAttCount; ++i)
+ cbD->cmdList->ClearRenderTargetView(rtD->rtv[i], clearColor, 0, nullptr);
+ }
+ if (rtD->dsAttCount && wantsDsClear) {
+ cbD->cmdList->ClearDepthStencilView(rtD->dsv,
+ D3D12_CLEAR_FLAGS(D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL),
+ depthStencilClearValue.depthClearValue(),
+ UINT8(depthStencilClearValue.stencilClearValue()),
+ 0,
+ nullptr);
+ }
+
+ cbD->recordingPass = QD3D12CommandBuffer::RenderPass;
+ cbD->currentTarget = rt;
+
+ cbD->resetPerPassState();
+}
+
+void QRhiD3D12::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::RenderPass);
+
+ if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
+ QD3D12TextureRenderTarget *rtTex = QRHI_RES(QD3D12TextureRenderTarget, cbD->currentTarget);
+ for (auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
+ it != itEnd; ++it)
+ {
+ const QRhiColorAttachment &colorAtt(*it);
+ if (!colorAtt.resolveTexture())
+ continue;
+
+ QD3D12Texture *dstTexD = QRHI_RES(QD3D12Texture, colorAtt.resolveTexture());
+ QD3D12Resource *dstRes = resourcePool.lookupRef(dstTexD->handle);
+ if (!dstRes)
+ continue;
+
+ QD3D12Texture *srcTexD = QRHI_RES(QD3D12Texture, colorAtt.texture());
+ QD3D12RenderBuffer *srcRbD = QRHI_RES(QD3D12RenderBuffer, colorAtt.renderBuffer());
+ Q_ASSERT(srcTexD || srcRbD);
+ QD3D12Resource *srcRes = resourcePool.lookupRef(srcTexD ? srcTexD->handle : srcRbD->handle);
+ if (!srcRes)
+ continue;
+
+ if (srcTexD) {
+ if (srcTexD->dxgiFormat != dstTexD->dxgiFormat) {
+ qWarning("Resolve source (%d) and destination (%d) formats do not match",
+ int(srcTexD->dxgiFormat), int(dstTexD->dxgiFormat));
+ continue;
+ }
+ if (srcTexD->sampleDesc.Count <= 1) {
+ qWarning("Cannot resolve a non-multisample texture");
+ continue;
+ }
+ if (srcTexD->m_pixelSize != dstTexD->m_pixelSize) {
+ qWarning("Resolve source and destination sizes do not match");
+ continue;
+ }
+ } else {
+ if (srcRbD->dxgiFormat != dstTexD->dxgiFormat) {
+ qWarning("Resolve source (%d) and destination (%d) formats do not match",
+ int(srcRbD->dxgiFormat), int(dstTexD->dxgiFormat));
+ continue;
+ }
+ if (srcRbD->m_pixelSize != dstTexD->m_pixelSize) {
+ qWarning("Resolve source and destination sizes do not match");
+ continue;
+ }
+ }
+
+ barrierGen.addTransitionBarrier(srcTexD ? srcTexD->handle : srcRbD->handle, D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
+ barrierGen.addTransitionBarrier(dstTexD->handle, D3D12_RESOURCE_STATE_RESOLVE_DEST);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+
+ const UINT resolveCount = colorAtt.multiViewCount() >= 2 ? colorAtt.multiViewCount() : 1;
+ for (UINT resolveIdx = 0; resolveIdx < resolveCount; ++resolveIdx) {
+ const UINT srcSubresource = calcSubresource(0, UINT(colorAtt.layer()) + resolveIdx, 1);
+ const UINT dstSubresource = calcSubresource(UINT(colorAtt.resolveLevel()),
+ UINT(colorAtt.resolveLayer()) + resolveIdx,
+ dstTexD->mipLevelCount);
+ cbD->cmdList->ResolveSubresource(dstRes->resource, dstSubresource,
+ srcRes->resource, srcSubresource,
+ dstTexD->dxgiFormat);
+ }
+ }
+ if (rtTex->m_desc.depthResolveTexture())
+ qWarning("Resolving multisample depth-stencil buffers is not supported with D3D");
+ }
+
+ cbD->recordingPass = QD3D12CommandBuffer::NoPass;
+ cbD->currentTarget = nullptr;
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cbD, resourceUpdates);
+}
+
+void QRhiD3D12::beginComputePass(QRhiCommandBuffer *cb,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::NoPass);
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cbD, resourceUpdates);
+
+ cbD->recordingPass = QD3D12CommandBuffer::ComputePass;
+
+ cbD->resetPerPassState();
+}
+
+void QRhiD3D12::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::ComputePass);
+
+ cbD->recordingPass = QD3D12CommandBuffer::NoPass;
+
+ if (resourceUpdates)
+ enqueueResourceUpdates(cbD, resourceUpdates);
+}
+
+void QRhiD3D12::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::ComputePass);
+ QD3D12ComputePipeline *psD = QRHI_RES(QD3D12ComputePipeline, ps);
+ const bool pipelineChanged = cbD->currentComputePipeline != psD || cbD->currentPipelineGeneration != psD->generation;
+
+ if (pipelineChanged) {
+ cbD->currentGraphicsPipeline = nullptr;
+ cbD->currentComputePipeline = psD;
+ cbD->currentPipelineGeneration = psD->generation;
+
+ if (QD3D12Pipeline *pipeline = pipelinePool.lookupRef(psD->handle)) {
+ Q_ASSERT(pipeline->type == QD3D12Pipeline::Compute);
+ cbD->cmdList->SetPipelineState(pipeline->pso);
+ if (QD3D12RootSignature *rs = rootSignaturePool.lookupRef(psD->rootSigHandle))
+ cbD->cmdList->SetComputeRootSignature(rs->rootSig);
+ }
+ }
+}
+
+void QRhiD3D12::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
+{
+ QD3D12CommandBuffer *cbD = QRHI_RES(QD3D12CommandBuffer, cb);
+ Q_ASSERT(cbD->recordingPass == QD3D12CommandBuffer::ComputePass);
+ cbD->cmdList->Dispatch(UINT(x), UINT(y), UINT(z));
+}
+
+bool QD3D12DescriptorHeap::create(ID3D12Device *device,
+ quint32 descriptorCount,
+ D3D12_DESCRIPTOR_HEAP_TYPE heapType,
+ D3D12_DESCRIPTOR_HEAP_FLAGS heapFlags)
+{
+ head = 0;
+ capacity = descriptorCount;
+ this->heapType = heapType;
+ this->heapFlags = heapFlags;
+
+ D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
+ heapDesc.Type = heapType;
+ heapDesc.NumDescriptors = capacity;
+ heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAGS(heapFlags);
+
+ HRESULT hr = device->CreateDescriptorHeap(&heapDesc, __uuidof(ID3D12DescriptorHeap), reinterpret_cast<void **>(&heap));
+ if (FAILED(hr)) {
+ qWarning("Failed to create descriptor heap: %s", qPrintable(QSystemError::windowsComString(hr)));
+ heap = nullptr;
+ capacity = descriptorByteSize = 0;
+ return false;
+ }
+
+ descriptorByteSize = device->GetDescriptorHandleIncrementSize(heapType);
+ heapStart.cpuHandle = heap->GetCPUDescriptorHandleForHeapStart();
+ if (heapFlags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
+ heapStart.gpuHandle = heap->GetGPUDescriptorHandleForHeapStart();
+
+ return true;
+}
+
+void QD3D12DescriptorHeap::createWithExisting(const QD3D12DescriptorHeap &other,
+ quint32 offsetInDescriptors,
+ quint32 descriptorCount)
+{
+ heap = nullptr;
+ head = 0;
+ capacity = descriptorCount;
+ heapType = other.heapType;
+ heapFlags = other.heapFlags;
+ descriptorByteSize = other.descriptorByteSize;
+ heapStart = incremented(other.heapStart, offsetInDescriptors);
+}
+
+void QD3D12DescriptorHeap::destroy()
+{
+ if (heap) {
+ heap->Release();
+ heap = nullptr;
+ }
+ capacity = 0;
+}
+
+void QD3D12DescriptorHeap::destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue)
+{
+ if (heap) {
+ releaseQueue->deferredReleaseDescriptorHeap(heap);
+ heap = nullptr;
+ }
+ capacity = 0;
+}
+
+QD3D12Descriptor QD3D12DescriptorHeap::get(quint32 count)
+{
+ Q_ASSERT(count > 0);
+ if (head + count > capacity) {
+ qWarning("Cannot get %u descriptors as that would exceed capacity %u", count, capacity);
+ return {};
+ }
+ head += count;
+ return at(head - count);
+}
+
+QD3D12Descriptor QD3D12DescriptorHeap::at(quint32 index) const
+{
+ const quint32 startOffset = index * descriptorByteSize;
+ QD3D12Descriptor result;
+ result.cpuHandle.ptr = heapStart.cpuHandle.ptr + startOffset;
+ if (heapStart.gpuHandle.ptr != 0)
+ result.gpuHandle.ptr = heapStart.gpuHandle.ptr + startOffset;
+ return result;
+}
+
+bool QD3D12CpuDescriptorPool::create(ID3D12Device *device, D3D12_DESCRIPTOR_HEAP_TYPE heapType, const char *debugName)
+{
+ QD3D12DescriptorHeap firstHeap;
+ if (!firstHeap.create(device, DESCRIPTORS_PER_HEAP, heapType, D3D12_DESCRIPTOR_HEAP_FLAG_NONE))
+ return false;
+ heaps.append(HeapWithMap::init(firstHeap, DESCRIPTORS_PER_HEAP));
+ descriptorByteSize = heaps[0].heap.descriptorByteSize;
+ this->device = device;
+ this->debugName = debugName;
+ return true;
+}
+
+void QD3D12CpuDescriptorPool::destroy()
+{
+#ifndef QT_NO_DEBUG
+ // debug builds: just do it always
+ static bool leakCheck = true;
+#else
+ // release builds: opt-in
+ static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK");
+#endif
+ if (leakCheck) {
+ for (HeapWithMap &heap : heaps) {
+ const int leakedDescriptorCount = heap.map.count(true);
+ if (leakedDescriptorCount > 0) {
+ qWarning("QD3D12CpuDescriptorPool::destroy(): "
+ "Heap %p for descriptor pool %p '%s' has %d unreleased descriptors",
+ &heap.heap, this, debugName, leakedDescriptorCount);
+ }
+ }
+ }
+ for (HeapWithMap &heap : heaps)
+ heap.heap.destroy();
+ heaps.clear();
+}
+
+QD3D12Descriptor QD3D12CpuDescriptorPool::allocate(quint32 count)
+{
+ Q_ASSERT(count > 0 && count <= DESCRIPTORS_PER_HEAP);
+
+ HeapWithMap &last(heaps.last());
+ if (last.heap.head + count <= last.heap.capacity) {
+ quint32 firstIndex = last.heap.head;
+ for (quint32 i = 0; i < count; ++i)
+ last.map.setBit(firstIndex + i);
+ return last.heap.get(count);
+ }
+
+ for (HeapWithMap &heap : heaps) {
+ quint32 freeCount = 0;
+ for (quint32 i = 0; i < DESCRIPTORS_PER_HEAP; ++i) {
+ if (heap.map.testBit(i)) {
+ freeCount = 0;
+ } else {
+ freeCount += 1;
+ if (freeCount == count) {
+ quint32 firstIndex = i - (freeCount - 1);
+ for (quint32 j = 0; j < count; ++j) {
+ heap.map.setBit(firstIndex + j);
+ return heap.heap.at(firstIndex);
+ }
+ }
+ }
+ }
+ }
+
+ QD3D12DescriptorHeap newHeap;
+ if (!newHeap.create(device, DESCRIPTORS_PER_HEAP, last.heap.heapType, last.heap.heapFlags))
+ return {};
+
+ heaps.append(HeapWithMap::init(newHeap, DESCRIPTORS_PER_HEAP));
+
+ for (quint32 i = 0; i < count; ++i)
+ heaps.last().map.setBit(i);
+
+ return heaps.last().heap.get(count);
+}
+
+void QD3D12CpuDescriptorPool::release(const QD3D12Descriptor &descriptor, quint32 count)
+{
+ Q_ASSERT(count > 0 && count <= DESCRIPTORS_PER_HEAP);
+ if (!descriptor.isValid())
+ return;
+
+ const SIZE_T addr = descriptor.cpuHandle.ptr;
+ for (HeapWithMap &heap : heaps) {
+ const SIZE_T begin = heap.heap.heapStart.cpuHandle.ptr;
+ const SIZE_T end = begin + heap.heap.descriptorByteSize * heap.heap.capacity;
+ if (addr >= begin && addr < end) {
+ quint32 firstIndex = (addr - begin) / heap.heap.descriptorByteSize;
+ for (quint32 i = 0; i < count; ++i)
+ heap.map.setBit(firstIndex + i, false);
+ return;
+ }
+ }
+
+ qWarning("QD3D12CpuDescriptorPool::release: Descriptor with address %llu is not in any heap",
+ quint64(descriptor.cpuHandle.ptr));
+}
+
+bool QD3D12QueryHeap::create(ID3D12Device *device,
+ quint32 queryCount,
+ D3D12_QUERY_HEAP_TYPE heapType)
+{
+ capacity = queryCount;
+
+ D3D12_QUERY_HEAP_DESC heapDesc = {};
+ heapDesc.Type = heapType;
+ heapDesc.Count = capacity;
+
+ HRESULT hr = device->CreateQueryHeap(&heapDesc, __uuidof(ID3D12QueryHeap), reinterpret_cast<void **>(&heap));
+ if (FAILED(hr)) {
+ qWarning("Failed to create query heap: %s", qPrintable(QSystemError::windowsComString(hr)));
+ heap = nullptr;
+ capacity = 0;
+ return false;
+ }
+
+ return true;
+}
+
+void QD3D12QueryHeap::destroy()
+{
+ if (heap) {
+ heap->Release();
+ heap = nullptr;
+ }
+ capacity = 0;
+}
+
+bool QD3D12StagingArea::create(QRhiD3D12 *rhi, quint32 capacity, D3D12_HEAP_TYPE heapType)
+{
+ Q_ASSERT(heapType == D3D12_HEAP_TYPE_UPLOAD || heapType == D3D12_HEAP_TYPE_READBACK);
+ D3D12_RESOURCE_DESC resourceDesc = {};
+ resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ resourceDesc.Width = capacity;
+ resourceDesc.Height = 1;
+ resourceDesc.DepthOrArraySize = 1;
+ resourceDesc.MipLevels = 1;
+ resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
+ resourceDesc.SampleDesc = { 1, 0 };
+ resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ UINT state = heapType == D3D12_HEAP_TYPE_UPLOAD ? D3D12_RESOURCE_STATE_GENERIC_READ : D3D12_RESOURCE_STATE_COPY_DEST;
+ HRESULT hr = rhi->vma.createResource(heapType,
+ &resourceDesc,
+ D3D12_RESOURCE_STATES(state),
+ nullptr,
+ &allocation,
+ __uuidof(ID3D12Resource),
+ reinterpret_cast<void **>(&resource));
+ if (FAILED(hr)) {
+ qWarning("Failed to create buffer for staging area: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ void *p = nullptr;
+ hr = resource->Map(0, nullptr, &p);
+ if (FAILED(hr)) {
+ qWarning("Failed to map buffer for staging area: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ destroy();
+ return false;
+ }
+
+ mem.p = static_cast<quint8 *>(p);
+ mem.gpuAddr = resource->GetGPUVirtualAddress();
+ mem.buffer = resource;
+ mem.bufferOffset = 0;
+
+ this->capacity = capacity;
+ head = 0;
+
+ return true;
+}
+
+void QD3D12StagingArea::destroy()
+{
+ if (resource) {
+ resource->Release();
+ resource = nullptr;
+ }
+ if (allocation) {
+ allocation->Release();
+ allocation = nullptr;
+ }
+ mem = {};
+}
+
+void QD3D12StagingArea::destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue)
+{
+ if (resource)
+ releaseQueue->deferredReleaseResourceAndAllocation(resource, allocation);
+ mem = {};
+}
+
+QD3D12StagingArea::Allocation QD3D12StagingArea::get(quint32 byteSize)
+{
+ const quint32 allocSize = aligned(byteSize, ALIGNMENT);
+ if (head + allocSize > capacity) {
+ qWarning("Failed to allocate %u (%u) bytes from staging area of size %u with %u bytes left",
+ allocSize, byteSize, capacity, remainingCapacity());
+ return {};
+ }
+ const quint32 offset = head;
+ head += allocSize;
+ return {
+ mem.p + offset,
+ mem.gpuAddr + offset,
+ mem.buffer,
+ offset
+ };
+}
+
+// Can be called inside and outside of begin-endFrame. Removes from the pool
+// and releases the underlying native resource only in the frames_in_flight'th
+// beginFrame() counted starting from the next endFrame().
+void QD3D12ReleaseQueue::deferredReleaseResource(const QD3D12ObjectHandle &handle)
+{
+ DeferredReleaseEntry e;
+ e.handle = handle;
+ queue.append(e);
+}
+
+void QD3D12ReleaseQueue::deferredReleaseResourceWithViews(const QD3D12ObjectHandle &handle,
+ QD3D12CpuDescriptorPool *pool,
+ const QD3D12Descriptor &viewsStart,
+ int viewCount)
+{
+ DeferredReleaseEntry e;
+ e.type = DeferredReleaseEntry::Resource;
+ e.handle = handle;
+ e.poolForViews = pool;
+ e.viewsStart = viewsStart;
+ e.viewCount = viewCount;
+ queue.append(e);
+}
+
+void QD3D12ReleaseQueue::deferredReleasePipeline(const QD3D12ObjectHandle &handle)
+{
+ DeferredReleaseEntry e;
+ e.type = DeferredReleaseEntry::Pipeline;
+ e.handle = handle;
+ queue.append(e);
+}
+
+void QD3D12ReleaseQueue::deferredReleaseRootSignature(const QD3D12ObjectHandle &handle)
+{
+ DeferredReleaseEntry e;
+ e.type = DeferredReleaseEntry::RootSignature;
+ e.handle = handle;
+ queue.append(e);
+}
+
+void QD3D12ReleaseQueue::deferredReleaseCallback(std::function<void(void*)> callback, void *userData)
+{
+ DeferredReleaseEntry e;
+ e.type = DeferredReleaseEntry::Callback;
+ e.callback = callback;
+ e.callbackUserData = userData;
+ queue.append(e);
+}
+
+void QD3D12ReleaseQueue::deferredReleaseResourceAndAllocation(ID3D12Resource *resource,
+ D3D12MA::Allocation *allocation)
+{
+ DeferredReleaseEntry e;
+ e.type = DeferredReleaseEntry::ResourceAndAllocation;
+ e.resourceAndAllocation = { resource, allocation };
+ queue.append(e);
+}
+
+void QD3D12ReleaseQueue::deferredReleaseDescriptorHeap(ID3D12DescriptorHeap *heap)
+{
+ DeferredReleaseEntry e;
+ e.type = DeferredReleaseEntry::DescriptorHeap;
+ e.descriptorHeap = heap;
+ queue.append(e);
+}
+
+void QD3D12ReleaseQueue::deferredReleaseViews(QD3D12CpuDescriptorPool *pool,
+ const QD3D12Descriptor &viewsStart,
+ int viewCount)
+{
+ DeferredReleaseEntry e;
+ e.type = DeferredReleaseEntry::Views;
+ e.poolForViews = pool;
+ e.viewsStart = viewsStart;
+ e.viewCount = viewCount;
+ queue.append(e);
+}
+
+void QD3D12ReleaseQueue::activatePendingDeferredReleaseRequests(int frameSlot)
+{
+ for (DeferredReleaseEntry &e : queue) {
+ if (!e.frameSlotToBeReleasedIn.has_value())
+ e.frameSlotToBeReleasedIn = frameSlot;
+ }
+}
+
+void QD3D12ReleaseQueue::executeDeferredReleases(int frameSlot, bool forced)
+{
+ for (int i = queue.count() - 1; i >= 0; --i) {
+ const DeferredReleaseEntry &e(queue[i]);
+ if (forced || (e.frameSlotToBeReleasedIn.has_value() && e.frameSlotToBeReleasedIn.value() == frameSlot)) {
+ switch (e.type) {
+ case DeferredReleaseEntry::Resource:
+ resourcePool->remove(e.handle);
+ if (e.poolForViews && e.viewsStart.isValid() && e.viewCount > 0)
+ e.poolForViews->release(e.viewsStart, e.viewCount);
+ break;
+ case DeferredReleaseEntry::Pipeline:
+ pipelinePool->remove(e.handle);
+ break;
+ case DeferredReleaseEntry::RootSignature:
+ rootSignaturePool->remove(e.handle);
+ break;
+ case DeferredReleaseEntry::Callback:
+ e.callback(e.callbackUserData);
+ break;
+ case DeferredReleaseEntry::ResourceAndAllocation:
+ // order matters: resource first, then the allocation (which
+ // may be null)
+ e.resourceAndAllocation.first->Release();
+ if (e.resourceAndAllocation.second)
+ e.resourceAndAllocation.second->Release();
+ break;
+ case DeferredReleaseEntry::DescriptorHeap:
+ e.descriptorHeap->Release();
+ break;
+ case DeferredReleaseEntry::Views:
+ e.poolForViews->release(e.viewsStart, e.viewCount);
+ break;
+ }
+ queue.removeAt(i);
+ }
+ }
+}
+
+void QD3D12ReleaseQueue::releaseAll()
+{
+ executeDeferredReleases(0, true);
+}
+
+void QD3D12ResourceBarrierGenerator::addTransitionBarrier(const QD3D12ObjectHandle &resourceHandle,
+ D3D12_RESOURCE_STATES stateAfter)
+{
+ if (QD3D12Resource *res = resourcePool->lookupRef(resourceHandle)) {
+ if (stateAfter != res->state) {
+ transitionResourceBarriers.append({ resourceHandle, res->state, stateAfter });
+ res->state = stateAfter;
+ }
+ }
+}
+
+void QD3D12ResourceBarrierGenerator::enqueueBufferedTransitionBarriers(QD3D12CommandBuffer *cbD)
+{
+ QVarLengthArray<D3D12_RESOURCE_BARRIER, PREALLOC> barriers;
+ for (const TransitionResourceBarrier &trb : transitionResourceBarriers) {
+ if (QD3D12Resource *res = resourcePool->lookupRef(trb.resourceHandle)) {
+ D3D12_RESOURCE_BARRIER barrier = {};
+ barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrier.Transition.pResource = res->resource;
+ barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
+ barrier.Transition.StateBefore = trb.stateBefore;
+ barrier.Transition.StateAfter = trb.stateAfter;
+ barriers.append(barrier);
+ }
+ }
+ transitionResourceBarriers.clear();
+ if (!barriers.isEmpty())
+ cbD->cmdList->ResourceBarrier(barriers.count(), barriers.constData());
+}
+
+void QD3D12ResourceBarrierGenerator::enqueueSubresourceTransitionBarrier(QD3D12CommandBuffer *cbD,
+ const QD3D12ObjectHandle &resourceHandle,
+ UINT subresource,
+ D3D12_RESOURCE_STATES stateBefore,
+ D3D12_RESOURCE_STATES stateAfter)
+{
+ if (QD3D12Resource *res = resourcePool->lookupRef(resourceHandle)) {
+ D3D12_RESOURCE_BARRIER barrier = {};
+ barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+ barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrier.Transition.pResource = res->resource;
+ barrier.Transition.Subresource = subresource;
+ barrier.Transition.StateBefore = stateBefore;
+ barrier.Transition.StateAfter = stateAfter;
+ cbD->cmdList->ResourceBarrier(1, &barrier);
+ }
+}
+
+void QD3D12ResourceBarrierGenerator::enqueueUavBarrier(QD3D12CommandBuffer *cbD,
+ const QD3D12ObjectHandle &resourceHandle)
+{
+ if (QD3D12Resource *res = resourcePool->lookupRef(resourceHandle)) {
+ D3D12_RESOURCE_BARRIER barrier = {};
+ barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
+ barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+ barrier.UAV.pResource = res->resource;
+ cbD->cmdList->ResourceBarrier(1, &barrier);
+ }
+}
+
+void QD3D12ShaderBytecodeCache::insertWithCapacityLimit(const QRhiShaderStage &key, const Shader &s)
+{
+ if (data.count() >= QRhiD3D12::MAX_SHADER_CACHE_ENTRIES)
+ data.clear();
+ data.insert(key, s);
+}
+
+bool QD3D12ShaderVisibleDescriptorHeap::create(ID3D12Device *device,
+ D3D12_DESCRIPTOR_HEAP_TYPE type,
+ quint32 perFrameDescriptorCount)
+{
+ Q_ASSERT(type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+
+ quint32 size = perFrameDescriptorCount * QD3D12_FRAMES_IN_FLIGHT;
+
+ // https://learn.microsoft.com/en-us/windows/win32/direct3d12/hardware-support
+ const quint32 CBV_SRV_UAV_MAX = 1000000;
+ const quint32 SAMPLER_MAX = 2048;
+ if (type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
+ size = qMin(size, CBV_SRV_UAV_MAX);
+ else if (type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER)
+ size = qMin(size, SAMPLER_MAX);
+
+ if (!heap.create(device, size, type, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)) {
+ qWarning("Failed to create shader-visible descriptor heap of size %u", size);
+ return false;
+ }
+
+ perFrameDescriptorCount = size / QD3D12_FRAMES_IN_FLIGHT;
+ quint32 currentOffsetInDescriptors = 0;
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ perFrameHeapSlice[i].createWithExisting(heap, currentOffsetInDescriptors, perFrameDescriptorCount);
+ currentOffsetInDescriptors += perFrameDescriptorCount;
+ }
+
+ return true;
+}
+
+void QD3D12ShaderVisibleDescriptorHeap::destroy()
+{
+ heap.destroy();
+}
+
+void QD3D12ShaderVisibleDescriptorHeap::destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue)
+{
+ heap.destroyWithDeferredRelease(releaseQueue);
+}
+
+static inline QPair<int, int> mapBinding(int binding, const QShader::NativeResourceBindingMap &map)
+{
+ if (map.isEmpty())
+ return { binding, binding }; // assume 1:1 mapping
+
+ 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 QD3D12ShaderResourceVisitor::visit()
+{
+ for (int bindingIdx = 0, bindingCount = srb->m_bindings.count(); bindingIdx != bindingCount; ++bindingIdx) {
+ const QRhiShaderResourceBinding &b(srb->m_bindings[bindingIdx]);
+ const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
+
+ for (int stageIdx = 0; stageIdx < stageCount; ++stageIdx) {
+ const QD3D12ShaderStageData *sd = &stageData[stageIdx];
+ if (!sd->valid)
+ continue;
+
+ if (!bd->stage.testFlag(qd3d12_stageToSrb(sd->stage)))
+ continue;
+
+ switch (bd->type) {
+ case QRhiShaderResourceBinding::UniformBuffer:
+ {
+ const int shaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
+ if (shaderRegister >= 0 && uniformBuffer)
+ uniformBuffer(sd->stage, bd->u.ubuf, shaderRegister, bd->binding);
+ }
+ break;
+ case QRhiShaderResourceBinding::SampledTexture:
+ {
+ Q_ASSERT(bd->u.stex.count > 0);
+ const int textureBaseShaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
+ const int samplerBaseShaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).second;
+ for (int i = 0; i < bd->u.stex.count; ++i) {
+ if (textureBaseShaderRegister >= 0 && texture)
+ texture(sd->stage, bd->u.stex.texSamplers[i], textureBaseShaderRegister + i);
+ if (samplerBaseShaderRegister >= 0 && sampler)
+ sampler(sd->stage, bd->u.stex.texSamplers[i], samplerBaseShaderRegister + i);
+ }
+ }
+ break;
+ case QRhiShaderResourceBinding::Texture:
+ {
+ Q_ASSERT(bd->u.stex.count > 0);
+ const int baseShaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
+ if (baseShaderRegister >= 0 && texture) {
+ for (int i = 0; i < bd->u.stex.count; ++i)
+ texture(sd->stage, bd->u.stex.texSamplers[i], baseShaderRegister + i);
+ }
+ }
+ break;
+ case QRhiShaderResourceBinding::Sampler:
+ {
+ Q_ASSERT(bd->u.stex.count > 0);
+ const int baseShaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
+ if (baseShaderRegister >= 0 && sampler) {
+ for (int i = 0; i < bd->u.stex.count; ++i)
+ sampler(sd->stage, bd->u.stex.texSamplers[i], baseShaderRegister + i);
+ }
+ }
+ break;
+ case QRhiShaderResourceBinding::ImageLoad:
+ {
+ const int shaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
+ if (shaderRegister >= 0 && storageImage)
+ storageImage(sd->stage, bd->u.simage, Load, shaderRegister);
+ }
+ break;
+ case QRhiShaderResourceBinding::ImageStore:
+ {
+ const int shaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
+ if (shaderRegister >= 0 && storageImage)
+ storageImage(sd->stage, bd->u.simage, Store, shaderRegister);
+ }
+ break;
+ case QRhiShaderResourceBinding::ImageLoadStore:
+ {
+ const int shaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
+ if (shaderRegister >= 0 && storageImage)
+ storageImage(sd->stage, bd->u.simage, LoadStore, shaderRegister);
+ }
+ break;
+ case QRhiShaderResourceBinding::BufferLoad:
+ {
+ const int shaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
+ if (shaderRegister >= 0 && storageBuffer)
+ storageBuffer(sd->stage, bd->u.sbuf, Load, shaderRegister);
+ }
+ break;
+ case QRhiShaderResourceBinding::BufferStore:
+ {
+ const int shaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
+ if (shaderRegister >= 0 && storageBuffer)
+ storageBuffer(sd->stage, bd->u.sbuf, Store, shaderRegister);
+ }
+ break;
+ case QRhiShaderResourceBinding::BufferLoadStore:
+ {
+ const int shaderRegister = mapBinding(bd->binding, sd->nativeResourceBindingMap).first;
+ if (shaderRegister >= 0 && storageBuffer)
+ storageBuffer(sd->stage, bd->u.sbuf, LoadStore, shaderRegister);
+ }
+ break;
+ }
+ }
+ }
+}
+
+bool QD3D12SamplerManager::create(ID3D12Device *device)
+{
+ // This does not need to be per-frame slot, just grab space for MAX_SAMPLERS samplers.
+ if (!shaderVisibleSamplerHeap.create(device,
+ D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
+ MAX_SAMPLERS / QD3D12_FRAMES_IN_FLIGHT))
+ {
+ qWarning("Could not create shader-visible SAMPLER heap");
+ return false;
+ }
+
+ this->device = device;
+ return true;
+}
+
+void QD3D12SamplerManager::destroy()
+{
+ if (device) {
+ shaderVisibleSamplerHeap.destroy();
+ device = nullptr;
+ }
+}
+
+QD3D12Descriptor QD3D12SamplerManager::getShaderVisibleDescriptor(const D3D12_SAMPLER_DESC &desc)
+{
+ auto it = gpuMap.constFind({desc});
+ if (it != gpuMap.cend())
+ return *it;
+
+ QD3D12Descriptor descriptor = shaderVisibleSamplerHeap.heap.get(1);
+ if (descriptor.isValid()) {
+ device->CreateSampler(&desc, descriptor.cpuHandle);
+ gpuMap.insert({desc}, descriptor);
+ } else {
+ qWarning("Out of shader-visible SAMPLER descriptor heap space,"
+ " this should not happen, maximum number of unique samplers is %u",
+ shaderVisibleSamplerHeap.heap.capacity);
+ }
+
+ return descriptor;
+}
+
+bool QD3D12MipmapGenerator::create(QRhiD3D12 *rhiD)
+{
+ this->rhiD = rhiD;
+
+ D3D12_ROOT_PARAMETER1 rootParams[3] = {};
+ D3D12_DESCRIPTOR_RANGE1 descriptorRanges[2] = {};
+
+ // b0
+ rootParams[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+ rootParams[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ rootParams[0].Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC;
+
+ // t0
+ descriptorRanges[0].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ descriptorRanges[0].NumDescriptors = 1;
+ descriptorRanges[0].Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
+ rootParams[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ rootParams[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ rootParams[1].DescriptorTable.NumDescriptorRanges = 1;
+ rootParams[1].DescriptorTable.pDescriptorRanges = &descriptorRanges[0];
+
+ // u0..3
+ descriptorRanges[1].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
+ descriptorRanges[1].NumDescriptors = 4;
+ rootParams[2].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ rootParams[2].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ rootParams[2].DescriptorTable.NumDescriptorRanges = 1;
+ rootParams[2].DescriptorTable.pDescriptorRanges = &descriptorRanges[1];
+
+ // s0
+ D3D12_STATIC_SAMPLER_DESC samplerDesc = {};
+ samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
+ samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ samplerDesc.MaxLOD = 10000.0f;
+ samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+
+ D3D12_VERSIONED_ROOT_SIGNATURE_DESC rsDesc = {};
+ rsDesc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;
+ rsDesc.Desc_1_1.NumParameters = 3;
+ rsDesc.Desc_1_1.pParameters = rootParams;
+ rsDesc.Desc_1_1.NumStaticSamplers = 1;
+ rsDesc.Desc_1_1.pStaticSamplers = &samplerDesc;
+
+ ID3DBlob *signature = nullptr;
+ HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
+ if (FAILED(hr)) {
+ qWarning("Failed to serialize root signature: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ ID3D12RootSignature *rootSig = nullptr;
+ hr = rhiD->dev->CreateRootSignature(0,
+ signature->GetBufferPointer(),
+ signature->GetBufferSize(),
+ __uuidof(ID3D12RootSignature),
+ reinterpret_cast<void **>(&rootSig));
+ signature->Release();
+ if (FAILED(hr)) {
+ qWarning("Failed to create root signature: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+
+ rootSigHandle = QD3D12RootSignature::addToPool(&rhiD->rootSignaturePool, rootSig);
+
+ D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {};
+ psoDesc.pRootSignature = rootSig;
+ psoDesc.CS.pShaderBytecode = g_csMipmap;
+ psoDesc.CS.BytecodeLength = sizeof(g_csMipmap);
+ ID3D12PipelineState *pso = nullptr;
+ hr = rhiD->dev->CreateComputePipelineState(&psoDesc,
+ __uuidof(ID3D12PipelineState),
+ reinterpret_cast<void **>(&pso));
+ if (FAILED(hr)) {
+ qWarning("Failed to create compute pipeline state: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ rhiD->rootSignaturePool.remove(rootSigHandle);
+ rootSigHandle = {};
+ return false;
+ }
+
+ pipelineHandle = QD3D12Pipeline::addToPool(&rhiD->pipelinePool, QD3D12Pipeline::Compute, pso);
+
+ return true;
+}
+
+void QD3D12MipmapGenerator::destroy()
+{
+ rhiD->pipelinePool.remove(pipelineHandle);
+ pipelineHandle = {};
+ rhiD->rootSignaturePool.remove(rootSigHandle);
+ rootSigHandle = {};
+}
+
+void QD3D12MipmapGenerator::generate(QD3D12CommandBuffer *cbD, const QD3D12ObjectHandle &textureHandle)
+{
+ QD3D12Pipeline *pipeline = rhiD->pipelinePool.lookupRef(pipelineHandle);
+ if (!pipeline)
+ return;
+ QD3D12RootSignature *rootSig = rhiD->rootSignaturePool.lookupRef(rootSigHandle);
+ if (!rootSig)
+ return;
+ QD3D12Resource *res = rhiD->resourcePool.lookupRef(textureHandle);
+ if (!res)
+ return;
+
+ const quint32 mipLevelCount = res->desc.MipLevels;
+ if (mipLevelCount < 2)
+ return;
+
+ if (res->desc.SampleDesc.Count > 1) {
+ qWarning("Cannot generate mipmaps for MSAA texture");
+ return;
+ }
+
+ const bool is1D = res->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D;
+ if (is1D) {
+ qWarning("Cannot generate mipmaps for 1D texture");
+ return;
+ }
+
+ const bool is3D = res->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D;
+ const bool isCubeOrArray = res->desc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D
+ && res->desc.DepthOrArraySize > 1;
+ const quint32 layerCount = isCubeOrArray ? res->desc.DepthOrArraySize : 1;
+
+ if (is3D) {
+ // ### needs its own shader and maybe a different solution
+ qWarning("3D texture mipmapping is not implemented for D3D12 atm");
+ return;
+ }
+
+ rhiD->barrierGen.addTransitionBarrier(textureHandle, D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+ rhiD->barrierGen.enqueueBufferedTransitionBarriers(cbD);
+
+ cbD->cmdList->SetPipelineState(pipeline->pso);
+ cbD->cmdList->SetComputeRootSignature(rootSig->rootSig);
+
+ const quint32 descriptorByteSize = rhiD->shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[rhiD->currentFrameSlot].descriptorByteSize;
+
+ struct CBufData {
+ quint32 srcMipLevel;
+ quint32 numMipLevels;
+ float texelWidth;
+ float texelHeight;
+ };
+
+ const quint32 allocSize = QD3D12StagingArea::allocSizeForArray(sizeof(CBufData), mipLevelCount * layerCount);
+ std::optional<QD3D12StagingArea> ownStagingArea;
+ if (rhiD->smallStagingAreas[rhiD->currentFrameSlot].remainingCapacity() < allocSize) {
+ ownStagingArea = QD3D12StagingArea();
+ if (!ownStagingArea->create(rhiD, allocSize, D3D12_HEAP_TYPE_UPLOAD)) {
+ qWarning("Could not create staging area for mipmap generation");
+ return;
+ }
+ }
+ QD3D12StagingArea *workArea = ownStagingArea.has_value()
+ ? &ownStagingArea.value()
+ : &rhiD->smallStagingAreas[rhiD->currentFrameSlot];
+
+ bool gotNewHeap = false;
+ if (!rhiD->ensureShaderVisibleDescriptorHeapCapacity(&rhiD->shaderVisibleCbvSrvUavHeap,
+ D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+ rhiD->currentFrameSlot,
+ (1 + 4) * mipLevelCount * layerCount,
+ &gotNewHeap))
+ {
+ qWarning("Could not ensure enough space in descriptor heap for mipmap generation");
+ return;
+ }
+ if (gotNewHeap)
+ rhiD->bindShaderVisibleHeaps(cbD);
+
+ for (quint32 layer = 0; layer < layerCount; ++layer) {
+ for (quint32 level = 0; level < mipLevelCount ;) {
+ UINT subresource = calcSubresource(level, layer, res->desc.MipLevels);
+ rhiD->barrierGen.enqueueSubresourceTransitionBarrier(cbD, textureHandle, subresource,
+ D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
+ D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
+
+ quint32 levelPlusOneMipWidth = res->desc.Width >> (level + 1);
+ quint32 levelPlusOneMipHeight = res->desc.Height >> (level + 1);
+ const quint32 dw = levelPlusOneMipWidth == 1 ? levelPlusOneMipHeight : levelPlusOneMipWidth;
+ const quint32 dh = levelPlusOneMipHeight == 1 ? levelPlusOneMipWidth : levelPlusOneMipHeight;
+ // number of times the size can be halved while still resulting in an even dimension
+ const quint32 additionalMips = qCountTrailingZeroBits(dw | dh);
+ const quint32 numGenMips = qMin(1u + qMin(3u, additionalMips), res->desc.MipLevels - level);
+ levelPlusOneMipWidth = qMax(1u, levelPlusOneMipWidth);
+ levelPlusOneMipHeight = qMax(1u, levelPlusOneMipHeight);
+
+ CBufData cbufData = {
+ level,
+ numGenMips,
+ 1.0f / float(levelPlusOneMipWidth),
+ 1.0f / float(levelPlusOneMipHeight)
+ };
+
+ QD3D12StagingArea::Allocation cbuf = workArea->get(sizeof(cbufData));
+ memcpy(cbuf.p, &cbufData, sizeof(cbufData));
+ cbD->cmdList->SetComputeRootConstantBufferView(0, cbuf.gpuAddr);
+
+ QD3D12Descriptor srv = rhiD->shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[rhiD->currentFrameSlot].get(1);
+ D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
+ srvDesc.Format = res->desc.Format;
+ srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+ if (isCubeOrArray) {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = level;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = layer;
+ srvDesc.Texture2DArray.ArraySize = 1;
+ } else if (is3D) {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
+ srvDesc.Texture3D.MostDetailedMip = level;
+ srvDesc.Texture3D.MipLevels = 1;
+ } else {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MostDetailedMip = level;
+ srvDesc.Texture2D.MipLevels = 1;
+ }
+ rhiD->dev->CreateShaderResourceView(res->resource, &srvDesc, srv.cpuHandle);
+ cbD->cmdList->SetComputeRootDescriptorTable(1, srv.gpuHandle);
+
+ QD3D12Descriptor uavStart = rhiD->shaderVisibleCbvSrvUavHeap.perFrameHeapSlice[rhiD->currentFrameSlot].get(4);
+ D3D12_CPU_DESCRIPTOR_HANDLE uavCpuHandle = uavStart.cpuHandle;
+ // if level is N, then need UAVs for levels N+1, ..., N+4
+ for (quint32 uavIdx = 0; uavIdx < 4; ++uavIdx) {
+ const quint32 uavMipLevel = qMin(level + 1u + uavIdx, res->desc.MipLevels - 1u);
+ D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
+ uavDesc.Format = res->desc.Format;
+ if (isCubeOrArray) {
+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
+ uavDesc.Texture2DArray.MipSlice = uavMipLevel;
+ uavDesc.Texture2DArray.FirstArraySlice = layer;
+ uavDesc.Texture2DArray.ArraySize = 1;
+ } else if (is3D) {
+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
+ uavDesc.Texture3D.MipSlice = uavMipLevel;
+ uavDesc.Texture3D.FirstWSlice = 0; // depth etc. not implemented yet
+ uavDesc.Texture3D.WSize = 1;
+ } else {
+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
+ uavDesc.Texture2D.MipSlice = uavMipLevel;
+ }
+ rhiD->dev->CreateUnorderedAccessView(res->resource, nullptr, &uavDesc, uavCpuHandle);
+ uavCpuHandle.ptr += descriptorByteSize;
+ }
+ cbD->cmdList->SetComputeRootDescriptorTable(2, uavStart.gpuHandle);
+
+ cbD->cmdList->Dispatch(levelPlusOneMipWidth, levelPlusOneMipHeight, 1);
+
+ rhiD->barrierGen.enqueueUavBarrier(cbD, textureHandle);
+ rhiD->barrierGen.enqueueSubresourceTransitionBarrier(cbD, textureHandle, subresource,
+ D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
+ D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+
+ level += numGenMips;
+ }
+ }
+
+ if (ownStagingArea.has_value())
+ ownStagingArea->destroyWithDeferredRelease(&rhiD->releaseQueue);
+}
+
+bool QD3D12MemoryAllocator::create(ID3D12Device *device, IDXGIAdapter1 *adapter)
+{
+ this->device = device;
+
+ // We can function with and without D3D12MA: CreateCommittedResource is
+ // just fine for our purposes and not any complicated API-wise; the memory
+ // allocator is interesting for efficiency mainly since it can suballocate
+ // instead of making everything a committed resource allocation.
+
+ static bool disableMA = qEnvironmentVariableIntValue("QT_D3D_NO_SUBALLOC");
+ if (disableMA)
+ return true;
+
+ DXGI_ADAPTER_DESC1 desc;
+ adapter->GetDesc1(&desc);
+ if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
+ return true;
+
+ D3D12MA::ALLOCATOR_DESC allocatorDesc = {};
+ allocatorDesc.pDevice = device;
+ allocatorDesc.pAdapter = adapter;
+ // A QRhi is supposed to be used from one single thread only. Disable
+ // the allocator's own mutexes. This may give a performance boost.
+ allocatorDesc.Flags = D3D12MA::ALLOCATOR_FLAG_SINGLETHREADED;
+ HRESULT hr = D3D12MA::CreateAllocator(&allocatorDesc, &allocator);
+ if (FAILED(hr)) {
+ qWarning("Failed to initialize D3D12 Memory Allocator: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ return true;
+}
+
+void QD3D12MemoryAllocator::destroy()
+{
+ if (allocator) {
+ allocator->Release();
+ allocator = nullptr;
+ }
+}
+
+HRESULT QD3D12MemoryAllocator::createResource(D3D12_HEAP_TYPE heapType,
+ const D3D12_RESOURCE_DESC *resourceDesc,
+ D3D12_RESOURCE_STATES initialState,
+ const D3D12_CLEAR_VALUE *optimizedClearValue,
+ D3D12MA::Allocation **maybeAllocation,
+ REFIID riidResource,
+ void **ppvResource)
+{
+ if (allocator) {
+ D3D12MA::ALLOCATION_DESC allocDesc = {};
+ allocDesc.HeapType = heapType;
+ return allocator->CreateResource(&allocDesc,
+ resourceDesc,
+ initialState,
+ optimizedClearValue,
+ maybeAllocation,
+ riidResource,
+ ppvResource);
+ } else {
+ *maybeAllocation = nullptr;
+ D3D12_HEAP_PROPERTIES heapProps = {};
+ heapProps.Type = heapType;
+ return device->CreateCommittedResource(&heapProps,
+ D3D12_HEAP_FLAG_NONE,
+ resourceDesc,
+ initialState,
+ optimizedClearValue,
+ riidResource,
+ ppvResource);
+ }
+}
+
+void QD3D12MemoryAllocator::getBudget(D3D12MA::Budget *localBudget, D3D12MA::Budget *nonLocalBudget)
+{
+ if (allocator) {
+ allocator->GetBudget(localBudget, nonLocalBudget);
+ } else {
+ *localBudget = {};
+ *nonLocalBudget = {};
+ }
+}
+
+void QRhiD3D12::waitGpu()
+{
+ fullFenceCounter += 1u;
+ if (SUCCEEDED(cmdQueue->Signal(fullFence, fullFenceCounter))) {
+ if (SUCCEEDED(fullFence->SetEventOnCompletion(fullFenceCounter, fullFenceEvent)))
+ WaitForSingleObject(fullFenceEvent, INFINITE);
+ }
+}
+
+DXGI_SAMPLE_DESC QRhiD3D12::effectiveSampleDesc(int sampleCount, DXGI_FORMAT format) const
+{
+ DXGI_SAMPLE_DESC desc;
+ desc.Count = 1;
+ desc.Quality = 0;
+
+ const int s = effectiveSampleCount(sampleCount);
+
+ if (s > 1) {
+ D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msaaInfo = {};
+ msaaInfo.Format = format;
+ msaaInfo.SampleCount = UINT(s);
+ if (SUCCEEDED(dev->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &msaaInfo, sizeof(msaaInfo)))) {
+ if (msaaInfo.NumQualityLevels > 0) {
+ desc.Count = UINT(s);
+ desc.Quality = msaaInfo.NumQualityLevels - 1;
+ } else {
+ qWarning("No quality levels for multisampling with sample count %d", s);
+ }
+ }
+ }
+
+ return desc;
+}
+
+bool QRhiD3D12::startCommandListForCurrentFrameSlot(ID3D12GraphicsCommandList1 **cmdList)
+{
+ ID3D12CommandAllocator *cmdAlloc = cmdAllocators[currentFrameSlot];
+ if (!*cmdList) {
+ HRESULT hr = dev->CreateCommandList(0,
+ D3D12_COMMAND_LIST_TYPE_DIRECT,
+ cmdAlloc,
+ nullptr,
+ __uuidof(ID3D12GraphicsCommandList1),
+ reinterpret_cast<void **>(cmdList));
+ if (FAILED(hr)) {
+ qWarning("Failed to create command list: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ } else {
+ HRESULT hr = (*cmdList)->Reset(cmdAlloc, nullptr);
+ if (FAILED(hr)) {
+ qWarning("Failed to reset command list: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ }
+ return true;
+}
+
+static inline QRhiTexture::Format swapchainReadbackTextureFormat(DXGI_FORMAT format, QRhiTexture::Flags *flags)
+{
+ switch (format) {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return QRhiTexture::RGBA8;
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ if (flags)
+ (*flags) |= QRhiTexture::sRGB;
+ return QRhiTexture::RGBA8;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return QRhiTexture::BGRA8;
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ if (flags)
+ (*flags) |= QRhiTexture::sRGB;
+ return QRhiTexture::BGRA8;
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ return QRhiTexture::RGBA16F;
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ return QRhiTexture::RGBA32F;
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ return QRhiTexture::RGB10A2;
+ default:
+ qWarning("DXGI_FORMAT %d cannot be read back", format);
+ break;
+ }
+ return QRhiTexture::UnknownFormat;
+}
+
+void QRhiD3D12::enqueueResourceUpdates(QD3D12CommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates)
+{
+ QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
+
+ for (int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::BufferOp &u(ud->bufferOps[opIdx]);
+ if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::DynamicUpdate) {
+ QD3D12Buffer *bufD = QRHI_RES(QD3D12Buffer, u.buf);
+ Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ if (u.offset == 0 && u.data.size() == bufD->m_size)
+ bufD->pendingHostWrites[i].clear();
+ bufD->pendingHostWrites[i].append({ u.offset, u.data });
+ }
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::StaticUpload) {
+ QD3D12Buffer *bufD = QRHI_RES(QD3D12Buffer, u.buf);
+ Q_ASSERT(bufD->m_type != QRhiBuffer::Dynamic);
+ Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
+
+ // The general approach to staging upload data is to first try
+ // using the per-frame "small" staging area, which is a very simple
+ // linear allocator; if that's not big enough then create a
+ // dedicated StagingArea and then deferred-release it to make sure
+ // if stays alive while the frame is possibly still in flight.
+
+ QD3D12StagingArea::Allocation stagingAlloc;
+ const quint32 allocSize = QD3D12StagingArea::allocSizeForArray(bufD->m_size, 1);
+ if (smallStagingAreas[currentFrameSlot].remainingCapacity() >= allocSize)
+ stagingAlloc = smallStagingAreas[currentFrameSlot].get(bufD->m_size);
+
+ std::optional<QD3D12StagingArea> ownStagingArea;
+ if (!stagingAlloc.isValid()) {
+ ownStagingArea = QD3D12StagingArea();
+ if (!ownStagingArea->create(this, allocSize, D3D12_HEAP_TYPE_UPLOAD))
+ continue;
+ stagingAlloc = ownStagingArea->get(allocSize);
+ if (!stagingAlloc.isValid()) {
+ ownStagingArea->destroy();
+ continue;
+ }
+ }
+
+ memcpy(stagingAlloc.p + u.offset, u.data.constData(), u.data.size());
+
+ barrierGen.addTransitionBarrier(bufD->handles[0], D3D12_RESOURCE_STATE_COPY_DEST);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+
+ if (QD3D12Resource *res = resourcePool.lookupRef(bufD->handles[0])) {
+ cbD->cmdList->CopyBufferRegion(res->resource,
+ u.offset,
+ stagingAlloc.buffer,
+ stagingAlloc.bufferOffset + u.offset,
+ u.data.size());
+ }
+
+ if (ownStagingArea.has_value())
+ ownStagingArea->destroyWithDeferredRelease(&releaseQueue);
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
+ QD3D12Buffer *bufD = QRHI_RES(QD3D12Buffer, u.buf);
+ if (bufD->m_type == QRhiBuffer::Dynamic) {
+ bufD->executeHostWritesForFrameSlot(currentFrameSlot);
+ if (QD3D12Resource *res = resourcePool.lookupRef(bufD->handles[currentFrameSlot])) {
+ Q_ASSERT(res->cpuMapPtr);
+ u.result->data.resize(u.readSize);
+ memcpy(u.result->data.data(), reinterpret_cast<char *>(res->cpuMapPtr) + u.offset, u.readSize);
+ }
+ if (u.result->completed)
+ u.result->completed();
+ } else {
+ QD3D12Readback readback;
+ readback.frameSlot = currentFrameSlot;
+ readback.result = u.result;
+ readback.byteSize = u.readSize;
+ const quint32 allocSize = aligned(u.readSize, QD3D12StagingArea::ALIGNMENT);
+ if (!readback.staging.create(this, allocSize, D3D12_HEAP_TYPE_READBACK)) {
+ if (u.result->completed)
+ u.result->completed();
+ continue;
+ }
+ QD3D12StagingArea::Allocation stagingAlloc = readback.staging.get(u.readSize);
+ if (!stagingAlloc.isValid()) {
+ readback.staging.destroy();
+ if (u.result->completed)
+ u.result->completed();
+ continue;
+ }
+ Q_ASSERT(stagingAlloc.bufferOffset == 0);
+ barrierGen.addTransitionBarrier(bufD->handles[0], D3D12_RESOURCE_STATE_COPY_SOURCE);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+ if (QD3D12Resource *res = resourcePool.lookupRef(bufD->handles[0])) {
+ cbD->cmdList->CopyBufferRegion(stagingAlloc.buffer, 0, res->resource, u.offset, u.readSize);
+ activeReadbacks.append(readback);
+ } else {
+ readback.staging.destroy();
+ if (u.result->completed)
+ u.result->completed();
+ }
+ }
+ }
+ }
+
+ for (int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
+ const QRhiResourceUpdateBatchPrivate::TextureOp &u(ud->textureOps[opIdx]);
+ if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
+ QD3D12Texture *texD = QRHI_RES(QD3D12Texture, u.dst);
+ const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ QD3D12Resource *res = resourcePool.lookupRef(texD->handle);
+ if (!res)
+ continue;
+ barrierGen.addTransitionBarrier(texD->handle, D3D12_RESOURCE_STATE_COPY_DEST);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+ for (int layer = 0, maxLayer = u.subresDesc.size(); layer < maxLayer; ++layer) {
+ for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level])) {
+ D3D12_SUBRESOURCE_FOOTPRINT footprint = {};
+ footprint.Format = res->desc.Format;
+ footprint.Depth = 1;
+ quint32 totalBytes = 0;
+
+ const QSize subresSize = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
+ : subresDesc.sourceSize();
+ const QPoint srcPos = subresDesc.sourceTopLeft();
+ QPoint dstPos = subresDesc.destinationTopLeft();
+
+ if (!subresDesc.image().isNull()) {
+ const QImage img = subresDesc.image();
+ const int bpl = img.bytesPerLine();
+ footprint.RowPitch = aligned<UINT>(bpl, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+ totalBytes = footprint.RowPitch * img.height();
+ } else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
+ QSize blockDim;
+ quint32 bpl = 0;
+ compressedFormatInfo(texD->m_format, subresSize, &bpl, nullptr, &blockDim);
+ footprint.RowPitch = aligned<UINT>(bpl, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+ const int rowCount = aligned(subresSize.height(), blockDim.height()) / blockDim.height();
+ totalBytes = footprint.RowPitch * rowCount;
+ } else if (!subresDesc.data().isEmpty()) {
+ quint32 bpl = 0;
+ if (subresDesc.dataStride())
+ bpl = subresDesc.dataStride();
+ else
+ textureFormatInfo(texD->m_format, subresSize, &bpl, nullptr, nullptr);
+ footprint.RowPitch = aligned<UINT>(bpl, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+ totalBytes = footprint.RowPitch * subresSize.height();
+ } else {
+ qWarning("Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
+ continue;
+ }
+
+ const quint32 allocSize = QD3D12StagingArea::allocSizeForArray(totalBytes, 1);
+ QD3D12StagingArea::Allocation stagingAlloc;
+ if (smallStagingAreas[currentFrameSlot].remainingCapacity() >= allocSize)
+ stagingAlloc = smallStagingAreas[currentFrameSlot].get(allocSize);
+
+ std::optional<QD3D12StagingArea> ownStagingArea;
+ if (!stagingAlloc.isValid()) {
+ ownStagingArea = QD3D12StagingArea();
+ if (!ownStagingArea->create(this, allocSize, D3D12_HEAP_TYPE_UPLOAD))
+ continue;
+ stagingAlloc = ownStagingArea->get(allocSize);
+ if (!stagingAlloc.isValid()) {
+ ownStagingArea->destroy();
+ continue;
+ }
+ }
+
+ D3D12_TEXTURE_COPY_LOCATION dst;
+ dst.pResource = res->resource;
+ dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ dst.SubresourceIndex = calcSubresource(UINT(level), is3D ? 0u : UINT(layer), texD->mipLevelCount);
+ D3D12_TEXTURE_COPY_LOCATION src;
+ src.pResource = stagingAlloc.buffer;
+ src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ src.PlacedFootprint.Offset = stagingAlloc.bufferOffset;
+
+ D3D12_BOX srcBox; // back, right, bottom are exclusive
+
+ if (!subresDesc.image().isNull()) {
+ const QImage img = subresDesc.image();
+ const int bpc = qMax(1, img.depth() / 8);
+ const int bpl = img.bytesPerLine();
+
+ QSize size = subresDesc.sourceSize().isEmpty() ? img.size() : subresDesc.sourceSize();
+ size.setWidth(qMin(size.width(), img.width() - srcPos.x()));
+ size.setHeight(qMin(size.height(), img.height() - srcPos.y()));
+
+ footprint.Width = size.width();
+ footprint.Height = size.height();
+
+ srcBox.left = 0;
+ srcBox.top = 0;
+ srcBox.right = UINT(size.width());
+ srcBox.bottom = UINT(size.height());
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ const uchar *imgPtr = img.constBits();
+ const quint32 lineBytes = size.width() * bpc;
+ for (int y = 0, h = size.height(); y < h; ++y) {
+ memcpy(stagingAlloc.p + y * footprint.RowPitch,
+ imgPtr + srcPos.x() * bpc + (y + srcPos.y()) * bpl,
+ lineBytes);
+ }
+ } else if (!subresDesc.data().isEmpty() && isCompressedFormat(texD->m_format)) {
+ QSize blockDim;
+ quint32 bpl = 0;
+ compressedFormatInfo(texD->m_format, subresSize, &bpl, nullptr, &blockDim);
+ // x and y must be multiples of the block width and height
+ dstPos.setX(aligned(dstPos.x(), blockDim.width()));
+ dstPos.setY(aligned(dstPos.y(), blockDim.height()));
+
+ srcBox.left = 0;
+ srcBox.top = 0;
+ // width and height must be multiples of the block width and height
+ srcBox.right = aligned(subresSize.width(), blockDim.width());
+ srcBox.bottom = aligned(subresSize.height(), blockDim.height());
+
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ footprint.Width = aligned(subresSize.width(), blockDim.width());
+ footprint.Height = aligned(subresSize.height(), blockDim.height());
+
+ const quint32 copyBytes = qMin(bpl, footprint.RowPitch);
+ const QByteArray imgData = subresDesc.data();
+ const char *imgPtr = imgData.constData();
+ const int rowCount = aligned(subresSize.height(), blockDim.height()) / blockDim.height();
+ for (int y = 0; y < rowCount; ++y)
+ memcpy(stagingAlloc.p + y * footprint.RowPitch, imgPtr + y * bpl, copyBytes);
+ } else if (!subresDesc.data().isEmpty()) {
+ srcBox.left = 0;
+ srcBox.top = 0;
+ srcBox.right = subresSize.width();
+ srcBox.bottom = subresSize.height();
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ footprint.Width = subresSize.width();
+ footprint.Height = subresSize.height();
+
+ quint32 bpl = 0;
+ if (subresDesc.dataStride())
+ bpl = subresDesc.dataStride();
+ else
+ textureFormatInfo(texD->m_format, subresSize, &bpl, nullptr, nullptr);
+
+ const quint32 copyBytes = qMin(bpl, footprint.RowPitch);
+ const QByteArray data = subresDesc.data();
+ const char *imgPtr = data.constData();
+ for (int y = 0, h = subresSize.height(); y < h; ++y)
+ memcpy(stagingAlloc.p + y * footprint.RowPitch, imgPtr + y * bpl, copyBytes);
+ }
+
+ src.PlacedFootprint.Footprint = footprint;
+
+ cbD->cmdList->CopyTextureRegion(&dst,
+ UINT(dstPos.x()),
+ UINT(dstPos.y()),
+ is3D ? UINT(layer) : 0u,
+ &src,
+ &srcBox);
+
+ if (ownStagingArea.has_value())
+ ownStagingArea->destroyWithDeferredRelease(&releaseQueue);
+ }
+ }
+ }
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Copy) {
+ Q_ASSERT(u.src && u.dst);
+ QD3D12Texture *srcD = QRHI_RES(QD3D12Texture, u.src);
+ QD3D12Texture *dstD = QRHI_RES(QD3D12Texture, u.dst);
+ const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ QD3D12Resource *srcRes = resourcePool.lookupRef(srcD->handle);
+ QD3D12Resource *dstRes = resourcePool.lookupRef(dstD->handle);
+ if (!srcRes || !dstRes)
+ continue;
+
+ barrierGen.addTransitionBarrier(srcD->handle, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ barrierGen.addTransitionBarrier(dstD->handle, D3D12_RESOURCE_STATE_COPY_DEST);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+
+ const UINT srcSubresource = calcSubresource(UINT(u.desc.sourceLevel()),
+ srcIs3D ? 0u : UINT(u.desc.sourceLayer()),
+ srcD->mipLevelCount);
+ const UINT dstSubresource = calcSubresource(UINT(u.desc.destinationLevel()),
+ dstIs3D ? 0u : UINT(u.desc.destinationLayer()),
+ dstD->mipLevelCount);
+ const QPoint dp = u.desc.destinationTopLeft();
+ const QSize mipSize = q->sizeForMipLevel(u.desc.sourceLevel(), srcD->m_pixelSize);
+ const QSize copySize = u.desc.pixelSize().isEmpty() ? mipSize : u.desc.pixelSize();
+ const QPoint sp = u.desc.sourceTopLeft();
+
+ D3D12_BOX srcBox;
+ srcBox.left = UINT(sp.x());
+ srcBox.top = UINT(sp.y());
+ srcBox.front = srcIs3D ? UINT(u.desc.sourceLayer()) : 0u;
+ // back, right, bottom are exclusive
+ srcBox.right = srcBox.left + UINT(copySize.width());
+ srcBox.bottom = srcBox.top + UINT(copySize.height());
+ srcBox.back = srcBox.front + 1;
+
+ D3D12_TEXTURE_COPY_LOCATION src;
+ src.pResource = srcRes->resource;
+ src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ src.SubresourceIndex = srcSubresource;
+ D3D12_TEXTURE_COPY_LOCATION dst;
+ dst.pResource = dstRes->resource;
+ dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ dst.SubresourceIndex = dstSubresource;
+
+ cbD->cmdList->CopyTextureRegion(&dst,
+ UINT(dp.x()),
+ UINT(dp.y()),
+ dstIs3D ? UINT(u.desc.destinationLayer()) : 0u,
+ &src,
+ &srcBox);
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Read) {
+ QD3D12Readback readback;
+ readback.frameSlot = currentFrameSlot;
+ readback.result = u.result;
+
+ QD3D12ObjectHandle srcHandle;
+ bool is3D = false;
+ if (u.rb.texture()) {
+ QD3D12Texture *texD = QRHI_RES(QD3D12Texture, u.rb.texture());
+ if (texD->sampleDesc.Count > 1) {
+ qWarning("Multisample texture cannot be read back");
+ continue;
+ }
+ is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ readback.pixelSize = q->sizeForMipLevel(u.rb.level(), texD->m_pixelSize);
+ readback.format = texD->m_format;
+ srcHandle = texD->handle;
+ } else {
+ Q_ASSERT(currentSwapChain);
+ readback.pixelSize = currentSwapChain->pixelSize;
+ readback.format = swapchainReadbackTextureFormat(currentSwapChain->colorFormat, nullptr);
+ if (readback.format == QRhiTexture::UnknownFormat)
+ continue;
+ srcHandle = currentSwapChain->colorBuffers[currentSwapChain->currentBackBufferIndex];
+ }
+
+ textureFormatInfo(readback.format,
+ readback.pixelSize,
+ &readback.bytesPerLine,
+ &readback.byteSize,
+ nullptr);
+
+ QD3D12Resource *srcRes = resourcePool.lookupRef(srcHandle);
+ if (!srcRes)
+ continue;
+
+ const UINT subresource = calcSubresource(UINT(u.rb.level()),
+ is3D ? 0u : UINT(u.rb.layer()),
+ srcRes->desc.MipLevels);
+ D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout;
+ // totalBytes is what we get from D3D, with the 256 aligned stride,
+ // readback.byteSize is the final result that's not relevant here yet
+ UINT64 totalBytes = 0;
+ dev->GetCopyableFootprints(&srcRes->desc, subresource, 1, 0,
+ &layout, nullptr, nullptr, &totalBytes);
+ readback.stagingRowPitch = layout.Footprint.RowPitch;
+
+ const quint32 allocSize = aligned<quint32>(totalBytes, QD3D12StagingArea::ALIGNMENT);
+ if (!readback.staging.create(this, allocSize, D3D12_HEAP_TYPE_READBACK)) {
+ if (u.result->completed)
+ u.result->completed();
+ continue;
+ }
+ QD3D12StagingArea::Allocation stagingAlloc = readback.staging.get(totalBytes);
+ if (!stagingAlloc.isValid()) {
+ readback.staging.destroy();
+ if (u.result->completed)
+ u.result->completed();
+ continue;
+ }
+ Q_ASSERT(stagingAlloc.bufferOffset == 0);
+
+ barrierGen.addTransitionBarrier(srcHandle, D3D12_RESOURCE_STATE_COPY_SOURCE);
+ barrierGen.enqueueBufferedTransitionBarriers(cbD);
+
+ D3D12_TEXTURE_COPY_LOCATION dst;
+ dst.pResource = stagingAlloc.buffer;
+ dst.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ dst.PlacedFootprint.Offset = 0;
+ dst.PlacedFootprint.Footprint = layout.Footprint;
+
+ D3D12_TEXTURE_COPY_LOCATION src;
+ src.pResource = srcRes->resource;
+ src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ src.SubresourceIndex = subresource;
+
+ D3D12_BOX srcBox = {};
+ if (is3D) {
+ srcBox.front = UINT(u.rb.layer());
+ srcBox.back = srcBox.front + 1;
+ srcBox.right = readback.pixelSize.width(); // exclusive
+ srcBox.bottom = readback.pixelSize.height();
+ }
+ cbD->cmdList->CopyTextureRegion(&dst, 0, 0, 0, &src, is3D ? &srcBox : nullptr);
+ activeReadbacks.append(readback);
+ } else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::GenMips) {
+ QD3D12Texture *texD = QRHI_RES(QD3D12Texture, u.dst);
+ Q_ASSERT(texD->flags().testFlag(QRhiTexture::UsedWithGenerateMips));
+ mipmapGen.generate(cbD, texD->handle);
+ }
+ }
+
+ ud->free();
+}
+
+void QRhiD3D12::finishActiveReadbacks(bool forced)
+{
+ QVarLengthArray<std::function<void()>, 4> completedCallbacks;
+
+ for (int i = activeReadbacks.size() - 1; i >= 0; --i) {
+ QD3D12Readback &readback(activeReadbacks[i]);
+ if (forced || currentFrameSlot == readback.frameSlot || readback.frameSlot < 0) {
+ readback.result->format = readback.format;
+ readback.result->pixelSize = readback.pixelSize;
+ readback.result->data.resize(int(readback.byteSize));
+
+ if (readback.format != QRhiTexture::UnknownFormat) {
+ quint8 *dstPtr = reinterpret_cast<quint8 *>(readback.result->data.data());
+ const quint8 *srcPtr = readback.staging.mem.p;
+ const quint32 lineSize = qMin(readback.bytesPerLine, readback.stagingRowPitch);
+ for (int y = 0, h = readback.pixelSize.height(); y < h; ++y)
+ memcpy(dstPtr + y * readback.bytesPerLine, srcPtr + y * readback.stagingRowPitch, lineSize);
+ } else {
+ memcpy(readback.result->data.data(), readback.staging.mem.p, readback.byteSize);
+ }
+
+ readback.staging.destroy();
+
+ if (readback.result->completed)
+ completedCallbacks.append(readback.result->completed);
+
+ activeReadbacks.removeLast();
+ }
+ }
+
+ for (auto f : completedCallbacks)
+ f();
+}
+
+bool QRhiD3D12::ensureShaderVisibleDescriptorHeapCapacity(QD3D12ShaderVisibleDescriptorHeap *h,
+ D3D12_DESCRIPTOR_HEAP_TYPE type,
+ int frameSlot,
+ quint32 neededDescriptorCount,
+ bool *gotNew)
+{
+ // Gets a new heap if needed. Note that the capacity we get is clamped
+ // automatically (e.g. to 1 million, or 2048 for samplers), so * 2 does not
+ // mean we can grow indefinitely, then again even using the same size would
+ // work (because we what we are after here is a new heap for the rest of
+ // the commands, not affecting what's already recorded).
+ if (h->perFrameHeapSlice[frameSlot].remainingCapacity() < neededDescriptorCount) {
+ const quint32 newPerFrameSize = qMax(h->perFrameHeapSlice[frameSlot].capacity * 2,
+ neededDescriptorCount);
+ QD3D12ShaderVisibleDescriptorHeap newHeap;
+ if (!newHeap.create(dev, type, newPerFrameSize)) {
+ qWarning("Could not create new shader-visible descriptor heap");
+ return false;
+ }
+ h->destroyWithDeferredRelease(&releaseQueue);
+ *h = newHeap;
+ *gotNew = true;
+ }
+ return true;
+}
+
+void QRhiD3D12::bindShaderVisibleHeaps(QD3D12CommandBuffer *cbD)
+{
+ ID3D12DescriptorHeap *heaps[] = {
+ shaderVisibleCbvSrvUavHeap.heap.heap,
+ samplerMgr.shaderVisibleSamplerHeap.heap.heap
+ };
+ cbD->cmdList->SetDescriptorHeaps(2, heaps);
+}
+
+QD3D12Buffer::QD3D12Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
+ : QRhiBuffer(rhi, type, usage, size)
+{
+}
+
+QD3D12Buffer::~QD3D12Buffer()
+{
+ destroy();
+}
+
+void QD3D12Buffer::destroy()
+{
+ if (handles[0].isNull())
+ return;
+
+ QRHI_RES_RHI(QRhiD3D12);
+
+ // destroy() implementations, unlike other functions, are expected to test
+ // for m_rhi (rhiD) being null, to allow surviving in case one attempts to
+ // destroy a (leaked) resource after the QRhi.
+ //
+ // If there is no QRhi anymore, we do not deferred-release but that's fine
+ // since the QRhi already released everything that was in the resourcePool.
+
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ if (rhiD)
+ rhiD->releaseQueue.deferredReleaseResource(handles[i]);
+ handles[i] = {};
+ pendingHostWrites[i].clear();
+ }
+
+ if (rhiD)
+ rhiD->unregisterResource(this);
+}
+
+bool QD3D12Buffer::create()
+{
+ if (!handles[0].isNull())
+ destroy();
+
+ if (m_usage.testFlag(QRhiBuffer::UniformBuffer) && m_type != Dynamic) {
+ qWarning("UniformBuffer must always be Dynamic");
+ return false;
+ }
+
+ if (m_usage.testFlag(QRhiBuffer::StorageBuffer) && m_type == Dynamic) {
+ qWarning("StorageBuffer cannot be combined with Dynamic");
+ return false;
+ }
+
+ const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
+ const quint32 roundedSize = aligned(nonZeroSize, m_usage.testFlag(QRhiBuffer::UniformBuffer) ? 256u : 4u);
+
+ UINT resourceFlags = D3D12_RESOURCE_FLAG_NONE;
+ if (m_usage.testFlag(QRhiBuffer::StorageBuffer))
+ resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+
+ QRHI_RES_RHI(QRhiD3D12);
+ HRESULT hr = 0;
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ if (i == 0 || m_type == Dynamic) {
+ D3D12_RESOURCE_DESC resourceDesc = {};
+ resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ resourceDesc.Width = roundedSize;
+ resourceDesc.Height = 1;
+ resourceDesc.DepthOrArraySize = 1;
+ resourceDesc.MipLevels = 1;
+ resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
+ resourceDesc.SampleDesc = { 1, 0 };
+ resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ resourceDesc.Flags = D3D12_RESOURCE_FLAGS(resourceFlags);
+ ID3D12Resource *resource = nullptr;
+ D3D12MA::Allocation *allocation = nullptr;
+ // Dynamic == host (CPU) visible
+ D3D12_HEAP_TYPE heapType = m_type == Dynamic
+ ? D3D12_HEAP_TYPE_UPLOAD
+ : D3D12_HEAP_TYPE_DEFAULT;
+ D3D12_RESOURCE_STATES resourceState = m_type == Dynamic
+ ? D3D12_RESOURCE_STATE_GENERIC_READ
+ : D3D12_RESOURCE_STATE_COMMON;
+ hr = rhiD->vma.createResource(heapType,
+ &resourceDesc,
+ resourceState,
+ nullptr,
+ &allocation,
+ __uuidof(resource),
+ reinterpret_cast<void **>(&resource));
+ if (FAILED(hr))
+ break;
+ if (!m_objectName.isEmpty()) {
+ QString decoratedName = QString::fromUtf8(m_objectName);
+ if (m_type == Dynamic) {
+ decoratedName += QLatin1Char('/');
+ decoratedName += QString::number(i);
+ }
+ resource->SetName(reinterpret_cast<LPCWSTR>(decoratedName.utf16()));
+ }
+ void *cpuMemPtr = nullptr;
+ if (m_type == Dynamic) {
+ // will be mapped for ever on the CPU, this makes future host write operations very simple
+ hr = resource->Map(0, nullptr, &cpuMemPtr);
+ if (FAILED(hr)) {
+ qWarning("Map() failed to dynamic buffer");
+ resource->Release();
+ if (allocation)
+ allocation->Release();
+ break;
+ }
+ }
+ handles[i] = QD3D12Resource::addToPool(&rhiD->resourcePool,
+ resource,
+ resourceState,
+ allocation,
+ cpuMemPtr);
+ }
+ }
+ if (FAILED(hr)) {
+ qWarning("Failed to create buffer: '%s' Type was %d, size was %u, using D3D12MA was %d.",
+ qPrintable(QSystemError::windowsComString(hr)),
+ int(m_type),
+ roundedSize,
+ int(rhiD->vma.isUsingD3D12MA()));
+ return false;
+ }
+
+ rhiD->registerResource(this);
+ return true;
+}
+
+QRhiBuffer::NativeBuffer QD3D12Buffer::nativeBuffer()
+{
+ NativeBuffer b;
+ Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QD3D12_FRAMES_IN_FLIGHT));
+ QRHI_RES_RHI(QRhiD3D12);
+ if (m_type == Dynamic) {
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ executeHostWritesForFrameSlot(i);
+ if (QD3D12Resource *res = rhiD->resourcePool.lookupRef(handles[i]))
+ b.objects[i] = res->resource;
+ else
+ b.objects[i] = nullptr;
+ }
+ b.slotCount = QD3D12_FRAMES_IN_FLIGHT;
+ return b;
+ }
+ if (QD3D12Resource *res = rhiD->resourcePool.lookupRef(handles[0]))
+ b.objects[0] = res->resource;
+ else
+ b.objects[0] = nullptr;
+ b.slotCount = 1;
+ return b;
+}
+
+char *QD3D12Buffer::beginFullDynamicBufferUpdateForCurrentFrame()
+{
+ // Shortcut the entire buffer update mechanism and allow the client to do
+ // the host writes directly to the buffer. This will lead to unexpected
+ // results when combined with QRhiResourceUpdateBatch-based updates for the
+ // buffer, but provides a fast path for dynamic buffers that have all their
+ // content changed in every frame.
+
+ Q_ASSERT(m_type == Dynamic);
+ QRHI_RES_RHI(QRhiD3D12);
+ Q_ASSERT(rhiD->inFrame);
+ if (QD3D12Resource *res = rhiD->resourcePool.lookupRef(handles[rhiD->currentFrameSlot]))
+ return static_cast<char *>(res->cpuMapPtr);
+
+ return nullptr;
+}
+
+void QD3D12Buffer::endFullDynamicBufferUpdateForCurrentFrame()
+{
+ // nothing to do here
+}
+
+void QD3D12Buffer::executeHostWritesForFrameSlot(int frameSlot)
+{
+ if (pendingHostWrites[frameSlot].isEmpty())
+ return;
+
+ Q_ASSERT(m_type == QRhiBuffer::Dynamic);
+ QRHI_RES_RHI(QRhiD3D12);
+ if (QD3D12Resource *res = rhiD->resourcePool.lookupRef(handles[frameSlot])) {
+ Q_ASSERT(res->cpuMapPtr);
+ for (const QD3D12Buffer::HostWrite &u : std::as_const(pendingHostWrites[frameSlot]))
+ memcpy(static_cast<char *>(res->cpuMapPtr) + u.offset, u.data.constData(), u.data.size());
+ }
+ pendingHostWrites[frameSlot].clear();
+}
+
+static inline DXGI_FORMAT toD3DTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
+{
+ const bool srgb = flags.testFlag(QRhiTexture::sRGB);
+ switch (format) {
+ case QRhiTexture::RGBA8:
+ return srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
+ case QRhiTexture::BGRA8:
+ return srgb ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM;
+ case QRhiTexture::R8:
+ return DXGI_FORMAT_R8_UNORM;
+ case QRhiTexture::RG8:
+ return DXGI_FORMAT_R8G8_UNORM;
+ case QRhiTexture::R16:
+ return DXGI_FORMAT_R16_UNORM;
+ case QRhiTexture::RG16:
+ return DXGI_FORMAT_R16G16_UNORM;
+ case QRhiTexture::RED_OR_ALPHA8:
+ return DXGI_FORMAT_R8_UNORM;
+
+ case QRhiTexture::RGBA16F:
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+ case QRhiTexture::RGBA32F:
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ case QRhiTexture::R16F:
+ return DXGI_FORMAT_R16_FLOAT;
+ case QRhiTexture::R32F:
+ return DXGI_FORMAT_R32_FLOAT;
+
+ case QRhiTexture::RGB10A2:
+ return DXGI_FORMAT_R10G10B10A2_UNORM;
+
+ case QRhiTexture::D16:
+ return DXGI_FORMAT_R16_TYPELESS;
+ case QRhiTexture::D24:
+ return DXGI_FORMAT_R24G8_TYPELESS;
+ case QRhiTexture::D24S8:
+ return DXGI_FORMAT_R24G8_TYPELESS;
+ case QRhiTexture::D32F:
+ return DXGI_FORMAT_R32_TYPELESS;
+
+ case QRhiTexture::BC1:
+ return srgb ? DXGI_FORMAT_BC1_UNORM_SRGB : DXGI_FORMAT_BC1_UNORM;
+ case QRhiTexture::BC2:
+ return srgb ? DXGI_FORMAT_BC2_UNORM_SRGB : DXGI_FORMAT_BC2_UNORM;
+ case QRhiTexture::BC3:
+ return srgb ? DXGI_FORMAT_BC3_UNORM_SRGB : DXGI_FORMAT_BC3_UNORM;
+ case QRhiTexture::BC4:
+ return DXGI_FORMAT_BC4_UNORM;
+ case QRhiTexture::BC5:
+ return DXGI_FORMAT_BC5_UNORM;
+ case QRhiTexture::BC6H:
+ return DXGI_FORMAT_BC6H_UF16;
+ case QRhiTexture::BC7:
+ return srgb ? DXGI_FORMAT_BC7_UNORM_SRGB : DXGI_FORMAT_BC7_UNORM;
+
+ case QRhiTexture::ETC2_RGB8:
+ case QRhiTexture::ETC2_RGB8A1:
+ case QRhiTexture::ETC2_RGBA8:
+ qWarning("QRhiD3D12 does not support ETC2 textures");
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ case QRhiTexture::ASTC_4x4:
+ case QRhiTexture::ASTC_5x4:
+ case QRhiTexture::ASTC_5x5:
+ case QRhiTexture::ASTC_6x5:
+ case QRhiTexture::ASTC_6x6:
+ case QRhiTexture::ASTC_8x5:
+ case QRhiTexture::ASTC_8x6:
+ case QRhiTexture::ASTC_8x8:
+ case QRhiTexture::ASTC_10x5:
+ case QRhiTexture::ASTC_10x6:
+ case QRhiTexture::ASTC_10x8:
+ case QRhiTexture::ASTC_10x10:
+ case QRhiTexture::ASTC_12x10:
+ case QRhiTexture::ASTC_12x12:
+ qWarning("QRhiD3D12 does not support ASTC textures");
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ default:
+ break;
+ }
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+}
+
+QD3D12RenderBuffer::QD3D12RenderBuffer(QRhiImplementation *rhi,
+ Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ Flags flags,
+ QRhiTexture::Format backingFormatHint)
+ : QRhiRenderBuffer(rhi, type, pixelSize, sampleCount, flags, backingFormatHint)
+{
+}
+
+QD3D12RenderBuffer::~QD3D12RenderBuffer()
+{
+ destroy();
+}
+
+void QD3D12RenderBuffer::destroy()
+{
+ if (handle.isNull())
+ return;
+
+ QRHI_RES_RHI(QRhiD3D12);
+ if (rhiD) {
+ if (rtv.isValid())
+ rhiD->releaseQueue.deferredReleaseResourceWithViews(handle, &rhiD->rtvPool, rtv, 1);
+ else if (dsv.isValid())
+ rhiD->releaseQueue.deferredReleaseResourceWithViews(handle, &rhiD->dsvPool, dsv, 1);
+ }
+
+ handle = {};
+ rtv = {};
+ dsv = {};
+
+ if (rhiD)
+ rhiD->unregisterResource(this);
+}
+
+bool QD3D12RenderBuffer::create()
+{
+ if (!handle.isNull())
+ destroy();
+
+ if (m_pixelSize.isEmpty())
+ return false;
+
+ QRHI_RES_RHI(QRhiD3D12);
+
+ switch (m_type) {
+ case QRhiRenderBuffer::Color:
+ {
+ dxgiFormat = toD3DTextureFormat(backingFormat(), {});
+ sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
+ D3D12_RESOURCE_DESC resourceDesc = {};
+ resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ resourceDesc.Width = UINT64(m_pixelSize.width());
+ resourceDesc.Height = UINT(m_pixelSize.height());
+ resourceDesc.DepthOrArraySize = 1;
+ resourceDesc.MipLevels = 1;
+ resourceDesc.Format = dxgiFormat;
+ resourceDesc.SampleDesc = sampleDesc;
+ resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+ D3D12_CLEAR_VALUE clearValue = {};
+ clearValue.Format = dxgiFormat;
+ // have a separate allocation and resource object (meaning both will need its own Release())
+ ID3D12Resource *resource = nullptr;
+ D3D12MA::Allocation *allocation = nullptr;
+ HRESULT hr = rhiD->vma.createResource(D3D12_HEAP_TYPE_DEFAULT,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_RENDER_TARGET,
+ &clearValue,
+ &allocation,
+ __uuidof(ID3D12Resource),
+ reinterpret_cast<void **>(&resource));
+ if (FAILED(hr)) {
+ qWarning("Failed to create color buffer: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ handle = QD3D12Resource::addToPool(&rhiD->resourcePool, resource, D3D12_RESOURCE_STATE_RENDER_TARGET, allocation);
+ rtv = rhiD->rtvPool.allocate(1);
+ if (!rtv.isValid())
+ return false;
+ D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
+ rtvDesc.Format = dxgiFormat;
+ rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMS
+ : D3D12_RTV_DIMENSION_TEXTURE2D;
+ rhiD->dev->CreateRenderTargetView(resource, &rtvDesc, rtv.cpuHandle);
+ }
+ break;
+ case QRhiRenderBuffer::DepthStencil:
+ {
+ dxgiFormat = DS_FORMAT;
+ sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
+ D3D12_RESOURCE_DESC resourceDesc = {};
+ resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ resourceDesc.Width = UINT64(m_pixelSize.width());
+ resourceDesc.Height = UINT(m_pixelSize.height());
+ resourceDesc.DepthOrArraySize = 1;
+ resourceDesc.MipLevels = 1;
+ resourceDesc.Format = dxgiFormat;
+ resourceDesc.SampleDesc = sampleDesc;
+ resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
+ if (m_flags.testFlag(UsedWithSwapChainOnly))
+ resourceDesc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
+ D3D12_CLEAR_VALUE clearValue = {};
+ clearValue.Format = dxgiFormat;
+ clearValue.DepthStencil.Depth = 1.0f;
+ clearValue.DepthStencil.Stencil = 0;
+ ID3D12Resource *resource = nullptr;
+ D3D12MA::Allocation *allocation = nullptr;
+ HRESULT hr = rhiD->vma.createResource(D3D12_HEAP_TYPE_DEFAULT,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_DEPTH_WRITE,
+ &clearValue,
+ &allocation,
+ __uuidof(ID3D12Resource),
+ reinterpret_cast<void **>(&resource));
+ if (FAILED(hr)) {
+ qWarning("Failed to create depth-stencil buffer: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ handle = QD3D12Resource::addToPool(&rhiD->resourcePool, resource, D3D12_RESOURCE_STATE_DEPTH_WRITE, allocation);
+ dsv = rhiD->dsvPool.allocate(1);
+ if (!dsv.isValid())
+ return false;
+ D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
+ dsvDesc.Format = dxgiFormat;
+ dsvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMS
+ : D3D12_DSV_DIMENSION_TEXTURE2D;
+ rhiD->dev->CreateDepthStencilView(resource, &dsvDesc, dsv.cpuHandle);
+ }
+ break;
+ }
+
+ if (!m_objectName.isEmpty()) {
+ if (QD3D12Resource *res = rhiD->resourcePool.lookupRef(handle)) {
+ const QString name = QString::fromUtf8(m_objectName);
+ res->resource->SetName(reinterpret_cast<LPCWSTR>(name.utf16()));
+ }
+ }
+
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QRhiTexture::Format QD3D12RenderBuffer::backingFormat() const
+{
+ if (m_backingFormatHint != QRhiTexture::UnknownFormat)
+ return m_backingFormatHint;
+ else
+ return m_type == Color ? QRhiTexture::RGBA8 : QRhiTexture::UnknownFormat;
+}
+
+QD3D12Texture::QD3D12Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
+ int arraySize, int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, arraySize, sampleCount, flags)
+{
+}
+
+QD3D12Texture::~QD3D12Texture()
+{
+ destroy();
+}
+
+void QD3D12Texture::destroy()
+{
+ if (handle.isNull())
+ return;
+
+ QRHI_RES_RHI(QRhiD3D12);
+ if (rhiD)
+ rhiD->releaseQueue.deferredReleaseResourceWithViews(handle, &rhiD->cbvSrvUavPool, srv, 1);
+
+ handle = {};
+ srv = {};
+
+ if (rhiD)
+ rhiD->unregisterResource(this);
+}
+
+static inline DXGI_FORMAT toD3DDepthTextureSRVFormat(QRhiTexture::Format format)
+{
+ switch (format) {
+ case QRhiTexture::Format::D16:
+ return DXGI_FORMAT_R16_FLOAT;
+ case QRhiTexture::Format::D24:
+ return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
+ case QRhiTexture::Format::D24S8:
+ return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
+ case QRhiTexture::Format::D32F:
+ return DXGI_FORMAT_R32_FLOAT;
+ default:
+ break;
+ }
+ Q_UNREACHABLE_RETURN(DXGI_FORMAT_R32_FLOAT);
+}
+
+static inline DXGI_FORMAT toD3DDepthTextureDSVFormat(QRhiTexture::Format format)
+{
+ // here the result cannot be typeless
+ switch (format) {
+ case QRhiTexture::Format::D16:
+ return DXGI_FORMAT_D16_UNORM;
+ case QRhiTexture::Format::D24:
+ return DXGI_FORMAT_D24_UNORM_S8_UINT;
+ case QRhiTexture::Format::D24S8:
+ return DXGI_FORMAT_D24_UNORM_S8_UINT;
+ case QRhiTexture::Format::D32F:
+ return DXGI_FORMAT_D32_FLOAT;
+ default:
+ break;
+ }
+ Q_UNREACHABLE_RETURN(DXGI_FORMAT_D32_FLOAT);
+}
+
+static inline bool isDepthTextureFormat(QRhiTexture::Format format)
+{
+ switch (format) {
+ case QRhiTexture::Format::D16:
+ case QRhiTexture::Format::D24:
+ case QRhiTexture::Format::D24S8:
+ case QRhiTexture::Format::D32F:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool QD3D12Texture::prepareCreate(QSize *adjustedSize)
+{
+ if (!handle.isNull())
+ destroy();
+
+ const bool isDepth = isDepthTextureFormat(m_format);
+ const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool isArray = m_flags.testFlag(TextureArray);
+ const bool hasMipMaps = m_flags.testFlag(MipMapped);
+ const bool is1D = m_flags.testFlag(OneDimensional);
+
+ const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
+ : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
+
+ dxgiFormat = toD3DTextureFormat(m_format, m_flags);
+ if (isDepth) {
+ srvFormat = toD3DDepthTextureSRVFormat(m_format);
+ rtFormat = toD3DDepthTextureDSVFormat(m_format);
+ } else {
+ srvFormat = dxgiFormat;
+ rtFormat = dxgiFormat;
+ }
+ if (m_writeViewFormat.format != UnknownFormat) {
+ if (isDepth)
+ rtFormat = toD3DDepthTextureDSVFormat(m_writeViewFormat.format);
+ else
+ rtFormat = toD3DTextureFormat(m_writeViewFormat.format, m_writeViewFormat.srgb ? sRGB : Flags());
+ }
+ if (m_readViewFormat.format != UnknownFormat) {
+ if (isDepth)
+ srvFormat = toD3DDepthTextureSRVFormat(m_readViewFormat.format);
+ else
+ srvFormat = toD3DTextureFormat(m_readViewFormat.format, m_readViewFormat.srgb ? sRGB : Flags());
+ }
+
+ QRHI_RES_RHI(QRhiD3D12);
+ mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
+ sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
+ if (sampleDesc.Count > 1) {
+ if (isCube) {
+ qWarning("Cubemap texture cannot be multisample");
+ return false;
+ }
+ if (is3D) {
+ qWarning("3D texture cannot be multisample");
+ return false;
+ }
+ if (hasMipMaps) {
+ qWarning("Multisample texture cannot have mipmaps");
+ return false;
+ }
+ }
+ if (isDepth && hasMipMaps) {
+ qWarning("Depth texture cannot have mipmaps");
+ return false;
+ }
+ if (isCube && is3D) {
+ qWarning("Texture cannot be both cube and 3D");
+ return false;
+ }
+ if (isArray && is3D) {
+ qWarning("Texture cannot be both array and 3D");
+ return false;
+ }
+ if (isCube && is1D) {
+ qWarning("Texture cannot be both cube and 1D");
+ return false;
+ }
+ if (is1D && is3D) {
+ qWarning("Texture cannot be both 1D and 3D");
+ return false;
+ }
+ if (m_depth > 1 && !is3D) {
+ qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
+ return false;
+ }
+ if (m_arraySize > 0 && !isArray) {
+ qWarning("Texture cannot have an array size of %d when it is not an array", m_arraySize);
+ return false;
+ }
+ if (m_arraySize < 1 && isArray) {
+ qWarning("Texture is an array but array size is %d", m_arraySize);
+ return false;
+ }
+
+ if (adjustedSize)
+ *adjustedSize = size;
+
+ return true;
+}
+
+bool QD3D12Texture::finishCreate()
+{
+ QRHI_RES_RHI(QRhiD3D12);
+ const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool isArray = m_flags.testFlag(TextureArray);
+ const bool is1D = m_flags.testFlag(OneDimensional);
+
+ D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
+ srvDesc.Format = srvFormat;
+ srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+
+ if (isCube) {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
+ srvDesc.TextureCube.MipLevels = mipLevelCount;
+ } else {
+ if (is1D) {
+ if (isArray) {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
+ srvDesc.Texture1DArray.MipLevels = mipLevelCount;
+ if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
+ srvDesc.Texture1DArray.FirstArraySlice = UINT(m_arrayRangeStart);
+ srvDesc.Texture1DArray.ArraySize = UINT(m_arrayRangeLength);
+ } else {
+ srvDesc.Texture1DArray.FirstArraySlice = 0;
+ srvDesc.Texture1DArray.ArraySize = UINT(qMax(0, m_arraySize));
+ }
+ } else {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
+ srvDesc.Texture1D.MipLevels = mipLevelCount;
+ }
+ } else if (isArray) {
+ if (sampleDesc.Count > 1) {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY;
+ if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
+ srvDesc.Texture2DMSArray.FirstArraySlice = UINT(m_arrayRangeStart);
+ srvDesc.Texture2DMSArray.ArraySize = UINT(m_arrayRangeLength);
+ } else {
+ srvDesc.Texture2DMSArray.FirstArraySlice = 0;
+ srvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, m_arraySize));
+ }
+ } else {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MipLevels = mipLevelCount;
+ if (m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
+ srvDesc.Texture2DArray.FirstArraySlice = UINT(m_arrayRangeStart);
+ srvDesc.Texture2DArray.ArraySize = UINT(m_arrayRangeLength);
+ } else {
+ srvDesc.Texture2DArray.FirstArraySlice = 0;
+ srvDesc.Texture2DArray.ArraySize = UINT(qMax(0, m_arraySize));
+ }
+ }
+ } else {
+ if (sampleDesc.Count > 1) {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS;
+ } else if (is3D) {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
+ srvDesc.Texture3D.MipLevels = mipLevelCount;
+ } else {
+ srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MipLevels = mipLevelCount;
+ }
+ }
+ }
+
+ srv = rhiD->cbvSrvUavPool.allocate(1);
+ if (!srv.isValid())
+ return false;
+
+ if (QD3D12Resource *res = rhiD->resourcePool.lookupRef(handle)) {
+ rhiD->dev->CreateShaderResourceView(res->resource, &srvDesc, srv.cpuHandle);
+ if (!m_objectName.isEmpty()) {
+ const QString name = QString::fromUtf8(m_objectName);
+ res->resource->SetName(reinterpret_cast<LPCWSTR>(name.utf16()));
+ }
+ } else {
+ return false;
+ }
+
+ generation += 1;
+ return true;
+}
+
+bool QD3D12Texture::create()
+{
+ QSize size;
+ if (!prepareCreate(&size))
+ return false;
+
+ const bool isDepth = isDepthTextureFormat(m_format);
+ const bool isCube = m_flags.testFlag(CubeMap);
+ const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool isArray = m_flags.testFlag(TextureArray);
+ const bool is1D = m_flags.testFlag(OneDimensional);
+
+ QRHI_RES_RHI(QRhiD3D12);
+
+ bool needsOptimizedClearValueSpecified = false;
+ UINT resourceFlags = 0;
+ if (m_flags.testFlag(RenderTarget) || sampleDesc.Count > 1) {
+ if (isDepth)
+ resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
+ else
+ resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+ needsOptimizedClearValueSpecified = true;
+ }
+ if (m_flags.testFlag(UsedWithGenerateMips)) {
+ if (isDepth) {
+ qWarning("Depth texture cannot have mipmaps generated");
+ return false;
+ }
+ resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+ }
+ if (m_flags.testFlag(UsedWithLoadStore))
+ resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+
+ D3D12_RESOURCE_DESC resourceDesc = {};
+ resourceDesc.Dimension = is1D ? D3D12_RESOURCE_DIMENSION_TEXTURE1D
+ : (is3D ? D3D12_RESOURCE_DIMENSION_TEXTURE3D
+ : D3D12_RESOURCE_DIMENSION_TEXTURE2D);
+ resourceDesc.Width = UINT64(size.width());
+ resourceDesc.Height = UINT(size.height());
+ resourceDesc.DepthOrArraySize = isCube ? 6
+ : (isArray ? UINT(qMax(0, m_arraySize))
+ : (is3D ? qMax(1, m_depth)
+ : 1));
+ resourceDesc.MipLevels = mipLevelCount;
+ resourceDesc.Format = dxgiFormat;
+ resourceDesc.SampleDesc = sampleDesc;
+ resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ resourceDesc.Flags = D3D12_RESOURCE_FLAGS(resourceFlags);
+ D3D12_CLEAR_VALUE clearValue = {};
+ clearValue.Format = dxgiFormat;
+ if (isDepth) {
+ clearValue.Format = toD3DDepthTextureDSVFormat(m_format);
+ clearValue.DepthStencil.Depth = 1.0f;
+ clearValue.DepthStencil.Stencil = 0;
+ }
+ ID3D12Resource *resource = nullptr;
+ D3D12MA::Allocation *allocation = nullptr;
+ HRESULT hr = rhiD->vma.createResource(D3D12_HEAP_TYPE_DEFAULT,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_COMMON,
+ needsOptimizedClearValueSpecified ? &clearValue : nullptr,
+ &allocation,
+ __uuidof(ID3D12Resource),
+ reinterpret_cast<void **>(&resource));
+ if (FAILED(hr)) {
+ qWarning("Failed to create texture: '%s'"
+ " Dim was %d Size was %ux%u Depth/ArraySize was %u MipLevels was %u Format was %d Sample count was %d",
+ qPrintable(QSystemError::windowsComString(hr)),
+ int(resourceDesc.Dimension),
+ uint(resourceDesc.Width),
+ uint(resourceDesc.Height),
+ uint(resourceDesc.DepthOrArraySize),
+ uint(resourceDesc.MipLevels),
+ int(resourceDesc.Format),
+ int(resourceDesc.SampleDesc.Count));
+ return false;
+ }
+
+ handle = QD3D12Resource::addToPool(&rhiD->resourcePool, resource, D3D12_RESOURCE_STATE_COMMON, allocation);
+
+ if (!finishCreate())
+ return false;
+
+ rhiD->registerResource(this);
+ return true;
+}
+
+bool QD3D12Texture::createFrom(QRhiTexture::NativeTexture src)
+{
+ if (!src.object)
+ return false;
+
+ if (!prepareCreate())
+ return false;
+
+ ID3D12Resource *resource = reinterpret_cast<ID3D12Resource *>(src.object);
+ D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATES(src.layout);
+
+ QRHI_RES_RHI(QRhiD3D12);
+ handle = QD3D12Resource::addNonOwningToPool(&rhiD->resourcePool, resource, state);
+
+ if (!finishCreate())
+ return false;
+
+ rhiD->registerResource(this);
+ return true;
+}
+
+QRhiTexture::NativeTexture QD3D12Texture::nativeTexture()
+{
+ QRHI_RES_RHI(QRhiD3D12);
+ if (QD3D12Resource *res = rhiD->resourcePool.lookupRef(handle))
+ return { quint64(res->resource), int(res->state) };
+
+ return {};
+}
+
+void QD3D12Texture::setNativeLayout(int layout)
+{
+ QRHI_RES_RHI(QRhiD3D12);
+ if (QD3D12Resource *res = rhiD->resourcePool.lookupRef(handle))
+ res->state = D3D12_RESOURCE_STATES(layout);
+}
+
+QD3D12Sampler::QD3D12Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w)
+{
+}
+
+QD3D12Sampler::~QD3D12Sampler()
+{
+ destroy();
+}
+
+void QD3D12Sampler::destroy()
+{
+ shaderVisibleDescriptor = {};
+
+ QRHI_RES_RHI(QRhiD3D12);
+ if (rhiD)
+ rhiD->unregisterResource(this);
+}
+
+static inline D3D12_FILTER toD3DFilter(QRhiSampler::Filter minFilter, QRhiSampler::Filter magFilter, QRhiSampler::Filter mipFilter)
+{
+ if (minFilter == QRhiSampler::Nearest) {
+ if (magFilter == QRhiSampler::Nearest) {
+ if (mipFilter == QRhiSampler::Linear)
+ return D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR;
+ else
+ return D3D12_FILTER_MIN_MAG_MIP_POINT;
+ } else {
+ if (mipFilter == QRhiSampler::Linear)
+ return D3D12_FILTER_MIN_POINT_MAG_MIP_LINEAR;
+ else
+ return D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
+ }
+ } else {
+ if (magFilter == QRhiSampler::Nearest) {
+ if (mipFilter == QRhiSampler::Linear)
+ return D3D12_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
+ else
+ return D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT;
+ } else {
+ if (mipFilter == QRhiSampler::Linear)
+ return D3D12_FILTER_MIN_MAG_MIP_LINEAR;
+ else
+ return D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
+ }
+ }
+ Q_UNREACHABLE_RETURN(D3D12_FILTER_MIN_MAG_MIP_LINEAR);
+}
+
+static inline D3D12_TEXTURE_ADDRESS_MODE toD3DAddressMode(QRhiSampler::AddressMode m)
+{
+ switch (m) {
+ case QRhiSampler::Repeat:
+ return D3D12_TEXTURE_ADDRESS_MODE_WRAP;
+ case QRhiSampler::ClampToEdge:
+ return D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+ case QRhiSampler::Mirror:
+ return D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
+ }
+ Q_UNREACHABLE_RETURN(D3D12_TEXTURE_ADDRESS_MODE_CLAMP);
+}
+
+static inline D3D12_COMPARISON_FUNC toD3DTextureComparisonFunc(QRhiSampler::CompareOp op)
+{
+ switch (op) {
+ case QRhiSampler::Never:
+ return D3D12_COMPARISON_FUNC_NEVER;
+ case QRhiSampler::Less:
+ return D3D12_COMPARISON_FUNC_LESS;
+ case QRhiSampler::Equal:
+ return D3D12_COMPARISON_FUNC_EQUAL;
+ case QRhiSampler::LessOrEqual:
+ return D3D12_COMPARISON_FUNC_LESS_EQUAL;
+ case QRhiSampler::Greater:
+ return D3D12_COMPARISON_FUNC_GREATER;
+ case QRhiSampler::NotEqual:
+ return D3D12_COMPARISON_FUNC_NOT_EQUAL;
+ case QRhiSampler::GreaterOrEqual:
+ return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
+ case QRhiSampler::Always:
+ return D3D12_COMPARISON_FUNC_ALWAYS;
+ }
+ Q_UNREACHABLE_RETURN(D3D12_COMPARISON_FUNC_NEVER);
+}
+
+bool QD3D12Sampler::create()
+{
+ desc = {};
+ desc.Filter = toD3DFilter(m_minFilter, m_magFilter, m_mipmapMode);
+ if (m_compareOp != Never)
+ desc.Filter = D3D12_FILTER(desc.Filter | 0x80);
+ desc.AddressU = toD3DAddressMode(m_addressU);
+ desc.AddressV = toD3DAddressMode(m_addressV);
+ desc.AddressW = toD3DAddressMode(m_addressW);
+ desc.MaxAnisotropy = 1.0f;
+ desc.ComparisonFunc = toD3DTextureComparisonFunc(m_compareOp);
+ desc.MaxLOD = m_mipmapMode == None ? 0.0f : 10000.0f;
+
+ QRHI_RES_RHI(QRhiD3D12);
+ rhiD->registerResource(this, false);
+ return true;
+}
+
+QD3D12Descriptor QD3D12Sampler::lookupOrCreateShaderVisibleDescriptor()
+{
+ if (!shaderVisibleDescriptor.isValid()) {
+ QRHI_RES_RHI(QRhiD3D12);
+ shaderVisibleDescriptor = rhiD->samplerMgr.getShaderVisibleDescriptor(desc);
+ }
+ return shaderVisibleDescriptor;
+}
+
+QD3D12TextureRenderTarget::QD3D12TextureRenderTarget(QRhiImplementation *rhi,
+ const QRhiTextureRenderTargetDescription &desc,
+ Flags flags)
+ : QRhiTextureRenderTarget(rhi, desc, flags),
+ d(rhi)
+{
+}
+
+QD3D12TextureRenderTarget::~QD3D12TextureRenderTarget()
+{
+ destroy();
+}
+
+void QD3D12TextureRenderTarget::destroy()
+{
+ if (!rtv[0].isValid() && !dsv.isValid())
+ return;
+
+ QRHI_RES_RHI(QRhiD3D12);
+ if (dsv.isValid()) {
+ if (ownsDsv && rhiD)
+ rhiD->releaseQueue.deferredReleaseViews(&rhiD->dsvPool, dsv, 1);
+ dsv = {};
+ }
+
+ for (int i = 0; i < QD3D12RenderTargetData::MAX_COLOR_ATTACHMENTS; ++i) {
+ if (rtv[i].isValid()) {
+ if (ownsRtv[i] && rhiD)
+ rhiD->releaseQueue.deferredReleaseViews(&rhiD->rtvPool, rtv[i], 1);
+ rtv[i] = {};
+ }
+ }
+
+ if (rhiD)
+ rhiD->unregisterResource(this);
+}
+
+QRhiRenderPassDescriptor *QD3D12TextureRenderTarget::newCompatibleRenderPassDescriptor()
+{
+ // not yet built so cannot rely on data computed in create()
+
+ QD3D12RenderPassDescriptor *rpD = new QD3D12RenderPassDescriptor(m_rhi);
+
+ rpD->colorAttachmentCount = 0;
+ for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it) {
+ QD3D12Texture *texD = QRHI_RES(QD3D12Texture, it->texture());
+ QD3D12RenderBuffer *rbD = QRHI_RES(QD3D12RenderBuffer, it->renderBuffer());
+ if (texD)
+ rpD->colorFormat[rpD->colorAttachmentCount] = texD->rtFormat;
+ else if (rbD)
+ rpD->colorFormat[rpD->colorAttachmentCount] = rbD->dxgiFormat;
+ rpD->colorAttachmentCount += 1;
+ }
+
+ rpD->hasDepthStencil = false;
+ if (m_desc.depthStencilBuffer()) {
+ rpD->hasDepthStencil = true;
+ rpD->dsFormat = QD3D12RenderBuffer::DS_FORMAT;
+ } else if (m_desc.depthTexture()) {
+ QD3D12Texture *depthTexD = QRHI_RES(QD3D12Texture, m_desc.depthTexture());
+ rpD->hasDepthStencil = true;
+ rpD->dsFormat = toD3DDepthTextureDSVFormat(depthTexD->format()); // cannot be a typeless format
+ }
+
+ rpD->updateSerializedFormat();
+
+ QRHI_RES_RHI(QRhiD3D12);
+ rhiD->registerResource(rpD);
+ return rpD;
+}
+
+bool QD3D12TextureRenderTarget::create()
+{
+ if (rtv[0].isValid() || dsv.isValid())
+ destroy();
+
+ QRHI_RES_RHI(QRhiD3D12);
+ Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
+ Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
+ const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
+ d.colorAttCount = 0;
+ int attIndex = 0;
+
+ for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
+ d.colorAttCount += 1;
+ const QRhiColorAttachment &colorAtt(*it);
+ QRhiTexture *texture = colorAtt.texture();
+ QRhiRenderBuffer *rb = colorAtt.renderBuffer();
+ Q_ASSERT(texture || rb);
+ if (texture) {
+ QD3D12Texture *texD = QRHI_RES(QD3D12Texture, texture);
+ QD3D12Resource *res = rhiD->resourcePool.lookupRef(texD->handle);
+ if (!res) {
+ qWarning("Could not look up texture handle for render target");
+ return false;
+ }
+ const bool isMultiView = it->multiViewCount() >= 2;
+ UINT layerCount = isMultiView ? UINT(it->multiViewCount()) : 1;
+ D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
+ rtvDesc.Format = texD->rtFormat;
+ if (texD->flags().testFlag(QRhiTexture::CubeMap)) {
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
+ rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
+ rtvDesc.Texture2DArray.ArraySize = layerCount;
+ } else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
+ if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE1DARRAY;
+ rtvDesc.Texture1DArray.MipSlice = UINT(colorAtt.level());
+ rtvDesc.Texture1DArray.FirstArraySlice = UINT(colorAtt.layer());
+ rtvDesc.Texture1DArray.ArraySize = layerCount;
+ } else {
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE1D;
+ rtvDesc.Texture1D.MipSlice = UINT(colorAtt.level());
+ }
+ } else if (texD->flags().testFlag(QRhiTexture::TextureArray)) {
+ if (texD->sampleDesc.Count > 1) {
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
+ rtvDesc.Texture2DMSArray.FirstArraySlice = UINT(colorAtt.layer());
+ rtvDesc.Texture2DMSArray.ArraySize = layerCount;
+ } else {
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = UINT(colorAtt.level());
+ rtvDesc.Texture2DArray.FirstArraySlice = UINT(colorAtt.layer());
+ rtvDesc.Texture2DArray.ArraySize = layerCount;
+ }
+ } else if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = UINT(colorAtt.level());
+ rtvDesc.Texture3D.FirstWSlice = UINT(colorAtt.layer());
+ rtvDesc.Texture3D.WSize = layerCount;
+ } else {
+ if (texD->sampleDesc.Count > 1) {
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DMS;
+ } else {
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = UINT(colorAtt.level());
+ }
+ }
+ rtv[attIndex] = rhiD->rtvPool.allocate(1);
+ if (!rtv[attIndex].isValid()) {
+ qWarning("Failed to allocate RTV for texture render target");
+ return false;
+ }
+ rhiD->dev->CreateRenderTargetView(res->resource, &rtvDesc, rtv[attIndex].cpuHandle);
+ ownsRtv[attIndex] = true;
+ if (attIndex == 0) {
+ d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
+ d.sampleCount = int(texD->sampleDesc.Count);
+ }
+ } else if (rb) {
+ QD3D12RenderBuffer *rbD = QRHI_RES(QD3D12RenderBuffer, rb);
+ ownsRtv[attIndex] = false;
+ rtv[attIndex] = rbD->rtv;
+ if (attIndex == 0) {
+ d.pixelSize = rbD->pixelSize();
+ d.sampleCount = int(rbD->sampleDesc.Count);
+ }
+ }
+ }
+
+ d.dpr = 1;
+
+ if (hasDepthStencil) {
+ if (m_desc.depthTexture()) {
+ ownsDsv = true;
+ QD3D12Texture *depthTexD = QRHI_RES(QD3D12Texture, m_desc.depthTexture());
+ QD3D12Resource *res = rhiD->resourcePool.lookupRef(depthTexD->handle);
+ if (!res) {
+ qWarning("Could not look up depth texture handle");
+ return false;
+ }
+ D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
+ dsvDesc.Format = depthTexD->rtFormat;
+ dsvDesc.ViewDimension = depthTexD->sampleDesc.Count > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMS
+ : D3D12_DSV_DIMENSION_TEXTURE2D;
+ if (depthTexD->flags().testFlag(QRhiTexture::TextureArray)) {
+ if (depthTexD->sampleDesc.Count > 1) {
+ dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;
+ if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
+ dsvDesc.Texture2DMSArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
+ dsvDesc.Texture2DMSArray.ArraySize = UINT(depthTexD->arrayRangeLength());
+ } else {
+ dsvDesc.Texture2DMSArray.FirstArraySlice = 0;
+ dsvDesc.Texture2DMSArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
+ }
+ } else {
+ dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
+ if (depthTexD->arrayRangeStart() >= 0 && depthTexD->arrayRangeLength() >= 0) {
+ dsvDesc.Texture2DArray.FirstArraySlice = UINT(depthTexD->arrayRangeStart());
+ dsvDesc.Texture2DArray.ArraySize = UINT(depthTexD->arrayRangeLength());
+ } else {
+ dsvDesc.Texture2DArray.FirstArraySlice = 0;
+ dsvDesc.Texture2DArray.ArraySize = UINT(qMax(0, depthTexD->arraySize()));
+ }
+ }
+ }
+ dsv = rhiD->dsvPool.allocate(1);
+ if (!dsv.isValid()) {
+ qWarning("Failed to allocate DSV for texture render target");
+ return false;
+ }
+ rhiD->dev->CreateDepthStencilView(res->resource, &dsvDesc, dsv.cpuHandle);
+ if (d.colorAttCount == 0) {
+ d.pixelSize = depthTexD->pixelSize();
+ d.sampleCount = int(depthTexD->sampleDesc.Count);
+ }
+ } else {
+ ownsDsv = false;
+ QD3D12RenderBuffer *depthRbD = QRHI_RES(QD3D12RenderBuffer, m_desc.depthStencilBuffer());
+ dsv = depthRbD->dsv;
+ if (d.colorAttCount == 0) {
+ d.pixelSize = m_desc.depthStencilBuffer()->pixelSize();
+ d.sampleCount = int(depthRbD->sampleDesc.Count);
+ }
+ }
+ d.dsAttCount = 1;
+ } else {
+ d.dsAttCount = 0;
+ }
+
+ D3D12_CPU_DESCRIPTOR_HANDLE nullDescHandle = { 0 };
+ for (int i = 0; i < QD3D12RenderTargetData::MAX_COLOR_ATTACHMENTS; ++i)
+ d.rtv[i] = i < d.colorAttCount ? rtv[i].cpuHandle : nullDescHandle;
+ d.dsv = dsv.cpuHandle;
+ d.rp = QRHI_RES(QD3D12RenderPassDescriptor, m_renderPassDesc);
+
+ QRhiRenderTargetAttachmentTracker::updateResIdList<QD3D12Texture, QD3D12RenderBuffer>(m_desc, &d.currentResIdList);
+
+ rhiD->registerResource(this);
+ return true;
+}
+
+QSize QD3D12TextureRenderTarget::pixelSize() const
+{
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QD3D12Texture, QD3D12RenderBuffer>(m_desc, d.currentResIdList))
+ const_cast<QD3D12TextureRenderTarget *>(this)->create();
+
+ return d.pixelSize;
+}
+
+float QD3D12TextureRenderTarget::devicePixelRatio() const
+{
+ return d.dpr;
+}
+
+int QD3D12TextureRenderTarget::sampleCount() const
+{
+ return d.sampleCount;
+}
+
+QD3D12ShaderResourceBindings::QD3D12ShaderResourceBindings(QRhiImplementation *rhi)
+ : QRhiShaderResourceBindings(rhi)
+{
+}
+
+QD3D12ShaderResourceBindings::~QD3D12ShaderResourceBindings()
+{
+ destroy();
+}
+
+void QD3D12ShaderResourceBindings::destroy()
+{
+ QRHI_RES_RHI(QRhiD3D12);
+ if (rhiD)
+ rhiD->unregisterResource(this);
+}
+
+bool QD3D12ShaderResourceBindings::create()
+{
+ QRHI_RES_RHI(QRhiD3D12);
+ if (!rhiD->sanityCheckShaderResourceBindings(this))
+ return false;
+
+ rhiD->updateLayoutDesc(this);
+
+ hasDynamicOffset = false;
+ for (const QRhiShaderResourceBinding &b : std::as_const(m_bindings)) {
+ const QRhiShaderResourceBinding::Data *bd = QRhiImplementation::shaderResourceBindingData(b);
+ if (bd->type == QRhiShaderResourceBinding::UniformBuffer && bd->u.ubuf.hasDynamicOffset) {
+ hasDynamicOffset = true;
+ break;
+ }
+ }
+
+ // The root signature is not part of the srb. Unintuitive, but the shader
+ // translation pipeline ties our hands: as long as the per-shader (so per
+ // stage!) nativeResourceBindingMap exist, meaning f.ex. that a SPIR-V
+ // combined image sampler binding X passed in here may map to the tY and sY
+ // HLSL registers, where Y is known only once the mapping table from the
+ // shader is looked up. Creating a root parameters at this stage is
+ // therefore impossible.
+
+ generation += 1;
+ rhiD->registerResource(this, false);
+ return true;
+}
+
+void QD3D12ShaderResourceBindings::updateResources(UpdateFlags flags)
+{
+ Q_UNUSED(flags);
+ generation += 1;
+}
+
+// Accessing the QRhiBuffer/Texture/Sampler resources must be avoided in the
+// callbacks; that would only be possible if the srb had those specified, and
+// that's not required at the time of srb and pipeline create() time, and
+// createRootSignature is called from the pipeline create().
+
+void QD3D12ShaderResourceBindings::visitUniformBuffer(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::UniformBufferData &,
+ int shaderRegister,
+ int)
+{
+ D3D12_ROOT_PARAMETER1 rootParam = {};
+ rootParam.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+ rootParam.ShaderVisibility = qd3d12_stageToVisibility(s);
+ rootParam.Descriptor.ShaderRegister = shaderRegister;
+ rootParam.Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC;
+ visitorData.cbParams[s].append(rootParam);
+}
+
+void QD3D12ShaderResourceBindings::visitTexture(QD3D12Stage s,
+ const QRhiShaderResourceBinding::TextureAndSampler &,
+ int shaderRegister)
+{
+ D3D12_DESCRIPTOR_RANGE1 range = {};
+ range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ range.NumDescriptors = 1;
+ range.BaseShaderRegister = shaderRegister;
+ range.OffsetInDescriptorsFromTableStart = visitorData.currentSrvRangeOffset[s];
+ visitorData.currentSrvRangeOffset[s] += 1;
+ visitorData.srvRanges[s].append(range);
+ if (visitorData.srvRanges[s].count() == 1) {
+ visitorData.srvTables[s].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ visitorData.srvTables[s].ShaderVisibility = qd3d12_stageToVisibility(s);
+ }
+}
+
+void QD3D12ShaderResourceBindings::visitSampler(QD3D12Stage s,
+ const QRhiShaderResourceBinding::TextureAndSampler &,
+ int shaderRegister)
+{
+ // Unlike SRVs and UAVs, samplers are handled so that each sampler becomes
+ // a root parameter with its own descriptor table.
+
+ int &rangeStoreIdx(visitorData.samplerRangeHeads[s]);
+ if (rangeStoreIdx == 16) {
+ qWarning("Sampler count in QD3D12Stage %d exceeds the limit of 16, this is disallowed by QRhi", s);
+ return;
+ }
+ D3D12_DESCRIPTOR_RANGE1 range = {};
+ range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
+ range.NumDescriptors = 1;
+ range.BaseShaderRegister = shaderRegister;
+ visitorData.samplerRanges[s][rangeStoreIdx] = range;
+ D3D12_ROOT_PARAMETER1 param = {};
+ param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ param.ShaderVisibility = qd3d12_stageToVisibility(s);
+ param.DescriptorTable.NumDescriptorRanges = 1;
+ param.DescriptorTable.pDescriptorRanges = &visitorData.samplerRanges[s][rangeStoreIdx];
+ rangeStoreIdx += 1;
+ visitorData.samplerTables[s].append(param);
+}
+
+void QD3D12ShaderResourceBindings::visitStorageBuffer(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::StorageBufferData &,
+ QD3D12ShaderResourceVisitor::StorageOp,
+ int shaderRegister)
+{
+ D3D12_DESCRIPTOR_RANGE1 range = {};
+ range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
+ range.NumDescriptors = 1;
+ range.BaseShaderRegister = shaderRegister;
+ range.OffsetInDescriptorsFromTableStart = visitorData.currentUavRangeOffset[s];
+ visitorData.currentUavRangeOffset[s] += 1;
+ visitorData.uavRanges[s].append(range);
+ if (visitorData.uavRanges[s].count() == 1) {
+ visitorData.uavTables[s].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ visitorData.uavTables[s].ShaderVisibility = qd3d12_stageToVisibility(s);
+ }
+}
+
+void QD3D12ShaderResourceBindings::visitStorageImage(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::StorageImageData &,
+ QD3D12ShaderResourceVisitor::StorageOp,
+ int shaderRegister)
+{
+ D3D12_DESCRIPTOR_RANGE1 range = {};
+ range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
+ range.NumDescriptors = 1;
+ range.BaseShaderRegister = shaderRegister;
+ range.OffsetInDescriptorsFromTableStart = visitorData.currentUavRangeOffset[s];
+ visitorData.currentUavRangeOffset[s] += 1;
+ visitorData.uavRanges[s].append(range);
+ if (visitorData.uavRanges[s].count() == 1) {
+ visitorData.uavTables[s].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ visitorData.uavTables[s].ShaderVisibility = qd3d12_stageToVisibility(s);
+ }
+}
+
+QD3D12ObjectHandle QD3D12ShaderResourceBindings::createRootSignature(const QD3D12ShaderStageData *stageData,
+ int stageCount)
+{
+ QRHI_RES_RHI(QRhiD3D12);
+
+ // It's not just that the root signature has to be tied to the pipeline
+ // (cannot just freely create it like e.g. with Vulkan where one just
+ // creates a descriptor layout 1:1 with the QRhiShaderResourceBindings'
+ // data), due to not knowing the shader-specific resource binding mapping
+ // tables at the point of srb creation, but each shader stage may have a
+ // different mapping table. (ugh!)
+ //
+ // Hence we set up everything per-stage, even if it means the root
+ // signature gets unnecessarily big. (note that the magic is in the
+ // ShaderVisibility: even though the register range is the same in the
+ // descriptor tables, the visibility is different)
+
+ QD3D12ShaderResourceVisitor visitor(this, stageData, stageCount);
+
+ visitorData = {};
+
+ using namespace std::placeholders;
+ visitor.uniformBuffer = std::bind(&QD3D12ShaderResourceBindings::visitUniformBuffer, this, _1, _2, _3, _4);
+ visitor.texture = std::bind(&QD3D12ShaderResourceBindings::visitTexture, this, _1, _2, _3);
+ visitor.sampler = std::bind(&QD3D12ShaderResourceBindings::visitSampler, this, _1, _2, _3);
+ visitor.storageBuffer = std::bind(&QD3D12ShaderResourceBindings::visitStorageBuffer, this, _1, _2, _3, _4);
+ visitor.storageImage = std::bind(&QD3D12ShaderResourceBindings::visitStorageImage, this, _1, _2, _3, _4);
+
+ visitor.visit();
+
+ // The maximum size of a root signature is 256 bytes, where a descriptor
+ // table is 4, a root descriptor (e.g. CBV) is 8. We have 5 stages at most
+ // (or 1 with compute) and a separate descriptor table for SRVs (->
+ // textures) and UAVs (-> storage buffers and images) per stage, plus each
+ // uniform buffer counts as a CBV in the stages it is visible.
+ //
+ // Due to the limited maximum size of a shader-visible sampler heap (2048)
+ // and the potential costly switching of descriptor heaps, each sampler is
+ // declared as a separate root parameter / descriptor table (meaning that
+ // two samplers in the same stage are two parameters and two tables, not
+ // just one). QRhi documents a hard limit of 16 on texture/sampler bindings
+ // in a shader (matching D3D11), so we can hopefully get away with this.
+ //
+ // This means that e.g. a vertex+fragment shader with a uniform buffer
+ // visible in both and one texture+sampler in the fragment shader would
+ // consume 2*8 + 4 + 4 = 24 bytes. This also implies that clients
+ // specifying the minimal stage bit mask for each entry in
+ // QRhiShaderResourceBindings are ideal for this backend since it helps
+ // reducing the chance of hitting the size limit.
+
+ QVarLengthArray<D3D12_ROOT_PARAMETER1, 4> rootParams;
+ for (int s = 0; s < 6; ++s) {
+ if (!visitorData.cbParams[s].isEmpty())
+ rootParams.append(visitorData.cbParams[s].constData(), visitorData.cbParams[s].count());
+ }
+ for (int s = 0; s < 6; ++s) {
+ if (!visitorData.srvRanges[s].isEmpty()) {
+ visitorData.srvTables[s].DescriptorTable.NumDescriptorRanges = visitorData.srvRanges[s].count();
+ visitorData.srvTables[s].DescriptorTable.pDescriptorRanges = visitorData.srvRanges[s].constData();
+ rootParams.append(visitorData.srvTables[s]);
+ }
+ }
+ for (int s = 0; s < 6; ++s) {
+ if (!visitorData.samplerTables[s].isEmpty())
+ rootParams.append(visitorData.samplerTables[s].constData(), visitorData.samplerTables[s].count());
+ }
+ for (int s = 0; s < 6; ++s) {
+ if (!visitorData.uavRanges[s].isEmpty()) {
+ visitorData.uavTables[s].DescriptorTable.NumDescriptorRanges = visitorData.uavRanges[s].count();
+ visitorData.uavTables[s].DescriptorTable.pDescriptorRanges = visitorData.uavRanges[s].constData();
+ rootParams.append(visitorData.uavTables[s]);
+ }
+ }
+
+ D3D12_VERSIONED_ROOT_SIGNATURE_DESC rsDesc = {};
+ rsDesc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1;
+ if (!rootParams.isEmpty()) {
+ rsDesc.Desc_1_1.NumParameters = rootParams.count();
+ rsDesc.Desc_1_1.pParameters = rootParams.constData();
+ }
+
+ UINT rsFlags = 0;
+ for (int stageIdx = 0; stageIdx < stageCount; ++stageIdx) {
+ if (stageData[stageIdx].valid && stageData[stageIdx].stage == VS)
+ rsFlags |= D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
+ }
+ rsDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAGS(rsFlags);
+
+ ID3DBlob *signature = nullptr;
+ HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
+ if (FAILED(hr)) {
+ qWarning("Failed to serialize root signature: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return {};
+ }
+ ID3D12RootSignature *rootSig = nullptr;
+ hr = rhiD->dev->CreateRootSignature(0,
+ signature->GetBufferPointer(),
+ signature->GetBufferSize(),
+ __uuidof(ID3D12RootSignature),
+ reinterpret_cast<void **>(&rootSig));
+ signature->Release();
+ if (FAILED(hr)) {
+ qWarning("Failed to create root signature: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return {};
+ }
+
+ return QD3D12RootSignature::addToPool(&rhiD->rootSignaturePool, rootSig);
+}
+
+// For shader model < 6.0 we do the same as the D3D11 backend: use the old
+// compiler (D3DCompile) to generate DXBC, just as qsb does (when -c is passed)
+// by invoking fxc, not dxc. For SM >= 6.0 we have to use the new compiler and
+// work with DXIL. And that involves IDxcCompiler and needs the presence of
+// dxcompiler.dll and dxil.dll at runtime. Plus there's a chance we have
+// ancient SDK headers when not using MSVC. So this is heavily optional,
+// meaning support for dxc can be disabled both at build time (no dxcapi.h) and
+// at run time (no DLLs).
+
+static inline void makeHlslTargetString(char target[7], const char stage[3], int version)
+{
+ const int smMajor = version / 10;
+ const int smMinor = version % 10;
+ target[0] = stage[0];
+ target[1] = stage[1];
+ target[2] = '_';
+ target[3] = '0' + smMajor;
+ target[4] = '_';
+ target[5] = '0' + smMinor;
+ target[6] = '\0';
+}
+
+enum class HlslCompileFlag
+{
+ WithDebugInfo = 0x01
+};
+
+static QByteArray legacyCompile(const QShaderCode &hlslSource, const char *target, int flags, QString *error)
+{
+ static const pD3DCompile d3dCompile = QRhiD3D::resolveD3DCompile();
+ if (!d3dCompile) {
+ qWarning("Unable to resolve function D3DCompile()");
+ return QByteArray();
+ }
+
+ ID3DBlob *bytecode = nullptr;
+ ID3DBlob *errors = nullptr;
+ UINT d3dCompileFlags = 0;
+ if (flags & int(HlslCompileFlag::WithDebugInfo))
+ d3dCompileFlags |= D3DCOMPILE_DEBUG;
+
+ HRESULT hr = d3dCompile(hlslSource.shader().constData(), SIZE_T(hlslSource.shader().size()),
+ nullptr, nullptr, nullptr,
+ hlslSource.entryPoint().constData(), target, d3dCompileFlags, 0, &bytecode, &errors);
+ if (FAILED(hr) || !bytecode) {
+ qWarning("HLSL shader compilation failed: 0x%x", uint(hr));
+ if (errors) {
+ *error = QString::fromUtf8(static_cast<const char *>(errors->GetBufferPointer()),
+ int(errors->GetBufferSize()));
+ errors->Release();
+ }
+ return QByteArray();
+ }
+
+ QByteArray result;
+ result.resize(int(bytecode->GetBufferSize()));
+ memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
+ bytecode->Release();
+ return result;
+}
+
+#ifdef QRHI_D3D12_HAS_DXC
+
+#ifndef DXC_CP_UTF8
+#define DXC_CP_UTF8 65001
+#endif
+
+#ifndef DXC_ARG_DEBUG
+#define DXC_ARG_DEBUG L"-Zi"
+#endif
+
+static QByteArray dxcCompile(const QShaderCode &hlslSource, const char *target, int flags, QString *error)
+{
+ static std::pair<IDxcCompiler *, IDxcLibrary *> dxc = QRhiD3D::createDxcCompiler();
+ IDxcCompiler *compiler = dxc.first;
+ if (!compiler) {
+ qWarning("Unable to instantiate IDxcCompiler. Likely no dxcompiler.dll and dxil.dll present. "
+ "Use windeployqt or try https://github.com/microsoft/DirectXShaderCompiler/releases");
+ return QByteArray();
+ }
+ IDxcLibrary *library = dxc.second;
+ if (!library)
+ return QByteArray();
+
+ IDxcBlobEncoding *sourceBlob = nullptr;
+ HRESULT hr = library->CreateBlobWithEncodingOnHeapCopy(hlslSource.shader().constData(),
+ UINT32(hlslSource.shader().size()),
+ DXC_CP_UTF8,
+ &sourceBlob);
+ if (FAILED(hr)) {
+ qWarning("Failed to create source blob for dxc: 0x%x (%s)",
+ uint(hr),
+ qPrintable(QSystemError::windowsComString(hr)));
+ return QByteArray();
+ }
+
+ const QString entryPointStr = QString::fromLatin1(hlslSource.entryPoint());
+ const QString targetStr = QString::fromLatin1(target);
+
+ QVarLengthArray<LPCWSTR, 4> argPtrs;
+ QString debugArg;
+ if (flags & int(HlslCompileFlag::WithDebugInfo)) {
+ debugArg = QString::fromUtf16(reinterpret_cast<const char16_t *>(DXC_ARG_DEBUG));
+ argPtrs.append(reinterpret_cast<LPCWSTR>(debugArg.utf16()));
+ }
+
+ IDxcOperationResult *result = nullptr;
+ hr = compiler->Compile(sourceBlob,
+ nullptr,
+ reinterpret_cast<LPCWSTR>(entryPointStr.utf16()),
+ reinterpret_cast<LPCWSTR>(targetStr.utf16()),
+ argPtrs.data(), argPtrs.count(),
+ nullptr, 0,
+ nullptr,
+ &result);
+ sourceBlob->Release();
+ if (SUCCEEDED(hr))
+ result->GetStatus(&hr);
+ if (FAILED(hr)) {
+ qWarning("HLSL shader compilation failed: 0x%x (%s)",
+ uint(hr),
+ qPrintable(QSystemError::windowsComString(hr)));
+ if (result) {
+ IDxcBlobEncoding *errorsBlob = nullptr;
+ if (SUCCEEDED(result->GetErrorBuffer(&errorsBlob))) {
+ if (errorsBlob) {
+ *error = QString::fromUtf8(static_cast<const char *>(errorsBlob->GetBufferPointer()),
+ int(errorsBlob->GetBufferSize()));
+ errorsBlob->Release();
+ }
+ }
+ }
+ return QByteArray();
+ }
+
+ IDxcBlob *bytecode = nullptr;
+ if FAILED(result->GetResult(&bytecode)) {
+ qWarning("No result from IDxcCompiler: 0x%x (%s)",
+ uint(hr),
+ qPrintable(QSystemError::windowsComString(hr)));
+ return QByteArray();
+ }
+
+ QByteArray ba;
+ ba.resize(int(bytecode->GetBufferSize()));
+ memcpy(ba.data(), bytecode->GetBufferPointer(), size_t(ba.size()));
+ bytecode->Release();
+ return ba;
+}
+
+#endif // QRHI_D3D12_HAS_DXC
+
+static QByteArray compileHlslShaderSource(const QShader &shader,
+ QShader::Variant shaderVariant,
+ int flags,
+ QString *error,
+ QShaderKey *usedShaderKey)
+{
+ // look for SM 6.7, 6.6, .., 5.0
+ const int shaderModelMax = 67;
+ for (int sm = shaderModelMax; sm >= 50; --sm) {
+ for (QShader::Source type : { QShader::DxilShader, QShader::DxbcShader }) {
+ QShaderKey key = { type, sm, shaderVariant };
+ QShaderCode intermediateBytecodeShader = shader.shader(key);
+ if (!intermediateBytecodeShader.shader().isEmpty()) {
+ if (usedShaderKey)
+ *usedShaderKey = key;
+ return intermediateBytecodeShader.shader();
+ }
+ }
+ }
+
+ QShaderCode hlslSource;
+ QShaderKey key;
+ for (int sm = shaderModelMax; sm >= 50; --sm) {
+ key = { QShader::HlslShader, sm, shaderVariant };
+ hlslSource = shader.shader(key);
+ if (!hlslSource.shader().isEmpty())
+ break;
+ }
+
+ if (hlslSource.shader().isEmpty()) {
+ qWarning() << "No HLSL (shader model 6.7..5.0) code found in baked shader" << shader;
+ return QByteArray();
+ }
+
+ if (usedShaderKey)
+ *usedShaderKey = key;
+
+ char target[7];
+ switch (shader.stage()) {
+ case QShader::VertexStage:
+ makeHlslTargetString(target, "vs", key.sourceVersion().version());
+ break;
+ case QShader::TessellationControlStage:
+ makeHlslTargetString(target, "hs", key.sourceVersion().version());
+ break;
+ case QShader::TessellationEvaluationStage:
+ makeHlslTargetString(target, "ds", key.sourceVersion().version());
+ break;
+ case QShader::GeometryStage:
+ makeHlslTargetString(target, "gs", key.sourceVersion().version());
+ break;
+ case QShader::FragmentStage:
+ makeHlslTargetString(target, "ps", key.sourceVersion().version());
+ break;
+ case QShader::ComputeStage:
+ makeHlslTargetString(target, "cs", key.sourceVersion().version());
+ break;
+ }
+
+ if (key.sourceVersion().version() >= 60) {
+#ifdef QRHI_D3D12_HAS_DXC
+ return dxcCompile(hlslSource, target, flags, error);
+#else
+ qWarning("Attempted to runtime-compile HLSL source code for shader model >= 6.0 "
+ "but the Qt build has no support for DXC. "
+ "Rebuild Qt with a recent Windows SDK or switch to an MSVC build.");
+#endif
+ }
+
+ return legacyCompile(hlslSource, target, flags, error);
+}
+
+static inline UINT8 toD3DColorWriteMask(QRhiGraphicsPipeline::ColorMask c)
+{
+ UINT8 f = 0;
+ if (c.testFlag(QRhiGraphicsPipeline::R))
+ f |= D3D12_COLOR_WRITE_ENABLE_RED;
+ if (c.testFlag(QRhiGraphicsPipeline::G))
+ f |= D3D12_COLOR_WRITE_ENABLE_GREEN;
+ if (c.testFlag(QRhiGraphicsPipeline::B))
+ f |= D3D12_COLOR_WRITE_ENABLE_BLUE;
+ if (c.testFlag(QRhiGraphicsPipeline::A))
+ f |= D3D12_COLOR_WRITE_ENABLE_ALPHA;
+ return f;
+}
+
+static inline D3D12_BLEND toD3DBlendFactor(QRhiGraphicsPipeline::BlendFactor f, bool rgb)
+{
+ // SrcBlendAlpha and DstBlendAlpha do not accept *_COLOR. With other APIs
+ // this is handled internally (so that e.g. VK_BLEND_FACTOR_SRC_COLOR is
+ // accepted and is in effect equivalent to VK_BLEND_FACTOR_SRC_ALPHA when
+ // set as an alpha src/dest factor), but for D3D we have to take care of it
+ // ourselves. Hence the rgb argument.
+
+ switch (f) {
+ case QRhiGraphicsPipeline::Zero:
+ return D3D12_BLEND_ZERO;
+ case QRhiGraphicsPipeline::One:
+ return D3D12_BLEND_ONE;
+ case QRhiGraphicsPipeline::SrcColor:
+ return rgb ? D3D12_BLEND_SRC_COLOR : D3D12_BLEND_SRC_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusSrcColor:
+ return rgb ? D3D12_BLEND_INV_SRC_COLOR : D3D12_BLEND_INV_SRC_ALPHA;
+ case QRhiGraphicsPipeline::DstColor:
+ return rgb ? D3D12_BLEND_DEST_COLOR : D3D12_BLEND_DEST_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusDstColor:
+ return rgb ? D3D12_BLEND_INV_DEST_COLOR : D3D12_BLEND_INV_DEST_ALPHA;
+ case QRhiGraphicsPipeline::SrcAlpha:
+ return D3D12_BLEND_SRC_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusSrcAlpha:
+ return D3D12_BLEND_INV_SRC_ALPHA;
+ case QRhiGraphicsPipeline::DstAlpha:
+ return D3D12_BLEND_DEST_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusDstAlpha:
+ return D3D12_BLEND_INV_DEST_ALPHA;
+ case QRhiGraphicsPipeline::ConstantColor:
+ case QRhiGraphicsPipeline::ConstantAlpha:
+ return D3D12_BLEND_BLEND_FACTOR;
+ case QRhiGraphicsPipeline::OneMinusConstantColor:
+ case QRhiGraphicsPipeline::OneMinusConstantAlpha:
+ return D3D12_BLEND_INV_BLEND_FACTOR;
+ case QRhiGraphicsPipeline::SrcAlphaSaturate:
+ return D3D12_BLEND_SRC_ALPHA_SAT;
+ case QRhiGraphicsPipeline::Src1Color:
+ return rgb ? D3D12_BLEND_SRC1_COLOR : D3D12_BLEND_SRC1_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusSrc1Color:
+ return rgb ? D3D12_BLEND_INV_SRC1_COLOR : D3D12_BLEND_INV_SRC1_ALPHA;
+ case QRhiGraphicsPipeline::Src1Alpha:
+ return D3D12_BLEND_SRC1_ALPHA;
+ case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
+ return D3D12_BLEND_INV_SRC1_ALPHA;
+ }
+ Q_UNREACHABLE_RETURN(D3D12_BLEND_ZERO);
+}
+
+static inline D3D12_BLEND_OP toD3DBlendOp(QRhiGraphicsPipeline::BlendOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::Add:
+ return D3D12_BLEND_OP_ADD;
+ case QRhiGraphicsPipeline::Subtract:
+ return D3D12_BLEND_OP_SUBTRACT;
+ case QRhiGraphicsPipeline::ReverseSubtract:
+ return D3D12_BLEND_OP_REV_SUBTRACT;
+ case QRhiGraphicsPipeline::Min:
+ return D3D12_BLEND_OP_MIN;
+ case QRhiGraphicsPipeline::Max:
+ return D3D12_BLEND_OP_MAX;
+ }
+ Q_UNREACHABLE_RETURN(D3D12_BLEND_OP_ADD);
+}
+
+static inline D3D12_CULL_MODE toD3DCullMode(QRhiGraphicsPipeline::CullMode c)
+{
+ switch (c) {
+ case QRhiGraphicsPipeline::None:
+ return D3D12_CULL_MODE_NONE;
+ case QRhiGraphicsPipeline::Front:
+ return D3D12_CULL_MODE_FRONT;
+ case QRhiGraphicsPipeline::Back:
+ return D3D12_CULL_MODE_BACK;
+ }
+ Q_UNREACHABLE_RETURN(D3D12_CULL_MODE_NONE);
+}
+
+static inline D3D12_FILL_MODE toD3DFillMode(QRhiGraphicsPipeline::PolygonMode mode)
+{
+ switch (mode) {
+ case QRhiGraphicsPipeline::Fill:
+ return D3D12_FILL_MODE_SOLID;
+ case QRhiGraphicsPipeline::Line:
+ return D3D12_FILL_MODE_WIREFRAME;
+ }
+ Q_UNREACHABLE_RETURN(D3D12_FILL_MODE_SOLID);
+}
+
+static inline D3D12_COMPARISON_FUNC toD3DCompareOp(QRhiGraphicsPipeline::CompareOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::Never:
+ return D3D12_COMPARISON_FUNC_NEVER;
+ case QRhiGraphicsPipeline::Less:
+ return D3D12_COMPARISON_FUNC_LESS;
+ case QRhiGraphicsPipeline::Equal:
+ return D3D12_COMPARISON_FUNC_EQUAL;
+ case QRhiGraphicsPipeline::LessOrEqual:
+ return D3D12_COMPARISON_FUNC_LESS_EQUAL;
+ case QRhiGraphicsPipeline::Greater:
+ return D3D12_COMPARISON_FUNC_GREATER;
+ case QRhiGraphicsPipeline::NotEqual:
+ return D3D12_COMPARISON_FUNC_NOT_EQUAL;
+ case QRhiGraphicsPipeline::GreaterOrEqual:
+ return D3D12_COMPARISON_FUNC_GREATER_EQUAL;
+ case QRhiGraphicsPipeline::Always:
+ return D3D12_COMPARISON_FUNC_ALWAYS;
+ }
+ Q_UNREACHABLE_RETURN(D3D12_COMPARISON_FUNC_ALWAYS);
+}
+
+static inline D3D12_STENCIL_OP toD3DStencilOp(QRhiGraphicsPipeline::StencilOp op)
+{
+ switch (op) {
+ case QRhiGraphicsPipeline::StencilZero:
+ return D3D12_STENCIL_OP_ZERO;
+ case QRhiGraphicsPipeline::Keep:
+ return D3D12_STENCIL_OP_KEEP;
+ case QRhiGraphicsPipeline::Replace:
+ return D3D12_STENCIL_OP_REPLACE;
+ case QRhiGraphicsPipeline::IncrementAndClamp:
+ return D3D12_STENCIL_OP_INCR_SAT;
+ case QRhiGraphicsPipeline::DecrementAndClamp:
+ return D3D12_STENCIL_OP_DECR_SAT;
+ case QRhiGraphicsPipeline::Invert:
+ return D3D12_STENCIL_OP_INVERT;
+ case QRhiGraphicsPipeline::IncrementAndWrap:
+ return D3D12_STENCIL_OP_INCR;
+ case QRhiGraphicsPipeline::DecrementAndWrap:
+ return D3D12_STENCIL_OP_DECR;
+ }
+ Q_UNREACHABLE_RETURN(D3D12_STENCIL_OP_KEEP);
+}
+
+static inline D3D12_PRIMITIVE_TOPOLOGY toD3DTopology(QRhiGraphicsPipeline::Topology t, int patchControlPointCount)
+{
+ switch (t) {
+ case QRhiGraphicsPipeline::Triangles:
+ return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ case QRhiGraphicsPipeline::TriangleStrip:
+ return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+ case QRhiGraphicsPipeline::TriangleFan:
+ qWarning("Triangle fans are not supported with D3D");
+ return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+ case QRhiGraphicsPipeline::Lines:
+ return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
+ case QRhiGraphicsPipeline::LineStrip:
+ return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
+ case QRhiGraphicsPipeline::Points:
+ return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
+ case QRhiGraphicsPipeline::Patches:
+ Q_ASSERT(patchControlPointCount >= 1 && patchControlPointCount <= 32);
+ return D3D_PRIMITIVE_TOPOLOGY(D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST + (patchControlPointCount - 1));
+ }
+ Q_UNREACHABLE_RETURN(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+}
+
+static inline D3D12_PRIMITIVE_TOPOLOGY_TYPE toD3DTopologyType(QRhiGraphicsPipeline::Topology t)
+{
+ switch (t) {
+ case QRhiGraphicsPipeline::Triangles:
+ case QRhiGraphicsPipeline::TriangleStrip:
+ case QRhiGraphicsPipeline::TriangleFan:
+ return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+ case QRhiGraphicsPipeline::Lines:
+ case QRhiGraphicsPipeline::LineStrip:
+ return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
+ case QRhiGraphicsPipeline::Points:
+ return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
+ case QRhiGraphicsPipeline::Patches:
+ return D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
+ }
+ Q_UNREACHABLE_RETURN(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);
+}
+
+static inline DXGI_FORMAT toD3DAttributeFormat(QRhiVertexInputAttribute::Format format)
+{
+ switch (format) {
+ case QRhiVertexInputAttribute::Float4:
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ case QRhiVertexInputAttribute::Float3:
+ return DXGI_FORMAT_R32G32B32_FLOAT;
+ case QRhiVertexInputAttribute::Float2:
+ return DXGI_FORMAT_R32G32_FLOAT;
+ case QRhiVertexInputAttribute::Float:
+ return DXGI_FORMAT_R32_FLOAT;
+ case QRhiVertexInputAttribute::UNormByte4:
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+ case QRhiVertexInputAttribute::UNormByte2:
+ return DXGI_FORMAT_R8G8_UNORM;
+ case QRhiVertexInputAttribute::UNormByte:
+ return DXGI_FORMAT_R8_UNORM;
+ case QRhiVertexInputAttribute::UInt4:
+ return DXGI_FORMAT_R32G32B32A32_UINT;
+ case QRhiVertexInputAttribute::UInt3:
+ return DXGI_FORMAT_R32G32B32_UINT;
+ case QRhiVertexInputAttribute::UInt2:
+ return DXGI_FORMAT_R32G32_UINT;
+ case QRhiVertexInputAttribute::UInt:
+ return DXGI_FORMAT_R32_UINT;
+ case QRhiVertexInputAttribute::SInt4:
+ return DXGI_FORMAT_R32G32B32A32_SINT;
+ case QRhiVertexInputAttribute::SInt3:
+ return DXGI_FORMAT_R32G32B32_SINT;
+ case QRhiVertexInputAttribute::SInt2:
+ return DXGI_FORMAT_R32G32_SINT;
+ case QRhiVertexInputAttribute::SInt:
+ return DXGI_FORMAT_R32_SINT;
+ case QRhiVertexInputAttribute::Half4:
+ // Note: D3D does not support half3. Pass through half3 as half4.
+ case QRhiVertexInputAttribute::Half3:
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+ case QRhiVertexInputAttribute::Half2:
+ return DXGI_FORMAT_R16G16_FLOAT;
+ case QRhiVertexInputAttribute::Half:
+ return DXGI_FORMAT_R16_FLOAT;
+ case QRhiVertexInputAttribute::UShort4:
+ // Note: D3D does not support UShort3. Pass through UShort3 as UShort4.
+ case QRhiVertexInputAttribute::UShort3:
+ return DXGI_FORMAT_R16G16B16A16_UINT;
+ case QRhiVertexInputAttribute::UShort2:
+ return DXGI_FORMAT_R16G16_UINT;
+ case QRhiVertexInputAttribute::UShort:
+ return DXGI_FORMAT_R16_UINT;
+ case QRhiVertexInputAttribute::SShort4:
+ // Note: D3D does not support SShort3. Pass through SShort3 as SShort4.
+ case QRhiVertexInputAttribute::SShort3:
+ return DXGI_FORMAT_R16G16B16A16_SINT;
+ case QRhiVertexInputAttribute::SShort2:
+ return DXGI_FORMAT_R16G16_SINT;
+ case QRhiVertexInputAttribute::SShort:
+ return DXGI_FORMAT_R16_SINT;
+ }
+ Q_UNREACHABLE_RETURN(DXGI_FORMAT_R32G32B32A32_FLOAT);
+}
+
+QD3D12GraphicsPipeline::QD3D12GraphicsPipeline(QRhiImplementation *rhi)
+ : QRhiGraphicsPipeline(rhi)
+{
+}
+
+QD3D12GraphicsPipeline::~QD3D12GraphicsPipeline()
+{
+ destroy();
+}
+
+void QD3D12GraphicsPipeline::destroy()
+{
+ if (handle.isNull())
+ return;
+
+ QRHI_RES_RHI(QRhiD3D12);
+ if (rhiD) {
+ rhiD->releaseQueue.deferredReleasePipeline(handle);
+ rhiD->releaseQueue.deferredReleaseRootSignature(rootSigHandle);
+ }
+
+ handle = {};
+ stageData = {};
+
+ if (rhiD)
+ rhiD->unregisterResource(this);
+}
+
+bool QD3D12GraphicsPipeline::create()
+{
+ if (!handle.isNull())
+ destroy();
+
+ QRHI_RES_RHI(QRhiD3D12);
+ if (!rhiD->sanityCheckGraphicsPipeline(this))
+ return false;
+
+ rhiD->pipelineCreationStart();
+
+ QByteArray shaderBytecode[5];
+ for (const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
+ const QD3D12Stage d3dStage = qd3d12_stage(shaderStage.type());
+ stageData[d3dStage].valid = true;
+ stageData[d3dStage].stage = d3dStage;
+ auto cacheIt = rhiD->shaderBytecodeCache.data.constFind(shaderStage);
+ if (cacheIt != rhiD->shaderBytecodeCache.data.constEnd()) {
+ shaderBytecode[d3dStage] = cacheIt->bytecode;
+ stageData[d3dStage].nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
+ } else {
+ QString error;
+ QShaderKey shaderKey;
+ int compileFlags = 0;
+ if (m_flags.testFlag(CompileShadersWithDebugInfo))
+ compileFlags |= int(HlslCompileFlag::WithDebugInfo);
+ const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(),
+ shaderStage.shaderVariant(),
+ compileFlags,
+ &error,
+ &shaderKey);
+ if (bytecode.isEmpty()) {
+ qWarning("HLSL graphics shader compilation failed: %s", qPrintable(error));
+ return false;
+ }
+
+ shaderBytecode[d3dStage] = bytecode;
+ stageData[d3dStage].nativeResourceBindingMap = shaderStage.shader().nativeResourceBindingMap(shaderKey);
+ rhiD->shaderBytecodeCache.insertWithCapacityLimit(shaderStage,
+ { bytecode, stageData[d3dStage].nativeResourceBindingMap });
+ }
+ }
+
+ QD3D12ShaderResourceBindings *srbD = QRHI_RES(QD3D12ShaderResourceBindings, m_shaderResourceBindings);
+ if (srbD) {
+ rootSigHandle = srbD->createRootSignature(stageData.data(), 5);
+ if (rootSigHandle.isNull()) {
+ qWarning("Failed to create root signature");
+ return false;
+ }
+ }
+ ID3D12RootSignature *rootSig = nullptr;
+ if (QD3D12RootSignature *rs = rhiD->rootSignaturePool.lookupRef(rootSigHandle))
+ rootSig = rs->rootSig;
+ if (!rootSig) {
+ qWarning("Cannot create graphics pipeline state without root signature");
+ return false;
+ }
+
+ QD3D12RenderPassDescriptor *rpD = QRHI_RES(QD3D12RenderPassDescriptor, m_renderPassDesc);
+ const DXGI_SAMPLE_DESC sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, DXGI_FORMAT(rpD->colorFormat[0]));
+
+ struct {
+ QD3D12PipelineStateSubObject<ID3D12RootSignature *, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> rootSig;
+ QD3D12PipelineStateSubObject<D3D12_INPUT_LAYOUT_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_INPUT_LAYOUT> inputLayout;
+ QD3D12PipelineStateSubObject<D3D12_PRIMITIVE_TOPOLOGY_TYPE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PRIMITIVE_TOPOLOGY> primitiveTopology;
+ QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VS> VS;
+ QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS> HS;
+ QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS> DS;
+ QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_GS> GS;
+ QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS> PS;
+ QD3D12PipelineStateSubObject<D3D12_RASTERIZER_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER> rasterizerState;
+ QD3D12PipelineStateSubObject<D3D12_DEPTH_STENCIL_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL> depthStencilState;
+ QD3D12PipelineStateSubObject<D3D12_BLEND_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND> blendState;
+ QD3D12PipelineStateSubObject<D3D12_RT_FORMAT_ARRAY, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS> rtFormats;
+ QD3D12PipelineStateSubObject<DXGI_FORMAT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT> dsFormat;
+ QD3D12PipelineStateSubObject<DXGI_SAMPLE_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC> sampleDesc;
+ QD3D12PipelineStateSubObject<UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK> sampleMask;
+ QD3D12PipelineStateSubObject<D3D12_VIEW_INSTANCING_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VIEW_INSTANCING> viewInstancingDesc;
+ } stream;
+
+ stream.rootSig.object = rootSig;
+
+ QVarLengthArray<D3D12_INPUT_ELEMENT_DESC, 4> inputDescs;
+ QByteArrayList matrixSliceSemantics;
+ if (!shaderBytecode[VS].isEmpty()) {
+ for (auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
+ it != itEnd; ++it)
+ {
+ D3D12_INPUT_ELEMENT_DESC desc = {};
+ // The output from SPIRV-Cross uses TEXCOORD<location> as the
+ // semantic, except for matrices that are unrolled into consecutive
+ // vec2/3/4s attributes and need TEXCOORD<location>_ as
+ // SemanticName and row/column index as SemanticIndex.
+ const int matrixSlice = it->matrixSlice();
+ if (matrixSlice < 0) {
+ desc.SemanticName = "TEXCOORD";
+ desc.SemanticIndex = UINT(it->location());
+ } else {
+ QByteArray sem;
+ sem.resize(16);
+ qsnprintf(sem.data(), sem.size(), "TEXCOORD%d_", it->location() - matrixSlice);
+ matrixSliceSemantics.append(sem);
+ desc.SemanticName = matrixSliceSemantics.last().constData();
+ desc.SemanticIndex = UINT(matrixSlice);
+ }
+ desc.Format = toD3DAttributeFormat(it->format());
+ desc.InputSlot = UINT(it->binding());
+ desc.AlignedByteOffset = it->offset();
+ const QRhiVertexInputBinding *inputBinding = m_vertexInputLayout.bindingAt(it->binding());
+ if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance) {
+ desc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
+ desc.InstanceDataStepRate = inputBinding->instanceStepRate();
+ } else {
+ desc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
+ }
+ inputDescs.append(desc);
+ }
+ }
+
+ stream.inputLayout.object.NumElements = inputDescs.count();
+ stream.inputLayout.object.pInputElementDescs = inputDescs.isEmpty() ? nullptr : inputDescs.constData();
+
+ stream.primitiveTopology.object = toD3DTopologyType(m_topology);
+ topology = toD3DTopology(m_topology, m_patchControlPointCount);
+
+ for (const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
+ const int d3dStage = qd3d12_stage(shaderStage.type());
+ switch (d3dStage) {
+ case VS:
+ stream.VS.object.pShaderBytecode = shaderBytecode[d3dStage].constData();
+ stream.VS.object.BytecodeLength = shaderBytecode[d3dStage].size();
+ break;
+ case HS:
+ stream.HS.object.pShaderBytecode = shaderBytecode[d3dStage].constData();
+ stream.HS.object.BytecodeLength = shaderBytecode[d3dStage].size();
+ break;
+ case DS:
+ stream.DS.object.pShaderBytecode = shaderBytecode[d3dStage].constData();
+ stream.DS.object.BytecodeLength = shaderBytecode[d3dStage].size();
+ break;
+ case GS:
+ stream.GS.object.pShaderBytecode = shaderBytecode[d3dStage].constData();
+ stream.GS.object.BytecodeLength = shaderBytecode[d3dStage].size();
+ break;
+ case PS:
+ stream.PS.object.pShaderBytecode = shaderBytecode[d3dStage].constData();
+ stream.PS.object.BytecodeLength = shaderBytecode[d3dStage].size();
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ }
+
+ stream.rasterizerState.object.FillMode = toD3DFillMode(m_polygonMode);
+ stream.rasterizerState.object.CullMode = toD3DCullMode(m_cullMode);
+ stream.rasterizerState.object.FrontCounterClockwise = m_frontFace == CCW;
+ stream.rasterizerState.object.DepthBias = m_depthBias;
+ stream.rasterizerState.object.SlopeScaledDepthBias = m_slopeScaledDepthBias;
+ stream.rasterizerState.object.DepthClipEnable = TRUE;
+ stream.rasterizerState.object.MultisampleEnable = sampleDesc.Count > 1;
+
+ stream.depthStencilState.object.DepthEnable = m_depthTest;
+ stream.depthStencilState.object.DepthWriteMask = m_depthWrite ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
+ stream.depthStencilState.object.DepthFunc = toD3DCompareOp(m_depthOp);
+ stream.depthStencilState.object.StencilEnable = m_stencilTest;
+ if (m_stencilTest) {
+ stream.depthStencilState.object.StencilReadMask = UINT8(m_stencilReadMask);
+ stream.depthStencilState.object.StencilWriteMask = UINT8(m_stencilWriteMask);
+ stream.depthStencilState.object.FrontFace.StencilFailOp = toD3DStencilOp(m_stencilFront.failOp);
+ stream.depthStencilState.object.FrontFace.StencilDepthFailOp = toD3DStencilOp(m_stencilFront.depthFailOp);
+ stream.depthStencilState.object.FrontFace.StencilPassOp = toD3DStencilOp(m_stencilFront.passOp);
+ stream.depthStencilState.object.FrontFace.StencilFunc = toD3DCompareOp(m_stencilFront.compareOp);
+ stream.depthStencilState.object.BackFace.StencilFailOp = toD3DStencilOp(m_stencilBack.failOp);
+ stream.depthStencilState.object.BackFace.StencilDepthFailOp = toD3DStencilOp(m_stencilBack.depthFailOp);
+ stream.depthStencilState.object.BackFace.StencilPassOp = toD3DStencilOp(m_stencilBack.passOp);
+ stream.depthStencilState.object.BackFace.StencilFunc = toD3DCompareOp(m_stencilBack.compareOp);
+ }
+
+ stream.blendState.object.IndependentBlendEnable = m_targetBlends.count() > 1;
+ for (int i = 0, ie = m_targetBlends.count(); i != ie; ++i) {
+ const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[i]);
+ D3D12_RENDER_TARGET_BLEND_DESC blend = {};
+ blend.BlendEnable = b.enable;
+ blend.SrcBlend = toD3DBlendFactor(b.srcColor, true);
+ blend.DestBlend = toD3DBlendFactor(b.dstColor, true);
+ blend.BlendOp = toD3DBlendOp(b.opColor);
+ blend.SrcBlendAlpha = toD3DBlendFactor(b.srcAlpha, false);
+ blend.DestBlendAlpha = toD3DBlendFactor(b.dstAlpha, false);
+ blend.BlendOpAlpha = toD3DBlendOp(b.opAlpha);
+ blend.RenderTargetWriteMask = toD3DColorWriteMask(b.colorWrite);
+ stream.blendState.object.RenderTarget[i] = blend;
+ }
+ if (m_targetBlends.isEmpty()) {
+ D3D12_RENDER_TARGET_BLEND_DESC blend = {};
+ blend.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
+ stream.blendState.object.RenderTarget[0] = blend;
+ }
+
+ stream.rtFormats.object.NumRenderTargets = rpD->colorAttachmentCount;
+ for (int i = 0; i < rpD->colorAttachmentCount; ++i)
+ stream.rtFormats.object.RTFormats[i] = DXGI_FORMAT(rpD->colorFormat[i]);
+
+ stream.dsFormat.object = rpD->hasDepthStencil ? DXGI_FORMAT(rpD->dsFormat) : DXGI_FORMAT_UNKNOWN;
+
+ stream.sampleDesc.object = sampleDesc;
+
+ stream.sampleMask.object = 0xFFFFFFFF;
+
+ viewInstanceMask = 0;
+ const bool isMultiView = m_multiViewCount >= 2;
+ stream.viewInstancingDesc.object.ViewInstanceCount = isMultiView ? m_multiViewCount : 0;
+ QVarLengthArray<D3D12_VIEW_INSTANCE_LOCATION, 4> viewInstanceLocations;
+ if (isMultiView) {
+ for (int i = 0; i < m_multiViewCount; ++i) {
+ viewInstanceMask |= (1 << i);
+ viewInstanceLocations.append({ 0, UINT(i) });
+ }
+ stream.viewInstancingDesc.object.pViewInstanceLocations = viewInstanceLocations.constData();
+ }
+
+ const D3D12_PIPELINE_STATE_STREAM_DESC streamDesc = { sizeof(stream), &stream };
+
+ ID3D12PipelineState *pso = nullptr;
+ HRESULT hr = rhiD->dev->CreatePipelineState(&streamDesc, __uuidof(ID3D12PipelineState), reinterpret_cast<void **>(&pso));
+ if (FAILED(hr)) {
+ qWarning("Failed to create graphics pipeline state: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ rhiD->rootSignaturePool.remove(rootSigHandle);
+ rootSigHandle = {};
+ return false;
+ }
+
+ handle = QD3D12Pipeline::addToPool(&rhiD->pipelinePool, QD3D12Pipeline::Graphics, pso);
+
+ rhiD->pipelineCreationEnd();
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+QD3D12ComputePipeline::QD3D12ComputePipeline(QRhiImplementation *rhi)
+ : QRhiComputePipeline(rhi)
+{
+}
+
+QD3D12ComputePipeline::~QD3D12ComputePipeline()
+{
+ destroy();
+}
+
+void QD3D12ComputePipeline::destroy()
+{
+ if (handle.isNull())
+ return;
+
+ QRHI_RES_RHI(QRhiD3D12);
+ if (rhiD) {
+ rhiD->releaseQueue.deferredReleasePipeline(handle);
+ rhiD->releaseQueue.deferredReleaseRootSignature(rootSigHandle);
+ }
+
+ handle = {};
+ stageData = {};
+
+ if (rhiD)
+ rhiD->unregisterResource(this);
+}
+
+bool QD3D12ComputePipeline::create()
+{
+ if (!handle.isNull())
+ destroy();
+
+ QRHI_RES_RHI(QRhiD3D12);
+ rhiD->pipelineCreationStart();
+
+ stageData.valid = true;
+ stageData.stage = CS;
+
+ QByteArray shaderBytecode;
+ auto cacheIt = rhiD->shaderBytecodeCache.data.constFind(m_shaderStage);
+ if (cacheIt != rhiD->shaderBytecodeCache.data.constEnd()) {
+ shaderBytecode = cacheIt->bytecode;
+ stageData.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
+ } else {
+ QString error;
+ QShaderKey shaderKey;
+ int compileFlags = 0;
+ if (m_flags.testFlag(CompileShadersWithDebugInfo))
+ compileFlags |= int(HlslCompileFlag::WithDebugInfo);
+ const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(),
+ m_shaderStage.shaderVariant(),
+ compileFlags,
+ &error,
+ &shaderKey);
+ if (bytecode.isEmpty()) {
+ qWarning("HLSL compute shader compilation failed: %s", qPrintable(error));
+ return false;
+ }
+
+ shaderBytecode = bytecode;
+ stageData.nativeResourceBindingMap = m_shaderStage.shader().nativeResourceBindingMap(shaderKey);
+ rhiD->shaderBytecodeCache.insertWithCapacityLimit(m_shaderStage, { bytecode,
+ stageData.nativeResourceBindingMap });
+ }
+
+ QD3D12ShaderResourceBindings *srbD = QRHI_RES(QD3D12ShaderResourceBindings, m_shaderResourceBindings);
+ if (srbD) {
+ rootSigHandle = srbD->createRootSignature(&stageData, 1);
+ if (rootSigHandle.isNull()) {
+ qWarning("Failed to create root signature");
+ return false;
+ }
+ }
+ ID3D12RootSignature *rootSig = nullptr;
+ if (QD3D12RootSignature *rs = rhiD->rootSignaturePool.lookupRef(rootSigHandle))
+ rootSig = rs->rootSig;
+ if (!rootSig) {
+ qWarning("Cannot create compute pipeline state without root signature");
+ return false;
+ }
+
+ struct {
+ QD3D12PipelineStateSubObject<ID3D12RootSignature *, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> rootSig;
+ QD3D12PipelineStateSubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS> CS;
+ } stream;
+ stream.rootSig.object = rootSig;
+ stream.CS.object.pShaderBytecode = shaderBytecode.constData();
+ stream.CS.object.BytecodeLength = shaderBytecode.size();
+ const D3D12_PIPELINE_STATE_STREAM_DESC streamDesc = { sizeof(stream), &stream };
+ ID3D12PipelineState *pso = nullptr;
+ HRESULT hr = rhiD->dev->CreatePipelineState(&streamDesc, __uuidof(ID3D12PipelineState), reinterpret_cast<void **>(&pso));
+ if (FAILED(hr)) {
+ qWarning("Failed to create compute pipeline state: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ rhiD->rootSignaturePool.remove(rootSigHandle);
+ rootSigHandle = {};
+ return false;
+ }
+
+ handle = QD3D12Pipeline::addToPool(&rhiD->pipelinePool, QD3D12Pipeline::Compute, pso);
+
+ rhiD->pipelineCreationEnd();
+ generation += 1;
+ rhiD->registerResource(this);
+ return true;
+}
+
+// This is a lot like in the Metal backend: we need to now the rtv and dsv
+// formats to create a graphics pipeline, and that's exactly what our
+// "renderpass descriptor" is going to hold.
+QD3D12RenderPassDescriptor::QD3D12RenderPassDescriptor(QRhiImplementation *rhi)
+ : QRhiRenderPassDescriptor(rhi)
+{
+ serializedFormatData.reserve(16);
+}
+
+QD3D12RenderPassDescriptor::~QD3D12RenderPassDescriptor()
+{
+ destroy();
+}
+
+void QD3D12RenderPassDescriptor::destroy()
+{
+ QRHI_RES_RHI(QRhiD3D12);
+ if (rhiD)
+ rhiD->unregisterResource(this);
+}
+
+bool QD3D12RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
+{
+ if (!other)
+ return false;
+
+ const QD3D12RenderPassDescriptor *o = QRHI_RES(const QD3D12RenderPassDescriptor, other);
+
+ if (colorAttachmentCount != o->colorAttachmentCount)
+ return false;
+
+ if (hasDepthStencil != o->hasDepthStencil)
+ return false;
+
+ for (int i = 0; i < colorAttachmentCount; ++i) {
+ if (colorFormat[i] != o->colorFormat[i])
+ return false;
+ }
+
+ if (hasDepthStencil) {
+ if (dsFormat != o->dsFormat)
+ return false;
+ }
+
+ return true;
+}
+
+void QD3D12RenderPassDescriptor::updateSerializedFormat()
+{
+ serializedFormatData.clear();
+ auto p = std::back_inserter(serializedFormatData);
+
+ *p++ = colorAttachmentCount;
+ *p++ = hasDepthStencil;
+ for (int i = 0; i < colorAttachmentCount; ++i)
+ *p++ = colorFormat[i];
+ *p++ = hasDepthStencil ? dsFormat : 0;
+}
+
+QRhiRenderPassDescriptor *QD3D12RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
+{
+ QD3D12RenderPassDescriptor *rpD = new QD3D12RenderPassDescriptor(m_rhi);
+ rpD->colorAttachmentCount = colorAttachmentCount;
+ rpD->hasDepthStencil = hasDepthStencil;
+ memcpy(rpD->colorFormat, colorFormat, sizeof(colorFormat));
+ rpD->dsFormat = dsFormat;
+
+ rpD->updateSerializedFormat();
+
+ QRHI_RES_RHI(QRhiD3D12);
+ rhiD->registerResource(rpD);
+ return rpD;
+}
+
+QVector<quint32> QD3D12RenderPassDescriptor::serializedFormat() const
+{
+ return serializedFormatData;
+}
+
+QD3D12CommandBuffer::QD3D12CommandBuffer(QRhiImplementation *rhi)
+ : QRhiCommandBuffer(rhi)
+{
+ resetState();
+}
+
+QD3D12CommandBuffer::~QD3D12CommandBuffer()
+{
+ destroy();
+}
+
+void QD3D12CommandBuffer::destroy()
+{
+ // nothing to do here, the command list is not owned by us
+}
+
+const QRhiNativeHandles *QD3D12CommandBuffer::nativeHandles()
+{
+ nativeHandlesStruct.commandList = cmdList;
+ return &nativeHandlesStruct;
+}
+
+QD3D12SwapChainRenderTarget::QD3D12SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
+ : QRhiSwapChainRenderTarget(rhi, swapchain),
+ d(rhi)
+{
+}
+
+QD3D12SwapChainRenderTarget::~QD3D12SwapChainRenderTarget()
+{
+ destroy();
+}
+
+void QD3D12SwapChainRenderTarget::destroy()
+{
+ // nothing to do here
+}
+
+QSize QD3D12SwapChainRenderTarget::pixelSize() const
+{
+ return d.pixelSize;
+}
+
+float QD3D12SwapChainRenderTarget::devicePixelRatio() const
+{
+ return d.dpr;
+}
+
+int QD3D12SwapChainRenderTarget::sampleCount() const
+{
+ return d.sampleCount;
+}
+
+QD3D12SwapChain::QD3D12SwapChain(QRhiImplementation *rhi)
+ : QRhiSwapChain(rhi),
+ rtWrapper(rhi, this),
+ rtWrapperRight(rhi, this),
+ cbWrapper(rhi)
+{
+}
+
+QD3D12SwapChain::~QD3D12SwapChain()
+{
+ destroy();
+}
+
+void QD3D12SwapChain::destroy()
+{
+ if (!swapChain)
+ return;
+
+ releaseBuffers();
+
+ swapChain->Release();
+ swapChain = nullptr;
+ sourceSwapChain1->Release();
+ sourceSwapChain1 = nullptr;
+
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ FrameResources &fr(frameRes[i]);
+ if (fr.fence)
+ fr.fence->Release();
+ if (fr.fenceEvent)
+ CloseHandle(fr.fenceEvent);
+ if (fr.cmdList)
+ fr.cmdList->Release();
+ fr = {};
+ }
+
+ if (dcompVisual) {
+ dcompVisual->Release();
+ dcompVisual = nullptr;
+ }
+
+ if (dcompTarget) {
+ dcompTarget->Release();
+ dcompTarget = nullptr;
+ }
+
+ QRHI_RES_RHI(QRhiD3D12);
+ if (rhiD) {
+ rhiD->swapchains.remove(this);
+ rhiD->unregisterResource(this);
+ }
+}
+
+void QD3D12SwapChain::releaseBuffers()
+{
+ QRHI_RES_RHI(QRhiD3D12);
+ rhiD->waitGpu();
+ for (UINT i = 0; i < BUFFER_COUNT; ++i) {
+ rhiD->resourcePool.remove(colorBuffers[i]);
+ rhiD->rtvPool.release(rtvs[i], 1);
+ if (stereo)
+ rhiD->rtvPool.release(rtvsRight[i], 1);
+ if (!msaaBuffers[i].isNull())
+ rhiD->resourcePool.remove(msaaBuffers[i]);
+ if (msaaRtvs[i].isValid())
+ rhiD->rtvPool.release(msaaRtvs[i], 1);
+ }
+}
+
+void QD3D12SwapChain::waitCommandCompletionForFrameSlot(int frameSlot)
+{
+ FrameResources &fr(frameRes[frameSlot]);
+ if (fr.fence->GetCompletedValue() < fr.fenceCounter) {
+ fr.fence->SetEventOnCompletion(fr.fenceCounter, fr.fenceEvent);
+ WaitForSingleObject(fr.fenceEvent, INFINITE);
+ }
+}
+
+void QD3D12SwapChain::addCommandCompletionSignalForCurrentFrameSlot()
+{
+ QRHI_RES_RHI(QRhiD3D12);
+ FrameResources &fr(frameRes[currentFrameSlot]);
+ fr.fenceCounter += 1u;
+ rhiD->cmdQueue->Signal(fr.fence, fr.fenceCounter);
+}
+
+QRhiCommandBuffer *QD3D12SwapChain::currentFrameCommandBuffer()
+{
+ return &cbWrapper;
+}
+
+QRhiRenderTarget *QD3D12SwapChain::currentFrameRenderTarget()
+{
+ return &rtWrapper;
+}
+
+QRhiRenderTarget *QD3D12SwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
+{
+ return !stereo || targetBuffer == StereoTargetBuffer::LeftBuffer ? &rtWrapper : &rtWrapperRight;
+}
+
+QSize QD3D12SwapChain::surfacePixelSize()
+{
+ Q_ASSERT(m_window);
+ return m_window->size() * m_window->devicePixelRatio();
+}
+
+bool QD3D12SwapChain::isFormatSupported(Format f)
+{
+ if (f == SDR)
+ return true;
+
+ if (!m_window) {
+ qWarning("Attempted to call isFormatSupported() without a window set");
+ return false;
+ }
+
+ QRHI_RES_RHI(QRhiD3D12);
+ DXGI_OUTPUT_DESC1 desc1;
+ if (QRhiD3D::outputDesc1ForWindow(m_window, rhiD->activeAdapter, &desc1)) {
+ if (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)
+ return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
+ }
+
+ return false;
+}
+
+QRhiSwapChainHdrInfo QD3D12SwapChain::hdrInfo()
+{
+ QRhiSwapChainHdrInfo info = QRhiSwapChain::hdrInfo();
+ // Must use m_window, not window, given this may be called before createOrResize().
+ if (m_window) {
+ QRHI_RES_RHI(QRhiD3D12);
+ DXGI_OUTPUT_DESC1 hdrOutputDesc;
+ if (QRhiD3D::outputDesc1ForWindow(m_window, rhiD->activeAdapter, &hdrOutputDesc)) {
+ info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
+ info.limits.luminanceInNits.minLuminance = hdrOutputDesc.MinLuminance;
+ info.limits.luminanceInNits.maxLuminance = hdrOutputDesc.MaxLuminance;
+ info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred; // 1.0 = 80 nits
+ info.sdrWhiteLevel = QRhiD3D::sdrWhiteLevelInNits(hdrOutputDesc);
+ }
+ }
+ return info;
+}
+
+QRhiRenderPassDescriptor *QD3D12SwapChain::newCompatibleRenderPassDescriptor()
+{
+ // not yet built so cannot rely on data computed in createOrResize()
+ chooseFormats();
+
+ QD3D12RenderPassDescriptor *rpD = new QD3D12RenderPassDescriptor(m_rhi);
+ rpD->colorAttachmentCount = 1;
+ rpD->hasDepthStencil = m_depthStencil != nullptr;
+ rpD->colorFormat[0] = int(srgbAdjustedColorFormat);
+ rpD->dsFormat = QD3D12RenderBuffer::DS_FORMAT;
+ rpD->updateSerializedFormat();
+
+ QRHI_RES_RHI(QRhiD3D12);
+ rhiD->registerResource(rpD);
+ return rpD;
+}
+
+bool QRhiD3D12::ensureDirectCompositionDevice()
+{
+ if (dcompDevice)
+ return true;
+
+ qCDebug(QRHI_LOG_INFO, "Creating Direct Composition device (needed for semi-transparent windows)");
+ dcompDevice = QRhiD3D::createDirectCompositionDevice();
+ return dcompDevice ? true : false;
+}
+
+static const DXGI_FORMAT DEFAULT_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM;
+static const DXGI_FORMAT DEFAULT_SRGB_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+
+void QD3D12SwapChain::chooseFormats()
+{
+ colorFormat = DEFAULT_FORMAT;
+ srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
+ hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; // SDR
+ DXGI_OUTPUT_DESC1 hdrOutputDesc;
+ QRHI_RES_RHI(QRhiD3D12);
+ if (QRhiD3D::outputDesc1ForWindow(m_window, rhiD->activeAdapter, &hdrOutputDesc) && m_format != SDR) {
+ // https://docs.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range
+ if (hdrOutputDesc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
+ switch (m_format) {
+ case HDRExtendedSrgbLinear:
+ colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
+ hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
+ srgbAdjustedColorFormat = colorFormat;
+ break;
+ case HDR10:
+ colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
+ hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
+ srgbAdjustedColorFormat = colorFormat;
+ break;
+ default:
+ break;
+ }
+ } else {
+ // This happens also when Use HDR is set to Off in the Windows
+ // Display settings. Show a helpful warning, but continue with the
+ // default non-HDR format.
+ qWarning("The output associated with the window is not HDR capable "
+ "(or Use HDR is Off in the Display Settings), ignoring HDR format request");
+ }
+ }
+ sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, colorFormat);
+}
+
+bool QD3D12SwapChain::createOrResize()
+{
+ // Can be called multiple times due to window resizes - that is not the
+ // same as a simple destroy+create (as with other resources). Just need to
+ // resize the buffers then.
+
+ const bool needsRegistration = !window || window != m_window;
+
+ // except if the window actually changes
+ if (window && window != m_window)
+ destroy();
+
+ window = m_window;
+ m_currentPixelSize = surfacePixelSize();
+ pixelSize = m_currentPixelSize;
+
+ if (pixelSize.isEmpty())
+ return false;
+
+ HWND hwnd = reinterpret_cast<HWND>(window->winId());
+ HRESULT hr;
+ QRHI_RES_RHI(QRhiD3D12);
+ stereo = m_window->format().stereo() && rhiD->dxgiFactory->IsWindowedStereoEnabled();
+
+ if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
+ if (rhiD->ensureDirectCompositionDevice()) {
+ if (!dcompTarget) {
+ hr = rhiD->dcompDevice->CreateTargetForHwnd(hwnd, false, &dcompTarget);
+ if (FAILED(hr)) {
+ qWarning("Failed to create Direct Composition target for the window: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ }
+ }
+ if (dcompTarget && !dcompVisual) {
+ hr = rhiD->dcompDevice->CreateVisual(&dcompVisual);
+ if (FAILED(hr)) {
+ qWarning("Failed to create DirectComposition visual: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ }
+ }
+ }
+ // simple consistency check
+ if (window->requestedFormat().alphaBufferSize() <= 0)
+ qWarning("Swapchain says surface has alpha but the window has no alphaBufferSize set. "
+ "This may lead to problems.");
+ }
+
+ swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
+ swapChainFlags = 0;
+ if (swapInterval == 0 && rhiD->supportsAllowTearing)
+ swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
+
+ if (!swapChain) {
+ chooseFormats();
+
+ DXGI_SWAP_CHAIN_DESC1 desc = {};
+ desc.Width = UINT(pixelSize.width());
+ desc.Height = UINT(pixelSize.height());
+ desc.Format = colorFormat;
+ desc.SampleDesc.Count = 1;
+ desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ desc.BufferCount = BUFFER_COUNT;
+ desc.Flags = swapChainFlags;
+ desc.Scaling = DXGI_SCALING_NONE;
+ desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+ desc.Stereo = stereo;
+
+ if (dcompVisual) {
+ // With DirectComposition setting AlphaMode to STRAIGHT fails the
+ // swapchain creation, whereas the result seems to be identical
+ // with any of the other values, including IGNORE. (?)
+ desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
+
+ // DirectComposition has its own limitations, cannot use
+ // SCALING_NONE. So with semi-transparency requested we are forced
+ // to SCALING_STRETCH.
+ desc.Scaling = DXGI_SCALING_STRETCH;
+ }
+
+ if (dcompVisual)
+ hr = rhiD->dxgiFactory->CreateSwapChainForComposition(rhiD->cmdQueue, &desc, nullptr, &sourceSwapChain1);
+ else
+ hr = rhiD->dxgiFactory->CreateSwapChainForHwnd(rhiD->cmdQueue, hwnd, &desc, nullptr, nullptr, &sourceSwapChain1);
+
+ // If failed and we tried a HDR format, then try with SDR. This
+ // matches other backends, such as Vulkan where if the format is
+ // not supported, the default one is used instead.
+ if (FAILED(hr) && m_format != SDR) {
+ colorFormat = DEFAULT_FORMAT;
+ desc.Format = DEFAULT_FORMAT;
+ if (dcompVisual)
+ hr = rhiD->dxgiFactory->CreateSwapChainForComposition(rhiD->cmdQueue, &desc, nullptr, &sourceSwapChain1);
+ else
+ hr = rhiD->dxgiFactory->CreateSwapChainForHwnd(rhiD->cmdQueue, hwnd, &desc, nullptr, nullptr, &sourceSwapChain1);
+ }
+
+ if (SUCCEEDED(hr)) {
+ if (FAILED(sourceSwapChain1->QueryInterface(__uuidof(IDXGISwapChain3), reinterpret_cast<void **>(&swapChain)))) {
+ qWarning("IDXGISwapChain3 not available");
+ return false;
+ }
+ if (m_format != SDR) {
+ hr = swapChain->SetColorSpace1(hdrColorSpace);
+ if (FAILED(hr)) {
+ qWarning("Failed to set color space on swapchain: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ }
+ }
+ if (dcompVisual) {
+ hr = dcompVisual->SetContent(swapChain);
+ if (SUCCEEDED(hr)) {
+ hr = dcompTarget->SetRoot(dcompVisual);
+ if (FAILED(hr)) {
+ qWarning("Failed to associate Direct Composition visual with the target: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ }
+ } else {
+ qWarning("Failed to set content for Direct Composition visual: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ }
+ } else {
+ // disable Alt+Enter; not relevant when using DirectComposition
+ rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
+ }
+ }
+ if (FAILED(hr)) {
+ qWarning("Failed to create D3D12 swapchain: %s"
+ " (Width=%u Height=%u Format=%u SampleCount=%u BufferCount=%u Scaling=%u SwapEffect=%u Stereo=%u)",
+ qPrintable(QSystemError::windowsComString(hr)),
+ desc.Width, desc.Height, UINT(desc.Format), desc.SampleDesc.Count,
+ desc.BufferCount, UINT(desc.Scaling), UINT(desc.SwapEffect), UINT(desc.Stereo));
+ return false;
+ }
+
+ for (int i = 0; i < QD3D12_FRAMES_IN_FLIGHT; ++i) {
+ hr = rhiD->dev->CreateFence(0,
+ D3D12_FENCE_FLAG_NONE,
+ __uuidof(ID3D12Fence),
+ reinterpret_cast<void **>(&frameRes[i].fence));
+ if (FAILED(hr)) {
+ qWarning("Failed to create fence for swapchain: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ frameRes[i].fenceEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
+
+ frameRes[i].fenceCounter = 0;
+ }
+ } else {
+ releaseBuffers();
+ hr = swapChain->ResizeBuffers(BUFFER_COUNT,
+ UINT(pixelSize.width()),
+ UINT(pixelSize.height()),
+ colorFormat,
+ swapChainFlags);
+ if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
+ qWarning("Device loss detected in ResizeBuffers()");
+ rhiD->deviceLost = true;
+ return false;
+ } else if (FAILED(hr)) {
+ qWarning("Failed to resize D3D12 swapchain: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ }
+
+ for (UINT i = 0; i < BUFFER_COUNT; ++i) {
+ ID3D12Resource *colorBuffer;
+ hr = swapChain->GetBuffer(i, __uuidof(ID3D12Resource), reinterpret_cast<void **>(&colorBuffer));
+ if (FAILED(hr)) {
+ qWarning("Failed to get buffer %u for D3D12 swapchain: %s",
+ i, qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ colorBuffers[i] = QD3D12Resource::addToPool(&rhiD->resourcePool, colorBuffer, D3D12_RESOURCE_STATE_PRESENT);
+ rtvs[i] = rhiD->rtvPool.allocate(1);
+ D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
+ rtvDesc.Format = srgbAdjustedColorFormat;
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
+ rhiD->dev->CreateRenderTargetView(colorBuffer, &rtvDesc, rtvs[i].cpuHandle);
+
+ if (stereo) {
+ rtvsRight[i] = rhiD->rtvPool.allocate(1);
+ D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
+ rtvDesc.Format = srgbAdjustedColorFormat;
+ rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.ArraySize = 1;
+ rtvDesc.Texture2DArray.FirstArraySlice = 1;
+ rhiD->dev->CreateRenderTargetView(colorBuffer, &rtvDesc, rtvsRight[i].cpuHandle);
+ }
+ }
+
+ if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
+ qWarning("Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
+ m_depthStencil->sampleCount(), m_sampleCount);
+ }
+ if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
+ if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
+ m_depthStencil->setPixelSize(pixelSize);
+ if (!m_depthStencil->create())
+ qWarning("Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
+ pixelSize.width(), pixelSize.height());
+ } else {
+ qWarning("Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
+ m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
+ pixelSize.width(), pixelSize.height());
+ }
+ }
+
+ ds = m_depthStencil ? QRHI_RES(QD3D12RenderBuffer, m_depthStencil) : nullptr;
+
+ if (sampleDesc.Count > 1) {
+ for (UINT i = 0; i < BUFFER_COUNT; ++i) {
+ D3D12_RESOURCE_DESC resourceDesc = {};
+ resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ resourceDesc.Width = UINT64(pixelSize.width());
+ resourceDesc.Height = UINT(pixelSize.height());
+ resourceDesc.DepthOrArraySize = 1;
+ resourceDesc.MipLevels = 1;
+ resourceDesc.Format = srgbAdjustedColorFormat;
+ resourceDesc.SampleDesc = sampleDesc;
+ resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+ D3D12_CLEAR_VALUE clearValue = {};
+ clearValue.Format = colorFormat;
+ ID3D12Resource *resource = nullptr;
+ D3D12MA::Allocation *allocation = nullptr;
+ HRESULT hr = rhiD->vma.createResource(D3D12_HEAP_TYPE_DEFAULT,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_RENDER_TARGET,
+ &clearValue,
+ &allocation,
+ __uuidof(ID3D12Resource),
+ reinterpret_cast<void **>(&resource));
+ if (FAILED(hr)) {
+ qWarning("Failed to create MSAA color buffer: %s", qPrintable(QSystemError::windowsComString(hr)));
+ return false;
+ }
+ msaaBuffers[i] = QD3D12Resource::addToPool(&rhiD->resourcePool, resource, D3D12_RESOURCE_STATE_RENDER_TARGET, allocation);
+ msaaRtvs[i] = rhiD->rtvPool.allocate(1);
+ if (!msaaRtvs[i].isValid())
+ return false;
+ D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {};
+ rtvDesc.Format = srgbAdjustedColorFormat;
+ rtvDesc.ViewDimension = sampleDesc.Count > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMS
+ : D3D12_RTV_DIMENSION_TEXTURE2D;
+ rhiD->dev->CreateRenderTargetView(resource, &rtvDesc, msaaRtvs[i].cpuHandle);
+ }
+ }
+
+ currentBackBufferIndex = swapChain->GetCurrentBackBufferIndex();
+ currentFrameSlot = 0;
+
+ rtWrapper.setRenderPassDescriptor(m_renderPassDesc); // for the public getter in QRhiRenderTarget
+ QD3D12SwapChainRenderTarget *rtD = QRHI_RES(QD3D12SwapChainRenderTarget, &rtWrapper);
+ rtD->d.rp = QRHI_RES(QD3D12RenderPassDescriptor, m_renderPassDesc);
+ rtD->d.pixelSize = pixelSize;
+ rtD->d.dpr = float(window->devicePixelRatio());
+ rtD->d.sampleCount = int(sampleDesc.Count);
+ rtD->d.colorAttCount = 1;
+ rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
+
+ rtWrapperRight.setRenderPassDescriptor(m_renderPassDesc);
+ QD3D12SwapChainRenderTarget *rtDr = QRHI_RES(QD3D12SwapChainRenderTarget, &rtWrapperRight);
+ rtDr->d.rp = QRHI_RES(QD3D12RenderPassDescriptor, m_renderPassDesc);
+ rtDr->d.pixelSize = pixelSize;
+ rtDr->d.dpr = float(window->devicePixelRatio());
+ rtDr->d.sampleCount = int(sampleDesc.Count);
+ rtDr->d.colorAttCount = 1;
+ rtDr->d.dsAttCount = m_depthStencil ? 1 : 0;
+
+ if (needsRegistration) {
+ rhiD->swapchains.insert(this);
+ rhiD->registerResource(this);
+ }
+
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // __ID3D12Device2_INTERFACE_DEFINED__
diff --git a/src/gui/rhi/qrhid3d12_p.h b/src/gui/rhi/qrhid3d12_p.h
new file mode 100644
index 0000000000..3f9abbb5ac
--- /dev/null
+++ b/src/gui/rhi/qrhid3d12_p.h
@@ -0,0 +1,1248 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHID3D12_P_H
+#define QRHID3D12_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qrhi_p.h"
+#include <QWindow>
+#include <QBitArray>
+
+#include <optional>
+#include <array>
+
+#include <d3d12.h>
+#include <d3d12sdklayers.h>
+#include <dxgi1_6.h>
+#include <dcomp.h>
+
+#include "D3D12MemAlloc.h"
+
+// ID3D12Device2 and ID3D12GraphicsCommandList1 and types and enums introduced
+// with those are hard requirements now. These should be declared in any
+// moderately recent d3d12.h, but if it is an SDK from before Windows 10
+// version 1703 then these types could be missing. In the absence of other
+// options, handle this by skipping all the code and making QRhi::create() fail
+// in such builds.
+#ifdef __ID3D12Device2_INTERFACE_DEFINED__
+#define QRHI_D3D12_AVAILABLE
+
+QT_BEGIN_NAMESPACE
+
+static const int QD3D12_FRAMES_IN_FLIGHT = 2;
+
+class QRhiD3D12;
+
+struct QD3D12Descriptor
+{
+ D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle = {};
+ D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = {};
+
+ bool isValid() const { return cpuHandle.ptr != 0; }
+};
+
+struct QD3D12ReleaseQueue;
+
+struct QD3D12DescriptorHeap
+{
+ bool isValid() const { return heap && capacity; }
+ bool create(ID3D12Device *device,
+ quint32 descriptorCount,
+ D3D12_DESCRIPTOR_HEAP_TYPE heapType,
+ D3D12_DESCRIPTOR_HEAP_FLAGS heapFlags);
+ void createWithExisting(const QD3D12DescriptorHeap &other,
+ quint32 offsetInDescriptors,
+ quint32 descriptorCount);
+ void destroy();
+ void destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue);
+
+ QD3D12Descriptor get(quint32 count);
+ QD3D12Descriptor at(quint32 index) const;
+ quint32 remainingCapacity() const { return capacity - head; }
+
+ QD3D12Descriptor incremented(const QD3D12Descriptor &descriptor, quint32 offsetInDescriptors) const
+ {
+ D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle = descriptor.cpuHandle;
+ cpuHandle.ptr += offsetInDescriptors * descriptorByteSize;
+ D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle = descriptor.gpuHandle;
+ if (gpuHandle.ptr)
+ gpuHandle.ptr += offsetInDescriptors * descriptorByteSize;
+ return { cpuHandle, gpuHandle };
+ }
+
+ ID3D12DescriptorHeap *heap = nullptr;
+ quint32 capacity = 0;
+ QD3D12Descriptor heapStart;
+ quint32 head = 0;
+ quint32 descriptorByteSize = 0;
+ D3D12_DESCRIPTOR_HEAP_TYPE heapType;
+ D3D12_DESCRIPTOR_HEAP_FLAGS heapFlags;
+};
+
+struct QD3D12CpuDescriptorPool
+{
+ bool isValid() const { return !heaps.isEmpty(); }
+ bool create(ID3D12Device *device, D3D12_DESCRIPTOR_HEAP_TYPE heapType, const char *debugName = "");
+ void destroy();
+
+ QD3D12Descriptor allocate(quint32 count);
+ void release(const QD3D12Descriptor &descriptor, quint32 count);
+
+ static const int DESCRIPTORS_PER_HEAP = 256;
+
+ struct HeapWithMap {
+ QD3D12DescriptorHeap heap;
+ QBitArray map;
+ static HeapWithMap init(const QD3D12DescriptorHeap &heap, quint32 descriptorCount) {
+ HeapWithMap result;
+ result.heap = heap;
+ result.map.resize(descriptorCount);
+ return result;
+ }
+ };
+
+ ID3D12Device *device;
+ quint32 descriptorByteSize;
+ QVector<HeapWithMap> heaps;
+ const char *debugName;
+};
+
+struct QD3D12QueryHeap
+{
+ bool isValid() const { return heap && capacity; }
+ bool create(ID3D12Device *device,
+ quint32 queryCount,
+ D3D12_QUERY_HEAP_TYPE heapType);
+ void destroy();
+
+ ID3D12QueryHeap *heap = nullptr;
+ quint32 capacity = 0;
+};
+
+struct QD3D12StagingArea
+{
+ static const quint32 ALIGNMENT = D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT; // 512 so good enough both for cb and texdata
+
+ struct Allocation {
+ quint8 *p = nullptr;
+ D3D12_GPU_VIRTUAL_ADDRESS gpuAddr = 0;
+ ID3D12Resource *buffer = nullptr;
+ quint32 bufferOffset = 0;
+ bool isValid() const { return p != nullptr; }
+ };
+
+ bool isValid() const { return allocation && mem.isValid(); }
+ bool create(QRhiD3D12 *rhi, quint32 capacity, D3D12_HEAP_TYPE heapType);
+ void destroy();
+ void destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue);
+
+ Allocation get(quint32 byteSize);
+
+ quint32 remainingCapacity() const
+ {
+ return capacity - head;
+ }
+
+ static quint32 allocSizeForArray(quint32 size, int count = 1)
+ {
+ return count * ((size + ALIGNMENT - 1) & ~(ALIGNMENT - 1));
+ }
+
+ Allocation mem;
+ ID3D12Resource *resource = nullptr;
+ D3D12MA::Allocation *allocation = nullptr;
+ quint32 head;
+ quint32 capacity;
+};
+
+struct QD3D12ObjectHandle
+{
+ quint32 index = 0;
+ quint32 generation = 0;
+
+ // the default, null handle is guaranteed to give ObjectPool::isValid() == false
+ bool isNull() const { return index == 0 && generation == 0; }
+};
+
+inline bool operator==(const QD3D12ObjectHandle &a, const QD3D12ObjectHandle &b) noexcept
+{
+ return a.index == b.index && a.generation == b.generation;
+}
+
+inline bool operator!=(const QD3D12ObjectHandle &a, const QD3D12ObjectHandle &b) noexcept
+{
+ return !(a == b);
+}
+
+template<typename T>
+struct QD3D12ObjectPool
+{
+ void create(const char *debugName = "")
+ {
+ this->debugName = debugName;
+ Q_ASSERT(data.isEmpty());
+ data.append(Data()); // index 0 is always invalid
+ }
+
+ void destroy() {
+ int leakCount = 0; // will nicely destroy everything here, but warn about it if enabled
+ for (Data &d : data) {
+ if (d.object.has_value()) {
+ leakCount += 1;
+ d.object->releaseResources();
+ }
+ }
+ data.clear();
+#ifndef QT_NO_DEBUG
+ // debug builds: just do it always
+ static bool leakCheck = true;
+#else
+ // release builds: opt-in
+ static bool leakCheck = qEnvironmentVariableIntValue("QT_RHI_LEAK_CHECK");
+#endif
+ if (leakCheck) {
+ if (leakCount > 0) {
+ qWarning("QD3D12ObjectPool::destroy(): Pool %p '%s' had %d unreleased objects",
+ this, debugName, leakCount);
+ }
+ }
+ }
+
+ bool isValid(const QD3D12ObjectHandle &handle) const
+ {
+ return handle.index > 0
+ && handle.index < quint32(data.count())
+ && handle.generation > 0
+ && handle.generation == data[handle.index].generation
+ && data[handle.index].object.has_value();
+ }
+
+ T lookup(const QD3D12ObjectHandle &handle) const
+ {
+ return isValid(handle) ? *data[handle.index].object : T();
+ }
+
+ const T *lookupRef(const QD3D12ObjectHandle &handle) const
+ {
+ return isValid(handle) ? &*data[handle.index].object : nullptr;
+ }
+
+ T *lookupRef(const QD3D12ObjectHandle &handle)
+ {
+ return isValid(handle) ? &*data[handle.index].object : nullptr;
+ }
+
+ QD3D12ObjectHandle add(const T &object)
+ {
+ Q_ASSERT(!data.isEmpty());
+ const quint32 count = quint32(data.count());
+ quint32 index = 1; // index 0 is always invalid
+ for (; index < count; ++index) {
+ if (!data[index].object.has_value())
+ break;
+ }
+ if (index < count) {
+ data[index].object = object;
+ quint32 &generation = data[index].generation;
+ generation += 1u;
+ return { index, generation };
+ } else {
+ data.append({ object, 1 });
+ return { count, 1 };
+ }
+ }
+
+ void remove(const QD3D12ObjectHandle &handle)
+ {
+ if (T *object = lookupRef(handle)) {
+ object->releaseResources();
+ data[handle.index].object.reset();
+ }
+ }
+
+ const char *debugName;
+ struct Data {
+ std::optional<T> object;
+ quint32 generation = 0;
+ };
+ QVector<Data> data;
+};
+
+struct QD3D12Resource
+{
+ ID3D12Resource *resource;
+ D3D12_RESOURCE_STATES state;
+ D3D12_RESOURCE_DESC desc;
+ D3D12MA::Allocation *allocation;
+ void *cpuMapPtr;
+ enum { UavUsageRead = 0x01, UavUsageWrite = 0x02 };
+ int uavUsage;
+ bool owns;
+
+ // note that this assumes the allocation (if there is one) and the resource
+ // are separately releaseable, see D3D12MemAlloc docs
+ static QD3D12ObjectHandle addToPool(QD3D12ObjectPool<QD3D12Resource> *pool,
+ ID3D12Resource *resource,
+ D3D12_RESOURCE_STATES state,
+ D3D12MA::Allocation *allocation = nullptr,
+ void *cpuMapPtr = nullptr)
+ {
+ Q_ASSERT(resource);
+ return pool->add({ resource, state, resource->GetDesc(), allocation, cpuMapPtr, 0, true });
+ }
+
+ // for QRhiTexture::createFrom() where the ID3D12Resource is not owned by us
+ static QD3D12ObjectHandle addNonOwningToPool(QD3D12ObjectPool<QD3D12Resource> *pool,
+ ID3D12Resource *resource,
+ D3D12_RESOURCE_STATES state)
+ {
+ Q_ASSERT(resource);
+ return pool->add({ resource, state, resource->GetDesc(), nullptr, nullptr, 0, false });
+ }
+
+ void releaseResources()
+ {
+ if (owns) {
+ // order matters: resource first, then the allocation
+ resource->Release();
+ if (allocation)
+ allocation->Release();
+ }
+ }
+};
+
+struct QD3D12Pipeline
+{
+ enum Type {
+ Graphics,
+ Compute
+ };
+ Type type;
+ ID3D12PipelineState *pso;
+
+ static QD3D12ObjectHandle addToPool(QD3D12ObjectPool<QD3D12Pipeline> *pool,
+ Type type,
+ ID3D12PipelineState *pso)
+ {
+ return pool->add({ type, pso });
+ }
+
+ void releaseResources()
+ {
+ pso->Release();
+ }
+};
+
+struct QD3D12RootSignature
+{
+ ID3D12RootSignature *rootSig;
+
+ static QD3D12ObjectHandle addToPool(QD3D12ObjectPool<QD3D12RootSignature> *pool,
+ ID3D12RootSignature *rootSig)
+ {
+ return pool->add({ rootSig });
+ }
+
+ void releaseResources()
+ {
+ rootSig->Release();
+ }
+};
+
+struct QD3D12ReleaseQueue
+{
+ void create(QD3D12ObjectPool<QD3D12Resource> *resourcePool,
+ QD3D12ObjectPool<QD3D12Pipeline> *pipelinePool,
+ QD3D12ObjectPool<QD3D12RootSignature> *rootSignaturePool)
+ {
+ this->resourcePool = resourcePool;
+ this->pipelinePool = pipelinePool;
+ this->rootSignaturePool = rootSignaturePool;
+ }
+
+ void deferredReleaseResource(const QD3D12ObjectHandle &handle);
+ void deferredReleaseResourceWithViews(const QD3D12ObjectHandle &handle,
+ QD3D12CpuDescriptorPool *pool,
+ const QD3D12Descriptor &viewsStart,
+ int viewCount);
+ void deferredReleasePipeline(const QD3D12ObjectHandle &handle);
+ void deferredReleaseRootSignature(const QD3D12ObjectHandle &handle);
+ void deferredReleaseCallback(std::function<void(void*)> callback, void *userData);
+ void deferredReleaseResourceAndAllocation(ID3D12Resource *resource,
+ D3D12MA::Allocation *allocation);
+ void deferredReleaseDescriptorHeap(ID3D12DescriptorHeap *heap);
+ void deferredReleaseViews(QD3D12CpuDescriptorPool *pool,
+ const QD3D12Descriptor &viewsStart,
+ int viewCount);
+
+ void activatePendingDeferredReleaseRequests(int frameSlot);
+ void executeDeferredReleases(int frameSlot, bool forced = false);
+ void releaseAll();
+
+ struct DeferredReleaseEntry {
+ enum Type {
+ Resource,
+ Pipeline,
+ RootSignature,
+ Callback,
+ ResourceAndAllocation,
+ DescriptorHeap,
+ Views
+ };
+ Type type = Resource;
+ std::optional<int> frameSlotToBeReleasedIn;
+ QD3D12ObjectHandle handle;
+ QD3D12CpuDescriptorPool *poolForViews = nullptr;
+ QD3D12Descriptor viewsStart;
+ int viewCount = 0;
+ std::function<void(void*)> callback = nullptr;
+ void *callbackUserData = nullptr;
+ QPair<ID3D12Resource *, D3D12MA::Allocation *> resourceAndAllocation = {};
+ ID3D12DescriptorHeap *descriptorHeap = nullptr;
+ };
+ QVector<DeferredReleaseEntry> queue;
+ QD3D12ObjectPool<QD3D12Resource> *resourcePool = nullptr;
+ QD3D12ObjectPool<QD3D12Pipeline> *pipelinePool = nullptr;
+ QD3D12ObjectPool<QD3D12RootSignature> *rootSignaturePool = nullptr;
+};
+
+struct QD3D12CommandBuffer;
+
+struct QD3D12ResourceBarrierGenerator
+{
+ static const int PREALLOC = 16;
+
+ void create(QD3D12ObjectPool<QD3D12Resource> *resourcePool)
+ {
+ this->resourcePool = resourcePool;
+ }
+
+ void addTransitionBarrier(const QD3D12ObjectHandle &resourceHandle, D3D12_RESOURCE_STATES stateAfter);
+ void enqueueBufferedTransitionBarriers(QD3D12CommandBuffer *cbD);
+ void enqueueSubresourceTransitionBarrier(QD3D12CommandBuffer *cbD,
+ const QD3D12ObjectHandle &resourceHandle,
+ UINT subresource,
+ D3D12_RESOURCE_STATES stateBefore,
+ D3D12_RESOURCE_STATES stateAfter);
+ void enqueueUavBarrier(QD3D12CommandBuffer *cbD, const QD3D12ObjectHandle &resourceHandle);
+
+ struct TransitionResourceBarrier {
+ QD3D12ObjectHandle resourceHandle;
+ D3D12_RESOURCE_STATES stateBefore;
+ D3D12_RESOURCE_STATES stateAfter;
+ };
+ QVarLengthArray<TransitionResourceBarrier, PREALLOC> transitionResourceBarriers;
+ QD3D12ObjectPool<QD3D12Resource> *resourcePool = nullptr;
+};
+
+struct QD3D12ShaderBytecodeCache
+{
+ struct Shader {
+ Shader() = default;
+ Shader(const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm)
+ : bytecode(bytecode), nativeResourceBindingMap(rbm)
+ { }
+ QByteArray bytecode;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ };
+
+ QHash<QRhiShaderStage, Shader> data;
+
+ void insertWithCapacityLimit(const QRhiShaderStage &key, const Shader &s);
+};
+
+struct QD3D12ShaderVisibleDescriptorHeap
+{
+ bool create(ID3D12Device *device, D3D12_DESCRIPTOR_HEAP_TYPE type, quint32 perFrameDescriptorCount);
+ void destroy();
+ void destroyWithDeferredRelease(QD3D12ReleaseQueue *releaseQueue);
+
+ QD3D12DescriptorHeap heap;
+ QD3D12DescriptorHeap perFrameHeapSlice[QD3D12_FRAMES_IN_FLIGHT];
+};
+
+// wrap foreign struct so we can legally supply equality operators and qHash:
+struct Q_D3D12_SAMPLER_DESC
+{
+ D3D12_SAMPLER_DESC desc;
+
+ friend bool operator==(const Q_D3D12_SAMPLER_DESC &lhs, const Q_D3D12_SAMPLER_DESC &rhs) noexcept
+ {
+ return lhs.desc.Filter == rhs.desc.Filter
+ && lhs.desc.AddressU == rhs.desc.AddressU
+ && lhs.desc.AddressV == rhs.desc.AddressV
+ && lhs.desc.AddressW == rhs.desc.AddressW
+ && lhs.desc.MipLODBias == rhs.desc.MipLODBias
+ && lhs.desc.MaxAnisotropy == rhs.desc.MaxAnisotropy
+ && lhs.desc.ComparisonFunc == rhs.desc.ComparisonFunc
+ // BorderColor is never used, skip it
+ && lhs.desc.MinLOD == rhs.desc.MinLOD
+ && lhs.desc.MaxLOD == rhs.desc.MaxLOD;
+ }
+
+ friend bool operator!=(const Q_D3D12_SAMPLER_DESC &lhs, const Q_D3D12_SAMPLER_DESC &rhs) noexcept
+ {
+ return !(lhs == rhs);
+ }
+
+ friend size_t qHash(const Q_D3D12_SAMPLER_DESC &key, size_t seed = 0) noexcept
+ {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, key.desc.Filter);
+ seed = hash(seed, key.desc.AddressU);
+ seed = hash(seed, key.desc.AddressV);
+ seed = hash(seed, key.desc.AddressW);
+ seed = hash(seed, key.desc.MipLODBias);
+ seed = hash(seed, key.desc.MaxAnisotropy);
+ seed = hash(seed, key.desc.ComparisonFunc);
+ // BorderColor is never used, skip it
+ seed = hash(seed, key.desc.MinLOD);
+ seed = hash(seed, key.desc.MaxLOD);
+ return seed;
+ }
+};
+
+struct QD3D12SamplerManager
+{
+ const quint32 MAX_SAMPLERS = 512;
+
+ bool create(ID3D12Device *device);
+ void destroy();
+
+ QD3D12Descriptor getShaderVisibleDescriptor(const D3D12_SAMPLER_DESC &desc);
+
+ ID3D12Device *device = nullptr;
+ QD3D12ShaderVisibleDescriptorHeap shaderVisibleSamplerHeap;
+ QHash<Q_D3D12_SAMPLER_DESC, QD3D12Descriptor> gpuMap;
+};
+
+enum QD3D12Stage { VS = 0, HS, DS, GS, PS, CS };
+
+static inline QD3D12Stage qd3d12_stage(QRhiShaderStage::Type type)
+{
+ switch (type) {
+ case QRhiShaderStage::Vertex:
+ return VS;
+ case QRhiShaderStage::TessellationControl:
+ return HS;
+ case QRhiShaderStage::TessellationEvaluation:
+ return DS;
+ case QRhiShaderStage::Geometry:
+ return GS;
+ case QRhiShaderStage::Fragment:
+ return PS;
+ case QRhiShaderStage::Compute:
+ return CS;
+ }
+ Q_UNREACHABLE_RETURN(VS);
+}
+
+static inline D3D12_SHADER_VISIBILITY qd3d12_stageToVisibility(QD3D12Stage s)
+{
+ switch (s) {
+ case VS:
+ return D3D12_SHADER_VISIBILITY_VERTEX;
+ case HS:
+ return D3D12_SHADER_VISIBILITY_HULL;
+ case DS:
+ return D3D12_SHADER_VISIBILITY_DOMAIN;
+ case GS:
+ return D3D12_SHADER_VISIBILITY_GEOMETRY;
+ case PS:
+ return D3D12_SHADER_VISIBILITY_PIXEL;
+ case CS:
+ return D3D12_SHADER_VISIBILITY_ALL;
+ }
+ Q_UNREACHABLE_RETURN(D3D12_SHADER_VISIBILITY_ALL);
+}
+
+static inline QRhiShaderResourceBinding::StageFlag qd3d12_stageToSrb(QD3D12Stage s)
+{
+ switch (s) {
+ case VS:
+ return QRhiShaderResourceBinding::VertexStage;
+ case HS:
+ return QRhiShaderResourceBinding::TessellationControlStage;
+ case DS:
+ return QRhiShaderResourceBinding::TessellationEvaluationStage;
+ case GS:
+ return QRhiShaderResourceBinding::GeometryStage;
+ case PS:
+ return QRhiShaderResourceBinding::FragmentStage;
+ case CS:
+ return QRhiShaderResourceBinding::ComputeStage;
+ }
+ Q_UNREACHABLE_RETURN(QRhiShaderResourceBinding::VertexStage);
+}
+
+struct QD3D12ShaderStageData
+{
+ bool valid = false; // to allow simple arrays where unused stages are indicated by !valid
+ QD3D12Stage stage = VS;
+ QShader::NativeResourceBindingMap nativeResourceBindingMap;
+};
+
+struct QD3D12ShaderResourceBindings;
+
+struct QD3D12ShaderResourceVisitor
+{
+ enum StorageOp { Load = 0, Store, LoadStore };
+
+ QD3D12ShaderResourceVisitor(const QD3D12ShaderResourceBindings *srb,
+ const QD3D12ShaderStageData *stageData,
+ int stageCount)
+ : srb(srb),
+ stageData(stageData),
+ stageCount(stageCount)
+ {
+ }
+
+ std::function<void(QD3D12Stage, const QRhiShaderResourceBinding::Data::UniformBufferData &, int, int)> uniformBuffer = nullptr;
+ std::function<void(QD3D12Stage, const QRhiShaderResourceBinding::TextureAndSampler &, int)> texture = nullptr;
+ std::function<void(QD3D12Stage, const QRhiShaderResourceBinding::TextureAndSampler &, int)> sampler = nullptr;
+ std::function<void(QD3D12Stage, const QRhiShaderResourceBinding::Data::StorageImageData &, StorageOp, int)> storageImage = nullptr;
+ std::function<void(QD3D12Stage, const QRhiShaderResourceBinding::Data::StorageBufferData &, StorageOp, int)> storageBuffer = nullptr;
+
+ void visit();
+
+ const QD3D12ShaderResourceBindings *srb;
+ const QD3D12ShaderStageData *stageData;
+ int stageCount;
+};
+
+struct QD3D12Readback
+{
+ // common
+ int frameSlot = -1;
+ QRhiReadbackResult *result = nullptr;
+ QD3D12StagingArea staging;
+ quint32 byteSize = 0;
+ // textures
+ quint32 bytesPerLine = 0;
+ QSize pixelSize;
+ QRhiTexture::Format format = QRhiTexture::UnknownFormat;
+ quint32 stagingRowPitch = 0;
+};
+
+struct QD3D12MipmapGenerator
+{
+ bool create(QRhiD3D12 *rhiD);
+ void destroy();
+ void generate(QD3D12CommandBuffer *cbD, const QD3D12ObjectHandle &textureHandle);
+
+ QRhiD3D12 *rhiD;
+ QD3D12ObjectHandle rootSigHandle;
+ QD3D12ObjectHandle pipelineHandle;
+};
+
+struct QD3D12MemoryAllocator
+{
+ bool create(ID3D12Device *device, IDXGIAdapter1 *adapter);
+ void destroy();
+
+ HRESULT createResource(D3D12_HEAP_TYPE heapType,
+ const D3D12_RESOURCE_DESC *resourceDesc,
+ D3D12_RESOURCE_STATES initialState,
+ const D3D12_CLEAR_VALUE *optimizedClearValue,
+ D3D12MA::Allocation **maybeAllocation,
+ REFIID riidResource,
+ void **ppvResource);
+
+ void getBudget(D3D12MA::Budget *localBudget, D3D12MA::Budget *nonLocalBudget);
+
+ bool isUsingD3D12MA() const { return allocator != nullptr; }
+
+ ID3D12Device *device = nullptr;
+ D3D12MA::Allocator *allocator = nullptr;
+};
+
+struct QD3D12Buffer : public QRhiBuffer
+{
+ QD3D12Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
+ ~QD3D12Buffer();
+
+ void destroy() override;
+ bool create() override;
+ QRhiBuffer::NativeBuffer nativeBuffer() override;
+ char *beginFullDynamicBufferUpdateForCurrentFrame() override;
+ void endFullDynamicBufferUpdateForCurrentFrame() override;
+
+ void executeHostWritesForFrameSlot(int frameSlot);
+
+ QD3D12ObjectHandle handles[QD3D12_FRAMES_IN_FLIGHT] = {};
+ struct HostWrite {
+ quint32 offset;
+ QRhiBufferData data;
+ };
+ QVarLengthArray<HostWrite, 16> pendingHostWrites[QD3D12_FRAMES_IN_FLIGHT];
+ friend class QRhiD3D12;
+ friend struct QD3D12CommandBuffer;
+};
+
+struct QD3D12RenderBuffer : public QRhiRenderBuffer
+{
+ QD3D12RenderBuffer(QRhiImplementation *rhi,
+ Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ Flags flags,
+ QRhiTexture::Format backingFormatHint);
+ ~QD3D12RenderBuffer();
+ void destroy() override;
+ bool create() override;
+ QRhiTexture::Format backingFormat() const override;
+
+ static const DXGI_FORMAT DS_FORMAT = DXGI_FORMAT_D24_UNORM_S8_UINT;
+
+ QD3D12ObjectHandle handle;
+ QD3D12Descriptor rtv;
+ QD3D12Descriptor dsv;
+ DXGI_FORMAT dxgiFormat;
+ DXGI_SAMPLE_DESC sampleDesc;
+ uint generation = 0;
+ friend class QRhiD3D12;
+};
+
+struct QD3D12Texture : public QRhiTexture
+{
+ QD3D12Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
+ int arraySize, int sampleCount, Flags flags);
+ ~QD3D12Texture();
+ void destroy() override;
+ bool create() override;
+ bool createFrom(NativeTexture src) override;
+ NativeTexture nativeTexture() override;
+ void setNativeLayout(int layout) override;
+
+ bool prepareCreate(QSize *adjustedSize = nullptr);
+ bool finishCreate();
+
+ QD3D12ObjectHandle handle;
+ QD3D12Descriptor srv;
+ DXGI_FORMAT dxgiFormat;
+ DXGI_FORMAT srvFormat;
+ DXGI_FORMAT rtFormat; // RTV/DSV/UAV
+ uint mipLevelCount;
+ DXGI_SAMPLE_DESC sampleDesc;
+ uint generation = 0;
+ friend class QRhiD3D12;
+ friend struct QD3D12CommandBuffer;
+};
+
+struct QD3D12Sampler : public QRhiSampler
+{
+ QD3D12Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v, AddressMode w);
+ ~QD3D12Sampler();
+ void destroy() override;
+ bool create() override;
+
+ QD3D12Descriptor lookupOrCreateShaderVisibleDescriptor();
+
+ D3D12_SAMPLER_DESC desc = {};
+ QD3D12Descriptor shaderVisibleDescriptor;
+};
+
+struct QD3D12RenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QD3D12RenderPassDescriptor(QRhiImplementation *rhi);
+ ~QD3D12RenderPassDescriptor();
+ void destroy() override;
+ bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
+ QVector<quint32> serializedFormat() const override;
+
+ void updateSerializedFormat();
+
+ static const int MAX_COLOR_ATTACHMENTS = 8;
+ int colorAttachmentCount = 0;
+ bool hasDepthStencil = false;
+ int colorFormat[MAX_COLOR_ATTACHMENTS];
+ int dsFormat;
+ QVector<quint32> serializedFormatData;
+};
+
+struct QD3D12RenderTargetData
+{
+ QD3D12RenderTargetData(QRhiImplementation *) { }
+
+ QD3D12RenderPassDescriptor *rp = nullptr;
+ QSize pixelSize;
+ float dpr = 1;
+ int sampleCount = 1;
+ int colorAttCount = 0;
+ int dsAttCount = 0;
+ QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList;
+ static const int MAX_COLOR_ATTACHMENTS = QD3D12RenderPassDescriptor::MAX_COLOR_ATTACHMENTS;
+ D3D12_CPU_DESCRIPTOR_HANDLE rtv[MAX_COLOR_ATTACHMENTS];
+ D3D12_CPU_DESCRIPTOR_HANDLE dsv;
+};
+
+struct QD3D12SwapChainRenderTarget : public QRhiSwapChainRenderTarget
+{
+ QD3D12SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
+ ~QD3D12SwapChainRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QD3D12RenderTargetData d;
+};
+
+struct QD3D12TextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QD3D12TextureRenderTarget(QRhiImplementation *rhi,
+ const QRhiTextureRenderTargetDescription &desc,
+ Flags flags);
+ ~QD3D12TextureRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool create() override;
+
+ QD3D12RenderTargetData d;
+ bool ownsRtv[QD3D12RenderTargetData::MAX_COLOR_ATTACHMENTS];
+ QD3D12Descriptor rtv[QD3D12RenderTargetData::MAX_COLOR_ATTACHMENTS];
+ bool ownsDsv = false;
+ QD3D12Descriptor dsv;
+ friend class QRhiD3D12;
+};
+
+struct QD3D12ShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QD3D12ShaderResourceBindings(QRhiImplementation *rhi);
+ ~QD3D12ShaderResourceBindings();
+ void destroy() override;
+ bool create() override;
+ void updateResources(UpdateFlags flags) override;
+
+ QD3D12ObjectHandle createRootSignature(const QD3D12ShaderStageData *stageData, int stageCount);
+
+ struct VisitorData {
+ QVarLengthArray<D3D12_ROOT_PARAMETER1, 2> cbParams[6];
+
+ D3D12_ROOT_PARAMETER1 srvTables[6] = {};
+ QVarLengthArray<D3D12_DESCRIPTOR_RANGE1, 4> srvRanges[6];
+ quint32 currentSrvRangeOffset[6] = {};
+
+ QVarLengthArray<D3D12_ROOT_PARAMETER1, 4> samplerTables[6];
+ std::array<D3D12_DESCRIPTOR_RANGE1, 16> samplerRanges[6] = {};
+ int samplerRangeHeads[6] = {};
+
+ D3D12_ROOT_PARAMETER1 uavTables[6] = {};
+ QVarLengthArray<D3D12_DESCRIPTOR_RANGE1, 4> uavRanges[6];
+ quint32 currentUavRangeOffset[6] = {};
+ } visitorData;
+
+
+ void visitUniformBuffer(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::UniformBufferData &d,
+ int shaderRegister,
+ int binding);
+ void visitTexture(QD3D12Stage s,
+ const QRhiShaderResourceBinding::TextureAndSampler &d,
+ int shaderRegister);
+ void visitSampler(QD3D12Stage s,
+ const QRhiShaderResourceBinding::TextureAndSampler &d,
+ int shaderRegister);
+ void visitStorageBuffer(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::StorageBufferData &d,
+ QD3D12ShaderResourceVisitor::StorageOp op,
+ int shaderRegister);
+ void visitStorageImage(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::StorageImageData &d,
+ QD3D12ShaderResourceVisitor::StorageOp op,
+ int shaderRegister);
+
+ bool hasDynamicOffset = false;
+ uint generation = 0;
+
+ friend class QRhiD3D12;
+ friend struct QD3D12ShaderResourceVisitor;
+};
+
+struct QD3D12GraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QD3D12GraphicsPipeline(QRhiImplementation *rhi);
+ ~QD3D12GraphicsPipeline();
+ void destroy() override;
+ bool create() override;
+
+ QD3D12ObjectHandle handle;
+ QD3D12ObjectHandle rootSigHandle;
+ std::array<QD3D12ShaderStageData, 5> stageData;
+ D3D12_PRIMITIVE_TOPOLOGY topology;
+ UINT viewInstanceMask = 0;
+ uint generation = 0;
+ friend class QRhiD3D12;
+};
+
+struct QD3D12ComputePipeline : public QRhiComputePipeline
+{
+ QD3D12ComputePipeline(QRhiImplementation *rhi);
+ ~QD3D12ComputePipeline();
+ void destroy() override;
+ bool create() override;
+
+ QD3D12ObjectHandle handle;
+ QD3D12ObjectHandle rootSigHandle;
+ QD3D12ShaderStageData stageData;
+ uint generation = 0;
+ friend class QRhiD3D12;
+};
+
+struct QD3D12CommandBuffer : public QRhiCommandBuffer
+{
+ QD3D12CommandBuffer(QRhiImplementation *rhi);
+ ~QD3D12CommandBuffer();
+ void destroy() override;
+
+ const QRhiNativeHandles *nativeHandles();
+
+ ID3D12GraphicsCommandList1 *cmdList = nullptr; // not owned
+ QRhiD3D12CommandBufferNativeHandles nativeHandlesStruct;
+
+ enum PassType {
+ NoPass,
+ RenderPass,
+ ComputePass
+ };
+
+ void resetState()
+ {
+ recordingPass = NoPass;
+ currentTarget = nullptr;
+
+ resetPerPassState();
+ }
+
+ void resetPerPassState()
+ {
+ currentGraphicsPipeline = nullptr;
+ currentComputePipeline = nullptr;
+ currentPipelineGeneration = 0;
+ currentGraphicsSrb = nullptr;
+ currentComputeSrb = nullptr;
+ currentSrbGeneration = 0;
+ currentIndexBuffer = {};
+ currentIndexOffset = 0;
+ currentIndexFormat = DXGI_FORMAT_R16_UINT;
+ currentVertexBuffers = {};
+ currentVertexOffsets = {};
+ }
+
+ // per-frame
+ PassType recordingPass;
+ QRhiRenderTarget *currentTarget;
+
+ // per-pass
+ QD3D12GraphicsPipeline *currentGraphicsPipeline;
+ QD3D12ComputePipeline *currentComputePipeline;
+ uint currentPipelineGeneration;
+ QRhiShaderResourceBindings *currentGraphicsSrb;
+ QRhiShaderResourceBindings *currentComputeSrb;
+ uint currentSrbGeneration;
+ QD3D12ObjectHandle currentIndexBuffer;
+ quint32 currentIndexOffset;
+ DXGI_FORMAT currentIndexFormat;
+ std::array<QD3D12ObjectHandle, D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> currentVertexBuffers;
+ std::array<quint32, D3D12_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT> currentVertexOffsets;
+
+ // global
+ double lastGpuTime = 0;
+
+ // per-setShaderResources
+ struct VisitorData {
+ QVarLengthArray<QPair<QD3D12ObjectHandle, quint32>, 4> cbufs[6];
+ QVarLengthArray<QD3D12Descriptor, 8> srvs[6];
+ QVarLengthArray<QD3D12Descriptor, 8> samplers[6];
+ QVarLengthArray<QPair<QD3D12ObjectHandle, D3D12_UNORDERED_ACCESS_VIEW_DESC>, 4> uavs[6];
+ } visitorData;
+
+ void visitUniformBuffer(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::UniformBufferData &d,
+ int shaderRegister,
+ int binding,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets);
+ void visitTexture(QD3D12Stage s,
+ const QRhiShaderResourceBinding::TextureAndSampler &d,
+ int shaderRegister);
+ void visitSampler(QD3D12Stage s,
+ const QRhiShaderResourceBinding::TextureAndSampler &d,
+ int shaderRegister);
+ void visitStorageBuffer(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::StorageBufferData &d,
+ QD3D12ShaderResourceVisitor::StorageOp op,
+ int shaderRegister);
+ void visitStorageImage(QD3D12Stage s,
+ const QRhiShaderResourceBinding::Data::StorageImageData &d,
+ QD3D12ShaderResourceVisitor::StorageOp op,
+ int shaderRegister);
+};
+
+struct QD3D12SwapChain : public QRhiSwapChain
+{
+ QD3D12SwapChain(QRhiImplementation *rhi);
+ ~QD3D12SwapChain();
+ void destroy() override;
+
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+ QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override;
+
+ QSize surfacePixelSize() override;
+ bool isFormatSupported(Format f) override;
+ QRhiSwapChainHdrInfo hdrInfo() override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool createOrResize() override;
+
+ void releaseBuffers();
+ void waitCommandCompletionForFrameSlot(int frameSlot);
+ void addCommandCompletionSignalForCurrentFrameSlot();
+ void chooseFormats();
+
+ QWindow *window = nullptr;
+ IDXGISwapChain1 *sourceSwapChain1 = nullptr;
+ IDXGISwapChain3 *swapChain = nullptr;
+ QSize pixelSize;
+ UINT swapInterval = 1;
+ UINT swapChainFlags = 0;
+ BOOL stereo = false;
+ DXGI_FORMAT colorFormat;
+ DXGI_FORMAT srgbAdjustedColorFormat;
+ DXGI_COLOR_SPACE_TYPE hdrColorSpace;
+ IDCompositionTarget *dcompTarget = nullptr;
+ IDCompositionVisual *dcompVisual = nullptr;
+ static const UINT BUFFER_COUNT = 3;
+ QD3D12ObjectHandle colorBuffers[BUFFER_COUNT];
+ QD3D12Descriptor rtvs[BUFFER_COUNT];
+ QD3D12Descriptor rtvsRight[BUFFER_COUNT];
+ DXGI_SAMPLE_DESC sampleDesc;
+ QD3D12ObjectHandle msaaBuffers[BUFFER_COUNT];
+ QD3D12Descriptor msaaRtvs[BUFFER_COUNT];
+ QD3D12RenderBuffer *ds = nullptr;
+ UINT currentBackBufferIndex = 0;
+ QD3D12SwapChainRenderTarget rtWrapper;
+ QD3D12SwapChainRenderTarget rtWrapperRight;
+ QD3D12CommandBuffer cbWrapper;
+
+ struct FrameResources {
+ ID3D12Fence *fence = nullptr;
+ HANDLE fenceEvent = nullptr;
+ UINT64 fenceCounter = 0;
+ ID3D12GraphicsCommandList1 *cmdList = nullptr;
+ } frameRes[QD3D12_FRAMES_IN_FLIGHT];
+
+ int currentFrameSlot = 0; // index in frameRes
+};
+
+template<typename T, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type>
+struct alignas(void*) QD3D12PipelineStateSubObject
+{
+ D3D12_PIPELINE_STATE_SUBOBJECT_TYPE type = Type;
+ T object = {};
+};
+
+class QRhiD3D12 : public QRhiImplementation
+{
+public:
+ // 16MB * QD3D12_FRAMES_IN_FLIGHT; buffer and texture upload staging data that
+ // gets no space from this will get their own temporary staging areas.
+ static const quint32 SMALL_STAGING_AREA_BYTES_PER_FRAME = 16 * 1024 * 1024;
+
+ static const quint32 SHADER_VISIBLE_CBV_SRV_UAV_HEAP_PER_FRAME_START_SIZE = 16384;
+
+ QRhiD3D12(QRhiD3D12InitParams *params, QRhiD3D12NativeHandles *importDevice = nullptr);
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiComputePipeline *createComputePipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ quint32 size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int depth,
+ int arraySize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ void beginComputePass(QRhiCommandBuffer *cb,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+ void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
+ void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+ double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
+
+ QList<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ QRhiDriverInfo driverInfo() const override;
+ QRhiStats statistics() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
+
+ QByteArray pipelineCacheData() override;
+ void setPipelineCacheData(const QByteArray &data) override;
+
+ void waitGpu();
+ DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount, DXGI_FORMAT format) const;
+ bool ensureDirectCompositionDevice();
+ bool startCommandListForCurrentFrameSlot(ID3D12GraphicsCommandList1 **cmdList);
+ void enqueueResourceUpdates(QD3D12CommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates);
+ void finishActiveReadbacks(bool forced = false);
+ bool ensureShaderVisibleDescriptorHeapCapacity(QD3D12ShaderVisibleDescriptorHeap *h,
+ D3D12_DESCRIPTOR_HEAP_TYPE type,
+ int frameSlot,
+ quint32 neededDescriptorCount,
+ bool *gotNew);
+ void bindShaderVisibleHeaps(QD3D12CommandBuffer *cbD);
+
+ bool debugLayer = false;
+ ID3D12Device2 *dev = nullptr;
+ D3D_FEATURE_LEVEL minimumFeatureLevel = D3D_FEATURE_LEVEL(0);
+ LUID adapterLuid = {};
+ bool importedDevice = false;
+ bool importedCommandQueue = false;
+ QRhi::Flags rhiFlags;
+ IDXGIFactory2 *dxgiFactory = nullptr;
+ bool supportsAllowTearing = false;
+ IDXGIAdapter1 *activeAdapter = nullptr;
+ QRhiDriverInfo driverInfoStruct;
+ QRhiD3D12NativeHandles nativeHandlesStruct;
+ bool deviceLost = false;
+ ID3D12CommandQueue *cmdQueue = nullptr;
+ ID3D12Fence *fullFence = nullptr;
+ HANDLE fullFenceEvent = nullptr;
+ UINT64 fullFenceCounter = 0;
+ ID3D12CommandAllocator *cmdAllocators[QD3D12_FRAMES_IN_FLIGHT] = {};
+ QD3D12MemoryAllocator vma;
+ QD3D12CpuDescriptorPool rtvPool;
+ QD3D12CpuDescriptorPool dsvPool;
+ QD3D12CpuDescriptorPool cbvSrvUavPool;
+ QD3D12ObjectPool<QD3D12Resource> resourcePool;
+ QD3D12ObjectPool<QD3D12Pipeline> pipelinePool;
+ QD3D12ObjectPool<QD3D12RootSignature> rootSignaturePool;
+ QD3D12ReleaseQueue releaseQueue;
+ QD3D12ResourceBarrierGenerator barrierGen;
+ QD3D12SamplerManager samplerMgr;
+ QD3D12MipmapGenerator mipmapGen;
+ QD3D12StagingArea smallStagingAreas[QD3D12_FRAMES_IN_FLIGHT];
+ QD3D12ShaderVisibleDescriptorHeap shaderVisibleCbvSrvUavHeap;
+ UINT64 timestampTicksPerSecond = 0;
+ QD3D12QueryHeap timestampQueryHeap;
+ QD3D12StagingArea timestampReadbackArea;
+ IDCompositionDevice *dcompDevice = nullptr;
+ QD3D12SwapChain *currentSwapChain = nullptr;
+ QSet<QD3D12SwapChain *> swapchains;
+ QD3D12ShaderBytecodeCache shaderBytecodeCache;
+ QVarLengthArray<QD3D12Readback, 4> activeReadbacks;
+ bool offscreenActive = false;
+ QD3D12CommandBuffer *offscreenCb[QD3D12_FRAMES_IN_FLIGHT] = {};
+
+ struct {
+ bool multiView = false;
+ bool textureViewFormat = false;
+ } caps;
+};
+
+QT_END_NAMESPACE
+
+#endif // __ID3D12Device2_INTERFACE_DEFINED__
+
+#endif
diff --git a/src/gui/rhi/qrhid3dhelpers.cpp b/src/gui/rhi/qrhid3dhelpers.cpp
new file mode 100644
index 0000000000..216c358cbe
--- /dev/null
+++ b/src/gui/rhi/qrhid3dhelpers.cpp
@@ -0,0 +1,172 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhid3dhelpers_p.h"
+#include <QtCore/private/qsystemlibrary_p.h>
+#include <QtCore/private/qsystemerror_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QRhiD3D {
+
+bool output6ForWindow(QWindow *w, IDXGIAdapter1 *adapter, IDXGIOutput6 **result)
+{
+ bool ok = false;
+ QRect wr = w->geometry();
+ wr = QRect(wr.topLeft() * w->devicePixelRatio(), wr.size() * w->devicePixelRatio());
+ const QPoint center = wr.center();
+ IDXGIOutput *currentOutput = nullptr;
+ IDXGIOutput *output = nullptr;
+ for (UINT i = 0; adapter->EnumOutputs(i, &output) != DXGI_ERROR_NOT_FOUND; ++i) {
+ DXGI_OUTPUT_DESC desc;
+ output->GetDesc(&desc);
+ const RECT r = desc.DesktopCoordinates;
+ const QRect dr(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
+ if (dr.contains(center)) {
+ currentOutput = output;
+ break;
+ } else {
+ output->Release();
+ }
+ }
+ if (currentOutput) {
+ ok = SUCCEEDED(currentOutput->QueryInterface(__uuidof(IDXGIOutput6), reinterpret_cast<void **>(result)));
+ currentOutput->Release();
+ }
+ return ok;
+}
+
+bool outputDesc1ForWindow(QWindow *w, IDXGIAdapter1 *adapter, DXGI_OUTPUT_DESC1 *result)
+{
+ bool ok = false;
+ IDXGIOutput6 *out6 = nullptr;
+ if (output6ForWindow(w, adapter, &out6)) {
+ ok = SUCCEEDED(out6->GetDesc1(result));
+ out6->Release();
+ }
+ return ok;
+}
+
+float sdrWhiteLevelInNits(const DXGI_OUTPUT_DESC1 &outputDesc)
+{
+ QVector<DISPLAYCONFIG_PATH_INFO> pathInfos;
+ uint32_t pathInfoCount, modeInfoCount;
+ LONG result;
+ do {
+ if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathInfoCount, &modeInfoCount) == ERROR_SUCCESS) {
+ pathInfos.resize(pathInfoCount);
+ QVector<DISPLAYCONFIG_MODE_INFO> modeInfos(modeInfoCount);
+ result = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathInfoCount, pathInfos.data(), &modeInfoCount, modeInfos.data(), nullptr);
+ } else {
+ return 200.0f;
+ }
+ } while (result == ERROR_INSUFFICIENT_BUFFER);
+
+ MONITORINFOEX monitorInfo = {};
+ monitorInfo.cbSize = sizeof(monitorInfo);
+ GetMonitorInfo(outputDesc.Monitor, &monitorInfo);
+
+ for (const DISPLAYCONFIG_PATH_INFO &info : pathInfos) {
+ DISPLAYCONFIG_SOURCE_DEVICE_NAME deviceName = {};
+ deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
+ deviceName.header.size = sizeof(deviceName);
+ deviceName.header.adapterId = info.sourceInfo.adapterId;
+ deviceName.header.id = info.sourceInfo.id;
+ if (DisplayConfigGetDeviceInfo(&deviceName.header) == ERROR_SUCCESS) {
+ if (!wcscmp(monitorInfo.szDevice, deviceName.viewGdiDeviceName)) {
+ DISPLAYCONFIG_SDR_WHITE_LEVEL whiteLevel = {};
+ whiteLevel.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL;
+ whiteLevel.header.size = sizeof(DISPLAYCONFIG_SDR_WHITE_LEVEL);
+ whiteLevel.header.adapterId = info.targetInfo.adapterId;
+ whiteLevel.header.id = info.targetInfo.id;
+ if (DisplayConfigGetDeviceInfo(&whiteLevel.header) == ERROR_SUCCESS)
+ return whiteLevel.SDRWhiteLevel * 80 / 1000.0f;
+ }
+ }
+ }
+
+ return 200.0f;
+}
+
+pD3DCompile resolveD3DCompile()
+{
+ for (const wchar_t *libraryName : {L"D3DCompiler_47", L"D3DCompiler_43"}) {
+ QSystemLibrary library(libraryName);
+ if (library.load()) {
+ if (auto symbol = library.resolve("D3DCompile"))
+ return reinterpret_cast<pD3DCompile>(symbol);
+ } else {
+ qWarning("Failed to load D3DCompiler_47/43.dll");
+ }
+ }
+ return nullptr;
+}
+
+IDCompositionDevice *createDirectCompositionDevice()
+{
+ QSystemLibrary dcomplib(QStringLiteral("dcomp"));
+ typedef HRESULT (__stdcall *DCompositionCreateDeviceFuncPtr)(
+ _In_opt_ IDXGIDevice *dxgiDevice,
+ _In_ REFIID iid,
+ _Outptr_ void **dcompositionDevice);
+ DCompositionCreateDeviceFuncPtr func = reinterpret_cast<DCompositionCreateDeviceFuncPtr>(
+ dcomplib.resolve("DCompositionCreateDevice"));
+ if (!func) {
+ qWarning("Unable to resolve DCompositionCreateDevice, perhaps dcomp.dll is missing?");
+ return nullptr;
+ }
+ IDCompositionDevice *device = nullptr;
+ HRESULT hr = func(nullptr, __uuidof(IDCompositionDevice), reinterpret_cast<void **>(&device));
+ if (FAILED(hr)) {
+ qWarning("Failed to create Direct Composition device: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return nullptr;
+ }
+ return device;
+}
+
+#ifdef QRHI_D3D12_HAS_DXC
+std::pair<IDxcCompiler *, IDxcLibrary *> createDxcCompiler()
+{
+ QSystemLibrary dxclib(QStringLiteral("dxcompiler"));
+ // this will not be in the system library location, hence onlySystemDirectory==false
+ if (!dxclib.load(false)) {
+ qWarning("Failed to load dxcompiler.dll");
+ return {};
+ }
+ DxcCreateInstanceProc func = reinterpret_cast<DxcCreateInstanceProc>(dxclib.resolve("DxcCreateInstance"));
+ if (!func) {
+ qWarning("Unable to resolve DxcCreateInstance");
+ return {};
+ }
+ IDxcCompiler *compiler = nullptr;
+ HRESULT hr = func(CLSID_DxcCompiler, __uuidof(IDxcCompiler), reinterpret_cast<void**>(&compiler));
+ if (FAILED(hr)) {
+ qWarning("Failed to create dxc compiler instance: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return {};
+ }
+ IDxcLibrary *library = nullptr;
+ hr = func(CLSID_DxcLibrary, __uuidof(IDxcLibrary), reinterpret_cast<void**>(&library));
+ if (FAILED(hr)) {
+ qWarning("Failed to create dxc library instance: %s",
+ qPrintable(QSystemError::windowsComString(hr)));
+ return {};
+ }
+ return { compiler, library };
+}
+#endif
+
+void fillDriverInfo(QRhiDriverInfo *info, const DXGI_ADAPTER_DESC1 &desc)
+{
+ const QString name = QString::fromUtf16(reinterpret_cast<const char16_t *>(desc.Description));
+ info->deviceName = name.toUtf8();
+ info->deviceId = desc.DeviceId;
+ info->vendorId = desc.VendorId;
+ info->deviceType = (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) ? QRhiDriverInfo::CpuDevice
+ : QRhiDriverInfo::UnknownDevice;
+}
+
+} // namespace
+
+QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhid3dhelpers_p.h b/src/gui/rhi/qrhid3dhelpers_p.h
new file mode 100644
index 0000000000..f31cdc8d11
--- /dev/null
+++ b/src/gui/rhi/qrhid3dhelpers_p.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHID3DHELPERS_P_H
+#define QRHID3DHELPERS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <rhi/qrhi.h>
+
+#include <QtGui/qwindow.h>
+
+#include <dxgi1_6.h>
+#include <dcomp.h>
+#include <d3dcompiler.h>
+
+#if __has_include(<dxcapi.h>)
+#include <dxcapi.h>
+#define QRHI_D3D12_HAS_DXC
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QRhiD3D {
+
+bool output6ForWindow(QWindow *w, IDXGIAdapter1 *adapter, IDXGIOutput6 **result);
+bool outputDesc1ForWindow(QWindow *w, IDXGIAdapter1 *adapter, DXGI_OUTPUT_DESC1 *result);
+float sdrWhiteLevelInNits(const DXGI_OUTPUT_DESC1 &outputDesc);
+
+pD3DCompile resolveD3DCompile();
+
+IDCompositionDevice *createDirectCompositionDevice();
+
+#ifdef QRHI_D3D12_HAS_DXC
+std::pair<IDxcCompiler *, IDxcLibrary *> createDxcCompiler();
+#endif
+
+void fillDriverInfo(QRhiDriverInfo *info, const DXGI_ADAPTER_DESC1 &desc);
+
+} // namespace
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 05465e40cc..62830c291d 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -1,48 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qrhigles2_p_p.h"
-#include <QWindow>
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhigles2_p.h"
#include <QOffscreenSurface>
#include <QOpenGLContext>
+#include <QtCore/qmap.h>
#include <QtGui/private/qopenglextensions_p.h>
#include <QtGui/private/qopenglprogrambinarycache_p.h>
+#include <QtGui/private/qwindow_p.h>
+#include <qpa/qplatformopenglcontext.h>
#include <qmath.h>
QT_BEGIN_NAMESPACE
@@ -62,13 +28,17 @@ QT_BEGIN_NAMESPACE
/*!
\class QRhiGles2InitParams
- \internal
\inmodule QtGui
+ \since 6.6
\brief OpenGL specific initialization parameters.
- An OpenGL-based QRhi needs an already created QOffscreenSurface at minimum.
- Additionally, while optional, it is recommended that the QWindow the first
- QRhiSwapChain will target is passed in as well.
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
+ An OpenGL-based QRhi needs an already created QSurface that can be used in
+ combination with QOpenGLContext. Most commonly, this is a QOffscreenSurface
+ in practice. Additionally, while optional, it is recommended that the QWindow
+ the first QRhiSwapChain will target is passed in as well.
\badcode
QOffscreenSurface *fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
@@ -85,21 +55,21 @@ QT_BEGIN_NAMESPACE
thread) are satisfied. The implicitly created context is destroyed
automatically together with the QRhi.
- The QSurfaceFormat for the context is specified in \l format. The
+ The QSurfaceFormat for the context is specified in \c format. The
constructor sets this to QSurfaceFormat::defaultFormat() so applications
- that use QSurfaceFormat::setDefaultFormat() do not need to set the format
- again.
+ that call QSurfaceFormat::setDefaultFormat() with the appropriate settings
+ before the constructor runs will not need to change value of \c format.
- \note The depth and stencil buffer sizes are set automatically to 24 and 8
- when no size was explicitly set for these buffers in \l format. As there
- are possible adjustments to \l format, applications can use
- adjustedFormat() to query the effective format that is passed to
- QOpenGLContext::setFormat() internally.
+ \note Remember to set the depth and stencil buffer sizes to 24 and 8 when
+ the renderer relies on depth or stencil testing, either in the global
+ default QSurfaceFormat, or, alternatively, separately in all the involved
+ QSurfaceFormat instances: in \c format, the format argument passed to
+ newFallbackSurface(), and on any QWindow that is used with the QRhi.
- A QOffscreenSurface has to be specified in \l fallbackSurface. In order to
- prevent mistakes in threaded situations, this is never created
- automatically by the QRhi since, like QWindow, QOffscreenSurface can only
- be created on the gui/main thread.
+ A QSurface has to be specified in \c fallbackSurface. In order to prevent
+ mistakes in threaded situations, this is never created automatically by the
+ QRhi because, like QWindow, instances of QSurface subclasses can often be
+ created on the gui/main thread only.
As a convenience, applications can use newFallbackSurface() which creates
and returns a QOffscreenSurface that is compatible with the QOpenGLContext
@@ -107,23 +77,27 @@ QT_BEGIN_NAMESPACE
of the returned QOffscreenSurface is transferred to the caller and the QRhi
will not destroy it.
- \note QRhiSwapChain can only target QWindow instances that have their
- surface type set to QSurface::OpenGLSurface.
+ \note With the OpenGL backend, QRhiSwapChain can only target QWindow
+ instances that have their surface type set to QSurface::OpenGLSurface or
+ QSurface::RasterGLSurface.
- \note \l window is optional. It is recommended to specify it whenever
+ \note \c window is optional. It is recommended to specify it whenever
possible, in order to avoid problems on multi-adapter and multi-screen
- systems. When \l window is not set, the very first
- QOpenGLContext::makeCurrent() happens with \l fallbackSurface which may be
+ systems. When \c window is not set, the very first
+ QOpenGLContext::makeCurrent() happens with \c fallbackSurface which may be
an invisible window on some platforms (for example, Windows) and that may
trigger unexpected problems in some cases.
+ In case resource sharing with an existing QOpenGLContext is desired, \c
+ shareContext can be set to an existing QOpenGLContext. Alternatively,
+ Qt::AA_ShareOpenGLContexts is honored as well, when enabled.
+
\section2 Working with existing OpenGL contexts
When interoperating with another graphics engine, it may be necessary to
get a QRhi instance that uses the same OpenGL context. This can be achieved
by passing a pointer to a QRhiGles2NativeHandles to QRhi::create(). The
- \l{QRhiGles2NativeHandles::context}{context} must be set to a non-null
- value.
+ \c{QRhiGles2NativeHandles::context} must be set to a non-null value then.
An alternative approach is to create a QOpenGLContext that
\l{QOpenGLContext::setShareContext()}{shares resources} with the other
@@ -134,12 +108,50 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \variable QRhiGles2InitParams::format
+
+ The QSurfaceFormat, initialized to QSurfaceFormat::defaultFormat() by default.
+*/
+
+/*!
+ \variable QRhiGles2InitParams::fallbackSurface
+
+ A QSurface compatible with \l format. Typically a QOffscreenSurface.
+ Providing this is mandatory. Be aware of the threading implications: a
+ QOffscreenSurface, like QWindow, must only ever be created and destroyed on
+ the main (gui) thread, even if the QRhi is created and operates on another
+ thread.
+*/
+
+/*!
+ \variable QRhiGles2InitParams::window
+
+ Optional, but setting it is recommended when targeting a QWindow with the
+ QRhi.
+*/
+
+/*!
+ \variable QRhiGles2InitParams::shareContext
+
+ Optional, the QOpenGLContext to share resource with. QRhi creates its own
+ context, and setting this member to a valid QOpenGLContext leads to calling
+ \l{QOpenGLContext::setShareContext()}{setShareContext()} with it.
+*/
+
+/*!
\class QRhiGles2NativeHandles
- \internal
\inmodule QtGui
+ \since 6.6
\brief Holds the OpenGL context used by the QRhi.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
+/*!
+ \variable QRhiGles2NativeHandles::context
+*/
+
#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif
@@ -204,6 +216,10 @@ QT_BEGIN_NAMESPACE
#define GL_DEPTH_COMPONENT32F 0x8CAC
#endif
+#ifndef GL_UNSIGNED_INT_24_8
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#endif
+
#ifndef GL_STENCIL_INDEX
#define GL_STENCIL_INDEX 0x1901
#endif
@@ -229,7 +245,7 @@ QT_BEGIN_NAMESPACE
#endif
#ifndef GL_FRAMEBUFFER_SRGB
-#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
#endif
#ifndef GL_READ_FRAMEBUFFER
@@ -280,16 +296,48 @@ QT_BEGIN_NAMESPACE
#define GL_COMPUTE_SHADER 0x91B9
#endif
-#ifndef GL_ALL_BARRIER_BITS
-#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#ifndef GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#endif
+
+#ifndef GL_ELEMENT_ARRAY_BARRIER_BIT
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#endif
+
+#ifndef GL_UNIFORM_BARRIER_BIT
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#endif
+
+#ifndef GL_BUFFER_UPDATE_BARRIER_BIT
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#endif
+
+#ifndef GL_SHADER_STORAGE_BARRIER_BIT
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#endif
+
+#ifndef GL_TEXTURE_FETCH_BARRIER_BIT
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
#endif
#ifndef GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
#endif
-#ifndef GL_SHADER_STORAGE_BARRIER_BIT
-#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#ifndef GL_PIXEL_BUFFER_BARRIER_BIT
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#endif
+
+#ifndef GL_TEXTURE_UPDATE_BARRIER_BIT
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#endif
+
+#ifndef GL_FRAMEBUFFER_BARRIER_BIT
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#endif
+
+#ifndef GL_ALL_BARRIER_BITS
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
#endif
#ifndef GL_VERTEX_PROGRAM_POINT_SIZE
@@ -312,6 +360,10 @@ QT_BEGIN_NAMESPACE
#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
#endif
+#ifndef GL_TEXTURE_2D_MULTISAMPLE_ARRAY
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#endif
+
#ifndef GL_TEXTURE_EXTERNAL_OES
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
#endif
@@ -356,6 +408,126 @@ QT_BEGIN_NAMESPACE
#define GL_TEXTURE_WRAP_R 0x8072
#endif
+#ifndef GL_TEXTURE_RECTANGLE
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#endif
+
+#ifndef GL_TEXTURE_2D_ARRAY
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#endif
+
+#ifndef GL_MAX_ARRAY_TEXTURE_LAYERS
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#endif
+
+#ifndef GL_MAX_VERTEX_UNIFORM_COMPONENTS
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#endif
+
+#ifndef GL_MAX_FRAGMENT_UNIFORM_COMPONENTS
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#endif
+
+#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#endif
+
+#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#endif
+
+#ifndef GL_RGB10_A2
+#define GL_RGB10_A2 0x8059
+#endif
+
+#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#endif
+
+#ifndef GL_MAX_VARYING_COMPONENTS
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#endif
+
+#ifndef GL_MAX_VARYING_FLOATS
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#endif
+
+#ifndef GL_MAX_VARYING_VECTORS
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#endif
+
+#ifndef GL_TESS_CONTROL_SHADER
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#endif
+
+#ifndef GL_TESS_EVALUATION_SHADER
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#endif
+
+#ifndef GL_PATCH_VERTICES
+#define GL_PATCH_VERTICES 0x8E72
+#endif
+
+#ifndef GL_LINE
+#define GL_LINE 0x1B01
+#endif
+
+#ifndef GL_FILL
+#define GL_FILL 0x1B02
+#endif
+
+#ifndef GL_PATCHES
+#define GL_PATCHES 0x000E
+#endif
+
+#ifndef GL_GEOMETRY_SHADER
+#define GL_GEOMETRY_SHADER 0x8DD9
+#endif
+
+#ifndef GL_BACK_LEFT
+#define GL_BACK_LEFT 0x0402
+#endif
+
+#ifndef GL_BACK_RIGHT
+#define GL_BACK_RIGHT 0x0403
+#endif
+
+#ifndef GL_TEXTURE_1D
+# define GL_TEXTURE_1D 0x0DE0
+#endif
+
+#ifndef GL_TEXTURE_1D_ARRAY
+# define GL_TEXTURE_1D_ARRAY 0x8C18
+#endif
+
+#ifndef GL_HALF_FLOAT
+#define GL_HALF_FLOAT 0x140B
+#endif
+
+#ifndef GL_MAX_VERTEX_OUTPUT_COMPONENTS
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#endif
+
+#ifndef GL_TIMESTAMP
+#define GL_TIMESTAMP 0x8E28
+#endif
+
+#ifndef GL_QUERY_RESULT
+#define GL_QUERY_RESULT 0x8866
+#endif
+
+#ifndef GL_QUERY_RESULT_AVAILABLE
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#endif
+
+#ifndef GL_BUFFER
+#define GL_BUFFER 0x82E0
+#endif
+
+#ifndef GL_PROGRAM
+#define GL_PROGRAM 0x82E2
+#endif
+
/*!
Constructs a new QRhiGles2InitParams.
@@ -367,28 +539,12 @@ QRhiGles2InitParams::QRhiGles2InitParams()
}
/*!
- \return the QSurfaceFormat that will be set on the QOpenGLContext before
- calling QOpenGLContext::create(). This format is based on \a format, but
- may be adjusted. Applicable only when QRhi creates the context.
- Applications are advised to set this format on their QWindow in order to
- avoid potential BAD_MATCH failures.
- */
-QSurfaceFormat QRhiGles2InitParams::adjustedFormat(const QSurfaceFormat &format)
-{
- QSurfaceFormat fmt = format;
-
- if (fmt.depthBufferSize() == -1)
- fmt.setDepthBufferSize(24);
- if (fmt.stencilBufferSize() == -1)
- fmt.setStencilBufferSize(8);
-
- return fmt;
-}
-
-/*!
\return a new QOffscreenSurface that can be used with a QRhi by passing it
via a QRhiGles2InitParams.
+ When \a format is not specified, its default value is the global default
+ format settable via QSurfaceFormat::setDefaultFormat().
+
\a format is adjusted as appropriate in order to avoid having problems
afterwards due to an incompatible context and surface.
@@ -400,7 +556,7 @@ QSurfaceFormat QRhiGles2InitParams::adjustedFormat(const QSurfaceFormat &format)
*/
QOffscreenSurface *QRhiGles2InitParams::newFallbackSurface(const QSurfaceFormat &format)
{
- QSurfaceFormat fmt = adjustedFormat(format);
+ QSurfaceFormat fmt = format;
// To resolve all fields in the format as much as possible, create a context.
// This may be heavy, but allows avoiding BAD_MATCH on some systems.
@@ -421,9 +577,10 @@ QOffscreenSurface *QRhiGles2InitParams::newFallbackSurface(const QSurfaceFormat
QRhiGles2::QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *importDevice)
: ofr(this)
{
- requestedFormat = QRhiGles2InitParams::adjustedFormat(params->format);
+ requestedFormat = params->format;
fallbackSurface = params->fallbackSurface;
maybeWindow = params->window; // may be null
+ maybeShareContext = params->shareContext; // may be null
importedContext = importDevice != nullptr;
if (importedContext) {
@@ -435,21 +592,50 @@ QRhiGles2::QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *import
}
}
-bool QRhiGles2::ensureContext(QSurface *surface) const
+static inline QSurface *currentSurfaceForCurrentContext(QOpenGLContext *ctx)
{
- bool nativeWindowGone = false;
- if (surface && surface->surfaceClass() == QSurface::Window && !surface->surfaceHandle()) {
- surface = fallbackSurface;
- nativeWindowGone = true;
- }
+ if (QOpenGLContext::currentContext() != ctx)
+ return nullptr;
+
+ QSurface *currentSurface = ctx->surface();
+ if (!currentSurface)
+ return nullptr;
+
+ if (currentSurface->surfaceClass() == QSurface::Window && !currentSurface->surfaceHandle())
+ return nullptr;
- if (!surface)
- surface = fallbackSurface;
+ return currentSurface;
+}
+
+QSurface *QRhiGles2::evaluateFallbackSurface() const
+{
+ // With Apple's deprecated OpenGL support we need to minimize the usage of
+ // QOffscreenSurface since delicate problems can pop up with
+ // NSOpenGLContext and drawables.
+#if defined(Q_OS_MACOS)
+ return maybeWindow && maybeWindow->handle() ? static_cast<QSurface *>(maybeWindow) : fallbackSurface;
+#else
+ return fallbackSurface;
+#endif
+}
- if (needsMakeCurrent)
- needsMakeCurrent = false;
- else if (!nativeWindowGone && QOpenGLContext::currentContext() == ctx && (surface == fallbackSurface || ctx->surface() == surface))
+bool QRhiGles2::ensureContext(QSurface *surface) const
+{
+ if (!surface) {
+ // null means any surface is good because not going to render
+ if (currentSurfaceForCurrentContext(ctx))
+ return true;
+ // if the context is not already current with a valid surface, use our
+ // fallback surface, but platform specific quirks may apply
+ surface = evaluateFallbackSurface();
+ } else if (surface->surfaceClass() == QSurface::Window && !surface->surfaceHandle()) {
+ // the window is not usable anymore (no native window underneath), behave as if offscreen
+ surface = evaluateFallbackSurface();
+ } else if (!needsMakeCurrentDueToSwap && currentSurfaceForCurrentContext(ctx) == surface) {
+ // bail out if the makeCurrent is not necessary
return true;
+ }
+ needsMakeCurrentDueToSwap = false;
if (!ctx->makeCurrent(surface)) {
if (ctx->isValid()) {
@@ -464,6 +650,58 @@ bool QRhiGles2::ensureContext(QSurface *surface) const
return true;
}
+static inline GLenum toGlCompressedTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
+{
+ const bool srgb = flags.testFlag(QRhiTexture::sRGB);
+ switch (format) {
+ case QRhiTexture::BC1:
+ return srgb ? 0x8C4C : 0x83F0;
+ case QRhiTexture::BC2:
+ return srgb ? 0x8C4E : 0x83F2;
+ case QRhiTexture::BC3:
+ return srgb ? 0x8C4F : 0x83F3;
+
+ case QRhiTexture::ETC2_RGB8:
+ return srgb ? 0x9275 : 0x9274;
+ case QRhiTexture::ETC2_RGB8A1:
+ return srgb ? 0x9277 : 0x9276;
+ case QRhiTexture::ETC2_RGBA8:
+ return srgb ? 0x9279 : 0x9278;
+
+ case QRhiTexture::ASTC_4x4:
+ return srgb ? 0x93D0 : 0x93B0;
+ case QRhiTexture::ASTC_5x4:
+ return srgb ? 0x93D1 : 0x93B1;
+ case QRhiTexture::ASTC_5x5:
+ return srgb ? 0x93D2 : 0x93B2;
+ case QRhiTexture::ASTC_6x5:
+ return srgb ? 0x93D3 : 0x93B3;
+ case QRhiTexture::ASTC_6x6:
+ return srgb ? 0x93D4 : 0x93B4;
+ case QRhiTexture::ASTC_8x5:
+ return srgb ? 0x93D5 : 0x93B5;
+ case QRhiTexture::ASTC_8x6:
+ return srgb ? 0x93D6 : 0x93B6;
+ case QRhiTexture::ASTC_8x8:
+ return srgb ? 0x93D7 : 0x93B7;
+ case QRhiTexture::ASTC_10x5:
+ return srgb ? 0x93D8 : 0x93B8;
+ case QRhiTexture::ASTC_10x6:
+ return srgb ? 0x93D9 : 0x93B9;
+ case QRhiTexture::ASTC_10x8:
+ return srgb ? 0x93DA : 0x93BA;
+ case QRhiTexture::ASTC_10x10:
+ return srgb ? 0x93DB : 0x93BB;
+ case QRhiTexture::ASTC_12x10:
+ return srgb ? 0x93DC : 0x93BC;
+ case QRhiTexture::ASTC_12x12:
+ return srgb ? 0x93DD : 0x93BD;
+
+ default:
+ return 0; // this is reachable, just return an invalid format
+ }
+}
+
bool QRhiGles2::create(QRhi::Flags flags)
{
Q_ASSERT(fallbackSurface);
@@ -472,9 +710,14 @@ bool QRhiGles2::create(QRhi::Flags flags)
if (!importedContext) {
ctx = new QOpenGLContext;
ctx->setFormat(requestedFormat);
- if (QOpenGLContext *shareContext = qt_gl_global_share_context()) {
+ if (maybeShareContext) {
+ ctx->setShareContext(maybeShareContext);
+ ctx->setScreen(maybeShareContext->screen());
+ } else if (QOpenGLContext *shareContext = qt_gl_global_share_context()) {
ctx->setShareContext(shareContext);
ctx->setScreen(shareContext->screen());
+ } else if (maybeWindow) {
+ ctx->setScreen(maybeWindow->screen());
}
if (!ctx->create()) {
qWarning("QRhiGles2: Failed to create context");
@@ -489,6 +732,40 @@ bool QRhiGles2::create(QRhi::Flags flags)
return false;
f = static_cast<QOpenGLExtensions *>(ctx->extraFunctions());
+ const QSurfaceFormat actualFormat = ctx->format();
+ caps.gles = actualFormat.renderableType() == QSurfaceFormat::OpenGLES;
+
+ if (!caps.gles) {
+ glPolygonMode = reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLenum, GLenum)>(
+ ctx->getProcAddress(QByteArrayLiteral("glPolygonMode")));
+
+ glTexImage1D = reinterpret_cast<void(QOPENGLF_APIENTRYP)(
+ GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, const void *)>(
+ ctx->getProcAddress(QByteArrayLiteral("glTexImage1D")));
+
+ glTexStorage1D = reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei)>(
+ ctx->getProcAddress(QByteArrayLiteral("glTexStorage1D")));
+
+ glTexSubImage1D = reinterpret_cast<void(QOPENGLF_APIENTRYP)(
+ GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *)>(
+ ctx->getProcAddress(QByteArrayLiteral("glTexSubImage1D")));
+
+ glCopyTexSubImage1D = reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint,
+ GLint, GLsizei)>(
+ ctx->getProcAddress(QByteArrayLiteral("glCopyTexSubImage1D")));
+
+ glCompressedTexImage1D = reinterpret_cast<void(QOPENGLF_APIENTRYP)(
+ GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid *)>(
+ ctx->getProcAddress(QByteArrayLiteral("glCompressedTexImage1D")));
+
+ glCompressedTexSubImage1D = reinterpret_cast<void(QOPENGLF_APIENTRYP)(
+ GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid *)>(
+ ctx->getProcAddress(QByteArrayLiteral("glCompressedTexSubImage1D")));
+
+ glFramebufferTexture1D =
+ reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint)>(
+ ctx->getProcAddress(QByteArrayLiteral("glFramebufferTexture1D")));
+ }
const char *vendor = reinterpret_cast<const char *>(f->glGetString(GL_VENDOR));
const char *renderer = reinterpret_cast<const char *>(f->glGetString(GL_RENDERER));
@@ -507,26 +784,78 @@ bool QRhiGles2::create(QRhi::Flags flags)
if (version)
driverInfoStruct.deviceName += QByteArray(version);
- const QSurfaceFormat actualFormat = ctx->format();
-
caps.ctxMajor = actualFormat.majorVersion();
caps.ctxMinor = actualFormat.minorVersion();
GLint n = 0;
f->glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &n);
- supportedCompressedFormats.resize(n);
- if (n > 0)
- f->glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, supportedCompressedFormats.data());
+ if (n > 0) {
+ QVarLengthArray<GLint, 16> compressedTextureFormats(n);
+ f->glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, compressedTextureFormats.data());
+ for (GLint format : compressedTextureFormats)
+ supportedCompressedFormats.insert(format);
+
+ }
+ // The above looks nice, if only it worked always. With GLES the list we
+ // query is likely the full list of compressed formats (mostly anything
+ // that can be decoded). With OpenGL however the list is not required to
+ // include all formats due to the way the spec is worded. For instance, we
+ // cannot rely on ASTC formats being present in the list on non-ES. Some
+ // drivers do include them (Intel, NVIDIA), some don't (Mesa). On the other
+ // hand, relying on extension strings only is not ok: for example, Intel
+ // reports GL_KHR_texture_compression_astc_ldr whereas NVIDIA doesn't. So
+ // the only reasonable thing to do is to query the list always and then see
+ // if there is something we can add - if not already in there.
+ std::array<QRhiTexture::Flags, 2> textureVariantFlags;
+ textureVariantFlags[0] = {};
+ textureVariantFlags[1] = QRhiTexture::sRGB;
+ if (f->hasOpenGLExtension(QOpenGLExtensions::DDSTextureCompression)) {
+ for (QRhiTexture::Flags f : textureVariantFlags) {
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC1, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC2, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::BC3, f));
+ }
+ }
+ if (f->hasOpenGLExtension(QOpenGLExtensions::ETC2TextureCompression)) {
+ for (QRhiTexture::Flags f : textureVariantFlags) {
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGB8A1, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ETC2_RGBA8, f));
+ }
+ }
+ if (f->hasOpenGLExtension(QOpenGLExtensions::ASTCTextureCompression)) {
+ for (QRhiTexture::Flags f : textureVariantFlags) {
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_4x4, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x4, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_5x5, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x5, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_6x6, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x5, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x6, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_8x8, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x5, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x8, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_10x10, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x10, f));
+ supportedCompressedFormats.insert(toGlCompressedTextureFormat(QRhiTexture::ASTC_12x12, f));
+ }
+ }
f->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.maxTextureSize);
- if (caps.ctxMajor >= 3 || actualFormat.renderableType() == QSurfaceFormat::OpenGL) {
+ if (!caps.gles || caps.ctxMajor >= 3) {
+ // non-ES or ES 3.0+
f->glGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.maxDrawBuffers);
+ caps.hasDrawBuffersFunc = true;
f->glGetIntegerv(GL_MAX_SAMPLES, &caps.maxSamples);
caps.maxSamples = qMax(1, caps.maxSamples);
} else {
+ // ES 2.0 / WebGL 1
caps.maxDrawBuffers = 1;
- caps.maxSamples = 1;
+ caps.hasDrawBuffersFunc = false;
+ // This does not mean MSAA is not supported, just that we cannot query
+ // the supported sample counts. Assume that 4x is always supported.
+ caps.maxSamples = 4;
}
caps.msaaRenderBuffer = f->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
@@ -535,20 +864,27 @@ bool QRhiGles2::create(QRhi::Flags flags)
caps.npotTextureFull = f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)
&& f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat);
- caps.gles = actualFormat.renderableType() == QSurfaceFormat::OpenGLES;
if (caps.gles)
caps.fixedIndexPrimitiveRestart = caps.ctxMajor >= 3; // ES 3.0
else
caps.fixedIndexPrimitiveRestart = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3); // 4.3
- if (caps.fixedIndexPrimitiveRestart)
+ if (caps.fixedIndexPrimitiveRestart) {
+#ifdef Q_OS_WASM
+ // WebGL 2 behaves as if GL_PRIMITIVE_RESTART_FIXED_INDEX was always
+ // enabled (i.e. matching D3D/Metal), and the value cannot be passed to
+ // glEnable, so skip the call.
+#else
f->glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
+#endif
+ }
caps.bgraExternalFormat = f->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat);
caps.bgraInternalFormat = caps.bgraExternalFormat && caps.gles;
caps.r8Format = f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats);
caps.r16Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats);
caps.floatFormats = caps.ctxMajor >= 3; // 3.0 or ES 3.0
+ caps.rgb10Formats = caps.ctxMajor >= 3; // 3.0 or ES 3.0
caps.depthTexture = caps.ctxMajor >= 3; // 3.0 or ES 3.0
caps.packedDepthStencil = f->hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil);
#ifdef Q_OS_WASM
@@ -556,7 +892,13 @@ bool QRhiGles2::create(QRhi::Flags flags)
#else
caps.needsDepthStencilCombinedAttach = false;
#endif
- caps.srgbCapableDefaultFramebuffer = f->hasOpenGLExtension(QOpenGLExtensions::SRGBFrameBuffer);
+
+ // QOpenGLExtensions::SRGBFrameBuffer is not useful here. We need to know if
+ // controlling the sRGB-on-shader-write state is supported, not that if the
+ // default framebuffer is sRGB-capable. And there are two different
+ // extensions for desktop and ES.
+ caps.srgbWriteControl = ctx->hasExtension("GL_EXT_framebuffer_sRGB") || ctx->hasExtension("GL_EXT_sRGB_write_control");
+
caps.coreProfile = actualFormat.profile() == QSurfaceFormat::CoreProfile;
if (caps.gles)
@@ -631,9 +973,67 @@ bool QRhiGles2::create(QRhi::Flags flags)
caps.texture3D = caps.ctxMajor >= 3; // 3.0
+ if (caps.gles)
+ caps.texture1D = false; // ES
+ else
+ caps.texture1D = glTexImage1D && (caps.ctxMajor >= 2); // 2.0
+
+ if (caps.gles)
+ caps.tessellation = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2); // ES 3.2
+ else
+ caps.tessellation = caps.ctxMajor >= 4; // 4.0
+
+ if (caps.gles)
+ caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2); // ES 3.2
+ else
+ caps.geometryShader = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2); // 3.2
+
+ if (caps.ctxMajor >= 3) { // 3.0 or ES 3.0
+ GLint maxArraySize = 0;
+ f->glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &maxArraySize);
+ caps.maxTextureArraySize = maxArraySize;
+ } else {
+ caps.maxTextureArraySize = 0;
+ }
+
+ // The ES 2.0 spec only has MAX_xxxx_VECTORS. ES 3.0 and up has both
+ // *VECTORS and *COMPONENTS. OpenGL 2.0-4.0 only has MAX_xxxx_COMPONENTS.
+ // 4.1 and above has both. What a mess.
+ if (caps.gles) {
+ GLint maxVertexUniformVectors = 0;
+ f->glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &maxVertexUniformVectors);
+ GLint maxFragmentUniformVectors = 0;
+ f->glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &maxFragmentUniformVectors);
+ caps.maxUniformVectors = qMin(maxVertexUniformVectors, maxFragmentUniformVectors);
+ } else {
+ GLint maxVertexUniformComponents = 0;
+ f->glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &maxVertexUniformComponents);
+ GLint maxFragmentUniformComponents = 0;
+ f->glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &maxFragmentUniformComponents);
+ caps.maxUniformVectors = qMin(maxVertexUniformComponents, maxFragmentUniformComponents) / 4;
+ }
+
+ f->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &caps.maxVertexInputs);
+
+ if (caps.gles) {
+ f->glGetIntegerv(GL_MAX_VARYING_VECTORS, &caps.maxVertexOutputs);
+ } else if (caps.ctxMajor >= 3) {
+ GLint components = 0;
+ f->glGetIntegerv(caps.coreProfile ? GL_MAX_VERTEX_OUTPUT_COMPONENTS : GL_MAX_VARYING_COMPONENTS, &components);
+ caps.maxVertexOutputs = components / 4;
+ } else {
+ // OpenGL before 3.0 only has this, and not the same as
+ // MAX_VARYING_COMPONENTS strictly speaking, but will do.
+ GLint components = 0;
+ f->glGetIntegerv(GL_MAX_VARYING_FLOATS, &components);
+ if (components > 0)
+ caps.maxVertexOutputs = components / 4;
+ }
+
if (!caps.gles) {
f->glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
- f->glEnable(GL_POINT_SPRITE);
+ if (!caps.coreProfile)
+ f->glEnable(GL_POINT_SPRITE);
} // else (with gles) these are always on
// Match D3D and others when it comes to seamless cubemap filtering.
@@ -642,6 +1042,60 @@ bool QRhiGles2::create(QRhi::Flags flags)
if (!caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2)))
f->glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
+ caps.halfAttributes = f->hasOpenGLExtension(QOpenGLExtensions::HalfFloatVertex);
+
+ // We always require GL_OVR_multiview2 for symmetry with other backends.
+ caps.multiView = f->hasOpenGLExtension(QOpenGLExtensions::MultiView)
+ && f->hasOpenGLExtension(QOpenGLExtensions::MultiViewExtended);
+ if (caps.multiView) {
+ glFramebufferTextureMultiviewOVR =
+ reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLint, GLsizei)>(
+ ctx->getProcAddress(QByteArrayLiteral("glFramebufferTextureMultiviewOVR")));
+ }
+
+ // Only do timestamp queries on OpenGL 3.3+.
+ caps.timestamps = !caps.gles && (caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 3));
+ if (caps.timestamps) {
+ glQueryCounter = reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLuint, GLenum)>(
+ ctx->getProcAddress(QByteArrayLiteral("glQueryCounter")));
+ glGetQueryObjectui64v = reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLuint, GLenum, quint64 *)>(
+ ctx->getProcAddress(QByteArrayLiteral("glGetQueryObjectui64v")));
+ if (!glQueryCounter || !glGetQueryObjectui64v)
+ caps.timestamps = false;
+ }
+
+ // glObjectLabel is available on OpenGL ES 3.2+ and OpenGL 4.3+
+ if (caps.gles)
+ caps.objectLabel = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2);
+ else
+ caps.objectLabel = caps.ctxMajor > 4 || (caps.ctxMajor == 4 && caps.ctxMinor >= 3);
+ if (caps.objectLabel) {
+ glObjectLabel = reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLenum, GLuint, GLsizei, const GLchar *)>(
+ ctx->getProcAddress(QByteArrayLiteral("glObjectLabel")));
+ }
+
+ if (caps.gles) {
+ // This is the third way to get multisample rendering with GLES. (1. is
+ // multisample render buffer -> resolve to texture; 2. is multisample
+ // texture with GLES 3.1; 3. is this, avoiding the explicit multisample
+ // buffer and should be more efficient with tiled architectures.
+ // Interesting also because 2. does not seem to work in practice on
+ // devices such as the Quest 3)
+ caps.glesMultisampleRenderToTexture = ctx->hasExtension("GL_EXT_multisampled_render_to_texture");
+ if (caps.glesMultisampleRenderToTexture) {
+ glFramebufferTexture2DMultisampleEXT = reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei)>(
+ ctx->getProcAddress(QByteArrayLiteral("glFramebufferTexture2DMultisampleEXT")));
+ }
+ caps.glesMultiviewMultisampleRenderToTexture = ctx->hasExtension("GL_OVR_multiview_multisampled_render_to_texture");
+ if (caps.glesMultiviewMultisampleRenderToTexture) {
+ glFramebufferTextureMultisampleMultiviewOVR = reinterpret_cast<void(QOPENGLF_APIENTRYP)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei)>(
+ ctx->getProcAddress(QByteArrayLiteral("glFramebufferTextureMultisampleMultiviewOVR")));
+ }
+ } else {
+ caps.glesMultisampleRenderToTexture = false;
+ caps.glesMultiviewMultisampleRenderToTexture = false;
+ }
+
nativeHandlesStruct.context = ctx;
contextLost = false;
@@ -657,6 +1111,11 @@ void QRhiGles2::destroy()
ensureContext();
executeDeferredReleases();
+ if (ofr.tsQueries[0]) {
+ f->glDeleteQueries(2, ofr.tsQueries);
+ ofr.tsQueries[0] = ofr.tsQueries[1] = 0;
+ }
+
if (vao) {
f->glDeleteVertexArrays(1, &vao);
vao = 0;
@@ -676,7 +1135,7 @@ void QRhiGles2::destroy()
void QRhiGles2::executeDeferredReleases()
{
- for (int i = releaseQueue.count() - 1; i >= 0; --i) {
+ for (int i = releaseQueue.size() - 1; i >= 0; --i) {
const QRhiGles2::DeferredReleaseEntry &e(releaseQueue[i]);
switch (e.type) {
case QRhiGles2::DeferredReleaseEntry::Buffer:
@@ -694,6 +1153,7 @@ void QRhiGles2::executeDeferredReleases()
break;
case QRhiGles2::DeferredReleaseEntry::TextureRenderTarget:
f->glDeleteFramebuffers(1, &e.textureRenderTarget.framebuffer);
+ f->glDeleteTextures(1, &e.textureRenderTarget.nonMsaaThrowawayDepthTexture);
break;
default:
Q_UNREACHABLE();
@@ -713,23 +1173,12 @@ QList<int> QRhiGles2::supportedSampleCounts() const
return supportedSampleCountList;
}
-int QRhiGles2::effectiveSampleCount(int sampleCount) const
-{
- // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
- const int s = qBound(1, sampleCount, 64);
- if (!supportedSampleCounts().contains(s)) {
- qWarning("Attempted to set unsupported sample count %d", sampleCount);
- return 1;
- }
- return s;
-}
-
QRhiSwapChain *QRhiGles2::createSwapChain()
{
return new QGles2SwapChain(this);
}
-QRhiBuffer *QRhiGles2::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+QRhiBuffer *QRhiGles2::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
{
return new QGles2Buffer(this, type, usage, size);
}
@@ -761,58 +1210,6 @@ QMatrix4x4 QRhiGles2::clipSpaceCorrMatrix() const
return QMatrix4x4(); // identity
}
-static inline GLenum toGlCompressedTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags)
-{
- const bool srgb = flags.testFlag(QRhiTexture::sRGB);
- switch (format) {
- case QRhiTexture::BC1:
- return srgb ? 0x8C4C : 0x83F0;
- case QRhiTexture::BC2:
- return srgb ? 0x8C4E : 0x83F2;
- case QRhiTexture::BC3:
- return srgb ? 0x8C4F : 0x83F3;
-
- case QRhiTexture::ETC2_RGB8:
- return srgb ? 0x9275 : 0x9274;
- case QRhiTexture::ETC2_RGB8A1:
- return srgb ? 0x9277 : 0x9276;
- case QRhiTexture::ETC2_RGBA8:
- return srgb ? 0x9279 : 0x9278;
-
- case QRhiTexture::ASTC_4x4:
- return srgb ? 0x93D0 : 0x93B0;
- case QRhiTexture::ASTC_5x4:
- return srgb ? 0x93D1 : 0x93B1;
- case QRhiTexture::ASTC_5x5:
- return srgb ? 0x93D2 : 0x93B2;
- case QRhiTexture::ASTC_6x5:
- return srgb ? 0x93D3 : 0x93B3;
- case QRhiTexture::ASTC_6x6:
- return srgb ? 0x93D4 : 0x93B4;
- case QRhiTexture::ASTC_8x5:
- return srgb ? 0x93D5 : 0x93B5;
- case QRhiTexture::ASTC_8x6:
- return srgb ? 0x93D6 : 0x93B6;
- case QRhiTexture::ASTC_8x8:
- return srgb ? 0x93D7 : 0x93B7;
- case QRhiTexture::ASTC_10x5:
- return srgb ? 0x93D8 : 0x93B8;
- case QRhiTexture::ASTC_10x6:
- return srgb ? 0x93D9 : 0x93B9;
- case QRhiTexture::ASTC_10x8:
- return srgb ? 0x93DA : 0x93BA;
- case QRhiTexture::ASTC_10x10:
- return srgb ? 0x93DB : 0x93BB;
- case QRhiTexture::ASTC_12x10:
- return srgb ? 0x93DC : 0x93BC;
- case QRhiTexture::ASTC_12x12:
- return srgb ? 0x93DD : 0x93BD;
-
- default:
- return 0; // this is reachable, just return an invalid format
- }
-}
-
static inline void toGlTextureFormat(QRhiTexture::Format format, const QRhiGles2::Caps &caps,
GLenum *glintformat, GLenum *glsizedintformat,
GLenum *glformat, GLenum *gltype)
@@ -884,6 +1281,12 @@ static inline void toGlTextureFormat(QRhiTexture::Format format, const QRhiGles2
*glformat = GL_RED;
*gltype = GL_FLOAT;
break;
+ case QRhiTexture::RGB10A2:
+ *glintformat = GL_RGB10_A2;
+ *glsizedintformat = *glintformat;
+ *glformat = GL_RGBA;
+ *gltype = GL_UNSIGNED_INT_2_10_10_10_REV;
+ break;
case QRhiTexture::D16:
*glintformat = GL_DEPTH_COMPONENT16;
*glsizedintformat = *glintformat;
@@ -894,13 +1297,13 @@ static inline void toGlTextureFormat(QRhiTexture::Format format, const QRhiGles2
*glintformat = GL_DEPTH_COMPONENT24;
*glsizedintformat = *glintformat;
*glformat = GL_DEPTH_COMPONENT;
- *gltype = GL_UNSIGNED_SHORT;
+ *gltype = GL_UNSIGNED_INT;
break;
case QRhiTexture::D24S8:
*glintformat = GL_DEPTH24_STENCIL8;
*glsizedintformat = *glintformat;
*glformat = GL_DEPTH_STENCIL;
- *gltype = GL_UNSIGNED_SHORT;
+ *gltype = GL_UNSIGNED_INT_24_8;
break;
case QRhiTexture::D32F:
*glintformat = GL_DEPTH_COMPONENT32F;
@@ -957,6 +1360,9 @@ bool QRhiGles2::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture
case QRhiTexture::R32F:
return caps.floatFormats;
+ case QRhiTexture::RGB10A2:
+ return caps.rgb10Formats;
+
default:
break;
}
@@ -974,7 +1380,7 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const
case QRhi::DebugMarkers:
return false;
case QRhi::Timestamps:
- return false;
+ return caps.timestamps;
case QRhi::Instancing:
return caps.instancing;
case QRhi::CustomInstanceStepRate:
@@ -1027,9 +1433,34 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const
return caps.texture3D;
case QRhi::RenderTo3DTextureSlice:
return caps.texture3D;
- default:
- Q_UNREACHABLE();
+ case QRhi::TextureArrays:
+ return caps.maxTextureArraySize > 0;
+ case QRhi::Tessellation:
+ return caps.tessellation;
+ case QRhi::GeometryShader:
+ return caps.geometryShader;
+ case QRhi::TextureArrayRange:
+ return false;
+ case QRhi::NonFillPolygonMode:
+ return !caps.gles;
+ case QRhi::OneDimensionalTextures:
+ return caps.texture1D;
+ case QRhi::OneDimensionalTextureMipmaps:
+ return caps.texture1D;
+ case QRhi::HalfAttributes:
+ return caps.halfAttributes;
+ case QRhi::RenderToOneDimensionalTexture:
+ return caps.texture1D;
+ case QRhi::ThreeDimensionalTextureMipmaps:
+ return caps.texture3D;
+ case QRhi::MultiView:
+ return caps.multiView && caps.maxTextureArraySize > 0;
+ case QRhi::TextureViewFormat:
return false;
+ case QRhi::ResolveDepthStencil:
+ return true;
+ default:
+ Q_UNREACHABLE_RETURN(false);
}
}
@@ -1058,9 +1489,16 @@ int QRhiGles2::resourceLimit(QRhi::ResourceLimit limit) const
return caps.maxThreadGroupsY;
case QRhi::MaxThreadGroupZ:
return caps.maxThreadGroupsZ;
+ case QRhi::TextureArraySizeMax:
+ return 2048;
+ case QRhi::MaxUniformBufferRange:
+ return int(qMin<qint64>(INT_MAX, caps.maxUniformVectors * qint64(16)));
+ case QRhi::MaxVertexInputs:
+ return caps.maxVertexInputs;
+ case QRhi::MaxVertexOutputs:
+ return caps.maxVertexOutputs;
default:
- Q_UNREACHABLE();
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
}
@@ -1074,9 +1512,11 @@ QRhiDriverInfo QRhiGles2::driverInfo() const
return driverInfoStruct;
}
-void QRhiGles2::sendVMemStatsToProfiler()
+QRhiStats QRhiGles2::statistics()
{
- // nothing to do here
+ QRhiStats result;
+ result.totalPipelineCreationTime = totalPipelineCreationTime();
+ return result;
}
bool QRhiGles2::makeThreadLocalNativeContextCurrent()
@@ -1125,8 +1565,8 @@ QByteArray QRhiGles2::pipelineCacheData()
memset(&header, 0, sizeof(header));
header.rhiId = pipelineCacheRhiId();
header.arch = quint32(sizeof(void*));
- header.programBinaryCount = m_pipelineCache.count();
- const size_t driverStrLen = qMin(sizeof(header.driver) - 1, size_t(driverInfoStruct.deviceName.count()));
+ header.programBinaryCount = m_pipelineCache.size();
+ const size_t driverStrLen = qMin(sizeof(header.driver) - 1, size_t(driverInfoStruct.deviceName.size()));
if (driverStrLen)
memcpy(header.driver, driverInfoStruct.deviceName.constData(), driverStrLen);
header.driver[driverStrLen] = '\0';
@@ -1176,7 +1616,7 @@ void QRhiGles2::setPipelineCacheData(const QByteArray &data)
const size_t headerSize = sizeof(QGles2PipelineCacheDataHeader);
if (data.size() < qsizetype(headerSize)) {
- qWarning("setPipelineCacheData: Invalid blob size (header incomplete)");
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Invalid blob size (header incomplete)");
return;
}
const size_t dataOffset = headerSize;
@@ -1185,27 +1625,27 @@ void QRhiGles2::setPipelineCacheData(const QByteArray &data)
const quint32 rhiId = pipelineCacheRhiId();
if (header.rhiId != rhiId) {
- qWarning("setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
- rhiId, header.rhiId);
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
+ rhiId, header.rhiId);
return;
}
const quint32 arch = quint32(sizeof(void*));
if (header.arch != arch) {
- qWarning("setPipelineCacheData: Architecture does not match (%u, %u)",
- arch, header.arch);
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Architecture does not match (%u, %u)",
+ arch, header.arch);
return;
}
if (header.programBinaryCount == 0)
return;
- const size_t driverStrLen = qMin(sizeof(header.driver) - 1, size_t(driverInfoStruct.deviceName.count()));
+ const size_t driverStrLen = qMin(sizeof(header.driver) - 1, size_t(driverInfoStruct.deviceName.size()));
if (strncmp(header.driver, driverInfoStruct.deviceName.constData(), driverStrLen)) {
- qWarning("setPipelineCacheData: OpenGL vendor/renderer/version does not match");
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: OpenGL vendor/renderer/version does not match");
return;
}
if (data.size() < qsizetype(dataOffset + header.dataSize)) {
- qWarning("setPipelineCacheData: Invalid blob size (data incomplete)");
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Invalid blob size (data incomplete)");
return;
}
@@ -1233,7 +1673,7 @@ void QRhiGles2::setPipelineCacheData(const QByteArray &data)
m_pipelineCache.insert(key, { format, data });
}
- qCDebug(QRHI_LOG_INFO, "Seeded pipeline cache with %d program binaries", int(m_pipelineCache.count()));
+ qCDebug(QRHI_LOG_INFO, "Seeded pipeline cache with %d program binaries", int(m_pipelineCache.size()));
}
QRhiRenderBuffer *QRhiGles2::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
@@ -1244,10 +1684,10 @@ QRhiRenderBuffer *QRhiGles2::createRenderBuffer(QRhiRenderBuffer::Type type, con
}
QRhiTexture *QRhiGles2::createTexture(QRhiTexture::Format format,
- const QSize &pixelSize, int depth,
+ const QSize &pixelSize, int depth, int arraySize,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QGles2Texture(this, format, pixelSize, depth, sampleCount, flags);
+ return new QGles2Texture(this, format, pixelSize, depth, arraySize, sampleCount, flags);
}
QRhiSampler *QRhiGles2::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -1315,13 +1755,14 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
QGles2ShaderResourceBindings *srbD = QRHI_RES(QGles2ShaderResourceBindings, srb);
if (cbD->passNeedsResourceTracking) {
QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]);
- for (int i = 0, ie = srbD->m_bindings.count(); i != ie; ++i) {
- const QRhiShaderResourceBinding::Data *b = srbD->m_bindings.at(i).data();
+ for (int i = 0, ie = srbD->m_bindings.size(); i != ie; ++i) {
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->m_bindings.at(i));
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
// no BufUniformRead / AccessUniform because no real uniform buffers are used
break;
case QRhiShaderResourceBinding::SampledTexture:
+ case QRhiShaderResourceBinding::Texture:
for (int elem = 0; elem < b->u.stex.count; ++elem) {
trackedRegisterTexture(&passResTracker,
QRHI_RES(QGles2Texture, b->u.stex.texSamplers[elem].tex),
@@ -1592,10 +2033,14 @@ const QRhiNativeHandles *QRhiGles2::nativeHandles(QRhiCommandBuffer *cb)
return nullptr;
}
-static inline void addBoundaryCommand(QGles2CommandBuffer *cbD, QGles2CommandBuffer::Command::Cmd type)
+static inline void addBoundaryCommand(QGles2CommandBuffer *cbD, QGles2CommandBuffer::Command::Cmd type, GLuint tsQuery = 0)
{
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = type;
+ if (type == QGles2CommandBuffer::Command::BeginFrame)
+ cmd.args.beginFrame.timestampQuery = tsQuery;
+ else if (type == QGles2CommandBuffer::Command::EndFrame)
+ cmd.args.endFrame.timestampQuery = tsQuery;
}
void QRhiGles2::beginExternal(QRhiCommandBuffer *cb)
@@ -1624,8 +2069,14 @@ void QRhiGles2::beginExternal(QRhiCommandBuffer *cb)
cbD->resetCommands();
- if (vao)
+ if (vao) {
f->glBindVertexArray(0);
+ } else {
+ f->glBindBuffer(GL_ARRAY_BUFFER, 0);
+ f->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ if (caps.compute)
+ f->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
+ }
}
void QRhiGles2::endExternal(QRhiCommandBuffer *cb)
@@ -1649,21 +2100,36 @@ void QRhiGles2::endExternal(QRhiCommandBuffer *cb)
enqueueBindFramebuffer(cbD->currentTarget, cbD);
}
+double QRhiGles2::lastCompletedGpuTime(QRhiCommandBuffer *cb)
+{
+ QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
+ return cbD->lastGpuTime;
+}
+
QRhi::FrameOpResult QRhiGles2::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags)
{
QGles2SwapChain *swapChainD = QRHI_RES(QGles2SwapChain, swapChain);
if (!ensureContext(swapChainD->surface))
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
- currentSwapChain = swapChainD;
+ ctx->handle()->beginFrame();
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- QRHI_PROF_F(beginSwapChainFrame(swapChain));
+ currentSwapChain = swapChainD;
executeDeferredReleases();
swapChainD->cb.resetState();
- addBoundaryCommand(&swapChainD->cb, QGles2CommandBuffer::Command::BeginFrame);
+ if (swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex]) {
+ double elapsedSec = 0;
+ if (swapChainD->timestamps.tryQueryTimestamps(swapChainD->currentTimestampPairIndex, this, &elapsedSec))
+ swapChainD->cb.lastGpuTime = elapsedSec;
+ }
+
+ GLuint tsStart = swapChainD->timestamps.query[swapChainD->currentTimestampPairIndex * 2];
+ GLuint tsEnd = swapChainD->timestamps.query[swapChainD->currentTimestampPairIndex * 2 + 1];
+ const bool recordTimestamps = tsStart && tsEnd && !swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex];
+
+ addBoundaryCommand(&swapChainD->cb, QGles2CommandBuffer::Command::BeginFrame, recordTimestamps ? tsStart : 0);
return QRhi::FrameOpSuccess;
}
@@ -1673,26 +2139,33 @@ QRhi::FrameOpResult QRhiGles2::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
QGles2SwapChain *swapChainD = QRHI_RES(QGles2SwapChain, swapChain);
Q_ASSERT(currentSwapChain == swapChainD);
- addBoundaryCommand(&swapChainD->cb, QGles2CommandBuffer::Command::EndFrame);
+ GLuint tsStart = swapChainD->timestamps.query[swapChainD->currentTimestampPairIndex * 2];
+ GLuint tsEnd = swapChainD->timestamps.query[swapChainD->currentTimestampPairIndex * 2 + 1];
+ const bool recordTimestamps = tsStart && tsEnd && !swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex];
+ if (recordTimestamps) {
+ swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex] = true;
+ swapChainD->currentTimestampPairIndex = (swapChainD->currentTimestampPairIndex + 1) % QGles2SwapChainTimestamps::TIMESTAMP_PAIRS;
+ }
+
+ addBoundaryCommand(&swapChainD->cb, QGles2CommandBuffer::Command::EndFrame, recordTimestamps ? tsEnd : 0);
if (!ensureContext(swapChainD->surface))
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
executeCommandBuffer(&swapChainD->cb);
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- // this must be done before the swap
- QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
-
if (swapChainD->surface && !flags.testFlag(QRhi::SkipPresent)) {
ctx->swapBuffers(swapChainD->surface);
- needsMakeCurrent = true;
+ needsMakeCurrentDueToSwap = true;
} else {
f->glFlush();
}
swapChainD->frameCount += 1;
currentSwapChain = nullptr;
+
+ ctx->handle()->endFrame();
+
return QRhi::FrameOpSuccess;
}
@@ -1706,7 +2179,12 @@ QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi:
executeDeferredReleases();
ofr.cbWrapper.resetState();
- addBoundaryCommand(&ofr.cbWrapper, QGles2CommandBuffer::Command::BeginFrame);
+ if (rhiFlags.testFlag(QRhi::EnableTimestamps) && caps.timestamps) {
+ if (!ofr.tsQueries[0])
+ f->glGenQueries(2, ofr.tsQueries);
+ }
+
+ addBoundaryCommand(&ofr.cbWrapper, QGles2CommandBuffer::Command::BeginFrame, ofr.tsQueries[0]);
*cb = &ofr.cbWrapper;
return QRhi::FrameOpSuccess;
@@ -1718,13 +2196,29 @@ QRhi::FrameOpResult QRhiGles2::endOffscreenFrame(QRhi::EndFrameFlags flags)
Q_ASSERT(ofr.active);
ofr.active = false;
- addBoundaryCommand(&ofr.cbWrapper, QGles2CommandBuffer::Command::EndFrame);
+ addBoundaryCommand(&ofr.cbWrapper, QGles2CommandBuffer::Command::EndFrame, ofr.tsQueries[1]);
if (!ensureContext())
return contextLost ? QRhi::FrameOpDeviceLost : QRhi::FrameOpError;
executeCommandBuffer(&ofr.cbWrapper);
+ // Just as endFrame() does a flush when skipping the swapBuffers(), do it
+ // here as well. This has the added benefit of playing nice when rendering
+ // to a texture from a context and then consuming that texture from
+ // another, sharing context.
+ f->glFlush();
+
+ if (ofr.tsQueries[0]) {
+ quint64 timestamps[2];
+ glGetQueryObjectui64v(ofr.tsQueries[1], GL_QUERY_RESULT, &timestamps[1]);
+ glGetQueryObjectui64v(ofr.tsQueries[0], GL_QUERY_RESULT, &timestamps[0]);
+ if (timestamps[1] >= timestamps[0]) {
+ const quint64 nanoseconds = timestamps[1] - timestamps[0];
+ ofr.cbWrapper.lastGpuTime = nanoseconds / 1000000000.0; // seconds
+ }
+ }
+
return QRhi::FrameOpSuccess;
}
@@ -1746,6 +2240,12 @@ QRhi::FrameOpResult QRhiGles2::finish()
executeCommandBuffer(&currentSwapChain->cb);
currentSwapChain->cb.resetCommands();
}
+ // Do an actual glFinish(). May seem superfluous, but this is what
+ // matches most other backends e.g. Vulkan/Metal that do a heavyweight
+ // wait-for-idle blocking in their finish(). More importantly, this
+ // allows clients simply call finish() in threaded or shared context
+ // situations where one explicitly needs to do a glFlush or Finish.
+ f->glFinish();
}
return QRhi::FrameOpSuccess;
}
@@ -1765,9 +2265,30 @@ static bool textureAccessIsWrite(QGles2Texture::Access access)
|| access == QGles2Texture::AccessFramebuffer;
}
+static inline GLbitfield barriersForBuffer()
+{
+ return GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT
+ | GL_ELEMENT_ARRAY_BARRIER_BIT
+ | GL_UNIFORM_BARRIER_BIT
+ | GL_BUFFER_UPDATE_BARRIER_BIT
+ | GL_SHADER_STORAGE_BARRIER_BIT;
+}
+
+static inline GLbitfield barriersForTexture()
+{
+ return GL_TEXTURE_FETCH_BARRIER_BIT
+ | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
+ | GL_PIXEL_BUFFER_BARRIER_BIT
+ | GL_TEXTURE_UPDATE_BARRIER_BIT
+ | GL_FRAMEBUFFER_BARRIER_BIT;
+}
+
void QRhiGles2::trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access)
{
Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::NoPass); // this is for resource updates only
+ if (!bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer))
+ return;
+
const QGles2Buffer::Access prevAccess = bufD->usageState.access;
if (access == prevAccess)
return;
@@ -1779,7 +2300,7 @@ void QRhiGles2::trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *buf
// for now.
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::Barrier;
- cmd.args.barrier.barriers = GL_ALL_BARRIER_BITS;
+ cmd.args.barrier.barriers = barriersForBuffer();
}
bufD->usageState.access = access;
@@ -1788,6 +2309,9 @@ void QRhiGles2::trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *buf
void QRhiGles2::trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access)
{
Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::NoPass); // this is for resource updates only
+ if (!texD->m_flags.testFlag(QRhiTexture::UsedWithLoadStore))
+ return;
+
const QGles2Texture::Access prevAccess = texD->usageState.access;
if (access == prevAccess)
return;
@@ -1795,7 +2319,7 @@ void QRhiGles2::trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *tex
if (textureAccessIsWrite(prevAccess)) {
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::Barrier;
- cmd.args.barrier.barriers = GL_ALL_BARRIER_BITS;
+ cmd.args.barrier.barriers = barriersForTexture();
}
texD->usageState.access = access;
@@ -1807,37 +2331,58 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
trackedImageBarrier(cbD, texD, QGles2Texture::AccessUpdate);
const bool isCompressed = isCompressedFormat(texD->m_format);
const bool isCubeMap = texD->m_flags.testFlag(QRhiTexture::CubeMap);
+ const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ const bool is1D = texD->m_flags.testFlag(QRhiTexture::OneDimensional);
+ const bool isArray = texD->m_flags.testFlag(QRhiTexture::TextureArray);
const GLenum faceTargetBase = isCubeMap ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
+ const GLenum effectiveTarget = faceTargetBase + (isCubeMap ? uint(layer) : 0u);
const QPoint dp = subresDesc.destinationTopLeft();
const QByteArray rawData = subresDesc.data();
- if (!subresDesc.image().isNull()) {
- QImage img = subresDesc.image();
- QSize size = img.size();
+
+ auto setCmdByNotCompressedData = [&](const void* data, QSize size, quint32 dataStride)
+ {
+ quint32 bytesPerLine = 0;
+ quint32 bytesPerPixel = 0;
+ textureFormatInfo(texD->m_format, size, &bytesPerLine, nullptr, &bytesPerPixel);
+
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::SubImage;
- if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
- const QPoint sp = subresDesc.sourceTopLeft();
- if (!subresDesc.sourceSize().isEmpty())
- size = subresDesc.sourceSize();
- img = img.copy(sp.x(), sp.y(), size.width(), size.height());
- }
cmd.args.subImage.target = texD->target;
cmd.args.subImage.texture = texD->texture;
- cmd.args.subImage.faceTarget = faceTargetBase + uint(layer);
+ cmd.args.subImage.faceTarget = effectiveTarget;
cmd.args.subImage.level = level;
cmd.args.subImage.dx = dp.x();
- cmd.args.subImage.dy = dp.y();
- cmd.args.subImage.dz = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional) ? layer : 0;
+ cmd.args.subImage.dy = is1D && isArray ? layer : dp.y();
+ cmd.args.subImage.dz = is3D || isArray ? layer : 0;
cmd.args.subImage.w = size.width();
cmd.args.subImage.h = size.height();
cmd.args.subImage.glformat = texD->glformat;
cmd.args.subImage.gltype = texD->gltype;
- cmd.args.subImage.rowStartAlign = 4;
- cmd.args.subImage.rowLength = 0;
- cmd.args.subImage.data = cbD->retainImage(img);
+
+ if (dataStride == 0)
+ dataStride = bytesPerLine;
+
+ cmd.args.subImage.rowStartAlign = (dataStride & 3) ? 1 : 4;
+ cmd.args.subImage.rowLength = bytesPerPixel ? dataStride / bytesPerPixel : 0;
+
+ cmd.args.subImage.data = data;
+ };
+
+ if (!subresDesc.image().isNull()) {
+ QImage img = subresDesc.image();
+ QSize size = img.size();
+ if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
+ const QPoint sp = subresDesc.sourceTopLeft();
+ if (!subresDesc.sourceSize().isEmpty())
+ size = subresDesc.sourceSize();
+ img = img.copy(sp.x(), sp.y(), size.width(), size.height());
+ }
+
+ setCmdByNotCompressedData(cbD->retainImage(img), size, img.bytesPerLine());
} else if (!rawData.isEmpty() && isCompressed) {
- const bool is3D = texD->flags().testFlag(QRhiTexture::ThreeDimensional);
- if ((texD->flags().testFlag(QRhiTexture::UsedAsCompressedAtlas) || is3D)
+ const int depth = qMax(1, texD->m_depth);
+ const int arraySize = qMax(0, texD->m_arraySize);
+ if ((texD->flags().testFlag(QRhiTexture::UsedAsCompressedAtlas) || is3D || isArray)
&& !texD->zeroInitialized)
{
// Create on first upload since glCompressedTexImage2D cannot take
@@ -1848,18 +2393,20 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
quint32 byteSize = 0;
compressedFormatInfo(texD->m_format, texD->m_pixelSize, nullptr, &byteSize, nullptr);
if (is3D)
- byteSize *= texD->m_depth;
+ byteSize *= depth;
+ if (isArray)
+ byteSize *= arraySize;
QByteArray zeroBuf(byteSize, 0);
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::CompressedImage;
cmd.args.compressedImage.target = texD->target;
cmd.args.compressedImage.texture = texD->texture;
- cmd.args.compressedImage.faceTarget = faceTargetBase + uint(layer);
+ cmd.args.compressedImage.faceTarget = effectiveTarget;
cmd.args.compressedImage.level = level;
cmd.args.compressedImage.glintformat = texD->glintformat;
cmd.args.compressedImage.w = texD->m_pixelSize.width();
- cmd.args.compressedImage.h = texD->m_pixelSize.height();
- cmd.args.compressedImage.depth = is3D ? texD->m_depth : 0;
+ cmd.args.compressedImage.h = is1D && isArray ? arraySize : texD->m_pixelSize.height();
+ cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
cmd.args.compressedImage.size = byteSize;
cmd.args.compressedImage.data = cbD->retainData(zeroBuf);
texD->zeroInitialized = true;
@@ -1872,11 +2419,11 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.cmd = QGles2CommandBuffer::Command::CompressedSubImage;
cmd.args.compressedSubImage.target = texD->target;
cmd.args.compressedSubImage.texture = texD->texture;
- cmd.args.compressedSubImage.faceTarget = faceTargetBase + uint(layer);
+ cmd.args.compressedSubImage.faceTarget = effectiveTarget;
cmd.args.compressedSubImage.level = level;
cmd.args.compressedSubImage.dx = dp.x();
- cmd.args.compressedSubImage.dy = dp.y();
- cmd.args.compressedSubImage.dz = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional) ? layer : 0;
+ cmd.args.compressedSubImage.dy = is1D && isArray ? layer : dp.y();
+ cmd.args.compressedSubImage.dz = is3D || isArray ? layer : 0;
cmd.args.compressedSubImage.w = size.width();
cmd.args.compressedSubImage.h = size.height();
cmd.args.compressedSubImage.glintformat = texD->glintformat;
@@ -1887,43 +2434,20 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
cmd.cmd = QGles2CommandBuffer::Command::CompressedImage;
cmd.args.compressedImage.target = texD->target;
cmd.args.compressedImage.texture = texD->texture;
- cmd.args.compressedImage.faceTarget = faceTargetBase + uint(layer);
+ cmd.args.compressedImage.faceTarget = effectiveTarget;
cmd.args.compressedImage.level = level;
cmd.args.compressedImage.glintformat = texD->glintformat;
cmd.args.compressedImage.w = size.width();
- cmd.args.compressedImage.h = size.height();
- cmd.args.compressedImage.depth = is3D ? texD->m_depth : 0;
+ cmd.args.compressedImage.h = is1D && isArray ? arraySize : size.height();
+ cmd.args.compressedImage.depth = is3D ? depth : (isArray ? arraySize : 0);
cmd.args.compressedImage.size = rawData.size();
cmd.args.compressedImage.data = cbD->retainData(rawData);
}
} else if (!rawData.isEmpty()) {
const QSize size = subresDesc.sourceSize().isEmpty() ? q->sizeForMipLevel(level, texD->m_pixelSize)
: subresDesc.sourceSize();
- quint32 bytesPerLine = 0;
- quint32 bytesPerPixel = 0;
- textureFormatInfo(texD->m_format, size, &bytesPerLine, nullptr, &bytesPerPixel);
- QGles2CommandBuffer::Command &cmd(cbD->commands.get());
- cmd.cmd = QGles2CommandBuffer::Command::SubImage;
- cmd.args.subImage.target = texD->target;
- cmd.args.subImage.texture = texD->texture;
- cmd.args.subImage.faceTarget = faceTargetBase + uint(layer);
- cmd.args.subImage.level = level;
- cmd.args.subImage.dx = dp.x();
- cmd.args.subImage.dy = dp.y();
- cmd.args.subImage.dz = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional) ? layer : 0;
- cmd.args.subImage.w = size.width();
- cmd.args.subImage.h = size.height();
- cmd.args.subImage.glformat = texD->glformat;
- cmd.args.subImage.gltype = texD->gltype;
- // Default unpack alignment (row start aligment
- // requirement) is 4. QImage guarantees 4 byte aligned
- // row starts, but our raw data here does not.
- cmd.args.subImage.rowStartAlign = (bytesPerLine & 3) ? 1 : 4;
- if (subresDesc.dataStride() && bytesPerPixel)
- cmd.args.subImage.rowLength = subresDesc.dataStride() / bytesPerPixel;
- else
- cmd.args.subImage.rowLength = 0;
- cmd.args.subImage.data = cbD->retainData(rawData);
+
+ setCmdByNotCompressedData(cbD->retainData(rawData), size, subresDesc.dataStride());
} else {
qWarning("Invalid texture upload for %p layer=%d mip=%d", texD, layer, level);
}
@@ -1990,9 +2514,9 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
const QRhiResourceUpdateBatchPrivate::TextureOp &u(ud->textureOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
QGles2Texture *texD = QRHI_RES(QGles2Texture, u.dst);
- for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int layer = 0, maxLayer = u.subresDesc.size(); layer < maxLayer; ++layer) {
for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
- for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level]))
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
enqueueSubresUpload(texD, cbD, layer, level, subresDesc);
}
}
@@ -2019,21 +2543,26 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::CopyTex;
+ const bool srcHasZ = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional) || srcD->m_flags.testFlag(QRhiTexture::TextureArray);
+ const bool dstHasZ = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional) || dstD->m_flags.testFlag(QRhiTexture::TextureArray);
+ const bool dstIs1dArray = dstD->m_flags.testFlag(QRhiTexture::OneDimensional)
+ && dstD->m_flags.testFlag(QRhiTexture::TextureArray);
+
cmd.args.copyTex.srcTarget = srcD->target;
- cmd.args.copyTex.srcFaceTarget = srcFaceTargetBase + uint(u.desc.sourceLayer());
+ cmd.args.copyTex.srcFaceTarget = srcFaceTargetBase + (srcHasZ ? 0u : uint(u.desc.sourceLayer()));
cmd.args.copyTex.srcTexture = srcD->texture;
cmd.args.copyTex.srcLevel = u.desc.sourceLevel();
cmd.args.copyTex.srcX = sp.x();
cmd.args.copyTex.srcY = sp.y();
- cmd.args.copyTex.srcZ = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional) ? u.desc.sourceLayer() : 0;
+ cmd.args.copyTex.srcZ = srcHasZ ? u.desc.sourceLayer() : 0;
cmd.args.copyTex.dstTarget = dstD->target;
- cmd.args.copyTex.dstFaceTarget = dstFaceTargetBase + uint(u.desc.destinationLayer());
+ cmd.args.copyTex.dstFaceTarget = dstFaceTargetBase + (dstHasZ ? 0u : uint(u.desc.destinationLayer()));
cmd.args.copyTex.dstTexture = dstD->texture;
cmd.args.copyTex.dstLevel = u.desc.destinationLevel();
cmd.args.copyTex.dstX = dp.x();
- cmd.args.copyTex.dstY = dp.y();
- cmd.args.copyTex.dstZ = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional) ? u.desc.destinationLayer() : 0;
+ cmd.args.copyTex.dstY = dstIs1dArray ? u.desc.destinationLayer() : dp.y();
+ cmd.args.copyTex.dstZ = dstHasZ ? u.desc.destinationLayer() : 0;
cmd.args.copyTex.w = copySize.width();
cmd.args.copyTex.h = copySize.height();
@@ -2051,7 +2580,9 @@ void QRhiGles2::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
cmd.args.readPixels.w = readImageSize.width();
cmd.args.readPixels.h = readImageSize.height();
cmd.args.readPixels.format = texD->m_format;
- if (texD->m_flags.testFlag(QRhiTexture::ThreeDimensional)) {
+ if (texD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
+ || texD->m_flags.testFlag(QRhiTexture::TextureArray))
+ {
cmd.args.readPixels.readTarget = texD->target;
cmd.args.readPixels.slice3D = u.rb.layer();
} else {
@@ -2089,9 +2620,10 @@ static inline GLenum toGlTopology(QRhiGraphicsPipeline::Topology t)
return GL_LINE_STRIP;
case QRhiGraphicsPipeline::Points:
return GL_POINTS;
+ case QRhiGraphicsPipeline::Patches:
+ return GL_PATCHES;
default:
- Q_UNREACHABLE();
- return GL_TRIANGLES;
+ Q_UNREACHABLE_RETURN(GL_TRIANGLES);
}
}
@@ -2103,8 +2635,7 @@ static inline GLenum toGlCullMode(QRhiGraphicsPipeline::CullMode c)
case QRhiGraphicsPipeline::Back:
return GL_BACK;
default:
- Q_UNREACHABLE();
- return GL_BACK;
+ Q_UNREACHABLE_RETURN(GL_BACK);
}
}
@@ -2116,8 +2647,7 @@ static inline GLenum toGlFrontFace(QRhiGraphicsPipeline::FrontFace f)
case QRhiGraphicsPipeline::CW:
return GL_CW;
default:
- Q_UNREACHABLE();
- return GL_CCW;
+ Q_UNREACHABLE_RETURN(GL_CCW);
}
}
@@ -2161,8 +2691,7 @@ static inline GLenum toGlBlendFactor(QRhiGraphicsPipeline::BlendFactor f)
qWarning("Unsupported blend factor %d", f);
return GL_ZERO;
default:
- Q_UNREACHABLE();
- return GL_ZERO;
+ Q_UNREACHABLE_RETURN(GL_ZERO);
}
}
@@ -2180,8 +2709,7 @@ static inline GLenum toGlBlendOp(QRhiGraphicsPipeline::BlendOp op)
case QRhiGraphicsPipeline::Max:
return GL_MAX;
default:
- Q_UNREACHABLE();
- return GL_FUNC_ADD;
+ Q_UNREACHABLE_RETURN(GL_FUNC_ADD);
}
}
@@ -2205,8 +2733,7 @@ static inline GLenum toGlCompareOp(QRhiGraphicsPipeline::CompareOp op)
case QRhiGraphicsPipeline::Always:
return GL_ALWAYS;
default:
- Q_UNREACHABLE();
- return GL_ALWAYS;
+ Q_UNREACHABLE_RETURN(GL_ALWAYS);
}
}
@@ -2230,8 +2757,19 @@ static inline GLenum toGlStencilOp(QRhiGraphicsPipeline::StencilOp op)
case QRhiGraphicsPipeline::DecrementAndWrap:
return GL_DECR_WRAP;
default:
- Q_UNREACHABLE();
- return GL_KEEP;
+ Q_UNREACHABLE_RETURN(GL_KEEP);
+ }
+}
+
+static inline GLenum toGlPolygonMode(QRhiGraphicsPipeline::PolygonMode mode)
+{
+ switch (mode) {
+ case QRhiGraphicsPipeline::PolygonMode::Fill:
+ return GL_FILL;
+ case QRhiGraphicsPipeline::PolygonMode::Line:
+ return GL_LINE;
+ default:
+ Q_UNREACHABLE_RETURN(GL_FILL);
}
}
@@ -2249,8 +2787,7 @@ static inline GLenum toGlMinFilter(QRhiSampler::Filter f, QRhiSampler::Filter m)
else
return m == QRhiSampler::Nearest ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR;
default:
- Q_UNREACHABLE();
- return GL_LINEAR;
+ Q_UNREACHABLE_RETURN(GL_LINEAR);
}
}
@@ -2262,8 +2799,7 @@ static inline GLenum toGlMagFilter(QRhiSampler::Filter f)
case QRhiSampler::Linear:
return GL_LINEAR;
default:
- Q_UNREACHABLE();
- return GL_LINEAR;
+ Q_UNREACHABLE_RETURN(GL_LINEAR);
}
}
@@ -2277,8 +2813,7 @@ static inline GLenum toGlWrapMode(QRhiSampler::AddressMode m)
case QRhiSampler::Mirror:
return GL_MIRRORED_REPEAT;
default:
- Q_UNREACHABLE();
- return GL_CLAMP_TO_EDGE;
+ Q_UNREACHABLE_RETURN(GL_CLAMP_TO_EDGE);
}
}
@@ -2302,8 +2837,7 @@ static inline GLenum toGlTextureCompareFunc(QRhiSampler::CompareOp op)
case QRhiSampler::Always:
return GL_ALWAYS;
default:
- Q_UNREACHABLE();
- return GL_NEVER;
+ Q_UNREACHABLE_RETURN(GL_NEVER);
}
}
@@ -2432,6 +2966,8 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
const QGles2CommandBuffer::Command &cmd(*it);
switch (cmd.cmd) {
case QGles2CommandBuffer::Command::BeginFrame:
+ if (cmd.args.beginFrame.timestampQuery)
+ glQueryCounter(cmd.args.beginFrame.timestampQuery, GL_TIMESTAMP);
if (caps.coreProfile) {
if (!vao)
f->glGenVertexArrays(1, &vao);
@@ -2448,8 +2984,18 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
f->glVertexAttribDivisor(GLuint(i), 0);
state.instancedAttributesUsed = false;
}
+#ifdef Q_OS_WASM
+ for (int i = 0; i < CommandBufferExecTrackedState::TRACKED_ATTRIB_COUNT; ++i) {
+ if (state.enabledAttribArrays[i]) {
+ f->glDisableVertexAttribArray(GLuint(i));
+ state.enabledAttribArrays[i] = false;
+ }
+ }
+#endif
if (vao)
f->glBindVertexArray(0);
+ if (cmd.args.endFrame.timestampQuery)
+ glQueryCounter(cmd.args.endFrame.timestampQuery, GL_TIMESTAMP);
break;
case QGles2CommandBuffer::Command::ResetFrame:
if (vao)
@@ -2578,6 +3124,54 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
type = GL_INT;
size = 1;
break;
+ case QRhiVertexInputAttribute::Half4:
+ type = GL_HALF_FLOAT;
+ size = 4;
+ break;
+ case QRhiVertexInputAttribute::Half3:
+ type = GL_HALF_FLOAT;
+ size = 3;
+ break;
+ case QRhiVertexInputAttribute::Half2:
+ type = GL_HALF_FLOAT;
+ size = 2;
+ break;
+ case QRhiVertexInputAttribute::Half:
+ type = GL_HALF_FLOAT;
+ size = 1;
+ break;
+ case QRhiVertexInputAttribute::UShort4:
+ type = GL_UNSIGNED_SHORT;
+ size = 4;
+ break;
+ case QRhiVertexInputAttribute::UShort3:
+ type = GL_UNSIGNED_SHORT;
+ size = 3;
+ break;
+ case QRhiVertexInputAttribute::UShort2:
+ type = GL_UNSIGNED_SHORT;
+ size = 2;
+ break;
+ case QRhiVertexInputAttribute::UShort:
+ type = GL_UNSIGNED_SHORT;
+ size = 1;
+ break;
+ case QRhiVertexInputAttribute::SShort4:
+ type = GL_SHORT;
+ size = 4;
+ break;
+ case QRhiVertexInputAttribute::SShort3:
+ type = GL_SHORT;
+ size = 3;
+ break;
+ case QRhiVertexInputAttribute::SShort2:
+ type = GL_SHORT;
+ size = 2;
+ break;
+ case QRhiVertexInputAttribute::SShort:
+ type = GL_SHORT;
+ size = 1;
+ break;
default:
break;
}
@@ -2604,7 +3198,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
f->glEnableVertexAttribArray(GLuint(locationIdx));
}
if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) {
- f->glVertexAttribDivisor(GLuint(locationIdx), GLuint(inputBinding->instanceStepRate()));
+ f->glVertexAttribDivisor(GLuint(locationIdx), inputBinding->instanceStepRate());
if (Q_LIKELY(locationIdx < CommandBufferExecTrackedState::TRACKED_ATTRIB_COUNT))
state.nonzeroAttribDivisor[locationIdx] = true;
else
@@ -2701,24 +3295,32 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
cmd.args.bindShaderResources.dynamicOffsetCount);
break;
case QGles2CommandBuffer::Command::BindFramebuffer:
+ {
+ QVarLengthArray<GLenum, 8> bufs;
if (cmd.args.bindFramebuffer.fbo) {
f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.bindFramebuffer.fbo);
+ const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
+ bufs.append(colorAttCount > 0 ? GL_COLOR_ATTACHMENT0 : GL_NONE);
if (caps.maxDrawBuffers > 1) {
- const int colorAttCount = cmd.args.bindFramebuffer.colorAttCount;
- QVarLengthArray<GLenum, 8> bufs;
- for (int i = 0; i < colorAttCount; ++i)
+ for (int i = 1; i < colorAttCount; ++i)
bufs.append(GL_COLOR_ATTACHMENT0 + uint(i));
- f->glDrawBuffers(colorAttCount, bufs.constData());
}
} else {
f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
+ if (cmd.args.bindFramebuffer.stereo && cmd.args.bindFramebuffer.stereoTarget == QRhiSwapChain::RightBuffer)
+ bufs.append(GL_BACK_RIGHT);
+ else
+ bufs.append(caps.gles ? GL_BACK : GL_BACK_LEFT);
}
- if (caps.srgbCapableDefaultFramebuffer) {
+ if (caps.hasDrawBuffersFunc)
+ f->glDrawBuffers(bufs.count(), bufs.constData());
+ if (caps.srgbWriteControl) {
if (cmd.args.bindFramebuffer.srgb)
f->glEnable(GL_FRAMEBUFFER_SRGB);
else
f->glDisable(GL_FRAMEBUFFER_SRGB);
}
+ }
break;
case QGles2CommandBuffer::Command::Clear:
f->glDisable(GL_SCISSOR_TEST);
@@ -2730,8 +3332,10 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
f->glDepthMask(GL_TRUE);
f->glClearDepthf(cmd.args.clear.d);
}
- if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT)
+ if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT) {
+ f->glStencilMask(0xFF);
f->glClearStencil(GLint(cmd.args.clear.s));
+ }
f->glClear(cmd.args.clear.mask);
cbD->graphicsPassState.reset(); // altered depth/color write, invalidate in order to avoid confusing the state tracking
break;
@@ -2742,7 +3346,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
break;
case QGles2CommandBuffer::Command::GetBufferSubData:
{
- QRhiBufferReadbackResult *result = cmd.args.getBufferSubData.result;
+ QRhiReadbackResult *result = cmd.args.getBufferSubData.result;
bindVertexIndexBufferWithStateReset(&state, f, cmd.args.getBufferSubData.target, cmd.args.getBufferSubData.buffer);
if (caps.gles) {
if (caps.properMapBuffer) {
@@ -2772,19 +3376,29 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
GLuint fbo;
f->glGenFramebuffers(1, &fbo);
f->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- if (cmd.args.copyTex.srcTarget == GL_TEXTURE_3D) {
+ if (cmd.args.copyTex.srcTarget == GL_TEXTURE_3D
+ || cmd.args.copyTex.srcTarget == GL_TEXTURE_2D_ARRAY
+ || cmd.args.copyTex.srcTarget == GL_TEXTURE_1D_ARRAY) {
f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.copyTex.srcTexture,
cmd.args.copyTex.srcLevel, cmd.args.copyTex.srcZ);
+ } else if (cmd.args.copyTex.srcTarget == GL_TEXTURE_1D) {
+ glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ cmd.args.copyTex.srcTarget, cmd.args.copyTex.srcTexture,
+ cmd.args.copyTex.srcLevel);
} else {
f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
cmd.args.copyTex.srcFaceTarget, cmd.args.copyTex.srcTexture, cmd.args.copyTex.srcLevel);
}
f->glBindTexture(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstTexture);
- if (cmd.args.copyTex.dstTarget == GL_TEXTURE_3D) {
+ if (cmd.args.copyTex.dstTarget == GL_TEXTURE_3D || cmd.args.copyTex.dstTarget == GL_TEXTURE_2D_ARRAY) {
f->glCopyTexSubImage3D(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstLevel,
cmd.args.copyTex.dstX, cmd.args.copyTex.dstY, cmd.args.copyTex.dstZ,
cmd.args.copyTex.srcX, cmd.args.copyTex.srcY,
cmd.args.copyTex.w, cmd.args.copyTex.h);
+ } else if (cmd.args.copyTex.dstTarget == GL_TEXTURE_1D) {
+ glCopyTexSubImage1D(cmd.args.copyTex.dstTarget, cmd.args.copyTex.dstLevel,
+ cmd.args.copyTex.dstX, cmd.args.copyTex.srcX,
+ cmd.args.copyTex.srcY, cmd.args.copyTex.w);
} else {
f->glCopyTexSubImage2D(cmd.args.copyTex.dstFaceTarget, cmd.args.copyTex.dstLevel,
cmd.args.copyTex.dstX, cmd.args.copyTex.dstY,
@@ -2811,6 +3425,9 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
if (cmd.args.readPixels.slice3D >= 0) {
f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
tex, mipLevel, cmd.args.readPixels.slice3D);
+ } else if (cmd.args.readPixels.readTarget == GL_TEXTURE_1D) {
+ glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ cmd.args.readPixels.readTarget, tex, mipLevel);
} else {
f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
cmd.args.readPixels.readTarget, tex, mipLevel);
@@ -2852,10 +3469,22 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
result->data.resize(w * h * 8);
f->glReadPixels(0, 0, w, h, GL_RGBA, GL_HALF_FLOAT, result->data.data());
break;
+ case QRhiTexture::R16F:
+ result->data.resize(w * h * 2);
+ f->glReadPixels(0, 0, w, h, GL_RED, GL_HALF_FLOAT, result->data.data());
+ break;
+ case QRhiTexture::R32F:
+ result->data.resize(w * h * 4);
+ f->glReadPixels(0, 0, w, h, GL_RED, GL_FLOAT, result->data.data());
+ break;
case QRhiTexture::RGBA32F:
result->data.resize(w * h * 16);
f->glReadPixels(0, 0, w, h, GL_RGBA, GL_FLOAT, result->data.data());
break;
+ case QRhiTexture::RGB10A2:
+ result->data.resize(w * h * 4);
+ f->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, result->data.data());
+ break;
default:
result->data.resize(w * h * 4);
f->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, result->data.data());
@@ -2880,12 +3509,17 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
f->glPixelStorei(GL_UNPACK_ALIGNMENT, cmd.args.subImage.rowStartAlign);
if (cmd.args.subImage.rowLength != 0)
f->glPixelStorei(GL_UNPACK_ROW_LENGTH, cmd.args.subImage.rowLength);
- if (cmd.args.subImage.target == GL_TEXTURE_3D) {
+ if (cmd.args.subImage.target == GL_TEXTURE_3D || cmd.args.subImage.target == GL_TEXTURE_2D_ARRAY) {
f->glTexSubImage3D(cmd.args.subImage.target, cmd.args.subImage.level,
cmd.args.subImage.dx, cmd.args.subImage.dy, cmd.args.subImage.dz,
cmd.args.subImage.w, cmd.args.subImage.h, 1,
cmd.args.subImage.glformat, cmd.args.subImage.gltype,
cmd.args.subImage.data);
+ } else if (cmd.args.subImage.target == GL_TEXTURE_1D) {
+ glTexSubImage1D(cmd.args.subImage.target, cmd.args.subImage.level,
+ cmd.args.subImage.dx, cmd.args.subImage.w,
+ cmd.args.subImage.glformat, cmd.args.subImage.gltype,
+ cmd.args.subImage.data);
} else {
f->glTexSubImage2D(cmd.args.subImage.faceTarget, cmd.args.subImage.level,
cmd.args.subImage.dx, cmd.args.subImage.dy,
@@ -2900,11 +3534,16 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
break;
case QGles2CommandBuffer::Command::CompressedImage:
f->glBindTexture(cmd.args.compressedImage.target, cmd.args.compressedImage.texture);
- if (cmd.args.compressedImage.target == GL_TEXTURE_3D) {
+ if (cmd.args.compressedImage.target == GL_TEXTURE_3D || cmd.args.compressedImage.target == GL_TEXTURE_2D_ARRAY) {
f->glCompressedTexImage3D(cmd.args.compressedImage.target, cmd.args.compressedImage.level,
cmd.args.compressedImage.glintformat,
cmd.args.compressedImage.w, cmd.args.compressedImage.h, cmd.args.compressedImage.depth,
0, cmd.args.compressedImage.size, cmd.args.compressedImage.data);
+ } else if (cmd.args.compressedImage.target == GL_TEXTURE_1D) {
+ glCompressedTexImage1D(
+ cmd.args.compressedImage.target, cmd.args.compressedImage.level,
+ cmd.args.compressedImage.glintformat, cmd.args.compressedImage.w, 0,
+ cmd.args.compressedImage.size, cmd.args.compressedImage.data);
} else {
f->glCompressedTexImage2D(cmd.args.compressedImage.faceTarget, cmd.args.compressedImage.level,
cmd.args.compressedImage.glintformat,
@@ -2914,12 +3553,18 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
break;
case QGles2CommandBuffer::Command::CompressedSubImage:
f->glBindTexture(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.texture);
- if (cmd.args.compressedSubImage.target == GL_TEXTURE_3D) {
+ if (cmd.args.compressedSubImage.target == GL_TEXTURE_3D || cmd.args.compressedSubImage.target == GL_TEXTURE_2D_ARRAY) {
f->glCompressedTexSubImage3D(cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.level,
cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy, cmd.args.compressedSubImage.dz,
cmd.args.compressedSubImage.w, cmd.args.compressedSubImage.h, 1,
cmd.args.compressedSubImage.glintformat,
cmd.args.compressedSubImage.size, cmd.args.compressedSubImage.data);
+ } else if (cmd.args.compressedImage.target == GL_TEXTURE_1D) {
+ glCompressedTexSubImage1D(
+ cmd.args.compressedSubImage.target, cmd.args.compressedSubImage.level,
+ cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.w,
+ cmd.args.compressedSubImage.glintformat, cmd.args.compressedSubImage.size,
+ cmd.args.compressedSubImage.data);
} else {
f->glCompressedTexSubImage2D(cmd.args.compressedSubImage.faceTarget, cmd.args.compressedSubImage.level,
cmd.args.compressedSubImage.dx, cmd.args.compressedSubImage.dy,
@@ -2930,19 +3575,128 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
break;
case QGles2CommandBuffer::Command::BlitFromRenderbuffer:
{
+ // Altering the scissor state, so reset the stored state, although
+ // not strictly required as long as blit is done in endPass() only.
+ cbD->graphicsPassState.reset();
+ f->glDisable(GL_SCISSOR_TEST);
+ GLuint fbo[2];
+ f->glGenFramebuffers(2, fbo);
+ f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo[0]);
+ const bool ds = cmd.args.blitFromRenderbuffer.isDepthStencil;
+ if (ds) {
+ f->glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
+ f->glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
+ } else {
+ f->glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, cmd.args.blitFromRenderbuffer.renderbuffer);
+ }
+ f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]);
+ if (cmd.args.blitFromRenderbuffer.target == GL_TEXTURE_3D || cmd.args.blitFromRenderbuffer.target == GL_TEXTURE_2D_ARRAY) {
+ if (ds) {
+ f->glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ cmd.args.blitFromRenderbuffer.dstTexture,
+ cmd.args.blitFromRenderbuffer.dstLevel,
+ cmd.args.blitFromRenderbuffer.dstLayer);
+ f->glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ cmd.args.blitFromRenderbuffer.dstTexture,
+ cmd.args.blitFromRenderbuffer.dstLevel,
+ cmd.args.blitFromRenderbuffer.dstLayer);
+ } else {
+ f->glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ cmd.args.blitFromRenderbuffer.dstTexture,
+ cmd.args.blitFromRenderbuffer.dstLevel,
+ cmd.args.blitFromRenderbuffer.dstLayer);
+ }
+ } else {
+ if (ds) {
+ f->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
+ cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
+ f->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromRenderbuffer.target,
+ cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
+ } else {
+ f->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromRenderbuffer.target,
+ cmd.args.blitFromRenderbuffer.dstTexture, cmd.args.blitFromRenderbuffer.dstLevel);
+ }
+ }
+ f->glBlitFramebuffer(0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
+ 0, 0, cmd.args.blitFromRenderbuffer.w, cmd.args.blitFromRenderbuffer.h,
+ ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT,
+ GL_NEAREST); // Qt 5 used Nearest when resolving samples, stick to that
+ f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
+ f->glDeleteFramebuffers(2, fbo);
+ }
+ break;
+ case QGles2CommandBuffer::Command::BlitFromTexture:
+ {
+ // Altering the scissor state, so reset the stored state, although
+ // not strictly required as long as blit is done in endPass() only.
+ cbD->graphicsPassState.reset();
+ f->glDisable(GL_SCISSOR_TEST);
GLuint fbo[2];
f->glGenFramebuffers(2, fbo);
f->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo[0]);
- f->glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER, cmd.args.blitFromRb.renderbuffer);
+ const bool ds = cmd.args.blitFromTexture.isDepthStencil;
+ if (cmd.args.blitFromTexture.srcTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) {
+ if (ds) {
+ f->glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ cmd.args.blitFromTexture.srcTexture,
+ cmd.args.blitFromTexture.srcLevel,
+ cmd.args.blitFromTexture.srcLayer);
+ f->glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ cmd.args.blitFromTexture.srcTexture,
+ cmd.args.blitFromTexture.srcLevel,
+ cmd.args.blitFromTexture.srcLayer);
+ } else {
+ f->glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ cmd.args.blitFromTexture.srcTexture,
+ cmd.args.blitFromTexture.srcLevel,
+ cmd.args.blitFromTexture.srcLayer);
+ }
+ } else {
+ if (ds) {
+ f->glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
+ cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
+ f->glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.srcTarget,
+ cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
+ } else {
+ f->glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.srcTarget,
+ cmd.args.blitFromTexture.srcTexture, cmd.args.blitFromTexture.srcLevel);
+ }
+ }
f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]);
-
- f->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromRb.target,
- cmd.args.blitFromRb.texture, cmd.args.blitFromRb.dstLevel);
- f->glBlitFramebuffer(0, 0, cmd.args.blitFromRb.w, cmd.args.blitFromRb.h,
- 0, 0, cmd.args.blitFromRb.w, cmd.args.blitFromRb.h,
- GL_COLOR_BUFFER_BIT,
- GL_LINEAR);
+ if (cmd.args.blitFromTexture.dstTarget == GL_TEXTURE_3D || cmd.args.blitFromTexture.dstTarget == GL_TEXTURE_2D_ARRAY) {
+ if (ds) {
+ f->glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ cmd.args.blitFromTexture.dstTexture,
+ cmd.args.blitFromTexture.dstLevel,
+ cmd.args.blitFromTexture.dstLayer);
+ f->glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ cmd.args.blitFromTexture.dstTexture,
+ cmd.args.blitFromTexture.dstLevel,
+ cmd.args.blitFromTexture.dstLayer);
+ } else {
+ f->glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ cmd.args.blitFromTexture.dstTexture,
+ cmd.args.blitFromTexture.dstLevel,
+ cmd.args.blitFromTexture.dstLayer);
+ }
+ } else {
+ if (ds) {
+ f->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
+ cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
+ f->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, cmd.args.blitFromTexture.dstTarget,
+ cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
+ } else {
+ f->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cmd.args.blitFromTexture.dstTarget,
+ cmd.args.blitFromTexture.dstTexture, cmd.args.blitFromTexture.dstLevel);
+ }
+ }
+ f->glBlitFramebuffer(0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
+ 0, 0, cmd.args.blitFromTexture.w, cmd.args.blitFromTexture.h,
+ ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT,
+ GL_NEAREST); // Qt 5 used Nearest when resolving samples, stick to that
f->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
f->glDeleteFramebuffers(2, fbo);
}
@@ -2976,12 +3730,12 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
for (auto it = tracker.cbeginBuffers(), itEnd = tracker.cendBuffers(); it != itEnd; ++it) {
QGles2Buffer::Access accessBeforePass = QGles2Buffer::Access(it->stateAtPassBegin.access);
if (bufferAccessIsWrite(accessBeforePass))
- barriers |= GL_ALL_BARRIER_BITS;
+ barriers |= barriersForBuffer();
}
for (auto it = tracker.cbeginTextures(), itEnd = tracker.cendTextures(); it != itEnd; ++it) {
QGles2Texture::Access accessBeforePass = QGles2Texture::Access(it->stateAtPassBegin.access);
if (textureAccessIsWrite(accessBeforePass))
- barriers |= GL_ALL_BARRIER_BITS;
+ barriers |= barriersForTexture();
}
if (barriers)
f->glMemoryBarrier(barriers);
@@ -2991,6 +3745,13 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
if (caps.compute)
f->glMemoryBarrier(cmd.args.barrier.barriers);
break;
+ case QGles2CommandBuffer::Command::InvalidateFramebuffer:
+ if (caps.gles && caps.ctxMajor >= 3) {
+ f->glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER,
+ cmd.args.invalidateFramebuffer.attCount,
+ cmd.args.invalidateFramebuffer.att);
+ }
+ break;
default:
break;
}
@@ -3039,6 +3800,12 @@ void QRhiGles2::executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2Grap
f->glFrontFace(frontFace);
}
+ const GLenum polygonMode = toGlPolygonMode(psD->m_polygonMode);
+ if (glPolygonMode && (forceUpdate || polygonMode != state.polygonMode)) {
+ state.polygonMode = polygonMode;
+ glPolygonMode(GL_FRONT_AND_BACK, polygonMode);
+ }
+
if (!psD->m_targetBlends.isEmpty()) {
// We do not have MRT support here, meaning all targets use the blend
// params from the first one. This is technically incorrect, even if
@@ -3179,12 +3946,21 @@ void QRhiGles2::executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2Grap
}
}
+ if (psD->m_topology == QRhiGraphicsPipeline::Patches) {
+ const int cpCount = psD->m_patchControlPointCount;
+ if (forceUpdate || cpCount != state.cpCount) {
+ state.cpCount = cpCount;
+ f->glPatchParameteri(GL_PATCH_VERTICES, qMax(1, cpCount));
+ }
+ }
+
f->glUseProgram(psD->program);
}
-static inline void qrhi_std140_to_packed(float *dst, int vecSize, int elemCount, const void *src)
+template <typename T>
+static inline void qrhi_std140_to_packed(T *dst, int vecSize, int elemCount, const void *src)
{
- const float *p = reinterpret_cast<const float *>(src);
+ const T *p = reinterpret_cast<const T *>(src);
for (int i = 0; i < elemCount; ++i) {
for (int j = 0; j < vecSize; ++j)
dst[vecSize * i + j] = *p++;
@@ -3192,6 +3968,59 @@ static inline void qrhi_std140_to_packed(float *dst, int vecSize, int elemCount,
}
}
+void QRhiGles2::bindCombinedSampler(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Sampler *samplerD,
+ void *ps, uint psGeneration, int glslLocation,
+ int *texUnit, bool *activeTexUnitAltered)
+{
+ const bool samplerStateValid = texD->samplerState == samplerD->d;
+ const bool cachedStateInRange = *texUnit < 16;
+ bool updateTextureBinding = true;
+ if (samplerStateValid && cachedStateInRange) {
+ // If we already encountered the same texture with
+ // the same pipeline for this texture unit in the
+ // current pass, then the shader program already
+ // has the uniform set. As in a 3D scene one model
+ // often has more than one associated texture map,
+ // the savings here can become significant,
+ // depending on the scene.
+ if (cbD->textureUnitState[*texUnit].ps == ps
+ && cbD->textureUnitState[*texUnit].psGeneration == psGeneration
+ && cbD->textureUnitState[*texUnit].texture == texD->texture)
+ {
+ updateTextureBinding = false;
+ }
+ }
+ if (updateTextureBinding) {
+ f->glActiveTexture(GL_TEXTURE0 + uint(*texUnit));
+ *activeTexUnitAltered = true;
+ f->glBindTexture(texD->target, texD->texture);
+ f->glUniform1i(glslLocation, *texUnit);
+ if (cachedStateInRange) {
+ cbD->textureUnitState[*texUnit].ps = ps;
+ cbD->textureUnitState[*texUnit].psGeneration = psGeneration;
+ cbD->textureUnitState[*texUnit].texture = texD->texture;
+ }
+ }
+ ++(*texUnit);
+ if (!samplerStateValid) {
+ f->glTexParameteri(texD->target, GL_TEXTURE_MIN_FILTER, GLint(samplerD->d.glminfilter));
+ f->glTexParameteri(texD->target, GL_TEXTURE_MAG_FILTER, GLint(samplerD->d.glmagfilter));
+ f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_S, GLint(samplerD->d.glwraps));
+ f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_T, GLint(samplerD->d.glwrapt));
+ if (caps.texture3D)
+ f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_R, GLint(samplerD->d.glwrapr));
+ if (caps.textureCompareMode) {
+ if (samplerD->d.gltexcomparefunc != GL_NEVER) {
+ f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_FUNC, GLint(samplerD->d.gltexcomparefunc));
+ } else {
+ f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ }
+ }
+ texD->samplerState = samplerD->d;
+ }
+}
+
void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs,
QRhiShaderResourceBindings *srb,
@@ -3200,14 +4029,29 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
QGles2ShaderResourceBindings *srbD = QRHI_RES(QGles2ShaderResourceBindings, srb);
int texUnit = 1; // start from unit 1, keep 0 for resource mgmt stuff to avoid clashes
bool activeTexUnitAltered = false;
- QVarLengthArray<float, 256> packedFloatArray;
+ union data32_t {
+ float f;
+ qint32 i;
+ };
+ QVarLengthArray<data32_t, 256> packedArray;
QGles2UniformDescriptionVector &uniforms(maybeGraphicsPs ? QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->uniforms
: QRHI_RES(QGles2ComputePipeline, maybeComputePs)->uniforms);
QGles2UniformState *uniformState = maybeGraphicsPs ? QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->uniformState
: QRHI_RES(QGles2ComputePipeline, maybeComputePs)->uniformState;
+ struct SeparateTexture {
+ QGles2Texture *texture;
+ int binding;
+ int elem;
+ };
+ QVarLengthArray<SeparateTexture, 8> separateTextureBindings;
+ struct SeparateSampler {
+ QGles2Sampler *sampler;
+ int binding;
+ };
+ QVarLengthArray<SeparateSampler, 4> separateSamplerBindings;
- for (int i = 0, ie = srbD->m_bindings.count(); i != ie; ++i) {
- const QRhiShaderResourceBinding::Data *b = srbD->m_bindings.at(i).data();
+ for (int i = 0, ie = srbD->m_bindings.size(); i != ie; ++i) {
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->m_bindings.at(i));
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
@@ -3221,7 +4065,7 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
}
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.ubuf.buf);
const char *bufView = bufD->data.constData() + viewOffset;
- for (const QGles2UniformDescription &uniform : qAsConst(uniforms)) {
+ for (const QGles2UniformDescription &uniform : std::as_const(uniforms)) {
if (uniform.binding == b->binding) {
// in a uniform buffer everything is at least 4 byte aligned
// so this should not cause unaligned reads
@@ -3233,11 +4077,16 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
&& uniform.type != QShaderDescription::Vec2
&& uniform.type != QShaderDescription::Vec3
&& uniform.type != QShaderDescription::Vec4
+ && uniform.type != QShaderDescription::Int
+ && uniform.type != QShaderDescription::Int2
+ && uniform.type != QShaderDescription::Int3
+ && uniform.type != QShaderDescription::Int4
&& uniform.type != QShaderDescription::Mat3
&& uniform.type != QShaderDescription::Mat4)
{
qWarning("Uniform with buffer binding %d, buffer offset %d, type %d is an array, "
- "but arrays are only supported for float, vec2, vec3, vec4, mat3 and mat4. "
+ "but arrays are only supported for float, vec2, vec3, vec4, int, "
+ "ivec2, ivec3, ivec4, mat3 and mat4. "
"Only the first element will be set.",
uniform.binding, uniform.offset, uniform.type);
}
@@ -3267,9 +4116,9 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
}
} else {
// input is 16 bytes per element as per std140, have to convert to packed
- packedFloatArray.resize(elemCount);
- qrhi_std140_to_packed(packedFloatArray.data(), 1, elemCount, src);
- f->glUniform1fv(uniform.glslLocation, elemCount, packedFloatArray.constData());
+ packedArray.resize(elemCount);
+ qrhi_std140_to_packed(&packedArray.data()->f, 1, elemCount, src);
+ f->glUniform1fv(uniform.glslLocation, elemCount, &packedArray.constData()->f);
}
}
break;
@@ -3293,9 +4142,9 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
f->glUniform2fv(uniform.glslLocation, 1, v);
}
} else {
- packedFloatArray.resize(elemCount * 2);
- qrhi_std140_to_packed(packedFloatArray.data(), 2, elemCount, src);
- f->glUniform2fv(uniform.glslLocation, elemCount, packedFloatArray.constData());
+ packedArray.resize(elemCount * 2);
+ qrhi_std140_to_packed(&packedArray.data()->f, 2, elemCount, src);
+ f->glUniform2fv(uniform.glslLocation, elemCount, &packedArray.constData()->f);
}
}
break;
@@ -3321,9 +4170,9 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
f->glUniform3fv(uniform.glslLocation, 1, v);
}
} else {
- packedFloatArray.resize(elemCount * 3);
- qrhi_std140_to_packed(packedFloatArray.data(), 3, elemCount, src);
- f->glUniform3fv(uniform.glslLocation, elemCount, packedFloatArray.constData());
+ packedArray.resize(elemCount * 3);
+ qrhi_std140_to_packed(&packedArray.data()->f, 3, elemCount, src);
+ f->glUniform3fv(uniform.glslLocation, elemCount, &packedArray.constData()->f);
}
}
break;
@@ -3351,7 +4200,7 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
f->glUniform4fv(uniform.glslLocation, 1, v);
}
} else {
- f->glUniform4fv(uniform.glslLocation, qMax(1, uniform.arrayDim), reinterpret_cast<const float *>(src));
+ f->glUniform4fv(uniform.glslLocation, elemCount, reinterpret_cast<const float *>(src));
}
}
break;
@@ -3370,9 +4219,9 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
memcpy(mat + 6, srcMat + 8, 3 * sizeof(float));
f->glUniformMatrix3fv(uniform.glslLocation, 1, GL_FALSE, mat);
} else {
- packedFloatArray.resize(elemCount * 9);
- qrhi_std140_to_packed(packedFloatArray.data(), 3, elemCount * 3, src);
- f->glUniformMatrix3fv(uniform.glslLocation, elemCount, GL_FALSE, packedFloatArray.constData());
+ packedArray.resize(elemCount * 9);
+ qrhi_std140_to_packed(&packedArray.data()->f, 3, elemCount * 3, src);
+ f->glUniformMatrix3fv(uniform.glslLocation, elemCount, GL_FALSE, &packedArray.constData()->f);
}
}
break;
@@ -3380,16 +4229,43 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
f->glUniformMatrix4fv(uniform.glslLocation, qMax(1, uniform.arrayDim), GL_FALSE, reinterpret_cast<const float *>(src));
break;
case QShaderDescription::Int:
- f->glUniform1i(uniform.glslLocation, *reinterpret_cast<const qint32 *>(src));
+ {
+ const int elemCount = uniform.arrayDim;
+ if (elemCount < 1) {
+ f->glUniform1i(uniform.glslLocation, *reinterpret_cast<const qint32 *>(src));
+ } else {
+ packedArray.resize(elemCount);
+ qrhi_std140_to_packed(&packedArray.data()->i, 1, elemCount, src);
+ f->glUniform1iv(uniform.glslLocation, elemCount, &packedArray.constData()->i);
+ }
+ }
break;
case QShaderDescription::Int2:
- f->glUniform2iv(uniform.glslLocation, 1, reinterpret_cast<const qint32 *>(src));
+ {
+ const int elemCount = uniform.arrayDim;
+ if (elemCount < 1) {
+ f->glUniform2iv(uniform.glslLocation, 1, reinterpret_cast<const qint32 *>(src));
+ } else {
+ packedArray.resize(elemCount * 2);
+ qrhi_std140_to_packed(&packedArray.data()->i, 2, elemCount, src);
+ f->glUniform2iv(uniform.glslLocation, elemCount, &packedArray.constData()->i);
+ }
+ }
break;
case QShaderDescription::Int3:
- f->glUniform3iv(uniform.glslLocation, 1, reinterpret_cast<const qint32 *>(src));
+ {
+ const int elemCount = uniform.arrayDim;
+ if (elemCount < 1) {
+ f->glUniform3iv(uniform.glslLocation, 1, reinterpret_cast<const qint32 *>(src));
+ } else {
+ packedArray.resize(elemCount * 3);
+ qrhi_std140_to_packed(&packedArray.data()->i, 3, elemCount, src);
+ f->glUniform3iv(uniform.glslLocation, elemCount, &packedArray.constData()->i);
+ }
+ }
break;
case QShaderDescription::Int4:
- f->glUniform4iv(uniform.glslLocation, 1, reinterpret_cast<const qint32 *>(src));
+ f->glUniform4iv(uniform.glslLocation, qMax(1, uniform.arrayDim), reinterpret_cast<const qint32 *>(src));
break;
case QShaderDescription::Uint:
f->glUniform1ui(uniform.glslLocation, *reinterpret_cast<const quint32 *>(src));
@@ -3441,64 +4317,33 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.stex.texSamplers[elem].tex);
QGles2Sampler *samplerD = QRHI_RES(QGles2Sampler, b->u.stex.texSamplers[elem].sampler);
for (const QGles2SamplerDescription &shaderSampler : samplers) {
- if (shaderSampler.binding == b->binding) {
- const bool samplerStateValid = texD->samplerState == samplerD->d;
- const bool cachedStateInRange = texUnit < 16;
- bool updateTextureBinding = true;
- if (samplerStateValid && cachedStateInRange) {
- // If we already encountered the same texture with
- // the same pipeline for this texture unit in the
- // current pass, then the shader program already
- // has the uniform set. As in a 3D scene one model
- // often has more than one associated texture map,
- // the savings here can become significant,
- // depending on the scene.
- if (cbD->textureUnitState[texUnit].ps == ps
- && cbD->textureUnitState[texUnit].psGeneration == psGeneration
- && cbD->textureUnitState[texUnit].texture == texD->texture)
- {
- updateTextureBinding = false;
- }
- }
- if (updateTextureBinding) {
- f->glActiveTexture(GL_TEXTURE0 + uint(texUnit));
- activeTexUnitAltered = true;
- f->glBindTexture(texD->target, texD->texture);
- f->glUniform1i(shaderSampler.glslLocation + elem, texUnit);
- if (cachedStateInRange) {
- cbD->textureUnitState[texUnit].ps = ps;
- cbD->textureUnitState[texUnit].psGeneration = psGeneration;
- cbD->textureUnitState[texUnit].texture = texD->texture;
- }
- }
- ++texUnit;
- if (!samplerStateValid) {
- f->glTexParameteri(texD->target, GL_TEXTURE_MIN_FILTER, GLint(samplerD->d.glminfilter));
- f->glTexParameteri(texD->target, GL_TEXTURE_MAG_FILTER, GLint(samplerD->d.glmagfilter));
- f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_S, GLint(samplerD->d.glwraps));
- f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_T, GLint(samplerD->d.glwrapt));
- if (caps.texture3D)
- f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_R, GLint(samplerD->d.glwrapr));
- if (caps.textureCompareMode) {
- if (samplerD->d.gltexcomparefunc != GL_NEVER) {
- f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_FUNC, GLint(samplerD->d.gltexcomparefunc));
- } else {
- f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- }
- }
- texD->samplerState = samplerD->d;
- }
+ if (shaderSampler.combinedBinding == b->binding) {
+ const int loc = shaderSampler.glslLocation + elem;
+ bindCombinedSampler(cbD, texD, samplerD, ps, psGeneration, loc, &texUnit, &activeTexUnitAltered);
+ break;
}
}
}
}
break;
+ case QRhiShaderResourceBinding::Texture:
+ for (int elem = 0; elem < b->u.stex.count; ++elem) {
+ QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.stex.texSamplers[elem].tex);
+ separateTextureBindings.append({ texD, b->binding, elem });
+ }
+ break;
+ case QRhiShaderResourceBinding::Sampler:
+ {
+ QGles2Sampler *samplerD = QRHI_RES(QGles2Sampler, b->u.stex.texSamplers[0].sampler);
+ separateSamplerBindings.append({ samplerD, b->binding });
+ }
+ break;
case QRhiShaderResourceBinding::ImageLoad:
case QRhiShaderResourceBinding::ImageStore:
case QRhiShaderResourceBinding::ImageLoadStore:
{
QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.simage.tex);
+ Q_ASSERT(texD->m_flags.testFlag(QRhiTexture::UsedWithLoadStore));
const bool layered = texD->m_flags.testFlag(QRhiTexture::CubeMap);
GLenum access = GL_READ_WRITE;
if (b->type == QRhiShaderResourceBinding::ImageLoad)
@@ -3515,6 +4360,7 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
case QRhiShaderResourceBinding::BufferLoadStore:
{
QGles2Buffer *bufD = QRHI_RES(QGles2Buffer, b->u.sbuf.buf);
+ Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
if (b->u.sbuf.offset == 0 && b->u.sbuf.maybeSize == 0)
f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, GLuint(b->binding), bufD->buffer);
else
@@ -3528,6 +4374,35 @@ void QRhiGles2::bindShaderResources(QGles2CommandBuffer *cbD,
}
}
+ if (!separateTextureBindings.isEmpty() || !separateSamplerBindings.isEmpty()) {
+ const QGles2SamplerDescriptionVector &samplers(maybeGraphicsPs ? QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->samplers
+ : QRHI_RES(QGles2ComputePipeline, maybeComputePs)->samplers);
+ void *ps;
+ uint psGeneration;
+ if (maybeGraphicsPs) {
+ ps = maybeGraphicsPs;
+ psGeneration = QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->generation;
+ } else {
+ ps = maybeComputePs;
+ psGeneration = QRHI_RES(QGles2ComputePipeline, maybeComputePs)->generation;
+ }
+ for (const QGles2SamplerDescription &shaderSampler : samplers) {
+ if (shaderSampler.combinedBinding >= 0)
+ continue;
+ for (const SeparateSampler &sepSampler : separateSamplerBindings) {
+ if (sepSampler.binding != shaderSampler.sbinding)
+ continue;
+ for (const SeparateTexture &sepTex : separateTextureBindings) {
+ if (sepTex.binding != shaderSampler.tbinding)
+ continue;
+ const int loc = shaderSampler.glslLocation + sepTex.elem;
+ bindCombinedSampler(cbD, sepTex.texture, sepSampler.sampler, ps, psGeneration,
+ loc, &texUnit, &activeTexUnitAltered);
+ }
+ }
+ }
+ }
+
if (activeTexUnitAltered)
f->glActiveTexture(GL_TEXTURE0);
}
@@ -3548,15 +4423,21 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt,
QGles2CommandBuffer::Command &fbCmd(cbD->commands.get());
fbCmd.cmd = QGles2CommandBuffer::Command::BindFramebuffer;
+ static const bool doClearBuffers = qEnvironmentVariableIntValue("QT_GL_NO_CLEAR_BUFFERS") == 0;
+ static const bool doClearColorBuffer = qEnvironmentVariableIntValue("QT_GL_NO_CLEAR_COLOR_BUFFER") == 0;
+
switch (rt->resourceType()) {
- case QRhiResource::RenderTarget:
- rtD = &QRHI_RES(QGles2ReferenceRenderTarget, rt)->d;
+ case QRhiResource::SwapChainRenderTarget:
+ rtD = &QRHI_RES(QGles2SwapChainRenderTarget, rt)->d;
if (wantsColorClear)
- *wantsColorClear = true;
+ *wantsColorClear = doClearBuffers && doClearColorBuffer;
if (wantsDsClear)
- *wantsDsClear = true;
+ *wantsDsClear = doClearBuffers;
fbCmd.args.bindFramebuffer.fbo = 0;
fbCmd.args.bindFramebuffer.colorAttCount = 1;
+ fbCmd.args.bindFramebuffer.stereo = rtD->stereoTarget.has_value();
+ if (fbCmd.args.bindFramebuffer.stereo)
+ fbCmd.args.bindFramebuffer.stereoTarget = rtD->stereoTarget.value();
break;
case QRhiResource::TextureRenderTarget:
{
@@ -3568,6 +4449,7 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt,
*wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
fbCmd.args.bindFramebuffer.fbo = rtTex->framebuffer;
fbCmd.args.bindFramebuffer.colorAttCount = rtD->colorAttCount;
+ fbCmd.args.bindFramebuffer.stereo = false;
for (auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
it != itEnd; ++it)
@@ -3608,7 +4490,7 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt,
void QRhiGles2::enqueueBarriersForPass(QGles2CommandBuffer *cbD)
{
cbD->passResTrackers.append(QRhiPassResourceTracker());
- cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1;
+ cbD->currentPassResTrackerIndex = cbD->passResTrackers.size() - 1;
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::BarriersForPass;
cmd.args.barriersForPass.trackerIndex = cbD->currentPassResTrackerIndex;
@@ -3631,6 +4513,12 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
// glMemoryBarrier() calls based on that tracker when submitted.
enqueueBarriersForPass(cbD);
+ if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
+ QGles2TextureRenderTarget *rtTex = QRHI_RES(QGles2TextureRenderTarget, rt);
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QGles2Texture, QGles2RenderBuffer>(rtTex->description(), rtTex->d.currentResIdList))
+ rtTex->create();
+ }
+
bool wantsColorClear, wantsDsClear;
QGles2RenderTargetData *rtD = enqueueBindFramebuffer(rt, cbD, &wantsColorClear, &wantsDsClear);
@@ -3662,28 +4550,129 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
if (cbD->currentTarget->resourceType() == QRhiResource::TextureRenderTarget) {
QGles2TextureRenderTarget *rtTex = QRHI_RES(QGles2TextureRenderTarget, cbD->currentTarget);
- if (rtTex->m_desc.cbeginColorAttachments() != rtTex->m_desc.cendColorAttachments()) {
- // handle only 1 color attachment and only (msaa) renderbuffer
- const QRhiColorAttachment &colorAtt(*rtTex->m_desc.cbeginColorAttachments());
- if (colorAtt.resolveTexture()) {
- Q_ASSERT(colorAtt.renderBuffer());
+ for (auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
+ it != itEnd; ++it)
+ {
+ const QRhiColorAttachment &colorAtt(*it);
+ if (!colorAtt.resolveTexture())
+ continue;
+
+ QGles2Texture *resolveTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
+ const QSize size = resolveTexD->pixelSize();
+ if (colorAtt.renderBuffer()) {
QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, colorAtt.renderBuffer());
- const QSize size = colorAtt.resolveTexture()->pixelSize();
if (rbD->pixelSize() != size) {
qWarning("Resolve source (%dx%d) and target (%dx%d) size does not match",
rbD->pixelSize().width(), rbD->pixelSize().height(), size.width(), size.height());
}
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::BlitFromRenderbuffer;
- cmd.args.blitFromRb.renderbuffer = rbD->renderbuffer;
- cmd.args.blitFromRb.w = size.width();
- cmd.args.blitFromRb.h = size.height();
- QGles2Texture *colorTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
- const GLenum faceTargetBase = colorTexD->m_flags.testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X
- : colorTexD->target;
- cmd.args.blitFromRb.target = faceTargetBase + uint(colorAtt.resolveLayer());
- cmd.args.blitFromRb.texture = colorTexD->texture;
- cmd.args.blitFromRb.dstLevel = colorAtt.resolveLevel();
+ cmd.args.blitFromRenderbuffer.renderbuffer = rbD->renderbuffer;
+ cmd.args.blitFromRenderbuffer.w = size.width();
+ cmd.args.blitFromRenderbuffer.h = size.height();
+ if (resolveTexD->m_flags.testFlag(QRhiTexture::CubeMap))
+ cmd.args.blitFromRenderbuffer.target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + uint(colorAtt.resolveLayer());
+ else
+ cmd.args.blitFromRenderbuffer.target = resolveTexD->target;
+ cmd.args.blitFromRenderbuffer.dstTexture = resolveTexD->texture;
+ cmd.args.blitFromRenderbuffer.dstLevel = colorAtt.resolveLevel();
+ const bool hasZ = resolveTexD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
+ || resolveTexD->m_flags.testFlag(QRhiTexture::TextureArray);
+ cmd.args.blitFromRenderbuffer.dstLayer = hasZ ? colorAtt.resolveLayer() : 0;
+ cmd.args.blitFromRenderbuffer.isDepthStencil = false;
+ } else if (caps.glesMultisampleRenderToTexture) {
+ // Nothing to do, resolving into colorAtt.resolveTexture() is automatic,
+ // colorAtt.texture() is in fact not used for anything.
+ } else {
+ Q_ASSERT(colorAtt.texture());
+ QGles2Texture *texD = QRHI_RES(QGles2Texture, colorAtt.texture());
+ if (texD->pixelSize() != size) {
+ qWarning("Resolve source (%dx%d) and target (%dx%d) size does not match",
+ texD->pixelSize().width(), texD->pixelSize().height(), size.width(), size.height());
+ }
+ const int resolveCount = colorAtt.multiViewCount() >= 2 ? colorAtt.multiViewCount() : 1;
+ for (int resolveIdx = 0; resolveIdx < resolveCount; ++resolveIdx) {
+ const int srcLayer = colorAtt.layer() + resolveIdx;
+ const int dstLayer = colorAtt.resolveLayer() + resolveIdx;
+ QGles2CommandBuffer::Command &cmd(cbD->commands.get());
+ cmd.cmd = QGles2CommandBuffer::Command::BlitFromTexture;
+ if (texD->m_flags.testFlag(QRhiTexture::CubeMap))
+ cmd.args.blitFromTexture.srcTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + uint(srcLayer);
+ else
+ cmd.args.blitFromTexture.srcTarget = texD->target;
+ cmd.args.blitFromTexture.srcTexture = texD->texture;
+ cmd.args.blitFromTexture.srcLevel = colorAtt.level();
+ cmd.args.blitFromTexture.srcLayer = 0;
+ if (texD->m_flags.testFlag(QRhiTexture::ThreeDimensional) || texD->m_flags.testFlag(QRhiTexture::TextureArray))
+ cmd.args.blitFromTexture.srcLayer = srcLayer;
+ cmd.args.blitFromTexture.w = size.width();
+ cmd.args.blitFromTexture.h = size.height();
+ if (resolveTexD->m_flags.testFlag(QRhiTexture::CubeMap))
+ cmd.args.blitFromTexture.dstTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + uint(dstLayer);
+ else
+ cmd.args.blitFromTexture.dstTarget = resolveTexD->target;
+ cmd.args.blitFromTexture.dstTexture = resolveTexD->texture;
+ cmd.args.blitFromTexture.dstLevel = colorAtt.resolveLevel();
+ cmd.args.blitFromTexture.dstLayer = 0;
+ if (resolveTexD->m_flags.testFlag(QRhiTexture::ThreeDimensional) || resolveTexD->m_flags.testFlag(QRhiTexture::TextureArray))
+ cmd.args.blitFromTexture.dstLayer = dstLayer;
+ cmd.args.blitFromTexture.isDepthStencil = false;
+ }
+ }
+ }
+
+ if (rtTex->m_desc.depthResolveTexture()) {
+ QGles2Texture *depthResolveTexD = QRHI_RES(QGles2Texture, rtTex->m_desc.depthResolveTexture());
+ const QSize size = depthResolveTexD->pixelSize();
+ if (rtTex->m_desc.depthStencilBuffer()) {
+ QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, rtTex->m_desc.depthStencilBuffer());
+ QGles2CommandBuffer::Command &cmd(cbD->commands.get());
+ cmd.cmd = QGles2CommandBuffer::Command::BlitFromRenderbuffer;
+ cmd.args.blitFromRenderbuffer.renderbuffer = rbD->renderbuffer;
+ cmd.args.blitFromRenderbuffer.w = size.width();
+ cmd.args.blitFromRenderbuffer.h = size.height();
+ cmd.args.blitFromRenderbuffer.target = depthResolveTexD->target;
+ cmd.args.blitFromRenderbuffer.dstTexture = depthResolveTexD->texture;
+ cmd.args.blitFromRenderbuffer.dstLevel = 0;
+ cmd.args.blitFromRenderbuffer.dstLayer = 0;
+ cmd.args.blitFromRenderbuffer.isDepthStencil = true;
+ } else if (caps.glesMultisampleRenderToTexture) {
+ // Nothing to do, resolving into depthResolveTexture() is automatic.
+ } else {
+ QGles2Texture *depthTexD = QRHI_RES(QGles2Texture, rtTex->m_desc.depthTexture());
+ const int resolveCount = depthTexD->arraySize() >= 2 ? depthTexD->arraySize() : 1;
+ for (int resolveIdx = 0; resolveIdx < resolveCount; ++resolveIdx) {
+ QGles2CommandBuffer::Command &cmd(cbD->commands.get());
+ cmd.cmd = QGles2CommandBuffer::Command::BlitFromTexture;
+ cmd.args.blitFromTexture.srcTarget = depthTexD->target;
+ cmd.args.blitFromTexture.srcTexture = depthTexD->texture;
+ cmd.args.blitFromTexture.srcLevel = 0;
+ cmd.args.blitFromTexture.srcLayer = resolveIdx;
+ cmd.args.blitFromTexture.w = size.width();
+ cmd.args.blitFromTexture.h = size.height();
+ cmd.args.blitFromTexture.dstTarget = depthResolveTexD->target;
+ cmd.args.blitFromTexture.dstTexture = depthResolveTexD->texture;
+ cmd.args.blitFromTexture.dstLevel = 0;
+ cmd.args.blitFromTexture.dstLayer = resolveIdx;
+ cmd.args.blitFromTexture.isDepthStencil = true;
+ }
+ }
+ }
+
+ const bool mayDiscardDepthStencil =
+ (rtTex->m_desc.depthStencilBuffer()
+ || (rtTex->m_desc.depthTexture() && rtTex->m_flags.testFlag(QRhiTextureRenderTarget::DoNotStoreDepthStencilContents)))
+ && !rtTex->m_desc.depthResolveTexture();
+ if (mayDiscardDepthStencil) {
+ QGles2CommandBuffer::Command &cmd(cbD->commands.get());
+ cmd.cmd = QGles2CommandBuffer::Command::InvalidateFramebuffer;
+ if (caps.needsDepthStencilCombinedAttach) {
+ cmd.args.invalidateFramebuffer.attCount = 1;
+ cmd.args.invalidateFramebuffer.att[0] = GL_DEPTH_STENCIL_ATTACHMENT;
+ } else {
+ cmd.args.invalidateFramebuffer.attCount = 2;
+ cmd.args.invalidateFramebuffer.att[0] = GL_DEPTH_ATTACHMENT;
+ cmd.args.invalidateFramebuffer.att[1] = GL_STENCIL_ATTACHMENT;
}
}
}
@@ -3776,9 +4765,9 @@ void QRhiGles2::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
accessAndIsNewFlag = { 0, false };
QGles2ShaderResourceBindings *srbD = QRHI_RES(QGles2ShaderResourceBindings, cbD->currentComputeSrb);
- const int bindingCount = srbD->m_bindings.count();
+ const int bindingCount = srbD->m_bindings.size();
for (int i = 0; i < bindingCount; ++i) {
- const QRhiShaderResourceBinding::Data *b = srbD->m_bindings.at(i).data();
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->m_bindings.at(i));
switch (b->type) {
case QRhiShaderResourceBinding::ImageLoad:
case QRhiShaderResourceBinding::ImageStore:
@@ -3842,17 +4831,22 @@ static inline GLenum toGlShaderType(QRhiShaderStage::Type type)
switch (type) {
case QRhiShaderStage::Vertex:
return GL_VERTEX_SHADER;
+ case QRhiShaderStage::TessellationControl:
+ return GL_TESS_CONTROL_SHADER;
+ case QRhiShaderStage::TessellationEvaluation:
+ return GL_TESS_EVALUATION_SHADER;
+ case QRhiShaderStage::Geometry:
+ return GL_GEOMETRY_SHADER;
case QRhiShaderStage::Fragment:
return GL_FRAGMENT_SHADER;
case QRhiShaderStage::Compute:
return GL_COMPUTE_SHADER;
default:
- Q_UNREACHABLE();
- return GL_VERTEX_SHADER;
+ Q_UNREACHABLE_RETURN(GL_VERTEX_SHADER);
}
}
-QByteArray QRhiGles2::shaderSource(const QRhiShaderStage &shaderStage, int *glslVersion)
+QByteArray QRhiGles2::shaderSource(const QRhiShaderStage &shaderStage, QShaderVersion *shaderVersion)
{
const QShader bakedShader = shaderStage.shader();
QList<int> versionsToTry;
@@ -3871,8 +4865,8 @@ QByteArray QRhiGles2::shaderSource(const QRhiShaderStage &shaderStage, int *glsl
QShaderVersion ver(v, QShaderVersion::GlslEs);
source = bakedShader.shader({ QShader::GlslShader, ver, shaderStage.shaderVariant() }).shader();
if (!source.isEmpty()) {
- if (glslVersion)
- *glslVersion = v;
+ if (shaderVersion)
+ *shaderVersion = ver;
break;
}
}
@@ -3905,8 +4899,8 @@ QByteArray QRhiGles2::shaderSource(const QRhiShaderStage &shaderStage, int *glsl
for (int v : versionsToTry) {
source = bakedShader.shader({ QShader::GlslShader, v, shaderStage.shaderVariant() }).shader();
if (!source.isEmpty()) {
- if (glslVersion)
- *glslVersion = v;
+ if (shaderVersion)
+ *shaderVersion = v;
break;
}
}
@@ -3918,9 +4912,9 @@ QByteArray QRhiGles2::shaderSource(const QRhiShaderStage &shaderStage, int *glsl
return source;
}
-bool QRhiGles2::compileShader(GLuint program, const QRhiShaderStage &shaderStage, int *glslVersion)
+bool QRhiGles2::compileShader(GLuint program, const QRhiShaderStage &shaderStage, QShaderVersion *shaderVersion)
{
- const QByteArray source = shaderSource(shaderStage, glslVersion);
+ const QByteArray source = shaderSource(shaderStage, shaderVersion);
if (source.isEmpty())
return false;
@@ -3931,7 +4925,7 @@ bool QRhiGles2::compileShader(GLuint program, const QRhiShaderStage &shaderStage
} else {
shader = f->glCreateShader(toGlShaderType(shaderStage.type()));
const char *srcStr = source.constData();
- const GLint srcLength = source.count();
+ const GLint srcLength = source.size();
f->glShaderSource(shader, 1, &srcStr, &srcLength);
f->glCompileShader(shader);
GLint compiled = 0;
@@ -3948,7 +4942,7 @@ bool QRhiGles2::compileShader(GLuint program, const QRhiShaderStage &shaderStage
qWarning("Failed to compile shader: %s\nSource was:\n%s", log.constData(), source.constData());
return false;
}
- if (m_shaderCache.count() >= MAX_SHADER_CACHE_ENTRIES) {
+ if (m_shaderCache.size() >= MAX_SHADER_CACHE_ENTRIES) {
// Use the simplest strategy: too many cached shaders -> drop them all.
for (uint shader : m_shaderCache)
f->glDeleteShader(shader); // does not actually get released yet when attached to a not-yet-released program
@@ -3987,7 +4981,7 @@ void QRhiGles2::registerUniformIfActive(const QShaderDescription::BlockVariable
int binding,
int baseOffset,
GLuint program,
- QSet<int> *activeUniformLocations,
+ QDuplicateTracker<int, 256> *activeUniformLocations,
QGles2UniformDescriptionVector *dst)
{
if (var.type == QShaderDescription::Struct) {
@@ -4004,9 +4998,8 @@ void QRhiGles2::registerUniformIfActive(const QShaderDescription::BlockVariable
// that is not the case, it won't break anything, but we'll generate
// unnecessary glUniform* calls then.
uniform.glslLocation = f->glGetUniformLocation(program, name.constData());
- if (uniform.glslLocation >= 0 && !activeUniformLocations->contains(uniform.glslLocation)) {
- activeUniformLocations->insert(uniform.glslLocation);
- if (var.arrayDims.count() > 1) {
+ if (uniform.glslLocation >= 0 && !activeUniformLocations->hasSeen(uniform.glslLocation)) {
+ if (var.arrayDims.size() > 1) {
qWarning("Array '%s' has more than one dimension. This is not supported.",
var.name.constData());
return;
@@ -4021,7 +5014,7 @@ void QRhiGles2::registerUniformIfActive(const QShaderDescription::BlockVariable
void QRhiGles2::gatherUniforms(GLuint program,
const QShaderDescription::UniformBlock &ub,
- QSet<int> *activeUniformLocations,
+ QDuplicateTracker<int, 256> *activeUniformLocations,
QGles2UniformDescriptionVector *dst)
{
QByteArray prefix = ub.structName + '.';
@@ -4035,7 +5028,7 @@ void QRhiGles2::gatherUniforms(GLuint program,
registerUniformIfActive(structMember, structPrefix + ".", ub.binding,
baseOffset, program, activeUniformLocations, dst);
} else {
- if (blockMember.arrayDims.count() > 1) {
+ if (blockMember.arrayDims.size() > 1) {
qWarning("Array of struct '%s' has more than one dimension. Only the first "
"dimension is used.",
blockMember.name.constData());
@@ -4063,7 +5056,23 @@ void QRhiGles2::gatherSamplers(GLuint program,
QGles2SamplerDescription sampler;
sampler.glslLocation = f->glGetUniformLocation(program, v.name.constData());
if (sampler.glslLocation >= 0) {
- sampler.binding = v.binding;
+ sampler.combinedBinding = v.binding;
+ sampler.tbinding = -1;
+ sampler.sbinding = -1;
+ dst->append(sampler);
+ }
+}
+
+void QRhiGles2::gatherGeneratedSamplers(GLuint program,
+ const QShader::SeparateToCombinedImageSamplerMapping &mapping,
+ QGles2SamplerDescriptionVector *dst)
+{
+ QGles2SamplerDescription sampler;
+ sampler.glslLocation = f->glGetUniformLocation(program, mapping.combinedSamplerName.constData());
+ if (sampler.glslLocation >= 0) {
+ sampler.combinedBinding = -1;
+ sampler.tbinding = mapping.textureBinding;
+ sampler.sbinding = mapping.samplerBinding;
dst->append(sampler);
}
}
@@ -4104,13 +5113,18 @@ static inline QShader::Stage toShaderStage(QRhiShaderStage::Type type)
switch (type) {
case QRhiShaderStage::Vertex:
return QShader::VertexStage;
+ case QRhiShaderStage::TessellationControl:
+ return QShader::TessellationControlStage;
+ case QRhiShaderStage::TessellationEvaluation:
+ return QShader::TessellationEvaluationStage;
+ case QRhiShaderStage::Geometry:
+ return QShader::GeometryStage;
case QRhiShaderStage::Fragment:
return QShader::FragmentStage;
case QRhiShaderStage::Compute:
return QShader::ComputeStage;
default:
- Q_UNREACHABLE();
- return QShader::VertexStage;
+ Q_UNREACHABLE_RETURN(QShader::VertexStage);
}
}
@@ -4233,7 +5247,7 @@ void QRhiGles2::trySaveToPipelineCache(GLuint program, const QByteArray &cacheKe
}
}
-QGles2Buffer::QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+QGles2Buffer::QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
: QRhiBuffer(rhi, type, usage, size)
{
}
@@ -4256,10 +5270,10 @@ void QGles2Buffer::destroy()
buffer = 0;
QRHI_RES_RHI(QRhiGles2);
- rhiD->releaseQueue.append(e);
- QRHI_PROF;
- QRHI_PROF_F(releaseBuffer(this));
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QGles2Buffer::create()
@@ -4268,7 +5282,6 @@ bool QGles2Buffer::create()
destroy();
QRHI_RES_RHI(QRhiGles2);
- QRHI_PROF;
nonZeroSize = m_size <= 0 ? 256 : m_size;
@@ -4278,7 +5291,6 @@ bool QGles2Buffer::create()
return false;
}
data.resize(nonZeroSize);
- QRHI_PROF_F(newBuffer(this, uint(nonZeroSize), 0, 1));
return true;
}
@@ -4295,9 +5307,11 @@ bool QGles2Buffer::create()
rhiD->f->glBindBuffer(targetForDataOps, buffer);
rhiD->f->glBufferData(targetForDataOps, nonZeroSize, nullptr, m_type == Dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
+ if (rhiD->glObjectLabel)
+ rhiD->glObjectLabel(GL_BUFFER, buffer, -1, m_objectName.constData());
+
usageState.access = AccessNone;
- QRHI_PROF_F(newBuffer(this, uint(nonZeroSize), 1, 0));
rhiD->registerResource(this);
return true;
}
@@ -4366,11 +5380,11 @@ void QGles2RenderBuffer::destroy()
stencilRenderbuffer = 0;
QRHI_RES_RHI(QRhiGles2);
- if (owns)
- rhiD->releaseQueue.append(e);
- QRHI_PROF;
- QRHI_PROF_F(releaseRenderBuffer(this));
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ if (owns)
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QGles2RenderBuffer::create()
@@ -4379,14 +5393,11 @@ bool QGles2RenderBuffer::create()
destroy();
QRHI_RES_RHI(QRhiGles2);
- QRHI_PROF;
samples = rhiD->effectiveSampleCount(m_sampleCount);
if (m_flags.testFlag(UsedWithSwapChainOnly)) {
- if (m_type == DepthStencil) {
- QRHI_PROF_F(newRenderBuffer(this, false, true, samples));
+ if (m_type == DepthStencil)
return true;
- }
qWarning("RenderBuffer: UsedWithSwapChainOnly is meaningless in combination with Color");
}
@@ -4426,7 +5437,6 @@ bool QGles2RenderBuffer::create()
rhiD->f->glRenderbufferStorage(GL_RENDERBUFFER, stencilStorage,
size.width(), size.height());
}
- QRHI_PROF_F(newRenderBuffer(this, false, false, samples));
break;
case QRhiRenderBuffer::Color:
{
@@ -4447,7 +5457,6 @@ bool QGles2RenderBuffer::create()
rhiD->f->glRenderbufferStorage(GL_RENDERBUFFER, internalFormat,
size.width(), size.height());
}
- QRHI_PROF_F(newRenderBuffer(this, false, false, samples));
}
break;
default:
@@ -4455,7 +5464,11 @@ bool QGles2RenderBuffer::create()
break;
}
+ if (rhiD->glObjectLabel)
+ rhiD->glObjectLabel(GL_RENDERBUFFER, renderbuffer, -1, m_objectName.constData());
+
owns = true;
+ generation += 1;
rhiD->registerResource(this);
return true;
}
@@ -4479,10 +5492,8 @@ bool QGles2RenderBuffer::createFrom(NativeRenderBuffer src)
renderbuffer = src.object;
- QRHI_PROF;
- QRHI_PROF_F(newRenderBuffer(this, false, false, samples));
-
owns = false;
+ generation += 1;
rhiD->registerResource(this);
return true;
}
@@ -4496,8 +5507,8 @@ QRhiTexture::Format QGles2RenderBuffer::backingFormat() const
}
QGles2Texture::QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags)
+ int arraySize, int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, arraySize, sampleCount, flags)
{
}
@@ -4521,11 +5532,11 @@ void QGles2Texture::destroy()
zeroInitialized = false;
QRHI_RES_RHI(QRhiGles2);
- if (owns)
- rhiD->releaseQueue.append(e);
- QRHI_PROF;
- QRHI_PROF_F(releaseTexture(this));
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ if (owns)
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QGles2Texture::prepareCreate(QSize *adjustedSize)
@@ -4537,12 +5548,15 @@ bool QGles2Texture::prepareCreate(QSize *adjustedSize)
if (!rhiD->ensureContext())
return false;
- const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
-
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool isArray = m_flags.testFlag(QRhiTexture::TextureArray);
const bool is3D = m_flags.testFlag(ThreeDimensional);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
const bool isCompressed = rhiD->isCompressedFormat(m_format);
+ const bool is1D = m_flags.testFlag(OneDimensional);
+
+ const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
+ : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
if (is3D && !rhiD->caps.texture3D) {
qWarning("3D textures are not supported");
@@ -4552,16 +5566,46 @@ bool QGles2Texture::prepareCreate(QSize *adjustedSize)
qWarning("Texture cannot be both cube and 3D");
return false;
}
- m_depth = qMax(1, m_depth);
+ if (isArray && is3D) {
+ qWarning("Texture cannot be both array and 3D");
+ return false;
+ }
+ if (is1D && !rhiD->caps.texture1D) {
+ qWarning("1D textures are not supported");
+ return false;
+ }
+ if (is1D && is3D) {
+ qWarning("Texture cannot be both 1D and 3D");
+ return false;
+ }
+ if (is1D && isCube) {
+ qWarning("Texture cannot be both 1D and cube");
+ return false;
+ }
+
if (m_depth > 1 && !is3D) {
qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
return false;
}
+ if (m_arraySize > 0 && !isArray) {
+ qWarning("Texture cannot have an array size of %d when it is not an array", m_arraySize);
+ return false;
+ }
+ if (m_arraySize < 1 && isArray) {
+ qWarning("Texture is an array but array size is %d", m_arraySize);
+ return false;
+ }
+
+ target = isCube ? GL_TEXTURE_CUBE_MAP
+ : m_sampleCount > 1 ? (isArray ? GL_TEXTURE_2D_MULTISAMPLE_ARRAY : GL_TEXTURE_2D_MULTISAMPLE)
+ : (is3D ? GL_TEXTURE_3D
+ : (is1D ? (isArray ? GL_TEXTURE_1D_ARRAY : GL_TEXTURE_1D)
+ : (isArray ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D)));
- target = isCube ? GL_TEXTURE_CUBE_MAP
- : m_sampleCount > 1 ? GL_TEXTURE_2D_MULTISAMPLE : (is3D ? GL_TEXTURE_3D : GL_TEXTURE_2D);
if (m_flags.testFlag(ExternalOES))
target = GL_TEXTURE_EXTERNAL_OES;
+ else if (m_flags.testFlag(TextureRectangleGL))
+ target = GL_TEXTURE_RECTANGLE;
mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
gltype = GL_UNSIGNED_BYTE;
@@ -4603,21 +5647,35 @@ bool QGles2Texture::create()
rhiD->f->glGenTextures(1, &texture);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool isArray = m_flags.testFlag(QRhiTexture::TextureArray);
const bool is3D = m_flags.testFlag(ThreeDimensional);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
const bool isCompressed = rhiD->isCompressedFormat(m_format);
+ const bool is1D = m_flags.testFlag(OneDimensional);
+
if (!isCompressed) {
rhiD->f->glBindTexture(target, texture);
if (!m_flags.testFlag(UsedWithLoadStore)) {
- if (is3D) {
+ if (is1D) {
+ for (int level = 0; level < mipLevelCount; ++level) {
+ const QSize mipSize = rhiD->q->sizeForMipLevel(level, size);
+ if (isArray)
+ rhiD->f->glTexImage2D(target, level, GLint(glintformat), mipSize.width(),
+ qMax(0, m_arraySize), 0, glformat, gltype, nullptr);
+ else
+ rhiD->glTexImage1D(target, level, GLint(glintformat), mipSize.width(), 0,
+ glformat, gltype, nullptr);
+ }
+ } else if (is3D || isArray) {
+ const int layerCount = is3D ? qMax(1, m_depth) : qMax(0, m_arraySize);
if (hasMipMaps) {
for (int level = 0; level != mipLevelCount; ++level) {
const QSize mipSize = rhiD->q->sizeForMipLevel(level, size);
- rhiD->f->glTexImage3D(target, level, GLint(glintformat), mipSize.width(), mipSize.height(), m_depth,
+ rhiD->f->glTexImage3D(target, level, GLint(glintformat), mipSize.width(), mipSize.height(), layerCount,
0, glformat, gltype, nullptr);
}
} else {
- rhiD->f->glTexImage3D(target, 0, GLint(glintformat), size.width(), size.height(), m_depth,
+ rhiD->f->glTexImage3D(target, 0, GLint(glintformat), size.width(), size.height(), layerCount,
0, glformat, gltype, nullptr);
}
} else if (hasMipMaps || isCube) {
@@ -4631,17 +5689,32 @@ bool QGles2Texture::create()
}
}
} else {
- rhiD->f->glTexImage2D(target, 0, GLint(glintformat), size.width(), size.height(),
- 0, glformat, gltype, nullptr);
+ // 2D texture. For multisample textures the GLES 3.1
+ // glStorage2DMultisample must be used for portability.
+ if (m_sampleCount > 1 && rhiD->caps.multisampledTexture) {
+ // internal format must be sized
+ rhiD->f->glTexStorage2DMultisample(target, m_sampleCount, glsizedintformat,
+ size.width(), size.height(), GL_TRUE);
+ } else {
+ rhiD->f->glTexImage2D(target, 0, GLint(glintformat), size.width(), size.height(),
+ 0, glformat, gltype, nullptr);
+ }
}
} else {
// Must be specified with immutable storage functions otherwise
// bindImageTexture may fail. Also, the internal format must be a
// sized format here.
- if (is3D)
- rhiD->f->glTexStorage3D(target, mipLevelCount, glsizedintformat, size.width(), size.height(), m_depth);
+ if (is1D && !isArray)
+ rhiD->glTexStorage1D(target, mipLevelCount, glsizedintformat, size.width());
+ else if (!is1D && (is3D || isArray))
+ rhiD->f->glTexStorage3D(target, mipLevelCount, glsizedintformat, size.width(), size.height(),
+ is3D ? qMax(1, m_depth) : qMax(0, m_arraySize));
+ else if (m_sampleCount > 1)
+ rhiD->f->glTexStorage2DMultisample(target, m_sampleCount, glsizedintformat,
+ size.width(), size.height(), GL_TRUE);
else
- rhiD->f->glTexStorage2D(target, mipLevelCount, glsizedintformat, size.width(), size.height());
+ rhiD->f->glTexStorage2D(target, mipLevelCount, glsizedintformat, size.width(),
+ is1D ? qMax(0, m_arraySize) : size.height());
}
specified = true;
} else {
@@ -4651,8 +5724,8 @@ bool QGles2Texture::create()
specified = false;
}
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, true, mipLevelCount, isCube ? 6 : 1, 1));
+ if (rhiD->glObjectLabel)
+ rhiD->glObjectLabel(GL_TEXTURE, texture, -1, m_objectName.constData());
owns = true;
@@ -4674,13 +5747,10 @@ bool QGles2Texture::createFrom(QRhiTexture::NativeTexture src)
specified = true;
zeroInitialized = true;
- QRHI_RES_RHI(QRhiGles2);
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, false, mipLevelCount, m_flags.testFlag(CubeMap) ? 6 : 1, 1));
-
owns = false;
generation += 1;
+ QRHI_RES_RHI(QRhiGles2);
rhiD->registerResource(this);
return true;
}
@@ -4703,7 +5773,9 @@ QGles2Sampler::~QGles2Sampler()
void QGles2Sampler::destroy()
{
- // nothing to do here
+ QRHI_RES_RHI(QRhiGles2);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QGles2Sampler::create()
@@ -4716,6 +5788,8 @@ bool QGles2Sampler::create()
d.gltexcomparefunc = toGlTextureCompareFunc(m_compareOp);
generation += 1;
+ QRHI_RES_RHI(QRhiGles2);
+ rhiD->registerResource(this, false);
return true;
}
@@ -4732,7 +5806,9 @@ QGles2RenderPassDescriptor::~QGles2RenderPassDescriptor()
void QGles2RenderPassDescriptor::destroy()
{
- // nothing to do here
+ QRHI_RES_RHI(QRhiGles2);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QGles2RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
@@ -4743,36 +5819,44 @@ bool QGles2RenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot
QRhiRenderPassDescriptor *QGles2RenderPassDescriptor::newCompatibleRenderPassDescriptor() const
{
- return new QGles2RenderPassDescriptor(m_rhi);
+ QGles2RenderPassDescriptor *rpD = new QGles2RenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiGles2);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
-QGles2ReferenceRenderTarget::QGles2ReferenceRenderTarget(QRhiImplementation *rhi)
- : QRhiRenderTarget(rhi),
+QVector<quint32> QGles2RenderPassDescriptor::serializedFormat() const
+{
+ return {};
+}
+
+QGles2SwapChainRenderTarget::QGles2SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
+ : QRhiSwapChainRenderTarget(rhi, swapchain),
d(rhi)
{
}
-QGles2ReferenceRenderTarget::~QGles2ReferenceRenderTarget()
+QGles2SwapChainRenderTarget::~QGles2SwapChainRenderTarget()
{
destroy();
}
-void QGles2ReferenceRenderTarget::destroy()
+void QGles2SwapChainRenderTarget::destroy()
{
// nothing to do here
}
-QSize QGles2ReferenceRenderTarget::pixelSize() const
+QSize QGles2SwapChainRenderTarget::pixelSize() const
{
return d.pixelSize;
}
-float QGles2ReferenceRenderTarget::devicePixelRatio() const
+float QGles2SwapChainRenderTarget::devicePixelRatio() const
{
return d.dpr;
}
-int QGles2ReferenceRenderTarget::sampleCount() const
+int QGles2SwapChainRenderTarget::sampleCount() const
{
return d.sampleCount;
}
@@ -4799,18 +5883,24 @@ void QGles2TextureRenderTarget::destroy()
e.type = QRhiGles2::DeferredReleaseEntry::TextureRenderTarget;
e.textureRenderTarget.framebuffer = framebuffer;
+ e.textureRenderTarget.nonMsaaThrowawayDepthTexture = nonMsaaThrowawayDepthTexture;
framebuffer = 0;
+ nonMsaaThrowawayDepthTexture = 0;
QRHI_RES_RHI(QRhiGles2);
- rhiD->releaseQueue.append(e);
-
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
QRhiRenderPassDescriptor *QGles2TextureRenderTarget::newCompatibleRenderPassDescriptor()
{
- return new QGles2RenderPassDescriptor(m_rhi);
+ QGles2RenderPassDescriptor *rpD = new QGles2RenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiGles2);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
bool QGles2TextureRenderTarget::create()
@@ -4820,13 +5910,13 @@ bool QGles2TextureRenderTarget::create()
if (framebuffer)
destroy();
- const bool hasColorAttachments = m_desc.cbeginColorAttachments() != m_desc.cendColorAttachments();
+ const bool hasColorAttachments = m_desc.colorAttachmentCount() > 0;
Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
if (hasColorAttachments) {
- const int count = m_desc.cendColorAttachments() - m_desc.cbeginColorAttachments();
+ const int count = int(m_desc.colorAttachmentCount());
if (count > rhiD->caps.maxDrawBuffers) {
qWarning("QGles2TextureRenderTarget: Too many color attachments (%d, max is %d)",
count, rhiD->caps.maxDrawBuffers);
@@ -4843,6 +5933,7 @@ bool QGles2TextureRenderTarget::create()
d.colorAttCount = 0;
int attIndex = 0;
+ int multiViewCount = 0;
for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
d.colorAttCount += 1;
const QRhiColorAttachment &colorAtt(*it);
@@ -4852,17 +5943,57 @@ bool QGles2TextureRenderTarget::create()
if (texture) {
QGles2Texture *texD = QRHI_RES(QGles2Texture, texture);
Q_ASSERT(texD->texture && texD->specified);
- if (texD->flags().testFlag(QRhiTexture::ThreeDimensional)) {
- rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture,
- colorAtt.level(), colorAtt.layer());
+ if (texD->flags().testFlag(QRhiTexture::ThreeDimensional) || texD->flags().testFlag(QRhiTexture::TextureArray)) {
+ if (colorAtt.multiViewCount() < 2) {
+ rhiD->f->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), texD->texture,
+ colorAtt.level(), colorAtt.layer());
+ } else {
+ multiViewCount = colorAtt.multiViewCount();
+ if (texD->sampleCount() > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture && colorAtt.resolveTexture()) {
+ // Special path for GLES and GL_OVR_multiview_multisampled_render_to_texture:
+ // ignore the color attachment's (multisample) texture
+ // array and give the resolve texture array to GL. (no
+ // explicit resolving is needed by us later on)
+ QGles2Texture *resolveTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
+ rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0 + uint(attIndex),
+ resolveTexD->texture,
+ colorAtt.resolveLevel(),
+ texD->sampleCount(),
+ colorAtt.resolveLayer(),
+ multiViewCount);
+ } else {
+ rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0 + uint(attIndex),
+ texD->texture,
+ colorAtt.level(),
+ colorAtt.layer(),
+ multiViewCount);
+ }
+ }
+ } else if (texD->flags().testFlag(QRhiTexture::OneDimensional)) {
+ rhiD->glFramebufferTexture1D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex),
+ texD->target + uint(colorAtt.layer()), texD->texture,
+ colorAtt.level());
} else {
- const GLenum faceTargetBase = texD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
- rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
- texD->texture, colorAtt.level());
+ if (texD->sampleCount() > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
+ // Special path for GLES and GL_EXT_multisampled_render_to_texture:
+ // ignore the color attachment's (multisample) texture and
+ // give the resolve texture to GL. (no explicit resolving is
+ // needed by us later on)
+ QGles2Texture *resolveTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
+ const GLenum faceTargetBase = resolveTexD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : resolveTexD->target;
+ rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
+ resolveTexD->texture, colorAtt.level(), texD->sampleCount());
+ } else {
+ const GLenum faceTargetBase = texD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
+ rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.layer()),
+ texD->texture, colorAtt.level());
+ }
}
if (attIndex == 0) {
d.pixelSize = rhiD->q->sizeForMipLevel(colorAtt.level(), texD->pixelSize());
- d.sampleCount = 1;
+ d.sampleCount = texD->sampleCount();
}
} else if (renderBuffer) {
QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, renderBuffer);
@@ -4883,12 +6014,14 @@ bool QGles2TextureRenderTarget::create()
} else {
rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
depthRbD->renderbuffer);
- if (depthRbD->stencilRenderbuffer)
+ if (depthRbD->stencilRenderbuffer) {
rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
depthRbD->stencilRenderbuffer);
- else // packed
+ } else {
+ // packed depth-stencil
rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
depthRbD->renderbuffer);
+ }
}
if (d.colorAttCount == 0) {
d.pixelSize = depthRbD->pixelSize();
@@ -4896,11 +6029,105 @@ bool QGles2TextureRenderTarget::create()
}
} else {
QGles2Texture *depthTexD = QRHI_RES(QGles2Texture, m_desc.depthTexture());
- rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->target,
- depthTexD->texture, 0);
+ if (multiViewCount < 2) {
+ if (depthTexD->sampleCount() > 1 && rhiD->caps.glesMultisampleRenderToTexture && m_desc.depthResolveTexture()) {
+ // Special path for GLES and
+ // GL_EXT_multisampled_render_to_texture, for depth-stencil.
+ // Relevant only when depthResolveTexture is set.
+ QGles2Texture *depthResolveTexD = QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
+ rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthResolveTexD->target,
+ depthResolveTexD->texture, 0, depthTexD->sampleCount());
+ if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
+ rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthResolveTexD->target,
+ depthResolveTexD->texture, 0, depthTexD->sampleCount());
+ }
+ } else {
+ rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->target,
+ depthTexD->texture, 0);
+ if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
+ rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->target,
+ depthTexD->texture, 0);
+ }
+ }
+ } else {
+ if (depthTexD->sampleCount() > 1 && rhiD->caps.glesMultiviewMultisampleRenderToTexture) {
+ // And so it turns out
+ // https://registry.khronos.org/OpenGL/extensions/OVR/OVR_multiview.txt
+ // does not work with multisample 2D texture arrays. (at least
+ // that's what Issue 30 in the extension spec seems to imply)
+ //
+ // There is https://registry.khronos.org/OpenGL/extensions/EXT/EXT_multiview_texture_multisample.txt
+ // that seems to resolve that, but that does not seem to
+ // work (or not available) on GLES devices such as the Quest 3.
+ //
+ // So instead, on GLES we can use the
+ // multisample-multiview-auto-resolving version (which in
+ // turn is not supported on desktop GL e.g. by NVIDIA), too
+ // bad we have a multisample depth texture array here as
+ // every other API out there requires that. So, in absence
+ // of a depthResolveTexture, create a temporary one ignoring
+ // what the user has already created.
+ //
+ if (!m_flags.testFlag(DoNotStoreDepthStencilContents) && !m_desc.depthResolveTexture()) {
+ qWarning("Attempted to create a multiview+multisample QRhiTextureRenderTarget, but DoNotStoreDepthStencilContents was not set."
+ " This path has no choice but to behave as if DoNotStoreDepthStencilContents was set, because QRhi is forced to create"
+ " a throwaway non-multisample depth texture here. Set the flag to silence this warning, or set a depthResolveTexture.");
+ }
+ if (m_desc.depthResolveTexture()) {
+ QGles2Texture *depthResolveTexD = QRHI_RES(QGles2Texture, m_desc.depthResolveTexture());
+ rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ depthResolveTexD->texture,
+ 0,
+ depthTexD->sampleCount(),
+ 0,
+ multiViewCount);
+ if (rhiD->isStencilSupportingFormat(depthResolveTexD->format())) {
+ rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ depthResolveTexD->texture,
+ 0,
+ depthTexD->sampleCount(),
+ 0,
+ multiViewCount);
+ }
+ } else {
+ if (!nonMsaaThrowawayDepthTexture) {
+ rhiD->f->glGenTextures(1, &nonMsaaThrowawayDepthTexture);
+ rhiD->f->glBindTexture(GL_TEXTURE_2D_ARRAY, nonMsaaThrowawayDepthTexture);
+ rhiD->f->glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_DEPTH24_STENCIL8,
+ depthTexD->pixelSize().width(), depthTexD->pixelSize().height(), multiViewCount);
+ }
+ rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ nonMsaaThrowawayDepthTexture,
+ 0,
+ depthTexD->sampleCount(),
+ 0,
+ multiViewCount);
+ rhiD->glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ nonMsaaThrowawayDepthTexture,
+ 0,
+ depthTexD->sampleCount(),
+ 0,
+ multiViewCount);
+ }
+ } else {
+ // The depth texture here must be an array with at least
+ // multiViewCount elements, and the format should be D24 or D32F
+ // for depth only, or D24S8 for depth and stencil.
+ rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexD->texture,
+ 0, 0, multiViewCount);
+ if (rhiD->isStencilSupportingFormat(depthTexD->format())) {
+ rhiD->glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexD->texture,
+ 0, 0, multiViewCount);
+ }
+ }
+ }
if (d.colorAttCount == 0) {
d.pixelSize = depthTexD->pixelSize();
- d.sampleCount = 1;
+ d.sampleCount = depthTexD->sampleCount();
}
}
d.dsAttCount = 1;
@@ -4917,12 +6144,20 @@ bool QGles2TextureRenderTarget::create()
return false;
}
+ if (rhiD->glObjectLabel)
+ rhiD->glObjectLabel(GL_FRAMEBUFFER, framebuffer, -1, m_objectName.constData());
+
+ QRhiRenderTargetAttachmentTracker::updateResIdList<QGles2Texture, QGles2RenderBuffer>(m_desc, &d.currentResIdList);
+
rhiD->registerResource(this);
return true;
}
QSize QGles2TextureRenderTarget::pixelSize() const
{
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QGles2Texture, QGles2RenderBuffer>(m_desc, d.currentResIdList))
+ const_cast<QGles2TextureRenderTarget *>(this)->create();
+
return d.pixelSize;
}
@@ -4948,7 +6183,9 @@ QGles2ShaderResourceBindings::~QGles2ShaderResourceBindings()
void QGles2ShaderResourceBindings::destroy()
{
- // nothing to do here
+ QRHI_RES_RHI(QRhiGles2);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QGles2ShaderResourceBindings::create()
@@ -4958,8 +6195,8 @@ bool QGles2ShaderResourceBindings::create()
return false;
hasDynamicOffset = false;
- for (int i = 0, ie = m_bindings.count(); i != ie; ++i) {
- const QRhiShaderResourceBinding::Data *b = m_bindings.at(i).data();
+ for (int i = 0, ie = m_bindings.size(); i != ie; ++i) {
+ const QRhiShaderResourceBinding::Data *b = QRhiImplementation::shaderResourceBindingData(m_bindings.at(i));
if (b->type == QRhiShaderResourceBinding::UniformBuffer) {
if (b->u.ubuf.hasDynamicOffset) {
hasDynamicOffset = true;
@@ -4971,9 +6208,16 @@ bool QGles2ShaderResourceBindings::create()
rhiD->updateLayoutDesc(this);
generation += 1;
+ rhiD->registerResource(this, false);
return true;
}
+void QGles2ShaderResourceBindings::updateResources(UpdateFlags flags)
+{
+ Q_UNUSED(flags);
+ generation += 1;
+}
+
QGles2GraphicsPipeline::QGles2GraphicsPipeline(QRhiImplementation *rhi)
: QRhiGraphicsPipeline(rhi)
{
@@ -4999,9 +6243,20 @@ void QGles2GraphicsPipeline::destroy()
samplers.clear();
QRHI_RES_RHI(QRhiGles2);
- rhiD->releaseQueue.append(e);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
+}
- rhiD->unregisterResource(this);
+static inline bool isGraphicsStage(const QRhiShaderStage &shaderStage)
+{
+ const QRhiShaderStage::Type t = shaderStage.type();
+ return t == QRhiShaderStage::Vertex
+ || t == QRhiShaderStage::TessellationControl
+ || t == QRhiShaderStage::TessellationEvaluation
+ || t == QRhiShaderStage::Geometry
+ || t == QRhiShaderStage::Fragment;
}
bool QGles2GraphicsPipeline::create()
@@ -5014,6 +6269,7 @@ bool QGles2GraphicsPipeline::create()
if (!rhiD->ensureContext())
return false;
+ rhiD->pipelineCreationStart();
if (!rhiD->sanityCheckGraphicsPipeline(this))
return false;
@@ -5021,40 +6277,72 @@ bool QGles2GraphicsPipeline::create()
program = rhiD->f->glCreateProgram();
- QShaderDescription vsDesc;
- QShaderDescription fsDesc;
- for (const QRhiShaderStage &shaderStage : qAsConst(m_shaderStages)) {
- if (shaderStage.type() == QRhiShaderStage::Vertex)
- vsDesc = shaderStage.shader().description();
- else if (shaderStage.type() == QRhiShaderStage::Fragment)
- fsDesc = shaderStage.shader().description();
+ enum {
+ VtxIdx = 0,
+ TCIdx,
+ TEIdx,
+ GeomIdx,
+ FragIdx,
+ LastIdx
+ };
+ const auto descIdxForStage = [](const QRhiShaderStage &shaderStage) {
+ switch (shaderStage.type()) {
+ case QRhiShaderStage::Vertex:
+ return VtxIdx;
+ case QRhiShaderStage::TessellationControl:
+ return TCIdx;
+ case QRhiShaderStage::TessellationEvaluation:
+ return TEIdx;
+ case QRhiShaderStage::Geometry:
+ return GeomIdx;
+ case QRhiShaderStage::Fragment:
+ return FragIdx;
+ default:
+ break;
+ }
+ Q_UNREACHABLE_RETURN(VtxIdx);
+ };
+ QShaderDescription desc[LastIdx];
+ QShader::SeparateToCombinedImageSamplerMappingList samplerMappingList[LastIdx];
+ bool vertexFragmentOnly = true;
+ for (const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
+ if (isGraphicsStage(shaderStage)) {
+ const int idx = descIdxForStage(shaderStage);
+ if (idx != VtxIdx && idx != FragIdx)
+ vertexFragmentOnly = false;
+ QShader shader = shaderStage.shader();
+ QShaderVersion shaderVersion;
+ desc[idx] = shader.description();
+ if (!rhiD->shaderSource(shaderStage, &shaderVersion).isEmpty()) {
+ samplerMappingList[idx] = shader.separateToCombinedImageSamplerMappingList(
+ { QShader::GlslShader, shaderVersion, shaderStage.shaderVariant() });
+ }
+ }
}
QByteArray cacheKey;
QRhiGles2::ProgramCacheResult cacheResult = rhiD->tryLoadFromDiskOrPipelineCache(m_shaderStages.constData(),
- m_shaderStages.count(),
+ m_shaderStages.size(),
program,
- vsDesc.inputVariables(),
+ desc[VtxIdx].inputVariables(),
&cacheKey);
if (cacheResult == QRhiGles2::ProgramCacheError)
return false;
if (cacheResult == QRhiGles2::ProgramCacheMiss) {
- for (const QRhiShaderStage &shaderStage : qAsConst(m_shaderStages)) {
- if (shaderStage.type() == QRhiShaderStage::Vertex) {
- if (!rhiD->compileShader(program, shaderStage, nullptr))
- return false;
- } else if (shaderStage.type() == QRhiShaderStage::Fragment) {
+ for (const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
+ if (isGraphicsStage(shaderStage)) {
if (!rhiD->compileShader(program, shaderStage, nullptr))
return false;
}
}
// important when GLSL <= 150 is used that does not have location qualifiers
- for (const QShaderDescription::InOutVariable &inVar : vsDesc.inputVariables())
+ for (const QShaderDescription::InOutVariable &inVar : desc[VtxIdx].inputVariables())
rhiD->f->glBindAttribLocation(program, GLuint(inVar.location), inVar.name);
- rhiD->sanityCheckVertexFragmentInterface(vsDesc, fsDesc);
+ if (vertexFragmentOnly)
+ rhiD->sanityCheckVertexFragmentInterface(desc[VtxIdx], desc[FragIdx]);
if (!rhiD->linkProgram(program))
return false;
@@ -5080,13 +6368,19 @@ bool QGles2GraphicsPipeline::create()
// Use the same work area for the vertex & fragment stages, thus ensuring
// that we will not do superfluous glUniform calls for uniforms that are
// present in both shaders.
- QSet<int> activeUniformLocations;
-
- for (const QShaderDescription::UniformBlock &ub : vsDesc.uniformBlocks())
- rhiD->gatherUniforms(program, ub, &activeUniformLocations, &uniforms);
-
- for (const QShaderDescription::UniformBlock &ub : fsDesc.uniformBlocks())
- rhiD->gatherUniforms(program, ub, &activeUniformLocations, &uniforms);
+ QDuplicateTracker<int, 256> activeUniformLocations;
+
+ for (const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
+ if (isGraphicsStage(shaderStage)) {
+ const int idx = descIdxForStage(shaderStage);
+ for (const QShaderDescription::UniformBlock &ub : desc[idx].uniformBlocks())
+ rhiD->gatherUniforms(program, ub, &activeUniformLocations, &uniforms);
+ for (const QShaderDescription::InOutVariable &v : desc[idx].combinedImageSamplers())
+ rhiD->gatherSamplers(program, v, &samplers);
+ for (const QShader::SeparateToCombinedImageSamplerMapping &mapping : samplerMappingList[idx])
+ rhiD->gatherGeneratedSamplers(program, mapping, &samplers);
+ }
+ }
std::sort(uniforms.begin(), uniforms.end(),
[](const QGles2UniformDescription &a, const QGles2UniformDescription &b)
@@ -5094,17 +6388,15 @@ bool QGles2GraphicsPipeline::create()
return a.offset < b.offset;
});
- for (const QShaderDescription::InOutVariable &v : vsDesc.combinedImageSamplers())
- rhiD->gatherSamplers(program, v, &samplers);
-
- for (const QShaderDescription::InOutVariable &v : fsDesc.combinedImageSamplers())
- rhiD->gatherSamplers(program, v, &samplers);
-
memset(uniformState, 0, sizeof(uniformState));
currentSrb = nullptr;
currentSrbGeneration = 0;
+ if (rhiD->glObjectLabel)
+ rhiD->glObjectLabel(GL_PROGRAM, program, -1, m_objectName.constData());
+
+ rhiD->pipelineCreationEnd();
generation += 1;
rhiD->registerResource(this);
return true;
@@ -5135,9 +6427,10 @@ void QGles2ComputePipeline::destroy()
samplers.clear();
QRHI_RES_RHI(QRhiGles2);
- rhiD->releaseQueue.append(e);
-
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QGles2ComputePipeline::create()
@@ -5150,7 +6443,16 @@ bool QGles2ComputePipeline::create()
if (!rhiD->ensureContext())
return false;
+ rhiD->pipelineCreationStart();
+
const QShaderDescription csDesc = m_shaderStage.shader().description();
+ QShader::SeparateToCombinedImageSamplerMappingList csSamplerMappingList;
+ QShaderVersion shaderVersion;
+ if (!rhiD->shaderSource(m_shaderStage, &shaderVersion).isEmpty()) {
+ csSamplerMappingList = m_shaderStage.shader().separateToCombinedImageSamplerMappingList(
+ { QShader::GlslShader, shaderVersion, m_shaderStage.shaderVariant() });
+ }
+
program = rhiD->f->glCreateProgram();
QByteArray cacheKey;
@@ -5183,11 +6485,13 @@ bool QGles2ComputePipeline::create()
}
}
- QSet<int> activeUniformLocations;
+ QDuplicateTracker<int, 256> activeUniformLocations;
for (const QShaderDescription::UniformBlock &ub : csDesc.uniformBlocks())
rhiD->gatherUniforms(program, ub, &activeUniformLocations, &uniforms);
for (const QShaderDescription::InOutVariable &v : csDesc.combinedImageSamplers())
rhiD->gatherSamplers(program, v, &samplers);
+ for (const QShader::SeparateToCombinedImageSamplerMapping &mapping : csSamplerMappingList)
+ rhiD->gatherGeneratedSamplers(program, mapping, &samplers);
// storage images and buffers need no special steps here
@@ -5196,6 +6500,7 @@ bool QGles2ComputePipeline::create()
currentSrb = nullptr;
currentSrbGeneration = 0;
+ rhiD->pipelineCreationEnd();
generation += 1;
rhiD->registerResource(this);
return true;
@@ -5219,7 +6524,9 @@ void QGles2CommandBuffer::destroy()
QGles2SwapChain::QGles2SwapChain(QRhiImplementation *rhi)
: QRhiSwapChain(rhi),
- rt(rhi),
+ rt(rhi, this),
+ rtLeft(rhi, this),
+ rtRight(rhi, this),
cb(rhi)
{
}
@@ -5231,8 +6538,9 @@ QGles2SwapChain::~QGles2SwapChain()
void QGles2SwapChain::destroy()
{
- QRHI_PROF;
- QRHI_PROF_F(releaseSwapChain(this));
+ QRHI_RES_RHI(QRhiGles2);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
QRhiCommandBuffer *QGles2SwapChain::currentFrameCommandBuffer()
@@ -5245,19 +6553,59 @@ QRhiRenderTarget *QGles2SwapChain::currentFrameRenderTarget()
return &rt;
}
+QRhiRenderTarget *QGles2SwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
+{
+ if (targetBuffer == LeftBuffer)
+ return rtLeft.d.isValid() ? &rtLeft : &rt;
+ else if (targetBuffer == RightBuffer)
+ return rtRight.d.isValid() ? &rtRight : &rt;
+ else
+ Q_UNREACHABLE_RETURN(nullptr);
+}
+
QSize QGles2SwapChain::surfacePixelSize()
{
Q_ASSERT(m_window);
- return m_window->size() * m_window->devicePixelRatio();
+ if (QPlatformWindow *platformWindow = m_window->handle())
+ // Prefer using QPlatformWindow geometry and DPR in order to avoid
+ // errors due to rounded QWindow geometry.
+ return platformWindow->geometry().size() * platformWindow->devicePixelRatio();
+ else
+ return m_window->size() * m_window->devicePixelRatio();
+}
+
+bool QGles2SwapChain::isFormatSupported(Format f)
+{
+ return f == SDR;
}
QRhiRenderPassDescriptor *QGles2SwapChain::newCompatibleRenderPassDescriptor()
{
- return new QGles2RenderPassDescriptor(m_rhi);
+ QGles2RenderPassDescriptor *rpD = new QGles2RenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiGles2);
+ rhiD->registerResource(rpD, false);
+ return rpD;
+}
+
+void QGles2SwapChain::initSwapChainRenderTarget(QGles2SwapChainRenderTarget *rt)
+{
+ rt->setRenderPassDescriptor(m_renderPassDesc); // for the public getter in QRhiRenderTarget
+ rt->d.rp = QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
+ rt->d.pixelSize = pixelSize;
+ rt->d.dpr = float(m_window->devicePixelRatio());
+ rt->d.sampleCount = qBound(1, m_sampleCount, 64);
+ rt->d.colorAttCount = 1;
+ rt->d.dsAttCount = m_depthStencil ? 1 : 0;
+ rt->d.srgbUpdateAndBlend = m_flags.testFlag(QRhiSwapChain::sRGB);
}
bool QGles2SwapChain::createOrResize()
{
+ // can be called multiple times due to window resizes
+ const bool needsRegistration = !surface || surface != m_window;
+ if (surface && surface != m_window)
+ destroy();
+
surface = m_window;
m_currentPixelSize = surfacePixelSize();
pixelSize = m_currentPixelSize;
@@ -5269,21 +6617,70 @@ bool QGles2SwapChain::createOrResize()
m_depthStencil->create();
}
- rt.d.rp = QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
- rt.d.pixelSize = pixelSize;
- rt.d.dpr = float(m_window->devicePixelRatio());
- rt.d.sampleCount = qBound(1, m_sampleCount, 64);
- rt.d.colorAttCount = 1;
- rt.d.dsAttCount = m_depthStencil ? 1 : 0;
- rt.d.srgbUpdateAndBlend = m_flags.testFlag(QRhiSwapChain::sRGB);
+ initSwapChainRenderTarget(&rt);
+
+ if (m_window->format().stereo()) {
+ initSwapChainRenderTarget(&rtLeft);
+ rtLeft.d.stereoTarget = QRhiSwapChain::LeftBuffer;
+ initSwapChainRenderTarget(&rtRight);
+ rtRight.d.stereoTarget = QRhiSwapChain::RightBuffer;
+ }
frameCount = 0;
- QRHI_PROF;
- // make something up
- QRHI_PROF_F(resizeSwapChain(this, 2, m_sampleCount > 1 ? 2 : 0, m_sampleCount));
+ QRHI_RES_RHI(QRhiGles2);
+ if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps) && rhiD->caps.timestamps)
+ timestamps.prepare(rhiD);
+
+ // The only reason to register this fairly fake gl swapchain
+ // object with no native resources underneath is to be able to
+ // implement a safe destroy().
+ if (needsRegistration)
+ rhiD->registerResource(this, false);
return true;
}
+void QGles2SwapChainTimestamps::prepare(QRhiGles2 *rhiD)
+{
+ if (!query[0])
+ rhiD->f->glGenQueries(TIMESTAMP_PAIRS * 2, query);
+}
+
+void QGles2SwapChainTimestamps::destroy(QRhiGles2 *rhiD)
+{
+ rhiD->f->glDeleteQueries(TIMESTAMP_PAIRS * 2, query);
+ memset(active, 0, sizeof(active));
+ memset(query, 0, sizeof(query));
+}
+
+bool QGles2SwapChainTimestamps::tryQueryTimestamps(int pairIndex, QRhiGles2 *rhiD, double *elapsedSec)
+{
+ if (!active[pairIndex])
+ return false;
+
+ GLuint tsStart = query[pairIndex * 2];
+ GLuint tsEnd = query[pairIndex * 2 + 1];
+
+ GLuint ready = GL_FALSE;
+ rhiD->f->glGetQueryObjectuiv(tsEnd, GL_QUERY_RESULT_AVAILABLE, &ready);
+
+ if (!ready)
+ return false;
+
+ bool result = false;
+ quint64 timestamps[2];
+ rhiD->glGetQueryObjectui64v(tsStart, GL_QUERY_RESULT, &timestamps[0]);
+ rhiD->glGetQueryObjectui64v(tsEnd, GL_QUERY_RESULT, &timestamps[1]);
+
+ if (timestamps[1] >= timestamps[0]) {
+ const quint64 nanoseconds = timestamps[1] - timestamps[0];
+ *elapsedSec = nanoseconds / 1000000000.0;
+ result = true;
+ }
+
+ active[pairIndex] = false;
+ return result;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhigles2_p.h b/src/gui/rhi/qrhigles2_p.h
index 7273b8ee9e..4305186c02 100644
--- a/src/gui/rhi/qrhigles2_p.h
+++ b/src/gui/rhi/qrhigles2_p.h
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHIGLES2_H
-#define QRHIGLES2_H
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHIGLES2_P_H
+#define QRHIGLES2_P_H
//
// W A R N I N G
@@ -51,32 +15,1121 @@
// We mean it.
//
-#include <private/qrhi_p.h>
-#include <QtGui/qsurfaceformat.h>
+#include "qrhi_p.h"
+#include <rhi/qshaderdescription.h>
+#include <qopengl.h>
+#include <QByteArray>
+#include <QWindow>
+#include <QPointer>
+#include <QtCore/private/qduplicatetracker_p.h>
+#include <optional>
QT_BEGIN_NAMESPACE
-class QOpenGLContext;
-class QOffscreenSurface;
-class QWindow;
+class QOpenGLExtensions;
+class QRhiGles2;
+
+struct QGles2Buffer : public QRhiBuffer
+{
+ QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
+ ~QGles2Buffer();
+ void destroy() override;
+ bool create() override;
+ QRhiBuffer::NativeBuffer nativeBuffer() override;
+ char *beginFullDynamicBufferUpdateForCurrentFrame() override;
+ void endFullDynamicBufferUpdateForCurrentFrame() override;
+
+ quint32 nonZeroSize = 0;
+ GLuint buffer = 0;
+ GLenum targetForDataOps;
+ QByteArray data;
+ enum Access {
+ AccessNone,
+ AccessVertex,
+ AccessIndex,
+ AccessUniform,
+ AccessStorageRead,
+ AccessStorageWrite,
+ AccessStorageReadWrite,
+ AccessUpdate
+ };
+ struct UsageState {
+ Access access;
+ };
+ UsageState usageState;
+ friend class QRhiGles2;
+};
+
+struct QGles2RenderBuffer : public QRhiRenderBuffer
+{
+ QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint);
+ ~QGles2RenderBuffer();
+ void destroy() override;
+ bool create() override;
+ bool createFrom(NativeRenderBuffer src) override;
+ QRhiTexture::Format backingFormat() const override;
+
+ GLuint renderbuffer = 0;
+ GLuint stencilRenderbuffer = 0; // when packed depth-stencil not supported
+ int samples;
+ bool owns = true;
+ uint generation = 0;
+ friend class QRhiGles2;
+};
+
+struct QGles2SamplerData
+{
+ GLenum glminfilter = 0;
+ GLenum glmagfilter = 0;
+ GLenum glwraps = 0;
+ GLenum glwrapt = 0;
+ GLenum glwrapr = 0;
+ GLenum gltexcomparefunc = 0;
+};
+
+inline bool operator==(const QGles2SamplerData &a, const QGles2SamplerData &b)
+{
+ return a.glminfilter == b.glminfilter
+ && a.glmagfilter == b.glmagfilter
+ && a.glwraps == b.glwraps
+ && a.glwrapt == b.glwrapt
+ && a.glwrapr == b.glwrapr
+ && a.gltexcomparefunc == b.gltexcomparefunc;
+}
+
+inline bool operator!=(const QGles2SamplerData &a, const QGles2SamplerData &b)
+{
+ return !(a == b);
+}
+
+struct QGles2Texture : public QRhiTexture
+{
+ QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
+ int arraySize, int sampleCount, Flags flags);
+ ~QGles2Texture();
+ void destroy() override;
+ bool create() override;
+ bool createFrom(NativeTexture src) override;
+ NativeTexture nativeTexture() override;
+
+ bool prepareCreate(QSize *adjustedSize = nullptr);
+
+ GLuint texture = 0;
+ bool owns = true;
+ GLenum target;
+ GLenum glintformat;
+ GLenum glsizedintformat;
+ GLenum glformat;
+ GLenum gltype;
+ QGles2SamplerData samplerState;
+ bool specified = false;
+ bool zeroInitialized = false;
+ int mipLevelCount = 0;
+
+ enum Access {
+ AccessNone,
+ AccessSample,
+ AccessFramebuffer,
+ AccessStorageRead,
+ AccessStorageWrite,
+ AccessStorageReadWrite,
+ AccessUpdate,
+ AccessRead
+ };
+ struct UsageState {
+ Access access;
+ };
+ UsageState usageState;
+
+ uint generation = 0;
+ friend class QRhiGles2;
+};
+
+struct QGles2Sampler : public QRhiSampler
+{
+ QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v, AddressMode w);
+ ~QGles2Sampler();
+ void destroy() override;
+ bool create() override;
+
+ QGles2SamplerData d;
+ uint generation = 0;
+ friend class QRhiGles2;
+};
+
+struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QGles2RenderPassDescriptor(QRhiImplementation *rhi);
+ ~QGles2RenderPassDescriptor();
+ void destroy() override;
+ bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
+ QVector<quint32> serializedFormat() const override;
+};
+
+struct QGles2RenderTargetData
+{
+ QGles2RenderTargetData(QRhiImplementation *) { }
+
+ bool isValid() const { return rp != nullptr; }
+
+ QGles2RenderPassDescriptor *rp = nullptr;
+ QSize pixelSize;
+ float dpr = 1;
+ int sampleCount = 1;
+ int colorAttCount = 0;
+ int dsAttCount = 0;
+ bool srgbUpdateAndBlend = false;
+ QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList;
+ std::optional<QRhiSwapChain::StereoTargetBuffer> stereoTarget;
+};
+
+struct QGles2SwapChainRenderTarget : public QRhiSwapChainRenderTarget
+{
+ QGles2SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
+ ~QGles2SwapChainRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QGles2RenderTargetData d;
+};
+
+struct QGles2TextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QGles2TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
+ ~QGles2TextureRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool create() override;
+
+ QGles2RenderTargetData d;
+ GLuint framebuffer = 0;
+ GLuint nonMsaaThrowawayDepthTexture = 0;
+ friend class QRhiGles2;
+};
+
+struct QGles2ShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QGles2ShaderResourceBindings(QRhiImplementation *rhi);
+ ~QGles2ShaderResourceBindings();
+ void destroy() override;
+ bool create() override;
+ void updateResources(UpdateFlags flags) override;
+
+ bool hasDynamicOffset = false;
+ uint generation = 0;
+ friend class QRhiGles2;
+};
+
+struct QGles2UniformDescription
+{
+ QShaderDescription::VariableType type;
+ int glslLocation;
+ int binding;
+ quint32 offset;
+ quint32 size;
+ int arrayDim;
+};
+
+Q_DECLARE_TYPEINFO(QGles2UniformDescription, Q_RELOCATABLE_TYPE);
+
+struct QGles2SamplerDescription
+{
+ int glslLocation;
+ int combinedBinding;
+ int tbinding;
+ int sbinding;
+};
+
+Q_DECLARE_TYPEINFO(QGles2SamplerDescription, Q_RELOCATABLE_TYPE);
+
+using QGles2UniformDescriptionVector = QVarLengthArray<QGles2UniformDescription, 8>;
+using QGles2SamplerDescriptionVector = QVarLengthArray<QGles2SamplerDescription, 4>;
+
+struct QGles2UniformState
+{
+ static constexpr int MAX_TRACKED_LOCATION = 1023;
+ int componentCount;
+ float v[4];
+};
+
+struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QGles2GraphicsPipeline(QRhiImplementation *rhi);
+ ~QGles2GraphicsPipeline();
+ void destroy() override;
+ bool create() override;
+
+ GLuint program = 0;
+ GLenum drawMode = GL_TRIANGLES;
+ QGles2UniformDescriptionVector uniforms;
+ QGles2SamplerDescriptionVector samplers;
+ QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1];
+ QRhiShaderResourceBindings *currentSrb = nullptr;
+ uint currentSrbGeneration = 0;
+ uint generation = 0;
+ friend class QRhiGles2;
+};
+
+struct QGles2ComputePipeline : public QRhiComputePipeline
+{
+ QGles2ComputePipeline(QRhiImplementation *rhi);
+ ~QGles2ComputePipeline();
+ void destroy() override;
+ bool create() override;
+
+ GLuint program = 0;
+ QGles2UniformDescriptionVector uniforms;
+ QGles2SamplerDescriptionVector samplers;
+ QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1];
+ QRhiShaderResourceBindings *currentSrb = nullptr;
+ uint currentSrbGeneration = 0;
+ uint generation = 0;
+ friend class QRhiGles2;
+};
-struct Q_GUI_EXPORT QRhiGles2InitParams : public QRhiInitParams
+struct QGles2CommandBuffer : public QRhiCommandBuffer
{
- QRhiGles2InitParams();
+ QGles2CommandBuffer(QRhiImplementation *rhi);
+ ~QGles2CommandBuffer();
+ void destroy() override;
+
+ // keep at a reasonably low value otherwise sizeof Command explodes
+ static const int MAX_DYNAMIC_OFFSET_COUNT = 8;
+
+ struct Command {
+ enum Cmd {
+ BeginFrame,
+ EndFrame,
+ ResetFrame,
+ Viewport,
+ Scissor,
+ BlendConstants,
+ StencilRef,
+ BindVertexBuffer,
+ BindIndexBuffer,
+ Draw,
+ DrawIndexed,
+ BindGraphicsPipeline,
+ BindShaderResources,
+ BindFramebuffer,
+ Clear,
+ BufferSubData,
+ GetBufferSubData,
+ CopyTex,
+ ReadPixels,
+ SubImage,
+ CompressedImage,
+ CompressedSubImage,
+ BlitFromRenderbuffer,
+ BlitFromTexture,
+ GenMip,
+ BindComputePipeline,
+ Dispatch,
+ BarriersForPass,
+ Barrier,
+ InvalidateFramebuffer
+ };
+ Cmd cmd;
+
+ // QRhi*/QGles2* references should be kept at minimum (so no
+ // QRhiTexture/Buffer/etc. pointers).
+ union Args {
+ struct {
+ GLuint timestampQuery;
+ } beginFrame;
+ struct {
+ GLuint timestampQuery;
+ } endFrame;
+ struct {
+ float x, y, w, h;
+ float d0, d1;
+ } viewport;
+ struct {
+ int x, y, w, h;
+ } scissor;
+ struct {
+ float r, g, b, a;
+ } blendConstants;
+ struct {
+ quint32 ref;
+ QRhiGraphicsPipeline *ps;
+ } stencilRef;
+ struct {
+ QRhiGraphicsPipeline *ps;
+ GLuint buffer;
+ quint32 offset;
+ int binding;
+ } bindVertexBuffer;
+ struct {
+ GLuint buffer;
+ quint32 offset;
+ GLenum type;
+ } bindIndexBuffer;
+ struct {
+ QRhiGraphicsPipeline *ps;
+ quint32 vertexCount;
+ quint32 firstVertex;
+ quint32 instanceCount;
+ quint32 baseInstance;
+ } draw;
+ struct {
+ QRhiGraphicsPipeline *ps;
+ quint32 indexCount;
+ quint32 firstIndex;
+ quint32 instanceCount;
+ quint32 baseInstance;
+ qint32 baseVertex;
+ } drawIndexed;
+ struct {
+ QRhiGraphicsPipeline *ps;
+ } bindGraphicsPipeline;
+ struct {
+ QRhiGraphicsPipeline *maybeGraphicsPs;
+ QRhiComputePipeline *maybeComputePs;
+ QRhiShaderResourceBindings *srb;
+ int dynamicOffsetCount;
+ uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offset
+ } bindShaderResources;
+ struct {
+ GLbitfield mask;
+ float c[4];
+ float d;
+ quint32 s;
+ } clear;
+ struct {
+ GLuint fbo;
+ bool srgb;
+ int colorAttCount;
+ bool stereo;
+ QRhiSwapChain::StereoTargetBuffer stereoTarget;
+ } bindFramebuffer;
+ struct {
+ GLenum target;
+ GLuint buffer;
+ int offset;
+ int size;
+ const void *data; // must come from retainData()
+ } bufferSubData;
+ struct {
+ QRhiReadbackResult *result;
+ GLenum target;
+ GLuint buffer;
+ int offset;
+ int size;
+ } getBufferSubData;
+ struct {
+ GLenum srcTarget;
+ GLenum srcFaceTarget;
+ GLuint srcTexture;
+ int srcLevel;
+ int srcX;
+ int srcY;
+ int srcZ;
+ GLenum dstTarget;
+ GLuint dstTexture;
+ GLenum dstFaceTarget;
+ int dstLevel;
+ int dstX;
+ int dstY;
+ int dstZ;
+ int w;
+ int h;
+ } copyTex;
+ struct {
+ QRhiReadbackResult *result;
+ GLuint texture;
+ int w;
+ int h;
+ QRhiTexture::Format format;
+ GLenum readTarget;
+ int level;
+ int slice3D;
+ } readPixels;
+ struct {
+ GLenum target;
+ GLuint texture;
+ GLenum faceTarget;
+ int level;
+ int dx;
+ int dy;
+ int dz;
+ int w;
+ int h;
+ GLenum glformat;
+ GLenum gltype;
+ int rowStartAlign;
+ int rowLength;
+ const void *data; // must come from retainImage()
+ } subImage;
+ struct {
+ GLenum target;
+ GLuint texture;
+ GLenum faceTarget;
+ int level;
+ GLenum glintformat;
+ int w;
+ int h;
+ int depth;
+ int size;
+ const void *data; // must come from retainData()
+ } compressedImage;
+ struct {
+ GLenum target;
+ GLuint texture;
+ GLenum faceTarget;
+ int level;
+ int dx;
+ int dy;
+ int dz;
+ int w;
+ int h;
+ GLenum glintformat;
+ int size;
+ const void *data; // must come from retainData()
+ } compressedSubImage;
+ struct {
+ GLuint renderbuffer;
+ int w;
+ int h;
+ GLenum target;
+ GLuint dstTexture;
+ int dstLevel;
+ int dstLayer;
+ bool isDepthStencil;
+ } blitFromRenderbuffer;
+ struct {
+ GLenum srcTarget;
+ GLuint srcTexture;
+ int srcLevel;
+ int srcLayer;
+ int w;
+ int h;
+ GLenum dstTarget;
+ GLuint dstTexture;
+ int dstLevel;
+ int dstLayer;
+ bool isDepthStencil;
+ } blitFromTexture;
+ struct {
+ GLenum target;
+ GLuint texture;
+ } genMip;
+ struct {
+ QRhiComputePipeline *ps;
+ } bindComputePipeline;
+ struct {
+ GLuint x;
+ GLuint y;
+ GLuint z;
+ } dispatch;
+ struct {
+ int trackerIndex;
+ } barriersForPass;
+ struct {
+ GLbitfield barriers;
+ } barrier;
+ struct {
+ int attCount;
+ GLenum att[3];
+ } invalidateFramebuffer;
+ } args;
+ };
+
+ enum PassType {
+ NoPass,
+ RenderPass,
+ ComputePass
+ };
- QSurfaceFormat format;
- QOffscreenSurface *fallbackSurface = nullptr;
- QWindow *window = nullptr;
+ QRhiBackendCommandList<Command> commands;
+ QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers;
+ int currentPassResTrackerIndex;
- static QOffscreenSurface *newFallbackSurface(const QSurfaceFormat &format = QSurfaceFormat::defaultFormat());
- static QSurfaceFormat adjustedFormat(const QSurfaceFormat &format = QSurfaceFormat::defaultFormat());
+ PassType recordingPass;
+ bool passNeedsResourceTracking;
+ double lastGpuTime = 0;
+ QRhiRenderTarget *currentTarget;
+ QRhiGraphicsPipeline *currentGraphicsPipeline;
+ QRhiComputePipeline *currentComputePipeline;
+ uint currentPipelineGeneration;
+ QRhiShaderResourceBindings *currentGraphicsSrb;
+ QRhiShaderResourceBindings *currentComputeSrb;
+ uint currentSrbGeneration;
+
+ struct GraphicsPassState {
+ bool valid = false;
+ bool scissor;
+ bool cullFace;
+ GLenum cullMode;
+ GLenum frontFace;
+ bool blendEnabled;
+ struct ColorMask { bool r, g, b, a; } colorMask;
+ struct Blend {
+ GLenum srcColor;
+ GLenum dstColor;
+ GLenum srcAlpha;
+ GLenum dstAlpha;
+ GLenum opColor;
+ GLenum opAlpha;
+ } blend;
+ bool depthTest;
+ bool depthWrite;
+ GLenum depthFunc;
+ bool stencilTest;
+ GLuint stencilReadMask;
+ GLuint stencilWriteMask;
+ struct StencilFace {
+ GLenum func;
+ GLenum failOp;
+ GLenum zfailOp;
+ GLenum zpassOp;
+ } stencil[2]; // front, back
+ bool polyOffsetFill;
+ float polyOffsetFactor;
+ float polyOffsetUnits;
+ float lineWidth;
+ int cpCount;
+ GLenum polygonMode;
+ void reset() { valid = false; }
+ struct {
+ // not part of QRhiGraphicsPipeline but used by setGraphicsPipeline()
+ GLint stencilRef = 0;
+ } dynamic;
+ } graphicsPassState;
+
+ struct ComputePassState {
+ enum Access {
+ Read = 0x01,
+ Write = 0x02
+ };
+ QHash<QRhiResource *, QPair<int, bool> > writtenResources;
+ void reset() {
+ writtenResources.clear();
+ }
+ } computePassState;
+
+ struct TextureUnitState {
+ void *ps;
+ uint psGeneration;
+ uint texture;
+ } textureUnitState[16];
+
+ QVarLengthArray<QByteArray, 4> dataRetainPool;
+ QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
+ QVarLengthArray<QImage, 4> imageRetainPool;
+
+ // relies heavily on implicit sharing (no copies of the actual data will be made)
+ const void *retainData(const QByteArray &data) {
+ dataRetainPool.append(data);
+ return dataRetainPool.last().constData();
+ }
+ const uchar *retainBufferData(const QRhiBufferData &data) {
+ bufferDataRetainPool.append(data);
+ return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData());
+ }
+ const void *retainImage(const QImage &image) {
+ imageRetainPool.append(image);
+ return imageRetainPool.last().constBits();
+ }
+ void resetCommands() {
+ commands.reset();
+ dataRetainPool.clear();
+ bufferDataRetainPool.clear();
+ imageRetainPool.clear();
+
+ passResTrackers.clear();
+ currentPassResTrackerIndex = -1;
+ }
+ void resetState() {
+ recordingPass = NoPass;
+ passNeedsResourceTracking = true;
+ // do not zero lastGpuTime
+ currentTarget = nullptr;
+ resetCommands();
+ resetCachedState();
+ }
+ void resetCachedState() {
+ currentGraphicsPipeline = nullptr;
+ currentComputePipeline = nullptr;
+ currentPipelineGeneration = 0;
+ currentGraphicsSrb = nullptr;
+ currentComputeSrb = nullptr;
+ currentSrbGeneration = 0;
+ graphicsPassState.reset();
+ computePassState.reset();
+ memset(textureUnitState, 0, sizeof(textureUnitState));
+ }
};
-struct Q_GUI_EXPORT QRhiGles2NativeHandles : public QRhiNativeHandles
+inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a,
+ const QGles2CommandBuffer::GraphicsPassState::StencilFace &b)
+{
+ return a.func == b.func
+ && a.failOp == b.failOp
+ && a.zfailOp == b.zfailOp
+ && a.zpassOp == b.zpassOp;
+}
+
+inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a,
+ const QGles2CommandBuffer::GraphicsPassState::StencilFace &b)
{
- QOpenGLContext *context = nullptr;
+ return !(a == b);
+}
+
+inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a,
+ const QGles2CommandBuffer::GraphicsPassState::ColorMask &b)
+{
+ return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
+}
+
+inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a,
+ const QGles2CommandBuffer::GraphicsPassState::ColorMask &b)
+{
+ return !(a == b);
+}
+
+inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::Blend &a,
+ const QGles2CommandBuffer::GraphicsPassState::Blend &b)
+{
+ return a.srcColor == b.srcColor
+ && a.dstColor == b.dstColor
+ && a.srcAlpha == b.srcAlpha
+ && a.dstAlpha == b.dstAlpha
+ && a.opColor == b.opColor
+ && a.opAlpha == b.opAlpha;
+}
+
+inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::Blend &a,
+ const QGles2CommandBuffer::GraphicsPassState::Blend &b)
+{
+ return !(a == b);
+}
+
+struct QGles2SwapChainTimestamps
+{
+ static const int TIMESTAMP_PAIRS = 2;
+
+ bool active[TIMESTAMP_PAIRS] = {};
+ GLuint query[TIMESTAMP_PAIRS * 2] = {};
+
+ void prepare(QRhiGles2 *rhiD);
+ void destroy(QRhiGles2 *rhiD);
+ bool tryQueryTimestamps(int pairIndex, QRhiGles2 *rhiD, double *elapsedSec);
};
+struct QGles2SwapChain : public QRhiSwapChain
+{
+ QGles2SwapChain(QRhiImplementation *rhi);
+ ~QGles2SwapChain();
+ void destroy() override;
+
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+ QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override;
+
+ QSize surfacePixelSize() override;
+ bool isFormatSupported(Format f) override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool createOrResize() override;
+
+ void initSwapChainRenderTarget(QGles2SwapChainRenderTarget *rt);
+
+ QSurface *surface = nullptr;
+ QSize pixelSize;
+ QGles2SwapChainRenderTarget rt;
+ QGles2SwapChainRenderTarget rtLeft;
+ QGles2SwapChainRenderTarget rtRight;
+ QGles2CommandBuffer cb;
+ int frameCount = 0;
+ QGles2SwapChainTimestamps timestamps;
+ int currentTimestampPairIndex = 0;
+};
+
+class QRhiGles2 : public QRhiImplementation
+{
+public:
+ QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *importDevice = nullptr);
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiComputePipeline *createComputePipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ quint32 size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int depth,
+ int arraySize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ void beginComputePass(QRhiCommandBuffer *cb,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+ void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
+ void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+ double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
+
+ QList<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ QRhiDriverInfo driverInfo() const override;
+ QRhiStats statistics() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
+
+ QByteArray pipelineCacheData() override;
+ void setPipelineCacheData(const QByteArray &data) override;
+
+ bool ensureContext(QSurface *surface = nullptr) const;
+ QSurface *evaluateFallbackSurface() const;
+ void executeDeferredReleases();
+ void trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access);
+ void trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access);
+ void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD,
+ int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
+ void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
+ void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
+ QGles2Buffer *bufD,
+ QRhiPassResourceTracker::BufferAccess access,
+ QRhiPassResourceTracker::BufferStage stage);
+ void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker,
+ QGles2Texture *texD,
+ QRhiPassResourceTracker::TextureAccess access,
+ QRhiPassResourceTracker::TextureStage stage);
+ void executeCommandBuffer(QRhiCommandBuffer *cb);
+ void executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2GraphicsPipeline *psD);
+ void bindCombinedSampler(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Sampler *samplerD,
+ void *ps, uint psGeneration, int glslLocation,
+ int *texUnit, bool *activeTexUnitAltered);
+ void bindShaderResources(QGles2CommandBuffer *cbD,
+ QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs,
+ QRhiShaderResourceBindings *srb,
+ const uint *dynOfsPairs, int dynOfsCount);
+ QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD,
+ bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr);
+ void enqueueBarriersForPass(QGles2CommandBuffer *cbD);
+ QByteArray shaderSource(const QRhiShaderStage &shaderStage, QShaderVersion *shaderVersion);
+ bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, QShaderVersion *shaderVersion);
+ bool linkProgram(GLuint program);
+ void registerUniformIfActive(const QShaderDescription::BlockVariable &var,
+ const QByteArray &namePrefix, int binding, int baseOffset,
+ GLuint program,
+ QDuplicateTracker<int, 256> *activeUniformLocations,
+ QGles2UniformDescriptionVector *dst);
+ void gatherUniforms(GLuint program, const QShaderDescription::UniformBlock &ub,
+ QDuplicateTracker<int, 256> *activeUniformLocations, QGles2UniformDescriptionVector *dst);
+ void gatherSamplers(GLuint program, const QShaderDescription::InOutVariable &v,
+ QGles2SamplerDescriptionVector *dst);
+ void gatherGeneratedSamplers(GLuint program,
+ const QShader::SeparateToCombinedImageSamplerMapping &mapping,
+ QGles2SamplerDescriptionVector *dst);
+ void sanityCheckVertexFragmentInterface(const QShaderDescription &vsDesc, const QShaderDescription &fsDesc);
+ bool isProgramBinaryDiskCacheEnabled() const;
+
+ enum ProgramCacheResult {
+ ProgramCacheHit,
+ ProgramCacheMiss,
+ ProgramCacheError
+ };
+ ProgramCacheResult tryLoadFromDiskOrPipelineCache(const QRhiShaderStage *stages,
+ int stageCount,
+ GLuint program,
+ const QVector<QShaderDescription::InOutVariable> &inputVars,
+ QByteArray *cacheKey);
+ void trySaveToDiskCache(GLuint program, const QByteArray &cacheKey);
+ void trySaveToPipelineCache(GLuint program, const QByteArray &cacheKey, bool force = false);
+
+ QRhi::Flags rhiFlags;
+ QOpenGLContext *ctx = nullptr;
+ bool importedContext = false;
+ QSurfaceFormat requestedFormat;
+ QSurface *fallbackSurface = nullptr;
+ QPointer<QWindow> maybeWindow = nullptr;
+ QOpenGLContext *maybeShareContext = nullptr;
+ mutable bool needsMakeCurrentDueToSwap = false;
+ QOpenGLExtensions *f = nullptr;
+ void (QOPENGLF_APIENTRYP glPolygonMode) (GLenum, GLenum) = nullptr;
+ void(QOPENGLF_APIENTRYP glTexImage1D)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum,
+ const void *) = nullptr;
+ void(QOPENGLF_APIENTRYP glTexStorage1D)(GLenum, GLint, GLenum, GLsizei) = nullptr;
+ void(QOPENGLF_APIENTRYP glTexSubImage1D)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum,
+ const GLvoid *) = nullptr;
+ void(QOPENGLF_APIENTRYP glCopyTexSubImage1D)(GLenum, GLint, GLint, GLint, GLint,
+ GLsizei) = nullptr;
+ void(QOPENGLF_APIENTRYP glCompressedTexImage1D)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei,
+ const GLvoid *) = nullptr;
+ void(QOPENGLF_APIENTRYP glCompressedTexSubImage1D)(GLenum, GLint, GLint, GLsizei, GLenum,
+ GLsizei, const GLvoid *) = nullptr;
+ void(QOPENGLF_APIENTRYP glFramebufferTexture1D)(GLenum, GLenum, GLenum, GLuint,
+ GLint) = nullptr;
+ void(QOPENGLF_APIENTRYP glFramebufferTextureMultiviewOVR)(GLenum, GLenum, GLuint, GLint,
+ GLint, GLsizei) = nullptr;
+ void (QOPENGLF_APIENTRYP glQueryCounter)(GLuint, GLenum) = nullptr;
+ void (QOPENGLF_APIENTRYP glGetQueryObjectui64v)(GLuint, GLenum, quint64 *) = nullptr;
+ void (QOPENGLF_APIENTRYP glObjectLabel)(GLenum, GLuint, GLsizei, const GLchar *) = nullptr;
+ void (QOPENGLF_APIENTRYP glFramebufferTexture2DMultisampleEXT)(GLenum, GLenum, GLenum, GLuint, GLint, GLsizei) = nullptr;
+ void (QOPENGLF_APIENTRYP glFramebufferTextureMultisampleMultiviewOVR)(GLenum, GLenum, GLuint, GLint, GLsizei, GLint, GLsizei) = nullptr;
+ uint vao = 0;
+ struct Caps {
+ Caps()
+ : ctxMajor(2),
+ ctxMinor(0),
+ maxTextureSize(2048),
+ maxDrawBuffers(4),
+ maxSamples(16),
+ maxTextureArraySize(0),
+ maxThreadGroupsPerDimension(0),
+ maxThreadsPerThreadGroup(0),
+ maxThreadGroupsX(0),
+ maxThreadGroupsY(0),
+ maxThreadGroupsZ(0),
+ maxUniformVectors(4096),
+ maxVertexInputs(8),
+ maxVertexOutputs(8),
+ msaaRenderBuffer(false),
+ multisampledTexture(false),
+ npotTextureFull(true),
+ gles(false),
+ fixedIndexPrimitiveRestart(false),
+ bgraExternalFormat(false),
+ bgraInternalFormat(false),
+ r8Format(false),
+ r16Format(false),
+ floatFormats(false),
+ rgb10Formats(false),
+ depthTexture(false),
+ packedDepthStencil(false),
+ needsDepthStencilCombinedAttach(false),
+ srgbWriteControl(false),
+ coreProfile(false),
+ uniformBuffers(false),
+ elementIndexUint(false),
+ depth24(false),
+ rgba8Format(false),
+ instancing(false),
+ baseVertex(false),
+ compute(false),
+ textureCompareMode(false),
+ properMapBuffer(false),
+ nonBaseLevelFramebufferTexture(false),
+ texelFetch(false),
+ intAttributes(true),
+ screenSpaceDerivatives(false),
+ programBinary(false),
+ texture3D(false),
+ tessellation(false),
+ geometryShader(false),
+ texture1D(false),
+ hasDrawBuffersFunc(false),
+ halfAttributes(false),
+ multiView(false),
+ timestamps(false),
+ objectLabel(false)
+ { }
+ int ctxMajor;
+ int ctxMinor;
+ int maxTextureSize;
+ int maxDrawBuffers;
+ int maxSamples;
+ int maxTextureArraySize;
+ int maxThreadGroupsPerDimension;
+ int maxThreadsPerThreadGroup;
+ int maxThreadGroupsX;
+ int maxThreadGroupsY;
+ int maxThreadGroupsZ;
+ int maxUniformVectors;
+ int maxVertexInputs;
+ int maxVertexOutputs;
+ // Multisample fb and blit are supported (GLES 3.0 or OpenGL 3.x). Not
+ // the same as multisample textures!
+ uint msaaRenderBuffer : 1;
+ uint multisampledTexture : 1;
+ uint npotTextureFull : 1;
+ uint gles : 1;
+ uint fixedIndexPrimitiveRestart : 1;
+ uint bgraExternalFormat : 1;
+ uint bgraInternalFormat : 1;
+ uint r8Format : 1;
+ uint r16Format : 1;
+ uint floatFormats : 1;
+ uint rgb10Formats : 1;
+ uint depthTexture : 1;
+ uint packedDepthStencil : 1;
+ uint needsDepthStencilCombinedAttach : 1;
+ uint srgbWriteControl : 1;
+ uint coreProfile : 1;
+ uint uniformBuffers : 1;
+ uint elementIndexUint : 1;
+ uint depth24 : 1;
+ uint rgba8Format : 1;
+ uint instancing : 1;
+ uint baseVertex : 1;
+ uint compute : 1;
+ uint textureCompareMode : 1;
+ uint properMapBuffer : 1;
+ uint nonBaseLevelFramebufferTexture : 1;
+ uint texelFetch : 1;
+ uint intAttributes : 1;
+ uint screenSpaceDerivatives : 1;
+ uint programBinary : 1;
+ uint texture3D : 1;
+ uint tessellation : 1;
+ uint geometryShader : 1;
+ uint texture1D : 1;
+ uint hasDrawBuffersFunc : 1;
+ uint halfAttributes : 1;
+ uint multiView : 1;
+ uint timestamps : 1;
+ uint objectLabel : 1;
+ uint glesMultisampleRenderToTexture : 1;
+ uint glesMultiviewMultisampleRenderToTexture : 1;
+ } caps;
+ QGles2SwapChain *currentSwapChain = nullptr;
+ QSet<GLint> supportedCompressedFormats;
+ mutable QList<int> supportedSampleCountList;
+ QRhiGles2NativeHandles nativeHandlesStruct;
+ QRhiDriverInfo driverInfoStruct;
+ mutable bool contextLost = false;
+
+ struct DeferredReleaseEntry {
+ enum Type {
+ Buffer,
+ Pipeline,
+ Texture,
+ RenderBuffer,
+ TextureRenderTarget
+ };
+ Type type;
+ union {
+ struct {
+ GLuint buffer;
+ } buffer;
+ struct {
+ GLuint program;
+ } pipeline;
+ struct {
+ GLuint texture;
+ } texture;
+ struct {
+ GLuint renderbuffer;
+ GLuint renderbuffer2;
+ } renderbuffer;
+ struct {
+ GLuint framebuffer;
+ GLuint nonMsaaThrowawayDepthTexture;
+ } textureRenderTarget;
+ };
+ };
+ QList<DeferredReleaseEntry> releaseQueue;
+
+ struct OffscreenFrame {
+ OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
+ bool active = false;
+ QGles2CommandBuffer cbWrapper;
+ GLuint tsQueries[2] = {};
+ } ofr;
+
+ QHash<QRhiShaderStage, uint> m_shaderCache;
+
+ struct PipelineCacheData {
+ quint32 format;
+ QByteArray data;
+ };
+ QHash<QByteArray, PipelineCacheData> m_pipelineCache;
+};
+
+Q_DECLARE_TYPEINFO(QRhiGles2::DeferredReleaseEntry, Q_RELOCATABLE_TYPE);
+
QT_END_NAMESPACE
#endif
diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h
deleted file mode 100644
index 8a0e0ec2a1..0000000000
--- a/src/gui/rhi/qrhigles2_p_p.h
+++ /dev/null
@@ -1,1045 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHIGLES2_P_H
-#define QRHIGLES2_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qrhigles2_p.h"
-#include "qrhi_p_p.h"
-#include "qshaderdescription_p.h"
-#include <qopengl.h>
-#include <QByteArray>
-#include <QSurface>
-
-QT_BEGIN_NAMESPACE
-
-class QOpenGLExtensions;
-
-struct QGles2Buffer : public QRhiBuffer
-{
- QGles2Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
- ~QGles2Buffer();
- void destroy() override;
- bool create() override;
- QRhiBuffer::NativeBuffer nativeBuffer() override;
- char *beginFullDynamicBufferUpdateForCurrentFrame() override;
- void endFullDynamicBufferUpdateForCurrentFrame() override;
-
- int nonZeroSize = 0;
- GLuint buffer = 0;
- GLenum targetForDataOps;
- QByteArray data;
- enum Access {
- AccessNone,
- AccessVertex,
- AccessIndex,
- AccessUniform,
- AccessStorageRead,
- AccessStorageWrite,
- AccessStorageReadWrite,
- AccessUpdate
- };
- struct UsageState {
- Access access;
- };
- UsageState usageState;
- friend class QRhiGles2;
-};
-
-struct QGles2RenderBuffer : public QRhiRenderBuffer
-{
- QGles2RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
- int sampleCount, QRhiRenderBuffer::Flags flags,
- QRhiTexture::Format backingFormatHint);
- ~QGles2RenderBuffer();
- void destroy() override;
- bool create() override;
- bool createFrom(NativeRenderBuffer src) override;
- QRhiTexture::Format backingFormat() const override;
-
- GLuint renderbuffer = 0;
- GLuint stencilRenderbuffer = 0; // when packed depth-stencil not supported
- int samples;
- bool owns = true;
- friend class QRhiGles2;
-};
-
-struct QGles2SamplerData
-{
- GLenum glminfilter = 0;
- GLenum glmagfilter = 0;
- GLenum glwraps = 0;
- GLenum glwrapt = 0;
- GLenum glwrapr = 0;
- GLenum gltexcomparefunc = 0;
-};
-
-inline bool operator==(const QGles2SamplerData &a, const QGles2SamplerData &b)
-{
- return a.glminfilter == b.glminfilter
- && a.glmagfilter == b.glmagfilter
- && a.glwraps == b.glwraps
- && a.glwrapt == b.glwrapt
- && a.glwrapr == b.glwrapr
- && a.gltexcomparefunc == b.gltexcomparefunc;
-}
-
-inline bool operator!=(const QGles2SamplerData &a, const QGles2SamplerData &b)
-{
- return !(a == b);
-}
-
-struct QGles2Texture : public QRhiTexture
-{
- QGles2Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags);
- ~QGles2Texture();
- void destroy() override;
- bool create() override;
- bool createFrom(NativeTexture src) override;
- NativeTexture nativeTexture() override;
-
- bool prepareCreate(QSize *adjustedSize = nullptr);
-
- GLuint texture = 0;
- bool owns = true;
- GLenum target;
- GLenum glintformat;
- GLenum glsizedintformat;
- GLenum glformat;
- GLenum gltype;
- QGles2SamplerData samplerState;
- bool specified = false;
- bool zeroInitialized = false;
- int mipLevelCount = 0;
-
- enum Access {
- AccessNone,
- AccessSample,
- AccessFramebuffer,
- AccessStorageRead,
- AccessStorageWrite,
- AccessStorageReadWrite,
- AccessUpdate,
- AccessRead
- };
- struct UsageState {
- Access access;
- };
- UsageState usageState;
-
- uint generation = 0;
- friend class QRhiGles2;
-};
-
-struct QGles2Sampler : public QRhiSampler
-{
- QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v, AddressMode w);
- ~QGles2Sampler();
- void destroy() override;
- bool create() override;
-
- QGles2SamplerData d;
- uint generation = 0;
- friend class QRhiGles2;
-};
-
-struct QGles2RenderPassDescriptor : public QRhiRenderPassDescriptor
-{
- QGles2RenderPassDescriptor(QRhiImplementation *rhi);
- ~QGles2RenderPassDescriptor();
- void destroy() override;
- bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
-};
-
-struct QGles2RenderTargetData
-{
- QGles2RenderTargetData(QRhiImplementation *) { }
-
- QGles2RenderPassDescriptor *rp = nullptr;
- QSize pixelSize;
- float dpr = 1;
- int sampleCount = 1;
- int colorAttCount = 0;
- int dsAttCount = 0;
- bool srgbUpdateAndBlend = false;
-};
-
-struct QGles2ReferenceRenderTarget : public QRhiRenderTarget
-{
- QGles2ReferenceRenderTarget(QRhiImplementation *rhi);
- ~QGles2ReferenceRenderTarget();
- void destroy() override;
-
- QSize pixelSize() const override;
- float devicePixelRatio() const override;
- int sampleCount() const override;
-
- QGles2RenderTargetData d;
-};
-
-struct QGles2TextureRenderTarget : public QRhiTextureRenderTarget
-{
- QGles2TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
- ~QGles2TextureRenderTarget();
- void destroy() override;
-
- QSize pixelSize() const override;
- float devicePixelRatio() const override;
- int sampleCount() const override;
-
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
- bool create() override;
-
- QGles2RenderTargetData d;
- GLuint framebuffer = 0;
- friend class QRhiGles2;
-};
-
-struct QGles2ShaderResourceBindings : public QRhiShaderResourceBindings
-{
- QGles2ShaderResourceBindings(QRhiImplementation *rhi);
- ~QGles2ShaderResourceBindings();
- void destroy() override;
- bool create() override;
-
- bool hasDynamicOffset = false;
- uint generation = 0;
- friend class QRhiGles2;
-};
-
-struct QGles2UniformDescription
-{
- QShaderDescription::VariableType type;
- int glslLocation;
- int binding;
- uint offset;
- int size;
- int arrayDim;
-};
-
-Q_DECLARE_TYPEINFO(QGles2UniformDescription, Q_RELOCATABLE_TYPE);
-
-struct QGles2SamplerDescription
-{
- int glslLocation;
- int binding;
-};
-
-Q_DECLARE_TYPEINFO(QGles2SamplerDescription, Q_RELOCATABLE_TYPE);
-
-using QGles2UniformDescriptionVector = QVarLengthArray<QGles2UniformDescription, 8>;
-using QGles2SamplerDescriptionVector = QVarLengthArray<QGles2SamplerDescription, 4>;
-
-struct QGles2UniformState
-{
- static constexpr int MAX_TRACKED_LOCATION = 1023;
- int componentCount;
- float v[4];
-};
-
-struct QGles2GraphicsPipeline : public QRhiGraphicsPipeline
-{
- QGles2GraphicsPipeline(QRhiImplementation *rhi);
- ~QGles2GraphicsPipeline();
- void destroy() override;
- bool create() override;
-
- GLuint program = 0;
- GLenum drawMode = GL_TRIANGLES;
- QGles2UniformDescriptionVector uniforms;
- QGles2SamplerDescriptionVector samplers;
- QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1];
- QRhiShaderResourceBindings *currentSrb = nullptr;
- uint currentSrbGeneration = 0;
- uint generation = 0;
- friend class QRhiGles2;
-};
-
-struct QGles2ComputePipeline : public QRhiComputePipeline
-{
- QGles2ComputePipeline(QRhiImplementation *rhi);
- ~QGles2ComputePipeline();
- void destroy() override;
- bool create() override;
-
- GLuint program = 0;
- QGles2UniformDescriptionVector uniforms;
- QGles2SamplerDescriptionVector samplers;
- QGles2UniformState uniformState[QGles2UniformState::MAX_TRACKED_LOCATION + 1];
- QRhiShaderResourceBindings *currentSrb = nullptr;
- uint currentSrbGeneration = 0;
- uint generation = 0;
- friend class QRhiGles2;
-};
-
-struct QGles2CommandBuffer : public QRhiCommandBuffer
-{
- QGles2CommandBuffer(QRhiImplementation *rhi);
- ~QGles2CommandBuffer();
- void destroy() override;
-
- // keep at a reasonably low value otherwise sizeof Command explodes
- static const int MAX_DYNAMIC_OFFSET_COUNT = 8;
-
- struct Command {
- enum Cmd {
- BeginFrame,
- EndFrame,
- ResetFrame,
- Viewport,
- Scissor,
- BlendConstants,
- StencilRef,
- BindVertexBuffer,
- BindIndexBuffer,
- Draw,
- DrawIndexed,
- BindGraphicsPipeline,
- BindShaderResources,
- BindFramebuffer,
- Clear,
- BufferSubData,
- GetBufferSubData,
- CopyTex,
- ReadPixels,
- SubImage,
- CompressedImage,
- CompressedSubImage,
- BlitFromRenderbuffer,
- GenMip,
- BindComputePipeline,
- Dispatch,
- BarriersForPass,
- Barrier
- };
- Cmd cmd;
-
- // QRhi*/QGles2* references should be kept at minimum (so no
- // QRhiTexture/Buffer/etc. pointers).
- union Args {
- struct {
- float x, y, w, h;
- float d0, d1;
- } viewport;
- struct {
- int x, y, w, h;
- } scissor;
- struct {
- float r, g, b, a;
- } blendConstants;
- struct {
- quint32 ref;
- QRhiGraphicsPipeline *ps;
- } stencilRef;
- struct {
- QRhiGraphicsPipeline *ps;
- GLuint buffer;
- quint32 offset;
- int binding;
- } bindVertexBuffer;
- struct {
- GLuint buffer;
- quint32 offset;
- GLenum type;
- } bindIndexBuffer;
- struct {
- QRhiGraphicsPipeline *ps;
- quint32 vertexCount;
- quint32 firstVertex;
- quint32 instanceCount;
- quint32 baseInstance;
- } draw;
- struct {
- QRhiGraphicsPipeline *ps;
- quint32 indexCount;
- quint32 firstIndex;
- quint32 instanceCount;
- quint32 baseInstance;
- qint32 baseVertex;
- } drawIndexed;
- struct {
- QRhiGraphicsPipeline *ps;
- } bindGraphicsPipeline;
- struct {
- QRhiGraphicsPipeline *maybeGraphicsPs;
- QRhiComputePipeline *maybeComputePs;
- QRhiShaderResourceBindings *srb;
- int dynamicOffsetCount;
- uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offset
- } bindShaderResources;
- struct {
- GLbitfield mask;
- float c[4];
- float d;
- quint32 s;
- } clear;
- struct {
- GLuint fbo;
- bool srgb;
- int colorAttCount;
- } bindFramebuffer;
- struct {
- GLenum target;
- GLuint buffer;
- int offset;
- int size;
- const void *data; // must come from retainData()
- } bufferSubData;
- struct {
- QRhiBufferReadbackResult *result;
- GLenum target;
- GLuint buffer;
- int offset;
- int size;
- } getBufferSubData;
- struct {
- GLenum srcTarget;
- GLenum srcFaceTarget;
- GLuint srcTexture;
- int srcLevel;
- int srcX;
- int srcY;
- int srcZ;
- GLenum dstTarget;
- GLuint dstTexture;
- GLenum dstFaceTarget;
- int dstLevel;
- int dstX;
- int dstY;
- int dstZ;
- int w;
- int h;
- } copyTex;
- struct {
- QRhiReadbackResult *result;
- GLuint texture;
- int w;
- int h;
- QRhiTexture::Format format;
- GLenum readTarget;
- int level;
- int slice3D;
- } readPixels;
- struct {
- GLenum target;
- GLuint texture;
- GLenum faceTarget;
- int level;
- int dx;
- int dy;
- int dz;
- int w;
- int h;
- GLenum glformat;
- GLenum gltype;
- int rowStartAlign;
- int rowLength;
- const void *data; // must come from retainImage()
- } subImage;
- struct {
- GLenum target;
- GLuint texture;
- GLenum faceTarget;
- int level;
- GLenum glintformat;
- int w;
- int h;
- int depth;
- int size;
- const void *data; // must come from retainData()
- } compressedImage;
- struct {
- GLenum target;
- GLuint texture;
- GLenum faceTarget;
- int level;
- int dx;
- int dy;
- int dz;
- int w;
- int h;
- GLenum glintformat;
- int size;
- const void *data; // must come from retainData()
- } compressedSubImage;
- struct {
- GLuint renderbuffer;
- int w;
- int h;
- GLenum target;
- GLuint texture;
- int dstLevel;
- } blitFromRb;
- struct {
- GLenum target;
- GLuint texture;
- } genMip;
- struct {
- QRhiComputePipeline *ps;
- } bindComputePipeline;
- struct {
- GLuint x;
- GLuint y;
- GLuint z;
- } dispatch;
- struct {
- int trackerIndex;
- } barriersForPass;
- struct {
- GLbitfield barriers;
- } barrier;
- } args;
- };
-
- enum PassType {
- NoPass,
- RenderPass,
- ComputePass
- };
-
- QRhiBackendCommandList<Command> commands;
- QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers;
- int currentPassResTrackerIndex;
-
- PassType recordingPass;
- bool passNeedsResourceTracking;
- QRhiRenderTarget *currentTarget;
- QRhiGraphicsPipeline *currentGraphicsPipeline;
- QRhiComputePipeline *currentComputePipeline;
- uint currentPipelineGeneration;
- QRhiShaderResourceBindings *currentGraphicsSrb;
- QRhiShaderResourceBindings *currentComputeSrb;
- uint currentSrbGeneration;
-
- struct GraphicsPassState {
- bool valid = false;
- bool scissor;
- bool cullFace;
- GLenum cullMode;
- GLenum frontFace;
- bool blendEnabled;
- struct ColorMask { bool r, g, b, a; } colorMask;
- struct Blend {
- GLenum srcColor;
- GLenum dstColor;
- GLenum srcAlpha;
- GLenum dstAlpha;
- GLenum opColor;
- GLenum opAlpha;
- } blend;
- bool depthTest;
- bool depthWrite;
- GLenum depthFunc;
- bool stencilTest;
- GLuint stencilReadMask;
- GLuint stencilWriteMask;
- struct StencilFace {
- GLenum func;
- GLenum failOp;
- GLenum zfailOp;
- GLenum zpassOp;
- } stencil[2]; // front, back
- bool polyOffsetFill;
- float polyOffsetFactor;
- float polyOffsetUnits;
- float lineWidth;
- void reset() { valid = false; }
- struct {
- // not part of QRhiGraphicsPipeline but used by setGraphicsPipeline()
- GLint stencilRef = 0;
- } dynamic;
- } graphicsPassState;
-
- struct ComputePassState {
- enum Access {
- Read = 0x01,
- Write = 0x02
- };
- QHash<QRhiResource *, QPair<int, bool> > writtenResources;
- void reset() {
- writtenResources.clear();
- }
- } computePassState;
-
- struct TextureUnitState {
- void *ps;
- uint psGeneration;
- uint texture;
- } textureUnitState[16];
-
- QVarLengthArray<QByteArray, 4> dataRetainPool;
- QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
- QVarLengthArray<QImage, 4> imageRetainPool;
-
- // relies heavily on implicit sharing (no copies of the actual data will be made)
- const void *retainData(const QByteArray &data) {
- dataRetainPool.append(data);
- return dataRetainPool.last().constData();
- }
- const uchar *retainBufferData(const QRhiBufferData &data) {
- bufferDataRetainPool.append(data);
- return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData());
- }
- const void *retainImage(const QImage &image) {
- imageRetainPool.append(image);
- return imageRetainPool.last().constBits();
- }
- void resetCommands() {
- commands.reset();
- dataRetainPool.clear();
- bufferDataRetainPool.clear();
- imageRetainPool.clear();
-
- passResTrackers.clear();
- currentPassResTrackerIndex = -1;
- }
- void resetState() {
- recordingPass = NoPass;
- passNeedsResourceTracking = true;
- currentTarget = nullptr;
- resetCommands();
- resetCachedState();
- }
- void resetCachedState() {
- currentGraphicsPipeline = nullptr;
- currentComputePipeline = nullptr;
- currentPipelineGeneration = 0;
- currentGraphicsSrb = nullptr;
- currentComputeSrb = nullptr;
- currentSrbGeneration = 0;
- graphicsPassState.reset();
- computePassState.reset();
- memset(textureUnitState, 0, sizeof(textureUnitState));
- }
-};
-
-inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a,
- const QGles2CommandBuffer::GraphicsPassState::StencilFace &b)
-{
- return a.func == b.func
- && a.failOp == b.failOp
- && a.zfailOp == b.zfailOp
- && a.zpassOp == b.zpassOp;
-}
-
-inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a,
- const QGles2CommandBuffer::GraphicsPassState::StencilFace &b)
-{
- return !(a == b);
-}
-
-inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a,
- const QGles2CommandBuffer::GraphicsPassState::ColorMask &b)
-{
- return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
-}
-
-inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a,
- const QGles2CommandBuffer::GraphicsPassState::ColorMask &b)
-{
- return !(a == b);
-}
-
-inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::Blend &a,
- const QGles2CommandBuffer::GraphicsPassState::Blend &b)
-{
- return a.srcColor == b.srcColor
- && a.dstColor == b.dstColor
- && a.srcAlpha == b.srcAlpha
- && a.dstAlpha == b.dstAlpha
- && a.opColor == b.opColor
- && a.opAlpha == b.opAlpha;
-}
-
-inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::Blend &a,
- const QGles2CommandBuffer::GraphicsPassState::Blend &b)
-{
- return !(a == b);
-}
-
-struct QGles2SwapChain : public QRhiSwapChain
-{
- QGles2SwapChain(QRhiImplementation *rhi);
- ~QGles2SwapChain();
- void destroy() override;
-
- QRhiCommandBuffer *currentFrameCommandBuffer() override;
- QRhiRenderTarget *currentFrameRenderTarget() override;
-
- QSize surfacePixelSize() override;
-
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
- bool createOrResize() override;
-
- QSurface *surface = nullptr;
- QSize pixelSize;
- QGles2ReferenceRenderTarget rt;
- QGles2CommandBuffer cb;
- int frameCount = 0;
-};
-
-class QRhiGles2 : public QRhiImplementation
-{
-public:
- QRhiGles2(QRhiGles2InitParams *params, QRhiGles2NativeHandles *importDevice = nullptr);
-
- bool create(QRhi::Flags flags) override;
- void destroy() override;
-
- QRhiGraphicsPipeline *createGraphicsPipeline() override;
- QRhiComputePipeline *createComputePipeline() override;
- QRhiShaderResourceBindings *createShaderResourceBindings() override;
- QRhiBuffer *createBuffer(QRhiBuffer::Type type,
- QRhiBuffer::UsageFlags usage,
- int size) override;
- QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
- const QSize &pixelSize,
- int sampleCount,
- QRhiRenderBuffer::Flags flags,
- QRhiTexture::Format backingFormatHint) override;
- QRhiTexture *createTexture(QRhiTexture::Format format,
- const QSize &pixelSize,
- int depth,
- int sampleCount,
- QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
- QRhiSampler::Filter minFilter,
- QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u,
- QRhiSampler::AddressMode v,
- QRhiSampler::AddressMode w) override;
-
- QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
- QRhiTextureRenderTarget::Flags flags) override;
-
- QRhiSwapChain *createSwapChain() override;
- QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
- QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
- QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
- QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
- QRhi::FrameOpResult finish() override;
-
- void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
-
- void beginPass(QRhiCommandBuffer *cb,
- QRhiRenderTarget *rt,
- const QColor &colorClearValue,
- const QRhiDepthStencilClearValue &depthStencilClearValue,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) override;
- void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
-
- void setGraphicsPipeline(QRhiCommandBuffer *cb,
- QRhiGraphicsPipeline *ps) override;
-
- void setShaderResources(QRhiCommandBuffer *cb,
- QRhiShaderResourceBindings *srb,
- int dynamicOffsetCount,
- const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
-
- void setVertexInput(QRhiCommandBuffer *cb,
- int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
- QRhiBuffer *indexBuf, quint32 indexOffset,
- QRhiCommandBuffer::IndexFormat indexFormat) override;
-
- void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
- void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
- void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
- void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
-
- void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
- quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
-
- void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
- quint32 instanceCount, quint32 firstIndex,
- qint32 vertexOffset, quint32 firstInstance) override;
-
- void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
- void debugMarkEnd(QRhiCommandBuffer *cb) override;
- void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
-
- void beginComputePass(QRhiCommandBuffer *cb,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) override;
- void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
- void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
- void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
-
- const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
- void beginExternal(QRhiCommandBuffer *cb) override;
- void endExternal(QRhiCommandBuffer *cb) override;
-
- QList<int> supportedSampleCounts() const override;
- int ubufAlignment() const override;
- bool isYUpInFramebuffer() const override;
- bool isYUpInNDC() const override;
- bool isClipDepthZeroToOne() const override;
- QMatrix4x4 clipSpaceCorrMatrix() const override;
- bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
- bool isFeatureSupported(QRhi::Feature feature) const override;
- int resourceLimit(QRhi::ResourceLimit limit) const override;
- const QRhiNativeHandles *nativeHandles() override;
- QRhiDriverInfo driverInfo() const override;
- void sendVMemStatsToProfiler() override;
- bool makeThreadLocalNativeContextCurrent() override;
- void releaseCachedResources() override;
- bool isDeviceLost() const override;
-
- QByteArray pipelineCacheData() override;
- void setPipelineCacheData(const QByteArray &data) override;
-
- bool ensureContext(QSurface *surface = nullptr) const;
- void executeDeferredReleases();
- void trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access);
- void trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access);
- void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD,
- int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
- void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
- void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
- QGles2Buffer *bufD,
- QRhiPassResourceTracker::BufferAccess access,
- QRhiPassResourceTracker::BufferStage stage);
- void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker,
- QGles2Texture *texD,
- QRhiPassResourceTracker::TextureAccess access,
- QRhiPassResourceTracker::TextureStage stage);
- void executeCommandBuffer(QRhiCommandBuffer *cb);
- void executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2GraphicsPipeline *psD);
- void bindShaderResources(QGles2CommandBuffer *cbD,
- QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs,
- QRhiShaderResourceBindings *srb,
- const uint *dynOfsPairs, int dynOfsCount);
- QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD,
- bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr);
- void enqueueBarriersForPass(QGles2CommandBuffer *cbD);
- int effectiveSampleCount(int sampleCount) const;
- QByteArray shaderSource(const QRhiShaderStage &shaderStage, int *glslVersion);
- bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, int *glslVersion);
- bool linkProgram(GLuint program);
- void registerUniformIfActive(const QShaderDescription::BlockVariable &var,
- const QByteArray &namePrefix, int binding, int baseOffset,
- GLuint program,
- QSet<int> *activeUniformLocations,
- QGles2UniformDescriptionVector *dst);
- void gatherUniforms(GLuint program, const QShaderDescription::UniformBlock &ub,
- QSet<int> *activeUniformLocations, QGles2UniformDescriptionVector *dst);
- void gatherSamplers(GLuint program, const QShaderDescription::InOutVariable &v,
- QGles2SamplerDescriptionVector *dst);
- void sanityCheckVertexFragmentInterface(const QShaderDescription &vsDesc, const QShaderDescription &fsDesc);
- bool isProgramBinaryDiskCacheEnabled() const;
-
- enum ProgramCacheResult {
- ProgramCacheHit,
- ProgramCacheMiss,
- ProgramCacheError
- };
- ProgramCacheResult tryLoadFromDiskOrPipelineCache(const QRhiShaderStage *stages,
- int stageCount,
- GLuint program,
- const QVector<QShaderDescription::InOutVariable> &inputVars,
- QByteArray *cacheKey);
- void trySaveToDiskCache(GLuint program, const QByteArray &cacheKey);
- void trySaveToPipelineCache(GLuint program, const QByteArray &cacheKey, bool force = false);
-
- QRhi::Flags rhiFlags;
- QOpenGLContext *ctx = nullptr;
- bool importedContext = false;
- QSurfaceFormat requestedFormat;
- QSurface *fallbackSurface = nullptr;
- QWindow *maybeWindow = nullptr;
- mutable bool needsMakeCurrent = false;
- QOpenGLExtensions *f = nullptr;
- uint vao = 0;
- struct Caps {
- Caps()
- : ctxMajor(2),
- ctxMinor(0),
- maxTextureSize(2048),
- maxDrawBuffers(4),
- maxSamples(16),
- maxThreadGroupsPerDimension(0),
- maxThreadsPerThreadGroup(0),
- maxThreadGroupsX(0),
- maxThreadGroupsY(0),
- maxThreadGroupsZ(0),
- msaaRenderBuffer(false),
- multisampledTexture(false),
- npotTextureFull(true),
- gles(false),
- fixedIndexPrimitiveRestart(false),
- bgraExternalFormat(false),
- bgraInternalFormat(false),
- r8Format(false),
- r16Format(false),
- floatFormats(false),
- depthTexture(false),
- packedDepthStencil(false),
- needsDepthStencilCombinedAttach(false),
- srgbCapableDefaultFramebuffer(false),
- coreProfile(false),
- uniformBuffers(false),
- elementIndexUint(false),
- depth24(false),
- rgba8Format(false),
- instancing(false),
- baseVertex(false),
- compute(false),
- textureCompareMode(false),
- properMapBuffer(false),
- nonBaseLevelFramebufferTexture(false),
- texelFetch(false),
- intAttributes(true),
- screenSpaceDerivatives(false),
- programBinary(false),
- texture3D(false)
- { }
- int ctxMajor;
- int ctxMinor;
- int maxTextureSize;
- int maxDrawBuffers;
- int maxSamples;
- int maxThreadGroupsPerDimension;
- int maxThreadsPerThreadGroup;
- int maxThreadGroupsX;
- int maxThreadGroupsY;
- int maxThreadGroupsZ;
- // Multisample fb and blit are supported (GLES 3.0 or OpenGL 3.x). Not
- // the same as multisample textures!
- uint msaaRenderBuffer : 1;
- uint multisampledTexture : 1;
- uint npotTextureFull : 1;
- uint gles : 1;
- uint fixedIndexPrimitiveRestart : 1;
- uint bgraExternalFormat : 1;
- uint bgraInternalFormat : 1;
- uint r8Format : 1;
- uint r16Format : 1;
- uint floatFormats : 1;
- uint depthTexture : 1;
- uint packedDepthStencil : 1;
- uint needsDepthStencilCombinedAttach : 1;
- uint srgbCapableDefaultFramebuffer : 1;
- uint coreProfile : 1;
- uint uniformBuffers : 1;
- uint elementIndexUint : 1;
- uint depth24 : 1;
- uint rgba8Format : 1;
- uint instancing : 1;
- uint baseVertex : 1;
- uint compute : 1;
- uint textureCompareMode : 1;
- uint properMapBuffer : 1;
- uint nonBaseLevelFramebufferTexture : 1;
- uint texelFetch : 1;
- uint intAttributes : 1;
- uint screenSpaceDerivatives : 1;
- uint programBinary : 1;
- uint texture3D : 1;
- } caps;
- QGles2SwapChain *currentSwapChain = nullptr;
- QList<GLint> supportedCompressedFormats;
- mutable QList<int> supportedSampleCountList;
- QRhiGles2NativeHandles nativeHandlesStruct;
- QRhiDriverInfo driverInfoStruct;
- mutable bool contextLost = false;
-
- struct DeferredReleaseEntry {
- enum Type {
- Buffer,
- Pipeline,
- Texture,
- RenderBuffer,
- TextureRenderTarget
- };
- Type type;
- union {
- struct {
- GLuint buffer;
- } buffer;
- struct {
- GLuint program;
- } pipeline;
- struct {
- GLuint texture;
- } texture;
- struct {
- GLuint renderbuffer;
- GLuint renderbuffer2;
- } renderbuffer;
- struct {
- GLuint framebuffer;
- } textureRenderTarget;
- };
- };
- QList<DeferredReleaseEntry> releaseQueue;
-
- struct OffscreenFrame {
- OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
- bool active = false;
- QGles2CommandBuffer cbWrapper;
- } ofr;
-
- QHash<QRhiShaderStage, uint> m_shaderCache;
-
- struct PipelineCacheData {
- quint32 format;
- QByteArray data;
- };
- QHash<QByteArray, PipelineCacheData> m_pipelineCache;
-};
-
-Q_DECLARE_TYPEINFO(QRhiGles2::DeferredReleaseEntry, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index cf11f12ead..1c7b397193 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -1,46 +1,18 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qrhimetal_p_p.h"
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhimetal_p.h"
+#include "qshader_p.h"
#include <QGuiApplication>
#include <QWindow>
+#include <QUrl>
+#include <QFile>
+#include <QTemporaryFile>
+#include <QFileInfo>
#include <qmath.h>
+#include <QOperatingSystemVersion>
+
+#include <QtCore/private/qcore_mac_p.h>
#ifdef Q_OS_MACOS
#include <AppKit/AppKit.h>
@@ -68,19 +40,28 @@ QT_BEGIN_NAMESPACE
#error ARC not supported
#endif
-// Note: we expect everything here pass the Metal API validation when running
-// in Debug mode in XCode. Some of the issues that break validation are not
-// obvious and not visible when running outside XCode.
-//
-// An exception is the nextDrawable Called Early blah blah warning, which is
-// plain and simply false.
+// Even though the macOS 13 MTLBinaryArchive problem (QTBUG-106703) seems
+// to be solved in later 13.x releases, we have reports from old Intel hardware
+// and older macOS versions where this causes problems (QTBUG-114338).
+// Thus we no longer do OS version based differentiation, but rather have a
+// single toggle that is currently on, and so QRhi::(set)pipelineCache()
+// does nothing with Metal.
+#define QRHI_METAL_DISABLE_BINARY_ARCHIVE
+
+// We should be able to operate with command buffers that do not automatically
+// retain/release the resources used by them. (since we have logic that mirrors
+// other backends such as the Vulkan one anyway)
+#define QRHI_METAL_COMMAND_BUFFERS_WITH_UNRETAINED_REFERENCES
/*!
\class QRhiMetalInitParams
\inmodule QtRhi
- \internal
+ \since 6.6
\brief Metal specific initialization parameters.
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
A Metal-based QRhi needs no special parameters for initialization.
\badcode
@@ -88,10 +69,13 @@ QT_BEGIN_NAMESPACE
rhi = QRhi::create(QRhi::Metal, &params);
\endcode
- \note Metal API validation cannot be enabled by the application. Instead,
- run the debug build of the application in XCode. Generating a
- \c{.xcodeproj} file via \c{qmake -spec macx-xcode} provides a convenient
- way to enable this.
+ \note Metal API validation cannot be enabled programmatically by the QRhi.
+ Instead, either run the debug build of the application in XCode, by
+ generating a \c{.xcodeproj} file via \c{cmake -G Xcode}, or set the
+ environment variable \c{METAL_DEVICE_WRAPPER_TYPE=1}. The variable needs to
+ be set early on in the environment, perferably before starting the process;
+ attempting to set it at QRhi creation time is not functional in practice.
+ (too late probably)
\note QRhiSwapChain can only target QWindow instances that have their
surface type set to QSurface::MetalSurface.
@@ -110,14 +94,30 @@ QT_BEGIN_NAMESPACE
/*!
\class QRhiMetalNativeHandles
\inmodule QtRhi
- \internal
+ \since 6.6
\brief Holds the Metal device used by the QRhi.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
+ \variable QRhiMetalNativeHandles::dev
+
+ Set to a valid MTLDevice to import an existing device.
+*/
+
+/*!
+ \variable QRhiMetalNativeHandles::cmdQueue
+
+ Set to a valid MTLCommandQueue when importing an existing command queue.
+ When \nullptr, QRhi will create a new command queue.
+*/
+
+/*!
\class QRhiMetalCommandBufferNativeHandles
\inmodule QtRhi
- \internal
+ \since 6.6
\brief Holds the MTLCommandBuffer and MTLRenderCommandEncoder objects that are backing a QRhiCommandBuffer.
\note The command buffer object is only guaranteed to be valid while
@@ -129,14 +129,28 @@ QT_BEGIN_NAMESPACE
\note The command encoder is only valid while recording a pass, that is,
between \l{QRhiCommandBuffer::beginPass()} -
\l{QRhiCommandBuffer::endPass()}.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
+/*!
+ \variable QRhiMetalCommandBufferNativeHandles::commandBuffer
+*/
+
+/*!
+ \variable QRhiMetalCommandBufferNativeHandles::encoder
+*/
+
struct QMetalShader
{
id<MTLLibrary> lib = nil;
id<MTLFunction> func = nil;
- std::array<uint, 3> localSize;
+ std::array<uint, 3> localSize = {};
+ uint outputVertexCount = 0;
+ QShaderDescription desc;
QShader::NativeResourceBindingMap nativeResourceBindingMap;
+ QShader::NativeShaderInfo nativeShaderInfo;
void destroy() {
nativeResourceBindingMap.clear();
@@ -149,11 +163,14 @@ struct QMetalShader
struct QRhiMetalData
{
- QRhiMetalData(QRhiImplementation *rhi) : ofr(rhi) { }
+ QRhiMetalData(QRhiMetal *rhi) : q(rhi), ofr(rhi) { }
+ QRhiMetal *q;
id<MTLDevice> dev = nil;
id<MTLCommandQueue> cmdQueue = nil;
+ API_AVAILABLE(macosx(11.0), ios(14.0)) id<MTLBinaryArchive> binArch = nil;
+ id<MTLCommandBuffer> newCommandBuffer();
MTLRenderPassDescriptor *createDefaultRenderPass(bool hasDepthStencil,
const QColor &colorClearValue,
const QRhiDepthStencilClearValue &depthStencilClearValue,
@@ -161,6 +178,11 @@ struct QRhiMetalData
id<MTLLibrary> createMetalLib(const QShader &shader, QShader::Variant shaderVariant,
QString *error, QByteArray *entryPoint, QShaderKey *activeKey);
id<MTLFunction> createMSLShaderFunction(id<MTLLibrary> lib, const QByteArray &entryPoint);
+ bool setupBinaryArchive(NSURL *sourceFileUrl = nil);
+ void addRenderPipelineToBinaryArchive(MTLRenderPipelineDescriptor *rpDesc);
+ void trySeedingRenderPipelineFromBinaryArchive(MTLRenderPipelineDescriptor *rpDesc);
+ void addComputePipelineToBinaryArchive(MTLComputePipelineDescriptor *cpDesc);
+ void trySeedingComputePipelineFromBinaryArchive(MTLComputePipelineDescriptor *cpDesc);
struct DeferredReleaseEntry {
enum Type {
@@ -168,7 +190,9 @@ struct QRhiMetalData
RenderBuffer,
Texture,
Sampler,
- StagingBuffer
+ StagingBuffer,
+ GraphicsPipeline,
+ ComputePipeline
};
Type type;
int lastActiveFrameSlot; // -1 if not used otherwise 0..FRAMES_IN_FLIGHT-1
@@ -190,6 +214,15 @@ struct QRhiMetalData
struct {
id<MTLBuffer> buffer;
} stagingBuffer;
+ struct {
+ id<MTLRenderPipelineState> pipelineState;
+ id<MTLDepthStencilState> depthStencilState;
+ std::array<id<MTLComputePipelineState>, 3> tessVertexComputeState;
+ id<MTLComputePipelineState> tessTessControlComputeState;
+ } graphicsPipeline;
+ struct {
+ id<MTLComputePipelineState> pipelineState;
+ } computePipeline;
};
};
QVector<DeferredReleaseEntry> releaseQueue;
@@ -197,6 +230,7 @@ struct QRhiMetalData
struct OffscreenFrame {
OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
bool active = false;
+ double lastGpuTime = 0;
QMetalCommandBuffer cbWrapper;
} ofr;
@@ -211,6 +245,17 @@ struct QRhiMetalData
};
QVarLengthArray<TextureReadback, 2> activeTextureReadbacks;
+ struct BufferReadback
+ {
+ int activeFrameSlot = -1;
+ QRhiReadbackResult *result;
+ quint32 offset;
+ quint32 readSize;
+ id<MTLBuffer> buf;
+ };
+
+ QVarLengthArray<BufferReadback, 2> activeBufferReadbacks;
+
MTLCaptureManager *captureMgr;
id<MTLCaptureScope> captureScope = nil;
@@ -228,7 +273,7 @@ struct QMetalBufferData
bool slotted;
id<MTLBuffer> buf[QMTL_FRAMES_IN_FLIGHT];
struct BufferUpdate {
- int offset;
+ quint32 offset;
QRhiBufferData data;
};
QVarLengthArray<BufferUpdate, 16> pendingUpdates[QMTL_FRAMES_IN_FLIGHT];
@@ -259,15 +304,45 @@ struct QMetalSamplerData
id<MTLSamplerState> samplerState = nil;
};
+struct QMetalShaderResourceBindingsData {
+ struct Stage {
+ struct Buffer {
+ int nativeBinding;
+ id<MTLBuffer> mtlbuf;
+ quint32 offset;
+ };
+ struct Texture {
+ int nativeBinding;
+ id<MTLTexture> mtltex;
+ };
+ struct Sampler {
+ int nativeBinding;
+ id<MTLSamplerState> mtlsampler;
+ };
+ QVarLengthArray<Buffer, 8> buffers;
+ QVarLengthArray<Texture, 8> textures;
+ QVarLengthArray<Sampler, 8> samplers;
+ QRhiBatchedBindings<id<MTLBuffer> > bufferBatches;
+ QRhiBatchedBindings<NSUInteger> bufferOffsetBatches;
+ QRhiBatchedBindings<id<MTLTexture> > textureBatches;
+ QRhiBatchedBindings<id<MTLSamplerState> > samplerBatches;
+ } res[QRhiMetal::SUPPORTED_STAGES];
+ enum { VERTEX = 0, FRAGMENT = 1, COMPUTE = 2, TESSCTRL = 3, TESSEVAL = 4 };
+};
+
struct QMetalCommandBufferData
{
id<MTLCommandBuffer> cb;
+ double lastGpuTime = 0;
id<MTLRenderCommandEncoder> currentRenderPassEncoder;
id<MTLComputeCommandEncoder> currentComputePassEncoder;
+ id<MTLComputeCommandEncoder> tessellationComputeEncoder;
MTLRenderPassDescriptor *currentPassRpDesc;
int currentFirstVertexBinding;
QRhiBatchedBindings<id<MTLBuffer> > currentVertexInputsBuffers;
QRhiBatchedBindings<NSUInteger> currentVertexInputOffsets;
+ id<MTLDepthStencilState> currentDepthStencilState;
+ QMetalShaderResourceBindingsData currentShaderResourceBindingState;
};
struct QMetalRenderTargetData
@@ -293,22 +368,77 @@ struct QMetalRenderTargetData
struct {
ColorAtt colorAtt[QMetalRenderPassDescriptor::MAX_COLOR_ATTACHMENTS];
id<MTLTexture> dsTex = nil;
+ id<MTLTexture> dsResolveTex = nil;
bool hasStencil = false;
bool depthNeedsStore = false;
+ bool preserveColor = false;
+ bool preserveDs = false;
} fb;
+
+ QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList;
};
struct QMetalGraphicsPipelineData
{
+ QMetalGraphicsPipeline *q = nullptr;
id<MTLRenderPipelineState> ps = nil;
id<MTLDepthStencilState> ds = nil;
MTLPrimitiveType primitiveType;
MTLWinding winding;
MTLCullMode cullMode;
+ MTLTriangleFillMode triangleFillMode;
float depthBias;
float slopeScaledDepthBias;
QMetalShader vs;
QMetalShader fs;
+ struct ExtraBufferManager {
+ enum class WorkBufType {
+ DeviceLocal,
+ HostVisible
+ };
+ QMetalBuffer *acquireWorkBuffer(QRhiMetal *rhiD, quint32 size, WorkBufType type = WorkBufType::DeviceLocal);
+ QVector<QMetalBuffer *> deviceLocalWorkBuffers;
+ QVector<QMetalBuffer *> hostVisibleWorkBuffers;
+ } extraBufMgr;
+ struct Tessellation {
+ QMetalGraphicsPipelineData *q = nullptr;
+ bool enabled = false;
+ bool failed = false;
+ uint inControlPointCount;
+ uint outControlPointCount;
+ QMetalShader compVs[3];
+ std::array<id<MTLComputePipelineState>, 3> vertexComputeState = {};
+ id<MTLComputePipelineState> tessControlComputeState = nil;
+ QMetalShader compTesc;
+ QMetalShader vertTese;
+ quint32 vsCompOutputBufferSize(quint32 vertexOrIndexCount, quint32 instanceCount) const
+ {
+ // max vertex output components = resourceLimit(MaxVertexOutputs) * 4 = 60
+ return vertexOrIndexCount * instanceCount * sizeof(float) * 60;
+ }
+ quint32 tescCompOutputBufferSize(quint32 patchCount) const
+ {
+ return outControlPointCount * patchCount * sizeof(float) * 60;
+ }
+ quint32 tescCompPatchOutputBufferSize(quint32 patchCount) const
+ {
+ // assume maxTessellationControlPerPatchOutputComponents is 128
+ return patchCount * sizeof(float) * 128;
+ }
+ quint32 patchCountForDrawCall(quint32 vertexOrIndexCount, quint32 instanceCount) const
+ {
+ return ((vertexOrIndexCount + inControlPointCount - 1) / inControlPointCount) * instanceCount;
+ }
+ static int vsCompVariantToIndex(QShader::Variant vertexCompVariant);
+ id<MTLComputePipelineState> vsCompPipeline(QRhiMetal *rhiD, QShader::Variant vertexCompVariant);
+ id<MTLComputePipelineState> tescCompPipeline(QRhiMetal *rhiD);
+ id<MTLRenderPipelineState> teseFragRenderPipeline(QRhiMetal *rhiD, QMetalGraphicsPipeline *pipeline);
+ } tess;
+ void setupVertexInputDescriptor(MTLVertexDescriptor *desc);
+ void setupStageInputDescriptor(MTLStageInputOutputDescriptor *desc);
+
+ // SPIRV-Cross buffer size buffers
+ QMetalBuffer *bufferSizeBuffer = nullptr;
};
struct QMetalComputePipelineData
@@ -316,6 +446,9 @@ struct QMetalComputePipelineData
id<MTLComputePipelineState> ps = nil;
QMetalShader cs;
MTLSize localSize;
+
+ // SPIRV-Cross buffer size buffers
+ QMetalBuffer *bufferSizeBuffer = nullptr;
};
struct QMetalSwapChainData
@@ -323,10 +456,16 @@ struct QMetalSwapChainData
CAMetalLayer *layer = nullptr;
id<CAMetalDrawable> curDrawable = nil;
dispatch_semaphore_t sem[QMTL_FRAMES_IN_FLIGHT];
+ double lastGpuTime[QMTL_FRAMES_IN_FLIGHT];
MTLRenderPassDescriptor *rp = nullptr;
id<MTLTexture> msaaTex[QMTL_FRAMES_IN_FLIGHT];
QRhiTexture::Format rhiColorFormat;
MTLPixelFormat colorFormat;
+#ifdef Q_OS_MACOS
+ bool liveResizeObserverSet = false;
+ QMacNotificationObserver liveResizeStartObserver;
+ QMacNotificationObserver liveResizeEndObserver;
+#endif
};
QRhiMetal::QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice)
@@ -337,7 +476,7 @@ QRhiMetal::QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *import
importedDevice = importDevice != nullptr;
if (importedDevice) {
- if (d->dev) {
+ if (importDevice->dev) {
d->dev = (id<MTLDevice>) importDevice->dev;
importedCmdQueue = importDevice->cmdQueue != nullptr;
if (importedCmdQueue)
@@ -360,9 +499,55 @@ inline Int aligned(Int v, Int byteAlign)
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
+bool QRhiMetal::probe(QRhiMetalInitParams *params)
+{
+ Q_UNUSED(params);
+ id<MTLDevice> dev = MTLCreateSystemDefaultDevice();
+ if (dev) {
+ [dev release];
+ return true;
+ }
+ return false;
+}
+
+id<MTLCommandBuffer> QRhiMetalData::newCommandBuffer()
+{
+#ifdef QRHI_METAL_COMMAND_BUFFERS_WITH_UNRETAINED_REFERENCES
+ // Do not let the command buffer mess with the refcount of objects. We do
+ // have a proper render loop and will manage lifetimes similarly to other
+ // backends (Vulkan).
+ return [cmdQueue commandBufferWithUnretainedReferences];
+#else
+ return [cmdQueue commandBuffer];
+#endif
+}
+
+bool QRhiMetalData::setupBinaryArchive(NSURL *sourceFileUrl)
+{
+#ifdef QRHI_METAL_DISABLE_BINARY_ARCHIVE
+ return false;
+#endif
+
+ if (@available(macOS 11.0, iOS 14.0, *)) {
+ [binArch release];
+ MTLBinaryArchiveDescriptor *binArchDesc = [MTLBinaryArchiveDescriptor new];
+ binArchDesc.url = sourceFileUrl;
+ NSError *err = nil;
+ binArch = [dev newBinaryArchiveWithDescriptor: binArchDesc error: &err];
+ [binArchDesc release];
+ if (!binArch) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ qWarning("newBinaryArchiveWithDescriptor failed: %s", qPrintable(msg));
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
+
bool QRhiMetal::create(QRhi::Flags flags)
{
- Q_UNUSED(flags);
+ rhiFlags = flags;
if (importedDevice)
[d->dev retain];
@@ -377,10 +562,12 @@ bool QRhiMetal::create(QRhi::Flags flags)
const QString deviceName = QString::fromNSString([d->dev name]);
qCDebug(QRHI_LOG_INFO, "Metal device: %s", qPrintable(deviceName));
driverInfoStruct.deviceName = deviceName.toUtf8();
- driverInfoStruct.deviceId = [d->dev registryID];
-#ifdef Q_OS_IOS
- driverInfoStruct.deviceType = QRhiDriverInfo::IntegratedDevice;
-#else
+
+ // deviceId and vendorId stay unset for now. Note that registryID is not
+ // suitable as deviceId because it does not seem stable on macOS and can
+ // apparently change when the system is rebooted.
+
+#ifdef Q_OS_MACOS
if (@available(macOS 10.15, *)) {
const MTLDeviceLocation deviceLocation = [d->dev location];
switch (deviceLocation) {
@@ -397,8 +584,14 @@ bool QRhiMetal::create(QRhi::Flags flags)
break;
}
}
+#else
+ driverInfoStruct.deviceType = QRhiDriverInfo::IntegratedDevice;
#endif
+ const QOperatingSystemVersion ver = QOperatingSystemVersion::current();
+ osMajor = ver.majorVersion();
+ osMinor = ver.minorVersion();
+
if (importedCmdQueue)
[d->cmdQueue retain];
else
@@ -414,11 +607,18 @@ bool QRhiMetal::create(QRhi::Flags flags)
#if defined(Q_OS_MACOS)
caps.maxTextureSize = 16384;
+ caps.baseVertexAndInstance = true;
+ if (@available(macOS 10.15, *))
+ caps.isAppleGPU = [d->dev supportsFamily:MTLGPUFamilyApple7];
+ caps.maxThreadGroupSize = 1024;
+ caps.multiView = true;
#elif defined(Q_OS_TVOS)
if ([d->dev supportsFeatureSet: MTLFeatureSet(30003)]) // MTLFeatureSet_tvOS_GPUFamily2_v1
caps.maxTextureSize = 16384;
else
caps.maxTextureSize = 8192;
+ caps.baseVertexAndInstance = false;
+ caps.isAppleGPU = true;
#elif defined(Q_OS_IOS)
// welcome to feature set hell
if ([d->dev supportsFeatureSet: MTLFeatureSet(16)] // MTLFeatureSet_iOS_GPUFamily5_v1
@@ -426,15 +626,34 @@ bool QRhiMetal::create(QRhi::Flags flags)
|| [d->dev supportsFeatureSet: MTLFeatureSet(4)]) // MTLFeatureSet_iOS_GPUFamily3_v1
{
caps.maxTextureSize = 16384;
+ caps.baseVertexAndInstance = true;
} else if ([d->dev supportsFeatureSet: MTLFeatureSet(3)] // MTLFeatureSet_iOS_GPUFamily2_v2
|| [d->dev supportsFeatureSet: MTLFeatureSet(2)]) // MTLFeatureSet_iOS_GPUFamily1_v2
{
caps.maxTextureSize = 8192;
+ caps.baseVertexAndInstance = false;
} else {
caps.maxTextureSize = 4096;
+ caps.baseVertexAndInstance = false;
+ }
+ caps.isAppleGPU = true;
+ if (@available(iOS 13, *)) {
+ if ([d->dev supportsFamily: MTLGPUFamilyApple4])
+ caps.maxThreadGroupSize = 1024;
+ if ([d->dev supportsFamily: MTLGPUFamilyApple5])
+ caps.multiView = true;
}
#endif
+ caps.supportedSampleCounts = { 1 };
+ for (int sampleCount : { 2, 4, 8 }) {
+ if ([d->dev supportsTextureSampleCount: sampleCount])
+ caps.supportedSampleCounts.append(sampleCount);
+ }
+
+ if (rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
+ d->setupBinaryArchive();
+
nativeHandlesStruct.dev = (MTLDevice *) d->dev;
nativeHandlesStruct.cmdQueue = (MTLCommandQueue *) d->cmdQueue;
@@ -453,6 +672,11 @@ void QRhiMetal::destroy()
[d->captureScope release];
d->captureScope = nil;
+ if (@available(macOS 11.0, iOS 14.0, *)) {
+ [d->binArch release];
+ d->binArch = nil;
+ }
+
[d->cmdQueue release];
if (!importedCmdQueue)
d->cmdQueue = nil;
@@ -464,18 +688,7 @@ void QRhiMetal::destroy()
QVector<int> QRhiMetal::supportedSampleCounts() const
{
- return { 1, 2, 4, 8 };
-}
-
-int QRhiMetal::effectiveSampleCount(int sampleCount) const
-{
- // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
- const int s = qBound(1, sampleCount, 64);
- if (!supportedSampleCounts().contains(s)) {
- qWarning("Attempted to set unsupported sample count %d", sampleCount);
- return 1;
- }
- return s;
+ return caps.supportedSampleCounts;
}
QRhiSwapChain *QRhiMetal::createSwapChain()
@@ -483,7 +696,7 @@ QRhiSwapChain *QRhiMetal::createSwapChain()
return new QMetalSwapChain(this);
}
-QRhiBuffer *QRhiMetal::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+QRhiBuffer *QRhiMetal::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
{
return new QMetalBuffer(this, type, usage, size);
}
@@ -526,16 +739,32 @@ bool QRhiMetal::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture
{
Q_UNUSED(flags);
+ bool supportsFamilyMac2 = false; // needed for BC* formats
+ bool supportsFamilyApple3 = false;
+
#ifdef Q_OS_MACOS
- if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
- return false;
- if (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12)
- return false;
+ supportsFamilyMac2 = true;
+ if (caps.isAppleGPU)
+ supportsFamilyApple3 = true;
#else
- if (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
- return false;
+ supportsFamilyApple3 = true;
#endif
+ // BC5 is not available for any Apple hardare
+ if (format == QRhiTexture::BC5)
+ return false;
+
+ if (!supportsFamilyApple3) {
+ if (format >= QRhiTexture::ETC2_RGB8 && format <= QRhiTexture::ETC2_RGBA8)
+ return false;
+ if (format >= QRhiTexture::ASTC_4x4 && format <= QRhiTexture::ASTC_12x12)
+ return false;
+ }
+
+ if (!supportsFamilyMac2)
+ if (format >= QRhiTexture::BC1 && format <= QRhiTexture::BC7)
+ return false;
+
return true;
}
@@ -549,7 +778,7 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const
case QRhi::DebugMarkers:
return true;
case QRhi::Timestamps:
- return false;
+ return true;
case QRhi::Instancing:
return true;
case QRhi::CustomInstanceStepRate:
@@ -573,9 +802,9 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const
case QRhi::VertexShaderPointSize:
return true;
case QRhi::BaseVertex:
- return true;
+ return caps.baseVertexAndInstance;
case QRhi::BaseInstance:
- return true;
+ return caps.baseVertexAndInstance;
case QRhi::TriangleFanTopology:
return false;
case QRhi::ReadBackNonUniformBuffer:
@@ -593,7 +822,12 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const
case QRhi::ReadBackAnyTextureFormat:
return true;
case QRhi::PipelineCacheDataLoadSave:
- return false;
+ {
+ if (@available(macOS 11.0, iOS 14.0, *))
+ return true;
+ else
+ return false;
+ }
case QRhi::ImageDataStride:
return true;
case QRhi::RenderBufferImport:
@@ -602,6 +836,32 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::RenderTo3DTextureSlice:
return true;
+ case QRhi::TextureArrays:
+ return true;
+ case QRhi::Tessellation:
+ return true;
+ case QRhi::GeometryShader:
+ return false;
+ case QRhi::TextureArrayRange:
+ return false;
+ case QRhi::NonFillPolygonMode:
+ return true;
+ case QRhi::OneDimensionalTextures:
+ return true;
+ case QRhi::OneDimensionalTextureMipmaps:
+ return false;
+ case QRhi::HalfAttributes:
+ return true;
+ case QRhi::RenderToOneDimensionalTexture:
+ return false;
+ case QRhi::ThreeDimensionalTextureMipmaps:
+ return true;
+ case QRhi::MultiView:
+ return caps.multiView;
+ case QRhi::TextureViewFormat:
+ return false;
+ case QRhi::ResolveDepthStencil:
+ return true;
default:
Q_UNREACHABLE();
return false;
@@ -630,11 +890,15 @@ int QRhiMetal::resourceLimit(QRhi::ResourceLimit limit) const
case QRhi::MaxThreadGroupY:
Q_FALLTHROUGH();
case QRhi::MaxThreadGroupZ:
-#if defined(Q_OS_MACOS)
- return 1024;
-#else
- return 512;
-#endif
+ return caps.maxThreadGroupSize;
+ case QRhi::TextureArraySizeMax:
+ return 2048;
+ case QRhi::MaxUniformBufferRange:
+ return 65536;
+ case QRhi::MaxVertexInputs:
+ return 31;
+ case QRhi::MaxVertexOutputs:
+ return 15; // use the minimum from MTLGPUFamily1/2/3
default:
Q_UNREACHABLE();
return 0;
@@ -651,9 +915,11 @@ QRhiDriverInfo QRhiMetal::driverInfo() const
return driverInfoStruct;
}
-void QRhiMetal::sendVMemStatsToProfiler()
+QRhiStats QRhiMetal::statistics()
{
- // nothing to do here
+ QRhiStats result;
+ result.totalPipelineCreationTime = totalPipelineCreationTime();
+ return result;
}
bool QRhiMetal::makeThreadLocalNativeContextCurrent()
@@ -675,14 +941,133 @@ bool QRhiMetal::isDeviceLost() const
return false;
}
+struct QMetalPipelineCacheDataHeader
+{
+ quint32 rhiId;
+ quint32 arch;
+ quint32 dataSize;
+ quint32 osMajor;
+ quint32 osMinor;
+ char driver[236];
+};
+
QByteArray QRhiMetal::pipelineCacheData()
{
- return QByteArray();
+ Q_STATIC_ASSERT(sizeof(QMetalPipelineCacheDataHeader) == 256);
+ QByteArray data;
+ if (@available(macOS 11.0, iOS 14.0, *)) {
+ if (!d->binArch || !rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
+ return data;
+
+ QTemporaryFile tmp;
+ if (!tmp.open()) {
+ qCDebug(QRHI_LOG_INFO, "pipelineCacheData: Failed to create temporary file for Metal");
+ return data;
+ }
+ tmp.close(); // the file exists until the tmp dtor runs
+
+ const QString fn = QFileInfo(tmp.fileName()).absoluteFilePath();
+ NSURL *url = QUrl::fromLocalFile(fn).toNSURL();
+ NSError *err = nil;
+ if (![d->binArch serializeToURL: url error: &err]) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ // Some of these "errors" are not actual errors. (think of "Nothing to serialize")
+ qCDebug(QRHI_LOG_INFO, "Failed to serialize MTLBinaryArchive: %s", qPrintable(msg));
+ return data;
+ }
+
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qCDebug(QRHI_LOG_INFO, "pipelineCacheData: Failed to reopen temporary file");
+ return data;
+ }
+ const QByteArray blob = f.readAll();
+ f.close();
+
+ const size_t headerSize = sizeof(QMetalPipelineCacheDataHeader);
+ const quint32 dataSize = quint32(blob.size());
+
+ data.resize(headerSize + dataSize);
+
+ QMetalPipelineCacheDataHeader header = {};
+ header.rhiId = pipelineCacheRhiId();
+ header.arch = quint32(sizeof(void*));
+ header.dataSize = quint32(dataSize);
+ header.osMajor = osMajor;
+ header.osMinor = osMinor;
+ const size_t driverStrLen = qMin(sizeof(header.driver) - 1, size_t(driverInfoStruct.deviceName.length()));
+ if (driverStrLen)
+ memcpy(header.driver, driverInfoStruct.deviceName.constData(), driverStrLen);
+ header.driver[driverStrLen] = '\0';
+
+ memcpy(data.data(), &header, headerSize);
+ memcpy(data.data() + headerSize, blob.constData(), dataSize);
+ }
+ return data;
}
void QRhiMetal::setPipelineCacheData(const QByteArray &data)
{
- Q_UNUSED(data);
+ if (data.isEmpty())
+ return;
+
+ const size_t headerSize = sizeof(QMetalPipelineCacheDataHeader);
+ if (data.size() < qsizetype(headerSize)) {
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Invalid blob size (header incomplete)");
+ return;
+ }
+
+ const size_t dataOffset = headerSize;
+ QMetalPipelineCacheDataHeader header;
+ memcpy(&header, data.constData(), headerSize);
+
+ const quint32 rhiId = pipelineCacheRhiId();
+ if (header.rhiId != rhiId) {
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
+ rhiId, header.rhiId);
+ return;
+ }
+
+ const quint32 arch = quint32(sizeof(void*));
+ if (header.arch != arch) {
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Architecture does not match (%u, %u)",
+ arch, header.arch);
+ return;
+ }
+
+ if (header.osMajor != osMajor || header.osMinor != osMinor) {
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: OS version does not match (%u.%u, %u.%u)",
+ osMajor, osMinor, header.osMajor, header.osMinor);
+ return;
+ }
+
+ const size_t driverStrLen = qMin(sizeof(header.driver) - 1, size_t(driverInfoStruct.deviceName.length()));
+ if (strncmp(header.driver, driverInfoStruct.deviceName.constData(), driverStrLen)) {
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Metal device name does not match");
+ return;
+ }
+
+ if (data.size() < qsizetype(dataOffset + header.dataSize)) {
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Invalid blob size (data incomplete)");
+ return;
+ }
+
+ if (@available(macOS 11.0, iOS 14.0, *)) {
+ const char *p = data.constData() + dataOffset;
+
+ QTemporaryFile tmp;
+ if (!tmp.open()) {
+ qCDebug(QRHI_LOG_INFO, "pipelineCacheData: Failed to create temporary file for Metal");
+ return;
+ }
+ tmp.write(p, header.dataSize);
+ tmp.close(); // the file exists until the tmp dtor runs
+
+ const QString fn = QFileInfo(tmp.fileName()).absoluteFilePath();
+ NSURL *url = QUrl::fromLocalFile(fn).toNSURL();
+ if (d->setupBinaryArchive(url))
+ qCDebug(QRHI_LOG_INFO, "Created MTLBinaryArchive with initial data of %u bytes", header.dataSize);
+ }
}
QRhiRenderBuffer *QRhiMetal::createRenderBuffer(QRhiRenderBuffer::Type type, const QSize &pixelSize,
@@ -693,10 +1078,10 @@ QRhiRenderBuffer *QRhiMetal::createRenderBuffer(QRhiRenderBuffer::Type type, con
}
QRhiTexture *QRhiMetal::createTexture(QRhiTexture::Format format,
- const QSize &pixelSize, int depth,
+ const QSize &pixelSize, int depth, int arraySize,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QMetalTexture(this, format, pixelSize, depth, sampleCount, flags);
+ return new QMetalTexture(this, format, pixelSize, depth, arraySize, sampleCount, flags);
}
QRhiSampler *QRhiMetal::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -752,6 +1137,136 @@ static inline int mapBinding(int binding,
return -1;
}
+static inline void bindStageBuffers(QMetalCommandBuffer *cbD,
+ int stage,
+ const QRhiBatchedBindings<id<MTLBuffer>>::Batch &bufferBatch,
+ const QRhiBatchedBindings<NSUInteger>::Batch &offsetBatch)
+{
+ switch (stage) {
+ case QMetalShaderResourceBindingsData::VERTEX:
+ [cbD->d->currentRenderPassEncoder setVertexBuffers: bufferBatch.resources.constData()
+ offsets: offsetBatch.resources.constData()
+ withRange: NSMakeRange(bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
+ break;
+ case QMetalShaderResourceBindingsData::FRAGMENT:
+ [cbD->d->currentRenderPassEncoder setFragmentBuffers: bufferBatch.resources.constData()
+ offsets: offsetBatch.resources.constData()
+ withRange: NSMakeRange(bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
+ break;
+ case QMetalShaderResourceBindingsData::COMPUTE:
+ [cbD->d->currentComputePassEncoder setBuffers: bufferBatch.resources.constData()
+ offsets: offsetBatch.resources.constData()
+ withRange: NSMakeRange(bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
+ break;
+ case QMetalShaderResourceBindingsData::TESSCTRL:
+ case QMetalShaderResourceBindingsData::TESSEVAL:
+ // do nothing. These are used later for tessellation
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+}
+
+static inline void bindStageTextures(QMetalCommandBuffer *cbD,
+ int stage,
+ const QRhiBatchedBindings<id<MTLTexture>>::Batch &textureBatch)
+{
+ switch (stage) {
+ case QMetalShaderResourceBindingsData::VERTEX:
+ [cbD->d->currentRenderPassEncoder setVertexTextures: textureBatch.resources.constData()
+ withRange: NSMakeRange(textureBatch.startBinding, NSUInteger(textureBatch.resources.count()))];
+ break;
+ case QMetalShaderResourceBindingsData::FRAGMENT:
+ [cbD->d->currentRenderPassEncoder setFragmentTextures: textureBatch.resources.constData()
+ withRange: NSMakeRange(textureBatch.startBinding, NSUInteger(textureBatch.resources.count()))];
+ break;
+ case QMetalShaderResourceBindingsData::COMPUTE:
+ [cbD->d->currentComputePassEncoder setTextures: textureBatch.resources.constData()
+ withRange: NSMakeRange(textureBatch.startBinding, NSUInteger(textureBatch.resources.count()))];
+ break;
+ case QMetalShaderResourceBindingsData::TESSCTRL:
+ case QMetalShaderResourceBindingsData::TESSEVAL:
+ // do nothing. These are used later for tessellation
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+}
+
+static inline void bindStageSamplers(QMetalCommandBuffer *cbD,
+ int encoderStage,
+ const QRhiBatchedBindings<id<MTLSamplerState>>::Batch &samplerBatch)
+{
+ switch (encoderStage) {
+ case QMetalShaderResourceBindingsData::VERTEX:
+ [cbD->d->currentRenderPassEncoder setVertexSamplerStates: samplerBatch.resources.constData()
+ withRange: NSMakeRange(samplerBatch.startBinding, NSUInteger(samplerBatch.resources.count()))];
+ break;
+ case QMetalShaderResourceBindingsData::FRAGMENT:
+ [cbD->d->currentRenderPassEncoder setFragmentSamplerStates: samplerBatch.resources.constData()
+ withRange: NSMakeRange(samplerBatch.startBinding, NSUInteger(samplerBatch.resources.count()))];
+ break;
+ case QMetalShaderResourceBindingsData::COMPUTE:
+ [cbD->d->currentComputePassEncoder setSamplerStates: samplerBatch.resources.constData()
+ withRange: NSMakeRange(samplerBatch.startBinding, NSUInteger(samplerBatch.resources.count()))];
+ break;
+ case QMetalShaderResourceBindingsData::TESSCTRL:
+ case QMetalShaderResourceBindingsData::TESSEVAL:
+ // do nothing. These are used later for tessellation
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+}
+
+// Helper that is not used during the common vertex+fragment and compute
+// pipelines, but is necessary when tessellation is involved and so the
+// graphics pipeline is under the hood a combination of multiple compute and
+// render pipelines. We need to be able to set the buffers, textures, samplers
+// when a switching between render and compute encoders.
+static inline void rebindShaderResources(QMetalCommandBuffer *cbD, int resourceStage, int encoderStage,
+ const QMetalShaderResourceBindingsData *customBindingState = nullptr)
+{
+ const QMetalShaderResourceBindingsData *bindingData = customBindingState ? customBindingState : &cbD->d->currentShaderResourceBindingState;
+
+ for (int i = 0, ie = bindingData->res[resourceStage].bufferBatches.batches.count(); i != ie; ++i) {
+ const auto &bufferBatch(bindingData->res[resourceStage].bufferBatches.batches[i]);
+ const auto &offsetBatch(bindingData->res[resourceStage].bufferOffsetBatches.batches[i]);
+ bindStageBuffers(cbD, encoderStage, bufferBatch, offsetBatch);
+ }
+
+ for (int i = 0, ie = bindingData->res[resourceStage].textureBatches.batches.count(); i != ie; ++i) {
+ const auto &batch(bindingData->res[resourceStage].textureBatches.batches[i]);
+ bindStageTextures(cbD, encoderStage, batch);
+ }
+
+ for (int i = 0, ie = bindingData->res[resourceStage].samplerBatches.batches.count(); i != ie; ++i) {
+ const auto &batch(bindingData->res[resourceStage].samplerBatches.batches[i]);
+ bindStageSamplers(cbD, encoderStage, batch);
+ }
+}
+
+static inline QRhiShaderResourceBinding::StageFlag toRhiSrbStage(int stage)
+{
+ switch (stage) {
+ case QMetalShaderResourceBindingsData::VERTEX:
+ return QRhiShaderResourceBinding::StageFlag::VertexStage;
+ case QMetalShaderResourceBindingsData::TESSCTRL:
+ return QRhiShaderResourceBinding::StageFlag::TessellationControlStage;
+ case QMetalShaderResourceBindingsData::TESSEVAL:
+ return QRhiShaderResourceBinding::StageFlag::TessellationEvaluationStage;
+ case QMetalShaderResourceBindingsData::FRAGMENT:
+ return QRhiShaderResourceBinding::StageFlag::FragmentStage;
+ case QMetalShaderResourceBindingsData::COMPUTE:
+ return QRhiShaderResourceBinding::StageFlag::ComputeStage;
+ }
+
+ Q_UNREACHABLE_RETURN(QRhiShaderResourceBinding::StageFlag::VertexStage);
+}
+
void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD,
QMetalCommandBuffer *cbD,
int dynamicOffsetCount,
@@ -759,38 +1274,16 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
bool offsetOnlyChange,
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES])
{
- struct Stage {
- struct Buffer {
- int nativeBinding;
- id<MTLBuffer> mtlbuf;
- uint offset;
- };
- struct Texture {
- int nativeBinding;
- id<MTLTexture> mtltex;
- };
- struct Sampler {
- int nativeBinding;
- id<MTLSamplerState> mtlsampler;
- };
- QVarLengthArray<Buffer, 8> buffers;
- QVarLengthArray<Texture, 8> textures;
- QVarLengthArray<Sampler, 8> samplers;
- QRhiBatchedBindings<id<MTLBuffer> > bufferBatches;
- QRhiBatchedBindings<NSUInteger> bufferOffsetBatches;
- QRhiBatchedBindings<id<MTLTexture> > textureBatches;
- QRhiBatchedBindings<id<MTLSamplerState> > samplerBatches;
- } res[SUPPORTED_STAGES];
- enum { VERTEX = 0, FRAGMENT = 1, COMPUTE = 2 };
+ QMetalShaderResourceBindingsData bindingData;
- for (const QRhiShaderResourceBinding &binding : qAsConst(srbD->sortedBindings)) {
- const QRhiShaderResourceBinding::Data *b = binding.data();
+ for (const QRhiShaderResourceBinding &binding : std::as_const(srbD->sortedBindings)) {
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(binding);
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, b->u.ubuf.buf);
id<MTLBuffer> mtlbuf = bufD->d->buf[bufD->d->slotted ? currentFrameSlot : 0];
- uint offset = uint(b->u.ubuf.offset);
+ quint32 offset = b->u.ubuf.offset;
for (int i = 0; i < dynamicOffsetCount; ++i) {
const QRhiCommandBuffer::DynamicOffset &dynOfs(dynamicOffsets[i]);
if (dynOfs.first == b->binding) {
@@ -798,51 +1291,38 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
break;
}
}
- if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0)
- res[VERTEX].buffers.append({ nativeBinding, mtlbuf, offset });
- }
- if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0)
- res[FRAGMENT].buffers.append({ nativeBinding, mtlbuf, offset });
- }
- if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0)
- res[COMPUTE].buffers.append({ nativeBinding, mtlbuf, offset });
+
+ for (int stage = 0; stage < SUPPORTED_STAGES; ++stage) {
+ if (b->stage.testFlag(toRhiSrbStage(stage))) {
+ const int nativeBinding = mapBinding(b->binding, stage, nativeResourceBindingMaps, BindingType::Buffer);
+ if (nativeBinding >= 0)
+ bindingData.res[stage].buffers.append({ nativeBinding, mtlbuf, offset });
+ }
}
}
break;
case QRhiShaderResourceBinding::SampledTexture:
+ case QRhiShaderResourceBinding::Texture:
+ case QRhiShaderResourceBinding::Sampler:
{
- const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
+ const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
for (int elem = 0; elem < data->count; ++elem) {
QMetalTexture *texD = QRHI_RES(QMetalTexture, b->u.stex.texSamplers[elem].tex);
QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b->u.stex.texSamplers[elem].sampler);
- if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- const int nativeBindingTexture = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture);
- const int nativeBindingSampler = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Sampler);
- if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[VERTEX].textures.append({ nativeBindingTexture + elem, texD->d->tex });
- res[VERTEX].samplers.append({ nativeBindingSampler + elem, samplerD->d->samplerState });
- }
- }
- if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- const int nativeBindingTexture = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture);
- const int nativeBindingSampler = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Sampler);
- if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[FRAGMENT].textures.append({ nativeBindingTexture + elem, texD->d->tex });
- res[FRAGMENT].samplers.append({ nativeBindingSampler + elem, samplerD->d->samplerState });
- }
- }
- if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- const int nativeBindingTexture = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture);
- const int nativeBindingSampler = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Sampler);
- if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[COMPUTE].textures.append({ nativeBindingTexture + elem, texD->d->tex });
- res[COMPUTE].samplers.append({ nativeBindingSampler + elem, samplerD->d->samplerState });
+
+ for (int stage = 0; stage < SUPPORTED_STAGES; ++stage) {
+ if (b->stage.testFlag(toRhiSrbStage(stage))) {
+ // Must handle all three cases (combined, separate, separate):
+ // first = texture binding, second = sampler binding
+ // first = texture binding
+ // first = sampler binding (i.e. BindingType::Texture...)
+ const int textureBinding = mapBinding(b->binding, stage, nativeResourceBindingMaps, BindingType::Texture);
+ const int samplerBinding = texD && samplerD ? mapBinding(b->binding, stage, nativeResourceBindingMaps, BindingType::Sampler)
+ : (samplerD ? mapBinding(b->binding, stage, nativeResourceBindingMaps, BindingType::Texture) : -1);
+ if (textureBinding >= 0 && texD)
+ bindingData.res[stage].textures.append({ textureBinding + elem, texD->d->tex });
+ if (samplerBinding >= 0)
+ bindingData.res[stage].samplers.append({ samplerBinding + elem, samplerD->d->samplerState });
}
}
}
@@ -854,20 +1334,13 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
{
QMetalTexture *texD = QRHI_RES(QMetalTexture, b->u.simage.tex);
id<MTLTexture> t = texD->d->viewForLevel(b->u.simage.level);
- if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture);
- if (nativeBinding >= 0)
- res[VERTEX].textures.append({ nativeBinding, t });
- }
- if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture);
- if (nativeBinding >= 0)
- res[FRAGMENT].textures.append({ nativeBinding, t });
- }
- if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture);
- if (nativeBinding >= 0)
- res[COMPUTE].textures.append({ nativeBinding, t });
+
+ for (int stage = 0; stage < SUPPORTED_STAGES; ++stage) {
+ if (b->stage.testFlag(toRhiSrbStage(stage))) {
+ const int nativeBinding = mapBinding(b->binding, stage, nativeResourceBindingMaps, BindingType::Texture);
+ if (nativeBinding >= 0)
+ bindingData.res[stage].textures.append({ nativeBinding, t });
+ }
}
}
break;
@@ -877,21 +1350,13 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
{
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, b->u.sbuf.buf);
id<MTLBuffer> mtlbuf = bufD->d->buf[0];
- uint offset = uint(b->u.sbuf.offset);
- if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
- const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0)
- res[VERTEX].buffers.append({ nativeBinding, mtlbuf, offset });
- }
- if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
- const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0)
- res[FRAGMENT].buffers.append({ nativeBinding, mtlbuf, offset });
- }
- if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
- const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0)
- res[COMPUTE].buffers.append({ nativeBinding, mtlbuf, offset });
+ quint32 offset = b->u.sbuf.offset;
+ for (int stage = 0; stage < SUPPORTED_STAGES; ++stage) {
+ if (b->stage.testFlag(toRhiSrbStage(stage))) {
+ const int nativeBinding = mapBinding(b->binding, stage, nativeResourceBindingMaps, BindingType::Buffer);
+ if (nativeBinding >= 0)
+ bindingData.res[stage].buffers.append({ nativeBinding, mtlbuf, offset });
+ }
}
}
break;
@@ -902,9 +1367,10 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
}
for (int stage = 0; stage < SUPPORTED_STAGES; ++stage) {
- if (cbD->recordingPass != QMetalCommandBuffer::RenderPass && (stage == VERTEX || stage == FRAGMENT))
+ if (cbD->recordingPass != QMetalCommandBuffer::RenderPass && (stage == QMetalShaderResourceBindingsData::VERTEX || stage == QMetalShaderResourceBindingsData::FRAGMENT
+ || stage == QMetalShaderResourceBindingsData::TESSCTRL || stage == QMetalShaderResourceBindingsData::TESSEVAL))
continue;
- if (cbD->recordingPass != QMetalCommandBuffer::ComputePass && stage == COMPUTE)
+ if (cbD->recordingPass != QMetalCommandBuffer::ComputePass && (stage == QMetalShaderResourceBindingsData::COMPUTE))
continue;
// QRhiBatchedBindings works with the native bindings and expects
@@ -912,104 +1378,107 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
// on the QRhi (SPIR-V) binding) is not helpful in this regard, so we
// have to sort here every time.
- std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](const Stage::Buffer &a, const Stage::Buffer &b) {
+ std::sort(bindingData.res[stage].buffers.begin(), bindingData.res[stage].buffers.end(), [](const QMetalShaderResourceBindingsData::Stage::Buffer &a, const QMetalShaderResourceBindingsData::Stage::Buffer &b) {
return a.nativeBinding < b.nativeBinding;
});
- for (const Stage::Buffer &buf : qAsConst(res[stage].buffers)) {
- res[stage].bufferBatches.feed(buf.nativeBinding, buf.mtlbuf);
- res[stage].bufferOffsetBatches.feed(buf.nativeBinding, buf.offset);
+ for (const QMetalShaderResourceBindingsData::Stage::Buffer &buf : std::as_const(bindingData.res[stage].buffers)) {
+ bindingData.res[stage].bufferBatches.feed(buf.nativeBinding, buf.mtlbuf);
+ bindingData.res[stage].bufferOffsetBatches.feed(buf.nativeBinding, buf.offset);
}
- res[stage].bufferBatches.finish();
- res[stage].bufferOffsetBatches.finish();
-
- for (int i = 0, ie = res[stage].bufferBatches.batches.count(); i != ie; ++i) {
- const auto &bufferBatch(res[stage].bufferBatches.batches[i]);
- const auto &offsetBatch(res[stage].bufferOffsetBatches.batches[i]);
- switch (stage) {
- case VERTEX:
- [cbD->d->currentRenderPassEncoder setVertexBuffers: bufferBatch.resources.constData()
- offsets: offsetBatch.resources.constData()
- withRange: NSMakeRange(bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
- break;
- case FRAGMENT:
- [cbD->d->currentRenderPassEncoder setFragmentBuffers: bufferBatch.resources.constData()
- offsets: offsetBatch.resources.constData()
- withRange: NSMakeRange(bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
- break;
- case COMPUTE:
- [cbD->d->currentComputePassEncoder setBuffers: bufferBatch.resources.constData()
- offsets: offsetBatch.resources.constData()
- withRange: NSMakeRange(bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
- break;
- default:
- Q_UNREACHABLE();
- break;
+ bindingData.res[stage].bufferBatches.finish();
+ bindingData.res[stage].bufferOffsetBatches.finish();
+
+ for (int i = 0, ie = bindingData.res[stage].bufferBatches.batches.count(); i != ie; ++i) {
+ const auto &bufferBatch(bindingData.res[stage].bufferBatches.batches[i]);
+ const auto &offsetBatch(bindingData.res[stage].bufferOffsetBatches.batches[i]);
+ // skip setting Buffer binding if the current state is already correct
+ if (cbD->d->currentShaderResourceBindingState.res[stage].bufferBatches.batches.count() > i
+ && cbD->d->currentShaderResourceBindingState.res[stage].bufferOffsetBatches.batches.count() > i
+ && bufferBatch == cbD->d->currentShaderResourceBindingState.res[stage].bufferBatches.batches[i]
+ && offsetBatch == cbD->d->currentShaderResourceBindingState.res[stage].bufferOffsetBatches.batches[i])
+ {
+ continue;
}
+ bindStageBuffers(cbD, stage, bufferBatch, offsetBatch);
}
if (offsetOnlyChange)
continue;
- std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](const Stage::Texture &a, const Stage::Texture &b) {
+ std::sort(bindingData.res[stage].textures.begin(), bindingData.res[stage].textures.end(), [](const QMetalShaderResourceBindingsData::Stage::Texture &a, const QMetalShaderResourceBindingsData::Stage::Texture &b) {
return a.nativeBinding < b.nativeBinding;
});
- std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](const Stage::Sampler &a, const Stage::Sampler &b) {
+ std::sort(bindingData.res[stage].samplers.begin(), bindingData.res[stage].samplers.end(), [](const QMetalShaderResourceBindingsData::Stage::Sampler &a, const QMetalShaderResourceBindingsData::Stage::Sampler &b) {
return a.nativeBinding < b.nativeBinding;
});
- for (const Stage::Texture &t : qAsConst(res[stage].textures))
- res[stage].textureBatches.feed(t.nativeBinding, t.mtltex);
+ for (const QMetalShaderResourceBindingsData::Stage::Texture &t : std::as_const(bindingData.res[stage].textures))
+ bindingData.res[stage].textureBatches.feed(t.nativeBinding, t.mtltex);
- for (const Stage::Sampler &s : qAsConst(res[stage].samplers))
- res[stage].samplerBatches.feed(s.nativeBinding, s.mtlsampler);
+ for (const QMetalShaderResourceBindingsData::Stage::Sampler &s : std::as_const(bindingData.res[stage].samplers))
+ bindingData.res[stage].samplerBatches.feed(s.nativeBinding, s.mtlsampler);
- res[stage].textureBatches.finish();
- res[stage].samplerBatches.finish();
+ bindingData.res[stage].textureBatches.finish();
+ bindingData.res[stage].samplerBatches.finish();
- for (int i = 0, ie = res[stage].textureBatches.batches.count(); i != ie; ++i) {
- const auto &batch(res[stage].textureBatches.batches[i]);
- switch (stage) {
- case VERTEX:
- [cbD->d->currentRenderPassEncoder setVertexTextures: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
- break;
- case FRAGMENT:
- [cbD->d->currentRenderPassEncoder setFragmentTextures: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
- break;
- case COMPUTE:
- [cbD->d->currentComputePassEncoder setTextures: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
- break;
- default:
- Q_UNREACHABLE();
- break;
+ for (int i = 0, ie = bindingData.res[stage].textureBatches.batches.count(); i != ie; ++i) {
+ const auto &batch(bindingData.res[stage].textureBatches.batches[i]);
+ // skip setting Texture binding if the current state is already correct
+ if (cbD->d->currentShaderResourceBindingState.res[stage].textureBatches.batches.count() > i
+ && batch == cbD->d->currentShaderResourceBindingState.res[stage].textureBatches.batches[i])
+ {
+ continue;
}
+ bindStageTextures(cbD, stage, batch);
}
- for (int i = 0, ie = res[stage].samplerBatches.batches.count(); i != ie; ++i) {
- const auto &batch(res[stage].samplerBatches.batches[i]);
- switch (stage) {
- case VERTEX:
- [cbD->d->currentRenderPassEncoder setVertexSamplerStates: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
- break;
- case FRAGMENT:
- [cbD->d->currentRenderPassEncoder setFragmentSamplerStates: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
- break;
- case COMPUTE:
- [cbD->d->currentComputePassEncoder setSamplerStates: batch.resources.constData()
- withRange: NSMakeRange(batch.startBinding, NSUInteger(batch.resources.count()))];
- break;
- default:
- Q_UNREACHABLE();
- break;
+
+ for (int i = 0, ie = bindingData.res[stage].samplerBatches.batches.count(); i != ie; ++i) {
+ const auto &batch(bindingData.res[stage].samplerBatches.batches[i]);
+ // skip setting Sampler State if the current state is already correct
+ if (cbD->d->currentShaderResourceBindingState.res[stage].samplerBatches.batches.count() > i
+ && batch == cbD->d->currentShaderResourceBindingState.res[stage].samplerBatches.batches[i])
+ {
+ continue;
}
+ bindStageSamplers(cbD, stage, batch);
}
}
+
+ cbD->d->currentShaderResourceBindingState = bindingData;
+}
+
+void QMetalGraphicsPipeline::makeActiveForCurrentRenderPassEncoder(QMetalCommandBuffer *cbD)
+{
+ [cbD->d->currentRenderPassEncoder setRenderPipelineState: d->ps];
+
+ if (cbD->d->currentDepthStencilState != d->ds) {
+ [cbD->d->currentRenderPassEncoder setDepthStencilState: d->ds];
+ cbD->d->currentDepthStencilState = d->ds;
+ }
+
+ if (cbD->currentCullMode == -1 || d->cullMode != uint(cbD->currentCullMode)) {
+ [cbD->d->currentRenderPassEncoder setCullMode: d->cullMode];
+ cbD->currentCullMode = int(d->cullMode);
+ }
+ if (cbD->currentTriangleFillMode == -1 || d->triangleFillMode != uint(cbD->currentTriangleFillMode)) {
+ [cbD->d->currentRenderPassEncoder setTriangleFillMode: d->triangleFillMode];
+ cbD->currentTriangleFillMode = int(d->triangleFillMode);
+ }
+ if (cbD->currentFrontFaceWinding == -1 || d->winding != uint(cbD->currentFrontFaceWinding)) {
+ [cbD->d->currentRenderPassEncoder setFrontFacingWinding: d->winding];
+ cbD->currentFrontFaceWinding = int(d->winding);
+ }
+ if (!qFuzzyCompare(d->depthBias, cbD->currentDepthBiasValues.first)
+ || !qFuzzyCompare(d->slopeScaledDepthBias, cbD->currentDepthBiasValues.second))
+ {
+ [cbD->d->currentRenderPassEncoder setDepthBias: d->depthBias
+ slopeScale: d->slopeScaledDepthBias
+ clamp: 0.0f];
+ cbD->currentDepthBiasValues = { d->depthBias, d->slopeScaledDepthBias };
+ }
}
void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline *ps)
@@ -1018,29 +1487,24 @@ void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::RenderPass);
QMetalGraphicsPipeline *psD = QRHI_RES(QMetalGraphicsPipeline, ps);
- if (cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
- cbD->currentGraphicsPipeline = ps;
- cbD->currentComputePipeline = nullptr;
- cbD->currentPipelineGeneration = psD->generation;
+ if (cbD->currentGraphicsPipeline == psD && cbD->currentPipelineGeneration == psD->generation)
+ return;
- [cbD->d->currentRenderPassEncoder setRenderPipelineState: psD->d->ps];
- [cbD->d->currentRenderPassEncoder setDepthStencilState: psD->d->ds];
+ cbD->currentGraphicsPipeline = psD;
+ cbD->currentComputePipeline = nullptr;
+ cbD->currentPipelineGeneration = psD->generation;
- if (cbD->currentCullMode == -1 || psD->d->cullMode != uint(cbD->currentCullMode)) {
- [cbD->d->currentRenderPassEncoder setCullMode: psD->d->cullMode];
- cbD->currentCullMode = int(psD->d->cullMode);
+ if (!psD->d->tess.enabled && !psD->d->tess.failed) {
+ psD->makeActiveForCurrentRenderPassEncoder(cbD);
+ } else {
+ // mark work buffers that can now be safely reused as reusable
+ for (QMetalBuffer *workBuf : psD->d->extraBufMgr.deviceLocalWorkBuffers) {
+ if (workBuf && workBuf->lastActiveFrameSlot == currentFrameSlot)
+ workBuf->lastActiveFrameSlot = -1;
}
- if (cbD->currentFrontFaceWinding == -1 || psD->d->winding != uint(cbD->currentFrontFaceWinding)) {
- [cbD->d->currentRenderPassEncoder setFrontFacingWinding: psD->d->winding];
- cbD->currentFrontFaceWinding = int(psD->d->winding);
- }
- if (!qFuzzyCompare(psD->d->depthBias, cbD->currentDepthBiasValues.first)
- || !qFuzzyCompare(psD->d->slopeScaledDepthBias, cbD->currentDepthBiasValues.second))
- {
- [cbD->d->currentRenderPassEncoder setDepthBias: psD->d->depthBias
- slopeScale: psD->d->slopeScaledDepthBias
- clamp: 0.0f];
- cbD->currentDepthBiasValues = { psD->d->depthBias, psD->d->slopeScaledDepthBias };
+ for (QMetalBuffer *workBuf : psD->d->extraBufMgr.hostVisibleWorkBuffers) {
+ if (workBuf && workBuf->lastActiveFrameSlot == currentFrameSlot)
+ workBuf->lastActiveFrameSlot = -1;
}
}
@@ -1053,8 +1517,8 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
{
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass != QMetalCommandBuffer::NoPass);
- QMetalGraphicsPipeline *gfxPsD = QRHI_RES(QMetalGraphicsPipeline, cbD->currentGraphicsPipeline);
- QMetalComputePipeline *compPsD = QRHI_RES(QMetalComputePipeline, cbD->currentComputePipeline);
+ QMetalGraphicsPipeline *gfxPsD = cbD->currentGraphicsPipeline;
+ QMetalComputePipeline *compPsD = cbD->currentComputePipeline;
if (!srb) {
if (gfxPsD)
@@ -1068,9 +1532,15 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
bool hasDynamicOffsetInSrb = false;
bool resNeedsRebind = false;
+ // SPIRV-Cross buffer size buffers
+ // Need to determine storage buffer sizes here as this is the last opportunity for storage
+ // buffer bindings (offset, size) to be specified before draw / dispatch call
+ const bool needsBufferSizeBuffer = (compPsD && compPsD->d->bufferSizeBuffer) || (gfxPsD && gfxPsD->d->bufferSizeBuffer);
+ QMap<QRhiShaderResourceBinding::StageFlag, QMap<int, quint32>> storageBufferSizes;
+
// do buffer writes, figure out if we need to rebind, and mark as in-use
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
- const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data();
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
QMetalShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
@@ -1091,8 +1561,10 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
}
break;
case QRhiShaderResourceBinding::SampledTexture:
+ case QRhiShaderResourceBinding::Texture:
+ case QRhiShaderResourceBinding::Sampler:
{
- const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
+ const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
if (bd.stex.count != data->count) {
bd.stex.count = data->count;
resNeedsRebind = true;
@@ -1100,19 +1572,26 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
for (int elem = 0; elem < data->count; ++elem) {
QMetalTexture *texD = QRHI_RES(QMetalTexture, data->texSamplers[elem].tex);
QMetalSampler *samplerD = QRHI_RES(QMetalSampler, data->texSamplers[elem].sampler);
- if (texD->generation != bd.stex.d[elem].texGeneration
- || texD->m_id != bd.stex.d[elem].texId
- || samplerD->generation != bd.stex.d[elem].samplerGeneration
- || samplerD->m_id != bd.stex.d[elem].samplerId)
+ Q_ASSERT(texD || samplerD);
+ const quint64 texId = texD ? texD->m_id : 0;
+ const uint texGen = texD ? texD->generation : 0;
+ const quint64 samplerId = samplerD ? samplerD->m_id : 0;
+ const uint samplerGen = samplerD ? samplerD->generation : 0;
+ if (texGen != bd.stex.d[elem].texGeneration
+ || texId != bd.stex.d[elem].texId
+ || samplerGen != bd.stex.d[elem].samplerGeneration
+ || samplerId != bd.stex.d[elem].samplerId)
{
resNeedsRebind = true;
- bd.stex.d[elem].texId = texD->m_id;
- bd.stex.d[elem].texGeneration = texD->generation;
- bd.stex.d[elem].samplerId = samplerD->m_id;
- bd.stex.d[elem].samplerGeneration = samplerD->generation;
+ bd.stex.d[elem].texId = texId;
+ bd.stex.d[elem].texGeneration = texGen;
+ bd.stex.d[elem].samplerId = samplerId;
+ bd.stex.d[elem].samplerGeneration = samplerGen;
}
- texD->lastActiveFrameSlot = currentFrameSlot;
- samplerD->lastActiveFrameSlot = currentFrameSlot;
+ if (texD)
+ texD->lastActiveFrameSlot = currentFrameSlot;
+ if (samplerD)
+ samplerD->lastActiveFrameSlot = currentFrameSlot;
}
}
break;
@@ -1135,6 +1614,17 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
{
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, b->u.sbuf.buf);
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
+
+ if (needsBufferSizeBuffer) {
+ for (int i = 0; i < 6; ++i) {
+ const QRhiShaderResourceBinding::StageFlag stage =
+ QRhiShaderResourceBinding::StageFlag(1 << i);
+ if (b->stage.testFlag(stage)) {
+ storageBufferSizes[stage][b->binding] = b->u.sbuf.maybeSize ? b->u.sbuf.maybeSize : bufD->size();
+ }
+ }
+ }
+
executeBufferHostWritesForCurrentFrame(bufD);
if (bufD->generation != bd.sbuf.generation || bufD->m_id != bd.sbuf.id) {
resNeedsRebind = true;
@@ -1150,26 +1640,141 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
}
}
+ if (needsBufferSizeBuffer) {
+ QMetalBuffer *bufD = nullptr;
+ QVarLengthArray<QPair<QMetalShader *, QRhiShaderResourceBinding::StageFlag>, 4> shaders;
+
+ if (compPsD) {
+ bufD = compPsD->d->bufferSizeBuffer;
+ Q_ASSERT(compPsD->d->cs.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding));
+ shaders.append(qMakePair(&compPsD->d->cs, QRhiShaderResourceBinding::StageFlag::ComputeStage));
+ } else {
+ bufD = gfxPsD->d->bufferSizeBuffer;
+ if (gfxPsD->d->tess.enabled) {
+
+ // Assumptions
+ // * We only use one of the compute vertex shader variants in a pipeline at any one time
+ // * The vertex shader variants all have the same storage block bindings
+ // * The vertex shader variants all have the same native resource binding map
+ // * The vertex shader variants all have the same MslBufferSizeBufferBinding requirement
+ // * The vertex shader variants all have the same MslBufferSizeBufferBinding binding
+ // => We only need to use one vertex shader variant to generate the identical shader
+ // resource bindings
+ Q_ASSERT(gfxPsD->d->tess.compVs[0].desc.storageBlocks() == gfxPsD->d->tess.compVs[1].desc.storageBlocks());
+ Q_ASSERT(gfxPsD->d->tess.compVs[0].desc.storageBlocks() == gfxPsD->d->tess.compVs[2].desc.storageBlocks());
+ Q_ASSERT(gfxPsD->d->tess.compVs[0].nativeResourceBindingMap == gfxPsD->d->tess.compVs[1].nativeResourceBindingMap);
+ Q_ASSERT(gfxPsD->d->tess.compVs[0].nativeResourceBindingMap == gfxPsD->d->tess.compVs[2].nativeResourceBindingMap);
+ Q_ASSERT(gfxPsD->d->tess.compVs[0].nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)
+ == gfxPsD->d->tess.compVs[1].nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding));
+ Q_ASSERT(gfxPsD->d->tess.compVs[0].nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)
+ == gfxPsD->d->tess.compVs[2].nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding));
+ Q_ASSERT(gfxPsD->d->tess.compVs[0].nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding]
+ == gfxPsD->d->tess.compVs[1].nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding]);
+ Q_ASSERT(gfxPsD->d->tess.compVs[0].nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding]
+ == gfxPsD->d->tess.compVs[2].nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding]);
+
+ if (gfxPsD->d->tess.compVs[0].nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding))
+ shaders.append(qMakePair(&gfxPsD->d->tess.compVs[0], QRhiShaderResourceBinding::StageFlag::VertexStage));
+
+ if (gfxPsD->d->tess.compTesc.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding))
+ shaders.append(qMakePair(&gfxPsD->d->tess.compTesc, QRhiShaderResourceBinding::StageFlag::TessellationControlStage));
+
+ if (gfxPsD->d->tess.vertTese.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding))
+ shaders.append(qMakePair(&gfxPsD->d->tess.vertTese, QRhiShaderResourceBinding::StageFlag::TessellationEvaluationStage));
+
+ } else {
+ if (gfxPsD->d->vs.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding))
+ shaders.append(qMakePair(&gfxPsD->d->vs, QRhiShaderResourceBinding::StageFlag::VertexStage));
+ }
+ if (gfxPsD->d->fs.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding))
+ shaders.append(qMakePair(&gfxPsD->d->fs, QRhiShaderResourceBinding::StageFlag::FragmentStage));
+ }
+
+ quint32 offset = 0;
+ for (const QPair<QMetalShader *, QRhiShaderResourceBinding::StageFlag> &shader : shaders) {
+
+ const int binding = shader.first->nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding];
+
+ // if we don't have a srb entry for the buffer size buffer
+ if (!(storageBufferSizes.contains(shader.second) && storageBufferSizes[shader.second].contains(binding))) {
+
+ int maxNativeBinding = 0;
+ for (const QShaderDescription::StorageBlock &block : shader.first->desc.storageBlocks())
+ maxNativeBinding = qMax(maxNativeBinding, shader.first->nativeResourceBindingMap[block.binding].first);
+
+ const int size = (maxNativeBinding + 1) * sizeof(int);
+
+ Q_ASSERT(offset + size <= bufD->size());
+ srbD->sortedBindings.append(QRhiShaderResourceBinding::bufferLoad(binding, shader.second, bufD, offset, size));
+
+ QMetalShaderResourceBindings::BoundResourceData bd;
+ bd.sbuf.id = bufD->m_id;
+ bd.sbuf.generation = bufD->generation;
+ srbD->boundResourceData.append(bd);
+ }
+
+ // create the buffer size buffer data
+ QVarLengthArray<int, 8> bufferSizeBufferData;
+ Q_ASSERT(storageBufferSizes.contains(shader.second));
+ const QMap<int, quint32> &sizes(storageBufferSizes[shader.second]);
+ for (const QShaderDescription::StorageBlock &block : shader.first->desc.storageBlocks()) {
+ const int index = shader.first->nativeResourceBindingMap[block.binding].first;
+
+ // if the native binding is -1, the buffer is present but not accessed in the shader
+ if (index < 0)
+ continue;
+
+ if (bufferSizeBufferData.size() <= index)
+ bufferSizeBufferData.resize(index + 1);
+
+ Q_ASSERT(sizes.contains(block.binding));
+ bufferSizeBufferData[index] = sizes[block.binding];
+ }
+
+ QRhiBufferData data;
+ const quint32 size = bufferSizeBufferData.size() * sizeof(int);
+ data.assign(reinterpret_cast<const char *>(bufferSizeBufferData.constData()), size);
+ Q_ASSERT(offset + size <= bufD->size());
+ bufD->d->pendingUpdates[bufD->d->slotted ? currentFrameSlot : 0].append({ offset, data });
+
+ // buffer offsets must be 32byte aligned
+ offset += ((size + 31) / 32) * 32;
+ }
+
+ executeBufferHostWritesForCurrentFrame(bufD);
+ bufD->lastActiveFrameSlot = currentFrameSlot;
+ }
+
// make sure the resources for the correct slot get bound
const int resSlot = hasSlottedResourceInSrb ? currentFrameSlot : 0;
if (hasSlottedResourceInSrb && cbD->currentResSlot != resSlot)
resNeedsRebind = true;
- const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
+ const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srbD) : (cbD->currentComputeSrb != srbD);
const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
// dynamic uniform buffer offsets always trigger a rebind
if (hasDynamicOffsetInSrb || resNeedsRebind || srbChanged || srbRebuilt) {
- const QShader::NativeResourceBindingMap *resBindMaps[SUPPORTED_STAGES] = { nullptr, nullptr, nullptr };
+ const QShader::NativeResourceBindingMap *resBindMaps[SUPPORTED_STAGES] = { nullptr, nullptr, nullptr, nullptr, nullptr };
if (gfxPsD) {
- cbD->currentGraphicsSrb = srb;
+ cbD->currentGraphicsSrb = srbD;
cbD->currentComputeSrb = nullptr;
- resBindMaps[0] = &gfxPsD->d->vs.nativeResourceBindingMap;
- resBindMaps[1] = &gfxPsD->d->fs.nativeResourceBindingMap;
+ if (gfxPsD->d->tess.enabled) {
+ // If tessellating, we don't know which compVs shader to use until the draw call is
+ // made. They should all have the same native resource binding map, so pick one.
+ Q_ASSERT(gfxPsD->d->tess.compVs[0].nativeResourceBindingMap == gfxPsD->d->tess.compVs[1].nativeResourceBindingMap);
+ Q_ASSERT(gfxPsD->d->tess.compVs[0].nativeResourceBindingMap == gfxPsD->d->tess.compVs[2].nativeResourceBindingMap);
+ resBindMaps[QMetalShaderResourceBindingsData::VERTEX] = &gfxPsD->d->tess.compVs[0].nativeResourceBindingMap;
+ resBindMaps[QMetalShaderResourceBindingsData::TESSCTRL] = &gfxPsD->d->tess.compTesc.nativeResourceBindingMap;
+ resBindMaps[QMetalShaderResourceBindingsData::TESSEVAL] = &gfxPsD->d->tess.vertTese.nativeResourceBindingMap;
+ } else {
+ resBindMaps[QMetalShaderResourceBindingsData::VERTEX] = &gfxPsD->d->vs.nativeResourceBindingMap;
+ }
+ resBindMaps[QMetalShaderResourceBindingsData::FRAGMENT] = &gfxPsD->d->fs.nativeResourceBindingMap;
} else {
cbD->currentGraphicsSrb = nullptr;
- cbD->currentComputeSrb = srb;
- resBindMaps[2] = &compPsD->d->cs.nativeResourceBindingMap;
+ cbD->currentComputeSrb = srbD;
+ resBindMaps[QMetalShaderResourceBindingsData::COMPUTE] = &compPsD->d->cs.nativeResourceBindingMap;
}
cbD->currentSrbGeneration = srbD->generation;
cbD->currentResSlot = resSlot;
@@ -1200,13 +1805,13 @@ void QRhiMetal::setVertexInput(QRhiCommandBuffer *cb,
offsets.finish();
// same binding space for vertex and constant buffers - work it around
- QRhiShaderResourceBindings *srb = cbD->currentGraphicsSrb;
+ QMetalShaderResourceBindings *srbD = cbD->currentGraphicsSrb;
// There's nothing guaranteeing setShaderResources() was called before
// setVertexInput()... but whatever srb will get bound will have to be
// layout-compatible anyways so maxBinding is the same.
- if (!srb)
- srb = cbD->currentGraphicsPipeline->shaderResourceBindings();
- const int firstVertexBinding = QRHI_RES(QMetalShaderResourceBindings, srb)->maxBinding + 1;
+ if (!srbD)
+ srbD = QRHI_RES(QMetalShaderResourceBindings, cbD->currentGraphicsPipeline->shaderResourceBindings());
+ const int firstVertexBinding = srbD->maxBinding + 1;
if (firstVertexBinding != cbD->d->currentFirstVertexBinding
|| buffers != cbD->d->currentVertexInputsBuffers
@@ -1230,7 +1835,7 @@ void QRhiMetal::setVertexInput(QRhiCommandBuffer *cb,
QMetalBuffer *ibufD = QRHI_RES(QMetalBuffer, indexBuf);
executeBufferHostWritesForCurrentFrame(ibufD);
ibufD->lastActiveFrameSlot = currentFrameSlot;
- cbD->currentIndexBuffer = indexBuf;
+ cbD->currentIndexBuffer = ibufD;
cbD->currentIndexOffset = indexOffset;
cbD->currentIndexFormat = indexFormat;
} else {
@@ -1246,7 +1851,7 @@ void QRhiMetal::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
// x,y is top-left in MTLViewportRect but bottom-left in QRhiViewport
float x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
return;
MTLViewport vp;
@@ -1259,8 +1864,10 @@ void QRhiMetal::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport)
[cbD->d->currentRenderPassEncoder setViewport: vp];
- if (!QRHI_RES(QMetalGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
+ if (cbD->currentGraphicsPipeline
+ && !cbD->currentGraphicsPipeline->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
MTLScissorRect s;
+ qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, viewport.viewport(), &x, &y, &w, &h);
s.x = NSUInteger(x);
s.y = NSUInteger(y);
s.width = NSUInteger(w);
@@ -1273,12 +1880,12 @@ void QRhiMetal::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
{
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::RenderPass);
- Q_ASSERT(QRHI_RES(QMetalGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor));
+ Q_ASSERT(cbD->currentGraphicsPipeline->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor));
const QSize outputSize = cbD->currentTarget->pixelSize();
// x,y is top-left in MTLScissorRect but bottom-left in QRhiScissor
int x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
return;
MTLScissorRect s;
@@ -1307,15 +1914,321 @@ void QRhiMetal::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
[cbD->d->currentRenderPassEncoder setStencilReferenceValue: refValue];
}
+static id<MTLComputeCommandEncoder> tessellationComputeEncoder(QMetalCommandBuffer *cbD)
+{
+ if (cbD->d->currentRenderPassEncoder) {
+ [cbD->d->currentRenderPassEncoder endEncoding];
+ cbD->d->currentRenderPassEncoder = nil;
+ }
+
+ if (!cbD->d->tessellationComputeEncoder)
+ cbD->d->tessellationComputeEncoder = [cbD->d->cb computeCommandEncoder];
+
+ return cbD->d->tessellationComputeEncoder;
+}
+
+static void endTessellationComputeEncoding(QMetalCommandBuffer *cbD)
+{
+ if (cbD->d->tessellationComputeEncoder) {
+ [cbD->d->tessellationComputeEncoder endEncoding];
+ cbD->d->tessellationComputeEncoder = nil;
+ }
+
+ QMetalRenderTargetData * rtD = nullptr;
+
+ switch (cbD->currentTarget->resourceType()) {
+ case QRhiResource::SwapChainRenderTarget:
+ rtD = QRHI_RES(QMetalSwapChainRenderTarget, cbD->currentTarget)->d;
+ break;
+ case QRhiResource::TextureRenderTarget:
+ rtD = QRHI_RES(QMetalTextureRenderTarget, cbD->currentTarget)->d;
+ break;
+ default:
+ break;
+ }
+
+ Q_ASSERT(rtD);
+
+ QVarLengthArray<MTLLoadAction, 4> oldColorLoad;
+ for (uint i = 0; i < uint(rtD->colorAttCount); ++i) {
+ oldColorLoad.append(cbD->d->currentPassRpDesc.colorAttachments[i].loadAction);
+ if (cbD->d->currentPassRpDesc.colorAttachments[i].storeAction != MTLStoreActionDontCare)
+ cbD->d->currentPassRpDesc.colorAttachments[i].loadAction = MTLLoadActionLoad;
+ }
+
+ MTLLoadAction oldDepthLoad;
+ MTLLoadAction oldStencilLoad;
+ if (rtD->dsAttCount) {
+ oldDepthLoad = cbD->d->currentPassRpDesc.depthAttachment.loadAction;
+ if (cbD->d->currentPassRpDesc.depthAttachment.storeAction != MTLStoreActionDontCare)
+ cbD->d->currentPassRpDesc.depthAttachment.loadAction = MTLLoadActionLoad;
+
+ oldStencilLoad = cbD->d->currentPassRpDesc.stencilAttachment.loadAction;
+ if (cbD->d->currentPassRpDesc.stencilAttachment.storeAction != MTLStoreActionDontCare)
+ cbD->d->currentPassRpDesc.stencilAttachment.loadAction = MTLLoadActionLoad;
+ }
+
+ cbD->d->currentRenderPassEncoder = [cbD->d->cb renderCommandEncoderWithDescriptor: cbD->d->currentPassRpDesc];
+ cbD->resetPerPassCachedState();
+
+ for (uint i = 0; i < uint(rtD->colorAttCount); ++i) {
+ cbD->d->currentPassRpDesc.colorAttachments[i].loadAction = oldColorLoad[i];
+ }
+
+ if (rtD->dsAttCount) {
+ cbD->d->currentPassRpDesc.depthAttachment.loadAction = oldDepthLoad;
+ cbD->d->currentPassRpDesc.stencilAttachment.loadAction = oldStencilLoad;
+ }
+
+}
+
+void QRhiMetal::tessellatedDraw(const TessDrawArgs &args)
+{
+ QMetalCommandBuffer *cbD = args.cbD;
+ QMetalGraphicsPipeline *graphicsPipeline = cbD->currentGraphicsPipeline;
+ if (graphicsPipeline->d->tess.failed)
+ return;
+
+ const bool indexed = args.type != TessDrawArgs::NonIndexed;
+ const quint32 instanceCount = indexed ? args.drawIndexed.instanceCount : args.draw.instanceCount;
+ const quint32 vertexOrIndexCount = indexed ? args.drawIndexed.indexCount : args.draw.vertexCount;
+
+ QMetalGraphicsPipelineData::Tessellation &tess(graphicsPipeline->d->tess);
+ QMetalGraphicsPipelineData::ExtraBufferManager &extraBufMgr(graphicsPipeline->d->extraBufMgr);
+ const quint32 patchCount = tess.patchCountForDrawCall(vertexOrIndexCount, instanceCount);
+ QMetalBuffer *vertOutBuf = nullptr;
+ QMetalBuffer *tescOutBuf = nullptr;
+ QMetalBuffer *tescPatchOutBuf = nullptr;
+ QMetalBuffer *tescFactorBuf = nullptr;
+ QMetalBuffer *tescParamsBuf = nullptr;
+ id<MTLComputeCommandEncoder> vertTescComputeEncoder = tessellationComputeEncoder(cbD);
+
+ // Step 1: vertex shader (as compute)
+ {
+ id<MTLComputeCommandEncoder> computeEncoder = vertTescComputeEncoder;
+ QShader::Variant shaderVariant = QShader::NonIndexedVertexAsComputeShader;
+ if (args.type == TessDrawArgs::U16Indexed)
+ shaderVariant = QShader::UInt16IndexedVertexAsComputeShader;
+ else if (args.type == TessDrawArgs::U32Indexed)
+ shaderVariant = QShader::UInt32IndexedVertexAsComputeShader;
+ const int varIndex = QMetalGraphicsPipelineData::Tessellation::vsCompVariantToIndex(shaderVariant);
+ id<MTLComputePipelineState> computePipelineState = tess.vsCompPipeline(this, shaderVariant);
+ [computeEncoder setComputePipelineState: computePipelineState];
+
+ // Make uniform buffers, textures, and samplers (meant for the
+ // vertex stage from the client's point of view) visible in the
+ // "vertex as compute" shader
+ cbD->d->currentComputePassEncoder = computeEncoder;
+ rebindShaderResources(cbD, QMetalShaderResourceBindingsData::VERTEX, QMetalShaderResourceBindingsData::COMPUTE);
+ cbD->d->currentComputePassEncoder = nil;
+
+ const QMap<int, int> &ebb(tess.compVs[varIndex].nativeShaderInfo.extraBufferBindings);
+ const int outputBufferBinding = ebb.value(QShaderPrivate::MslTessVertTescOutputBufferBinding, -1);
+ const int indexBufferBinding = ebb.value(QShaderPrivate::MslTessVertIndicesBufferBinding, -1);
+
+ if (outputBufferBinding >= 0) {
+ const quint32 workBufSize = tess.vsCompOutputBufferSize(vertexOrIndexCount, instanceCount);
+ vertOutBuf = extraBufMgr.acquireWorkBuffer(this, workBufSize);
+ if (!vertOutBuf)
+ return;
+ [computeEncoder setBuffer: vertOutBuf->d->buf[0] offset: 0 atIndex: outputBufferBinding];
+ }
+
+ if (indexBufferBinding >= 0)
+ [computeEncoder setBuffer: (id<MTLBuffer>) args.drawIndexed.indexBuffer offset: 0 atIndex: indexBufferBinding];
+
+ for (int i = 0, ie = cbD->d->currentVertexInputsBuffers.batches.count(); i != ie; ++i) {
+ const auto &bufferBatch(cbD->d->currentVertexInputsBuffers.batches[i]);
+ const auto &offsetBatch(cbD->d->currentVertexInputOffsets.batches[i]);
+ [computeEncoder setBuffers: bufferBatch.resources.constData()
+ offsets: offsetBatch.resources.constData()
+ withRange: NSMakeRange(uint(cbD->d->currentFirstVertexBinding) + bufferBatch.startBinding, NSUInteger(bufferBatch.resources.count()))];
+ }
+
+ if (indexed) {
+ [computeEncoder setStageInRegion: MTLRegionMake2D(args.drawIndexed.vertexOffset, args.drawIndexed.firstInstance,
+ args.drawIndexed.indexCount, args.drawIndexed.instanceCount)];
+ } else {
+ [computeEncoder setStageInRegion: MTLRegionMake2D(args.draw.firstVertex, args.draw.firstInstance,
+ args.draw.vertexCount, args.draw.instanceCount)];
+ }
+
+ [computeEncoder dispatchThreads: MTLSizeMake(vertexOrIndexCount, instanceCount, 1)
+ threadsPerThreadgroup: MTLSizeMake(computePipelineState.threadExecutionWidth, 1, 1)];
+ }
+
+ // Step 2: tessellation control shader (as compute)
+ {
+ id<MTLComputeCommandEncoder> computeEncoder = vertTescComputeEncoder;
+ id<MTLComputePipelineState> computePipelineState = tess.tescCompPipeline(this);
+ [computeEncoder setComputePipelineState: computePipelineState];
+
+ cbD->d->currentComputePassEncoder = computeEncoder;
+ rebindShaderResources(cbD, QMetalShaderResourceBindingsData::TESSCTRL, QMetalShaderResourceBindingsData::COMPUTE);
+ cbD->d->currentComputePassEncoder = nil;
+
+ const QMap<int, int> &ebb(tess.compTesc.nativeShaderInfo.extraBufferBindings);
+ const int outputBufferBinding = ebb.value(QShaderPrivate::MslTessVertTescOutputBufferBinding, -1);
+ const int patchOutputBufferBinding = ebb.value(QShaderPrivate::MslTessTescPatchOutputBufferBinding, -1);
+ const int tessFactorBufferBinding = ebb.value(QShaderPrivate::MslTessTescTessLevelBufferBinding, -1);
+ const int paramsBufferBinding = ebb.value(QShaderPrivate::MslTessTescParamsBufferBinding, -1);
+ const int inputBufferBinding = ebb.value(QShaderPrivate::MslTessTescInputBufferBinding, -1);
+
+ if (outputBufferBinding >= 0) {
+ const quint32 workBufSize = tess.tescCompOutputBufferSize(patchCount);
+ tescOutBuf = extraBufMgr.acquireWorkBuffer(this, workBufSize);
+ if (!tescOutBuf)
+ return;
+ [computeEncoder setBuffer: tescOutBuf->d->buf[0] offset: 0 atIndex: outputBufferBinding];
+ }
+
+ if (patchOutputBufferBinding >= 0) {
+ const quint32 workBufSize = tess.tescCompPatchOutputBufferSize(patchCount);
+ tescPatchOutBuf = extraBufMgr.acquireWorkBuffer(this, workBufSize);
+ if (!tescPatchOutBuf)
+ return;
+ [computeEncoder setBuffer: tescPatchOutBuf->d->buf[0] offset: 0 atIndex: patchOutputBufferBinding];
+ }
+
+ if (tessFactorBufferBinding >= 0) {
+ tescFactorBuf = extraBufMgr.acquireWorkBuffer(this, patchCount * sizeof(MTLQuadTessellationFactorsHalf));
+ [computeEncoder setBuffer: tescFactorBuf->d->buf[0] offset: 0 atIndex: tessFactorBufferBinding];
+ }
+
+ if (paramsBufferBinding >= 0) {
+ struct {
+ quint32 inControlPointCount;
+ quint32 patchCount;
+ } params;
+ tescParamsBuf = extraBufMgr.acquireWorkBuffer(this, sizeof(params), QMetalGraphicsPipelineData::ExtraBufferManager::WorkBufType::HostVisible);
+ if (!tescParamsBuf)
+ return;
+ params.inControlPointCount = tess.inControlPointCount;
+ params.patchCount = patchCount;
+ id<MTLBuffer> paramsBuf = tescParamsBuf->d->buf[0];
+ char *p = reinterpret_cast<char *>([paramsBuf contents]);
+ memcpy(p, &params, sizeof(params));
+ [computeEncoder setBuffer: paramsBuf offset: 0 atIndex: paramsBufferBinding];
+ }
+
+ if (vertOutBuf && inputBufferBinding >= 0)
+ [computeEncoder setBuffer: vertOutBuf->d->buf[0] offset: 0 atIndex: inputBufferBinding];
+
+ int sgSize = int(computePipelineState.threadExecutionWidth);
+ int wgSize = std::lcm(tess.outControlPointCount, sgSize);
+ while (wgSize > caps.maxThreadGroupSize) {
+ sgSize /= 2;
+ wgSize = std::lcm(tess.outControlPointCount, sgSize);
+ }
+ [computeEncoder dispatchThreads: MTLSizeMake(patchCount * tess.outControlPointCount, 1, 1)
+ threadsPerThreadgroup: MTLSizeMake(wgSize, 1, 1)];
+ }
+
+ // Much of the state in the QMetalCommandBuffer is going to be reset
+ // when we get a new render encoder. Save what we need. (cheaper than
+ // starting to walk over the srb again)
+ const QMetalShaderResourceBindingsData resourceBindings = cbD->d->currentShaderResourceBindingState;
+
+ endTessellationComputeEncoding(cbD);
+
+ // Step 3: tessellation evaluation (as vertex) + fragment shader
+ {
+ // No need to call tess.teseFragRenderPipeline because it was done
+ // once and we know the result is stored in the standard place
+ // (graphicsPipeline->d->ps).
+
+ graphicsPipeline->makeActiveForCurrentRenderPassEncoder(cbD);
+ id<MTLRenderCommandEncoder> renderEncoder = cbD->d->currentRenderPassEncoder;
+
+ rebindShaderResources(cbD, QMetalShaderResourceBindingsData::TESSEVAL, QMetalShaderResourceBindingsData::VERTEX, &resourceBindings);
+ rebindShaderResources(cbD, QMetalShaderResourceBindingsData::FRAGMENT, QMetalShaderResourceBindingsData::FRAGMENT, &resourceBindings);
+
+ const QMap<int, int> &ebb(tess.compTesc.nativeShaderInfo.extraBufferBindings);
+ const int outputBufferBinding = ebb.value(QShaderPrivate::MslTessVertTescOutputBufferBinding, -1);
+ const int patchOutputBufferBinding = ebb.value(QShaderPrivate::MslTessTescPatchOutputBufferBinding, -1);
+ const int tessFactorBufferBinding = ebb.value(QShaderPrivate::MslTessTescTessLevelBufferBinding, -1);
+
+ if (outputBufferBinding >= 0 && tescOutBuf)
+ [renderEncoder setVertexBuffer: tescOutBuf->d->buf[0] offset: 0 atIndex: outputBufferBinding];
+
+ if (patchOutputBufferBinding >= 0 && tescPatchOutBuf)
+ [renderEncoder setVertexBuffer: tescPatchOutBuf->d->buf[0] offset: 0 atIndex: patchOutputBufferBinding];
+
+ if (tessFactorBufferBinding >= 0 && tescFactorBuf) {
+ [renderEncoder setTessellationFactorBuffer: tescFactorBuf->d->buf[0] offset: 0 instanceStride: 0];
+ [renderEncoder setVertexBuffer: tescFactorBuf->d->buf[0] offset: 0 atIndex: tessFactorBufferBinding];
+ }
+
+ [cbD->d->currentRenderPassEncoder drawPatches: tess.outControlPointCount
+ patchStart: 0
+ patchCount: patchCount
+ patchIndexBuffer: nil
+ patchIndexBufferOffset: 0
+ instanceCount: 1
+ baseInstance: 0];
+ }
+}
+
+void QRhiMetal::adjustForMultiViewDraw(quint32 *instanceCount, QRhiCommandBuffer *cb)
+{
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ const int multiViewCount = cbD->currentGraphicsPipeline->m_multiViewCount;
+ if (multiViewCount <= 1)
+ return;
+
+ const QMap<int, int> &ebb(cbD->currentGraphicsPipeline->d->vs.nativeShaderInfo.extraBufferBindings);
+ const int viewMaskBufBinding = ebb.value(QShaderPrivate::MslMultiViewMaskBufferBinding, -1);
+ if (viewMaskBufBinding == -1) {
+ qWarning("No extra buffer for multiview in the vertex shader; was it built with --view-count specified?");
+ return;
+ }
+ struct {
+ quint32 viewOffset;
+ quint32 viewCount;
+ } multiViewInfo;
+ multiViewInfo.viewOffset = 0;
+ multiViewInfo.viewCount = quint32(multiViewCount);
+ QMetalBuffer *buf = cbD->currentGraphicsPipeline->d->extraBufMgr.acquireWorkBuffer(this, sizeof(multiViewInfo),
+ QMetalGraphicsPipelineData::ExtraBufferManager::WorkBufType::HostVisible);
+ if (buf) {
+ id<MTLBuffer> mtlbuf = buf->d->buf[0];
+ char *p = reinterpret_cast<char *>([mtlbuf contents]);
+ memcpy(p, &multiViewInfo, sizeof(multiViewInfo));
+ [cbD->d->currentRenderPassEncoder setVertexBuffer: mtlbuf offset: 0 atIndex: viewMaskBufBinding];
+ // The instance count is adjusted for layered rendering. The vertex shader is expected to contain something like:
+ // uint gl_ViewIndex = spvViewMask[0] + (gl_InstanceIndex - gl_BaseInstance) % spvViewMask[1];
+ // where spvViewMask is the buffer with multiViewInfo passed in above.
+ *instanceCount *= multiViewCount;
+ }
+}
+
void QRhiMetal::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
quint32 instanceCount, quint32 firstVertex, quint32 firstInstance)
{
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::RenderPass);
- [cbD->d->currentRenderPassEncoder drawPrimitives:
- QRHI_RES(QMetalGraphicsPipeline, cbD->currentGraphicsPipeline)->d->primitiveType
- vertexStart: firstVertex vertexCount: vertexCount instanceCount: instanceCount baseInstance: firstInstance];
+ if (cbD->currentGraphicsPipeline->d->tess.enabled) {
+ TessDrawArgs a;
+ a.cbD = cbD;
+ a.type = TessDrawArgs::NonIndexed;
+ a.draw.vertexCount = vertexCount;
+ a.draw.instanceCount = instanceCount;
+ a.draw.firstVertex = firstVertex;
+ a.draw.firstInstance = firstInstance;
+ tessellatedDraw(a);
+ return;
+ }
+
+ adjustForMultiViewDraw(&instanceCount, cb);
+
+ if (caps.baseVertexAndInstance) {
+ [cbD->d->currentRenderPassEncoder drawPrimitives: cbD->currentGraphicsPipeline->d->primitiveType
+ vertexStart: firstVertex vertexCount: vertexCount instanceCount: instanceCount baseInstance: firstInstance];
+ } else {
+ [cbD->d->currentRenderPassEncoder drawPrimitives: cbD->currentGraphicsPipeline->d->primitiveType
+ vertexStart: firstVertex vertexCount: vertexCount instanceCount: instanceCount];
+ }
}
void QRhiMetal::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
@@ -1328,19 +2241,44 @@ void QRhiMetal::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
return;
const quint32 indexOffset = cbD->currentIndexOffset + firstIndex * (cbD->currentIndexFormat == QRhiCommandBuffer::IndexUInt16 ? 2 : 4);
- Q_ASSERT(indexOffset == aligned<quint32>(indexOffset, 4));
-
- QMetalBuffer *ibufD = QRHI_RES(QMetalBuffer, cbD->currentIndexBuffer);
- id<MTLBuffer> mtlbuf = ibufD->d->buf[ibufD->d->slotted ? currentFrameSlot : 0];
+ Q_ASSERT(indexOffset == aligned(indexOffset, 4u));
+
+ QMetalBuffer *ibufD = cbD->currentIndexBuffer;
+ id<MTLBuffer> mtlibuf = ibufD->d->buf[ibufD->d->slotted ? currentFrameSlot : 0];
+
+ if (cbD->currentGraphicsPipeline->d->tess.enabled) {
+ TessDrawArgs a;
+ a.cbD = cbD;
+ a.type = cbD->currentIndexFormat == QRhiCommandBuffer::IndexUInt16 ? TessDrawArgs::U16Indexed : TessDrawArgs::U32Indexed;
+ a.drawIndexed.indexCount = indexCount;
+ a.drawIndexed.instanceCount = instanceCount;
+ a.drawIndexed.firstIndex = firstIndex;
+ a.drawIndexed.vertexOffset = vertexOffset;
+ a.drawIndexed.firstInstance = firstInstance;
+ a.drawIndexed.indexBuffer = mtlibuf;
+ tessellatedDraw(a);
+ return;
+ }
- [cbD->d->currentRenderPassEncoder drawIndexedPrimitives: QRHI_RES(QMetalGraphicsPipeline, cbD->currentGraphicsPipeline)->d->primitiveType
- indexCount: indexCount
- indexType: cbD->currentIndexFormat == QRhiCommandBuffer::IndexUInt16 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
- indexBuffer: mtlbuf
- indexBufferOffset: indexOffset
- instanceCount: instanceCount
- baseVertex: vertexOffset
- baseInstance: firstInstance];
+ adjustForMultiViewDraw(&instanceCount, cb);
+
+ if (caps.baseVertexAndInstance) {
+ [cbD->d->currentRenderPassEncoder drawIndexedPrimitives: cbD->currentGraphicsPipeline->d->primitiveType
+ indexCount: indexCount
+ indexType: cbD->currentIndexFormat == QRhiCommandBuffer::IndexUInt16 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
+ indexBuffer: mtlibuf
+ indexBufferOffset: indexOffset
+ instanceCount: instanceCount
+ baseVertex: vertexOffset
+ baseInstance: firstInstance];
+ } else {
+ [cbD->d->currentRenderPassEncoder drawIndexedPrimitives: cbD->currentGraphicsPipeline->d->primitiveType
+ indexCount: indexCount
+ indexType: cbD->currentIndexFormat == QRhiCommandBuffer::IndexUInt16 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32
+ indexBuffer: mtlibuf
+ indexBufferOffset: indexOffset
+ instanceCount: instanceCount];
+ }
}
void QRhiMetal::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
@@ -1394,34 +2332,39 @@ void QRhiMetal::endExternal(QRhiCommandBuffer *cb)
cbD->resetPerPassCachedState();
}
+double QRhiMetal::lastCompletedGpuTime(QRhiCommandBuffer *cb)
+{
+ QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
+ return cbD->d->lastGpuTime;
+}
+
QRhi::FrameOpResult QRhiMetal::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
{
Q_UNUSED(flags);
QMetalSwapChain *swapChainD = QRHI_RES(QMetalSwapChain, swapChain);
+ currentSwapChain = swapChainD;
+ currentFrameSlot = swapChainD->currentFrameSlot;
- // This is a bit messed up since for this swapchain we want to wait for the
- // commands+present to complete, while for others just for the commands
- // (for this same frame slot) but not sure how to do that in a sane way so
- // wait for full cb completion for now.
- for (QMetalSwapChain *sc : qAsConst(swapchains)) {
- dispatch_semaphore_t sem = sc->d->sem[swapChainD->currentFrameSlot];
- dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ // If we are too far ahead, block. This is also what ensures that any
+ // resource used in the previous frame for this slot is now not in use
+ // anymore by the GPU.
+ dispatch_semaphore_wait(swapChainD->d->sem[currentFrameSlot], DISPATCH_TIME_FOREVER);
+
+ // Do this also for any other swapchain's commands with the same frame slot
+ // While this reduces concurrency, it keeps resource usage safe: swapchain
+ // A starting its frame 0, followed by swapchain B starting its own frame 0
+ // will make B wait for A's frame 0 commands, so if a resource is written
+ // in B's frame or when B checks for pending resource releases, that won't
+ // mess up A's in-flight commands (as they are not in flight anymore).
+ for (QMetalSwapChain *sc : std::as_const(swapchains)) {
if (sc != swapChainD)
- dispatch_semaphore_signal(sem);
+ sc->waitUntilCompleted(currentFrameSlot); // wait+signal
}
- currentSwapChain = swapChainD;
- currentFrameSlot = swapChainD->currentFrameSlot;
- if (swapChainD->ds)
- swapChainD->ds->lastActiveFrameSlot = currentFrameSlot;
-
[d->captureScope beginScope];
- // Do not let the command buffer mess with the refcount of objects. We do
- // have a proper render loop and will manage lifetimes similarly to other
- // backends (Vulkan).
- swapChainD->cbWrapper.d->cb = [d->cmdQueue commandBufferWithUnretainedReferences];
+ swapChainD->cbWrapper.d->cb = d->newCommandBuffer();
QMetalRenderTargetData::ColorAtt colorAtt;
if (swapChainD->samples > 1) {
@@ -1433,14 +2376,16 @@ QRhi::FrameOpResult QRhiMetal::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginF
swapChainD->rtWrapper.d->fb.colorAtt[0] = colorAtt;
swapChainD->rtWrapper.d->fb.dsTex = swapChainD->ds ? swapChainD->ds->d->tex : nil;
+ swapChainD->rtWrapper.d->fb.dsResolveTex = nil;
swapChainD->rtWrapper.d->fb.hasStencil = swapChainD->ds ? true : false;
swapChainD->rtWrapper.d->fb.depthNeedsStore = false;
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- QRHI_PROF_F(beginSwapChainFrame(swapChain));
+ if (swapChainD->ds)
+ swapChainD->ds->lastActiveFrameSlot = currentFrameSlot;
executeDeferredReleases();
- swapChainD->cbWrapper.resetState();
+ swapChainD->cbWrapper.resetState(swapChainD->d->lastGpuTime[currentFrameSlot]);
+ swapChainD->d->lastGpuTime[currentFrameSlot] = 0;
finishActiveReadbacks();
return QRhi::FrameOpSuccess;
@@ -1451,28 +2396,37 @@ QRhi::FrameOpResult QRhiMetal::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
QMetalSwapChain *swapChainD = QRHI_RES(QMetalSwapChain, swapChain);
Q_ASSERT(currentSwapChain == swapChainD);
+ __block int thisFrameSlot = currentFrameSlot;
+ [swapChainD->cbWrapper.d->cb addCompletedHandler: ^(id<MTLCommandBuffer> cb) {
+ swapChainD->d->lastGpuTime[thisFrameSlot] += cb.GPUEndTime - cb.GPUStartTime;
+ dispatch_semaphore_signal(swapChainD->d->sem[thisFrameSlot]);
+ }];
+
const bool needsPresent = !flags.testFlag(QRhi::SkipPresent);
- if (needsPresent) {
- auto drawable = swapChainD->d->curDrawable;
- [swapChainD->cbWrapper.d->cb addScheduledHandler:^(id<MTLCommandBuffer>) {
+ const bool presentsWithTransaction = swapChainD->d->layer.presentsWithTransaction;
+ if (!presentsWithTransaction && needsPresent) {
+ // beginFrame-endFrame without a render pass inbetween means there is no drawable.
+ if (id<CAMetalDrawable> drawable = swapChainD->d->curDrawable)
+ [swapChainD->cbWrapper.d->cb presentDrawable: drawable];
+ }
+
+ [swapChainD->cbWrapper.d->cb commit];
+
+ if (presentsWithTransaction && needsPresent) {
+ // beginFrame-endFrame without a render pass inbetween means there is no drawable.
+ if (id<CAMetalDrawable> drawable = swapChainD->d->curDrawable) {
+ // The layer has presentsWithTransaction set to true to avoid flicker on resizing,
+ // so here it is important to follow what the Metal docs say when it comes to the
+ // issuing the present.
+ [swapChainD->cbWrapper.d->cb waitUntilScheduled];
[drawable present];
- }];
+ }
}
// Must not hold on to the drawable, regardless of needsPresent
[swapChainD->d->curDrawable release];
swapChainD->d->curDrawable = nil;
- __block int thisFrameSlot = currentFrameSlot;
- [swapChainD->cbWrapper.d->cb addCompletedHandler: ^(id<MTLCommandBuffer>) {
- dispatch_semaphore_signal(swapChainD->d->sem[thisFrameSlot]);
- }];
-
- [swapChainD->cbWrapper.d->cb commit];
-
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
-
[d->captureScope endScope];
if (needsPresent)
@@ -1488,23 +2442,17 @@ QRhi::FrameOpResult QRhiMetal::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi:
Q_UNUSED(flags);
currentFrameSlot = (currentFrameSlot + 1) % QMTL_FRAMES_IN_FLIGHT;
- if (swapchains.count() > 1) {
- for (QMetalSwapChain *sc : qAsConst(swapchains)) {
- // wait+signal is the general pattern to ensure the commands for a
- // given frame slot have completed (if sem is 1, we go 0 then 1; if
- // sem is 0 we go -1, block, completion increments to 0, then us to 1)
- dispatch_semaphore_t sem = sc->d->sem[currentFrameSlot];
- dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
- dispatch_semaphore_signal(sem);
- }
- }
+
+ for (QMetalSwapChain *sc : std::as_const(swapchains))
+ sc->waitUntilCompleted(currentFrameSlot);
d->ofr.active = true;
*cb = &d->ofr.cbWrapper;
- d->ofr.cbWrapper.d->cb = [d->cmdQueue commandBufferWithUnretainedReferences];
+ d->ofr.cbWrapper.d->cb = d->newCommandBuffer();
executeDeferredReleases();
- d->ofr.cbWrapper.resetState();
+ d->ofr.cbWrapper.resetState(d->ofr.lastGpuTime);
+ d->ofr.lastGpuTime = 0;
finishActiveReadbacks();
return QRhi::FrameOpSuccess;
@@ -1516,10 +2464,13 @@ QRhi::FrameOpResult QRhiMetal::endOffscreenFrame(QRhi::EndFrameFlags flags)
Q_ASSERT(d->ofr.active);
d->ofr.active = false;
- [d->ofr.cbWrapper.d->cb commit];
+ id<MTLCommandBuffer> cb = d->ofr.cbWrapper.d->cb;
+ [cb commit];
// offscreen frames wait for completion, unlike swapchain ones
- [d->ofr.cbWrapper.d->cb waitUntilCompleted];
+ [cb waitUntilCompleted];
+
+ d->ofr.lastGpuTime += cb.GPUEndTime - cb.GPUStartTime;
finishActiveReadbacks(true);
@@ -1543,16 +2494,14 @@ QRhi::FrameOpResult QRhiMetal::finish()
}
}
- for (QMetalSwapChain *sc : qAsConst(swapchains)) {
+ for (QMetalSwapChain *sc : std::as_const(swapchains)) {
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
if (currentSwapChain && sc == currentSwapChain && i == currentFrameSlot) {
// no wait as this is the thing we're going to be commit below and
// beginFrame decremented sem already and going to be signaled by endFrame
continue;
}
- dispatch_semaphore_t sem = sc->d->sem[i];
- dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
- dispatch_semaphore_signal(sem);
+ sc->waitUntilCompleted(i);
}
}
@@ -1562,10 +2511,13 @@ QRhi::FrameOpResult QRhiMetal::finish()
}
if (inFrame) {
- if (d->ofr.active)
- d->ofr.cbWrapper.d->cb = [d->cmdQueue commandBufferWithUnretainedReferences];
- else
- swapChainD->cbWrapper.d->cb = [d->cmdQueue commandBufferWithUnretainedReferences];
+ if (d->ofr.active) {
+ d->ofr.lastGpuTime += cb.GPUEndTime - cb.GPUStartTime;
+ d->ofr.cbWrapper.d->cb = d->newCommandBuffer();
+ } else {
+ swapChainD->d->lastGpuTime[currentFrameSlot] += cb.GPUEndTime - cb.GPUStartTime;
+ swapChainD->cbWrapper.d->cb = d->newCommandBuffer();
+ }
}
executeDeferredReleases(true);
@@ -1742,7 +2694,15 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
{
QMetalCommandBuffer *cbD = QRHI_RES(QMetalCommandBuffer, cb);
QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+
+ id<MTLBlitCommandEncoder> blitEnc = nil;
+ auto ensureBlit = [&blitEnc, cbD, this]() {
+ if (!blitEnc) {
+ blitEnc = [cbD->d->cb blitCommandEncoder];
+ if (debugMarkers)
+ [blitEnc pushDebugGroup: @"Texture upload/copy"];
+ }
+ };
for (int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
const QRhiResourceUpdateBatchPrivate::BufferOp &u(ud->bufferOps[opIdx]);
@@ -1766,25 +2726,33 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
QMetalBuffer *bufD = QRHI_RES(QMetalBuffer, u.buf);
executeBufferHostWritesForCurrentFrame(bufD);
const int idx = bufD->d->slotted ? currentFrameSlot : 0;
- char *p = reinterpret_cast<char *>([bufD->d->buf[idx] contents]);
- if (p) {
- u.result->data.resize(u.readSize);
- memcpy(u.result->data.data(), p + u.offset, size_t(u.readSize));
+ if (bufD->m_type == QRhiBuffer::Dynamic) {
+ char *p = reinterpret_cast<char *>([bufD->d->buf[idx] contents]);
+ if (p) {
+ u.result->data.resize(u.readSize);
+ memcpy(u.result->data.data(), p + u.offset, size_t(u.readSize));
+ }
+ if (u.result->completed)
+ u.result->completed();
+ } else {
+ QRhiMetalData::BufferReadback readback;
+ readback.activeFrameSlot = idx;
+ readback.buf = bufD->d->buf[idx];
+ readback.offset = u.offset;
+ readback.readSize = u.readSize;
+ readback.result = u.result;
+ d->activeBufferReadbacks.append(readback);
+#ifdef Q_OS_MACOS
+ if (bufD->d->managed) {
+ // On non-Apple Silicon, manually synchronize memory from GPU to CPU
+ ensureBlit();
+ [blitEnc synchronizeResource:readback.buf];
+ }
+#endif
}
- if (u.result->completed)
- u.result->completed();
}
}
- id<MTLBlitCommandEncoder> blitEnc = nil;
- auto ensureBlit = [&blitEnc, cbD, this] {
- if (!blitEnc) {
- blitEnc = [cbD->d->cb blitCommandEncoder];
- if (debugMarkers)
- [blitEnc pushDebugGroup: @"Texture upload/copy"];
- }
- };
-
for (int opIdx = 0; opIdx < ud->activeTextureOpCount; ++opIdx) {
const QRhiResourceUpdateBatchPrivate::TextureOp &u(ud->textureOps[opIdx]);
if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Upload) {
@@ -1792,7 +2760,7 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
qsizetype stagingSize = 0;
for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
- for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level]))
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
stagingSize += subresUploadByteSize(subresDesc);
}
}
@@ -1801,13 +2769,12 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
Q_ASSERT(!utexD->d->stagingBuf[currentFrameSlot]);
utexD->d->stagingBuf[currentFrameSlot] = [d->dev newBufferWithLength: NSUInteger(stagingSize)
options: MTLResourceStorageModeShared];
- QRHI_PROF_F(newTextureStagingArea(utexD, currentFrameSlot, quint32(stagingSize)));
void *mp = [utexD->d->stagingBuf[currentFrameSlot] contents];
qsizetype curOfs = 0;
for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
- for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level]))
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
enqueueSubresUpload(utexD, mp, blitEnc, layer, level, subresDesc, &curOfs);
}
}
@@ -1820,7 +2787,6 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
e.stagingBuffer.buffer = utexD->d->stagingBuf[currentFrameSlot];
utexD->d->stagingBuf[currentFrameSlot] = nil;
d->releaseQueue.append(e);
- QRHI_PROF_F(releaseTextureStagingArea(utexD, currentFrameSlot));
} else if (u.type == QRhiResourceUpdateBatchPrivate::TextureOp::Copy) {
Q_ASSERT(u.src && u.dst);
QMetalTexture *srcD = QRHI_RES(QMetalTexture, u.src);
@@ -1882,10 +2848,6 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
textureFormatInfo(readback.format, readback.pixelSize, &bpl, &readback.bufSize, nullptr);
readback.buf = [d->dev newBufferWithLength: readback.bufSize options: MTLResourceStorageModeShared];
- QRHI_PROF_F(newReadbackBuffer(qint64(qintptr(readback.buf)),
- texD ? static_cast<QRhiResource *>(texD) : static_cast<QRhiResource *>(swapChainD),
- readback.bufSize));
-
ensureBlit();
[blitEnc copyFromTexture: src
sourceSlice: NSUInteger(is3D ? 0 : u.rb.layer())
@@ -1923,17 +2885,17 @@ void QRhiMetal::executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot)
return;
void *p = [bufD->d->buf[slot] contents];
- int changeBegin = -1;
- int changeEnd = -1;
- for (const QMetalBufferData::BufferUpdate &u : qAsConst(bufD->d->pendingUpdates[slot])) {
+ quint32 changeBegin = UINT32_MAX;
+ quint32 changeEnd = 0;
+ for (const QMetalBufferData::BufferUpdate &u : std::as_const(bufD->d->pendingUpdates[slot])) {
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
- if (changeBegin == -1 || u.offset < changeBegin)
+ if (u.offset < changeBegin)
changeBegin = u.offset;
- if (changeEnd == -1 || u.offset + u.data.size() > changeEnd)
+ if (u.offset + u.data.size() > changeEnd)
changeEnd = u.offset + u.data.size();
}
#ifdef Q_OS_MACOS
- if (changeBegin >= 0 && bufD->d->managed)
+ if (changeBegin < UINT32_MAX && changeBegin < changeEnd && bufD->d->managed)
[bufD->d->buf[slot] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))];
#endif
@@ -1967,8 +2929,8 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
QMetalRenderTargetData *rtD = nullptr;
switch (rt->resourceType()) {
- case QRhiResource::RenderTarget:
- rtD = QRHI_RES(QMetalReferenceRenderTarget, rt)->d;
+ case QRhiResource::SwapChainRenderTarget:
+ rtD = QRHI_RES(QMetalSwapChainRenderTarget, rt)->d;
cbD->d->currentPassRpDesc = d->createDefaultRenderPass(rtD->dsAttCount, colorClearValue, depthStencilClearValue, rtD->colorAttCount);
if (rtD->colorAttCount) {
QMetalRenderTargetData::ColorAtt &color0(rtD->fb.colorAtt[0]);
@@ -1998,22 +2960,27 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
{
QMetalTextureRenderTarget *rtTex = QRHI_RES(QMetalTextureRenderTarget, rt);
rtD = rtTex->d;
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QMetalTexture, QMetalRenderBuffer>(rtTex->description(), rtD->currentResIdList))
+ rtTex->create();
cbD->d->currentPassRpDesc = d->createDefaultRenderPass(rtD->dsAttCount, colorClearValue, depthStencilClearValue, rtD->colorAttCount);
- if (rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents)) {
+ if (rtD->fb.preserveColor) {
for (uint i = 0; i < uint(rtD->colorAttCount); ++i)
cbD->d->currentPassRpDesc.colorAttachments[i].loadAction = MTLLoadActionLoad;
}
- if (rtD->dsAttCount && rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents)) {
+ if (rtD->dsAttCount && rtD->fb.preserveDs) {
cbD->d->currentPassRpDesc.depthAttachment.loadAction = MTLLoadActionLoad;
cbD->d->currentPassRpDesc.stencilAttachment.loadAction = MTLLoadActionLoad;
}
for (auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
it != itEnd; ++it)
{
- if (it->texture())
+ if (it->texture()) {
QRHI_RES(QMetalTexture, it->texture())->lastActiveFrameSlot = currentFrameSlot;
- else if (it->renderBuffer())
+ if (it->multiViewCount() >= 2)
+ cbD->d->currentPassRpDesc.renderTargetArrayLength = NSUInteger(it->multiViewCount());
+ } else if (it->renderBuffer()) {
QRHI_RES(QMetalRenderBuffer, it->renderBuffer())->lastActiveFrameSlot = currentFrameSlot;
+ }
if (it->resolveTexture())
QRHI_RES(QMetalTexture, it->resolveTexture())->lastActiveFrameSlot = currentFrameSlot;
}
@@ -2021,6 +2988,8 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
QRHI_RES(QMetalRenderBuffer, rtTex->m_desc.depthStencilBuffer())->lastActiveFrameSlot = currentFrameSlot;
if (rtTex->m_desc.depthTexture())
QRHI_RES(QMetalTexture, rtTex->m_desc.depthTexture())->lastActiveFrameSlot = currentFrameSlot;
+ if (rtTex->m_desc.depthResolveTexture())
+ QRHI_RES(QMetalTexture, rtTex->m_desc.depthResolveTexture())->lastActiveFrameSlot = currentFrameSlot;
}
break;
default:
@@ -2034,7 +3003,8 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
cbD->d->currentPassRpDesc.colorAttachments[i].depthPlane = NSUInteger(rtD->fb.colorAtt[i].slice);
cbD->d->currentPassRpDesc.colorAttachments[i].level = NSUInteger(rtD->fb.colorAtt[i].level);
if (rtD->fb.colorAtt[i].resolveTex) {
- cbD->d->currentPassRpDesc.colorAttachments[i].storeAction = MTLStoreActionMultisampleResolve;
+ cbD->d->currentPassRpDesc.colorAttachments[i].storeAction = rtD->fb.preserveColor ? MTLStoreActionStoreAndMultisampleResolve
+ : MTLStoreActionMultisampleResolve;
cbD->d->currentPassRpDesc.colorAttachments[i].resolveTexture = rtD->fb.colorAtt[i].resolveTex;
cbD->d->currentPassRpDesc.colorAttachments[i].resolveSlice = NSUInteger(rtD->fb.colorAtt[i].resolveLayer);
cbD->d->currentPassRpDesc.colorAttachments[i].resolveLevel = NSUInteger(rtD->fb.colorAtt[i].resolveLevel);
@@ -2047,6 +3017,15 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
cbD->d->currentPassRpDesc.stencilAttachment.texture = rtD->fb.hasStencil ? rtD->fb.dsTex : nil;
if (rtD->fb.depthNeedsStore) // Depth/Stencil is set to DontCare by default, override if needed
cbD->d->currentPassRpDesc.depthAttachment.storeAction = MTLStoreActionStore;
+ if (rtD->fb.dsResolveTex) {
+ cbD->d->currentPassRpDesc.depthAttachment.storeAction = rtD->fb.depthNeedsStore ? MTLStoreActionStoreAndMultisampleResolve
+ : MTLStoreActionMultisampleResolve;
+ cbD->d->currentPassRpDesc.depthAttachment.resolveTexture = rtD->fb.dsResolveTex;
+ if (rtD->fb.hasStencil) {
+ cbD->d->currentPassRpDesc.stencilAttachment.resolveTexture = rtD->fb.dsResolveTex;
+ cbD->d->currentPassRpDesc.stencilAttachment.storeAction = cbD->d->currentPassRpDesc.depthAttachment.storeAction;
+ }
+ }
}
cbD->d->currentRenderPassEncoder = [cbD->d->cb renderCommandEncoderWithDescriptor: cbD->d->currentPassRpDesc];
@@ -2104,9 +3083,9 @@ void QRhiMetal::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *p
Q_ASSERT(cbD->recordingPass == QMetalCommandBuffer::ComputePass);
QMetalComputePipeline *psD = QRHI_RES(QMetalComputePipeline, ps);
- if (cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
+ if (cbD->currentComputePipeline != psD || cbD->currentPipelineGeneration != psD->generation) {
cbD->currentGraphicsPipeline = nullptr;
- cbD->currentComputePipeline = ps;
+ cbD->currentComputePipeline = psD;
cbD->currentPipelineGeneration = psD->generation;
[cbD->d->currentComputePassEncoder setComputePipelineState: psD->d->ps];
@@ -2171,6 +3150,17 @@ void QRhiMetal::executeDeferredReleases(bool forced)
case QRhiMetalData::DeferredReleaseEntry::StagingBuffer:
[e.stagingBuffer.buffer release];
break;
+ case QRhiMetalData::DeferredReleaseEntry::GraphicsPipeline:
+ [e.graphicsPipeline.pipelineState release];
+ [e.graphicsPipeline.depthStencilState release];
+ [e.graphicsPipeline.tessVertexComputeState[0] release];
+ [e.graphicsPipeline.tessVertexComputeState[1] release];
+ [e.graphicsPipeline.tessVertexComputeState[2] release];
+ [e.graphicsPipeline.tessTessControlComputeState release];
+ break;
+ case QRhiMetalData::DeferredReleaseEntry::ComputePipeline:
+ [e.computePipeline.pipelineState release];
+ break;
default:
break;
}
@@ -2182,7 +3172,6 @@ void QRhiMetal::executeDeferredReleases(bool forced)
void QRhiMetal::finishActiveReadbacks(bool forced)
{
QVarLengthArray<std::function<void()>, 4> completedCallbacks;
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
for (int i = d->activeTextureReadbacks.count() - 1; i >= 0; --i) {
const QRhiMetalData::TextureReadback &readback(d->activeTextureReadbacks[i]);
@@ -2194,12 +3183,26 @@ void QRhiMetal::finishActiveReadbacks(bool forced)
memcpy(readback.result->data.data(), p, readback.bufSize);
[readback.buf release];
- QRHI_PROF_F(releaseReadbackBuffer(qint64(qintptr(readback.buf))));
+ if (readback.result->completed)
+ completedCallbacks.append(readback.result->completed);
+
+ d->activeTextureReadbacks.remove(i);
+ }
+ }
+
+ for (int i = d->activeBufferReadbacks.count() - 1; i >= 0; --i) {
+ const QRhiMetalData::BufferReadback &readback(d->activeBufferReadbacks[i]);
+ if (forced || currentFrameSlot == readback.activeFrameSlot
+ || readback.activeFrameSlot < 0) {
+ readback.result->data.resize(readback.readSize);
+ char *p = reinterpret_cast<char *>([readback.buf contents]);
+ Q_ASSERT(p);
+ memcpy(readback.result->data.data(), p + readback.offset, size_t(readback.readSize));
if (readback.result->completed)
completedCallbacks.append(readback.result->completed);
- d->activeTextureReadbacks.removeLast();
+ d->activeBufferReadbacks.remove(i);
}
}
@@ -2207,7 +3210,7 @@ void QRhiMetal::finishActiveReadbacks(bool forced)
f();
}
-QMetalBuffer::QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+QMetalBuffer::QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
: QRhiBuffer(rhi, type, usage, size),
d(new QMetalBufferData)
{
@@ -2237,10 +3240,10 @@ void QMetalBuffer::destroy()
}
QRHI_RES_RHI(QRhiMetal);
- rhiD->d->releaseQueue.append(e);
- QRHI_PROF;
- QRHI_PROF_F(releaseBuffer(this));
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->d->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QMetalBuffer::create()
@@ -2253,13 +3256,15 @@ bool QMetalBuffer::create()
return false;
}
- const uint nonZeroSize = m_size <= 0 ? 256 : uint(m_size);
- const uint roundedSize = m_usage.testFlag(QRhiBuffer::UniformBuffer) ? aligned<uint>(nonZeroSize, 256) : nonZeroSize;
+ const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
+ const quint32 roundedSize = m_usage.testFlag(QRhiBuffer::UniformBuffer) ? aligned(nonZeroSize, 256u) : nonZeroSize;
d->managed = false;
MTLResourceOptions opts = MTLResourceStorageModeShared;
+
+ QRHI_RES_RHI(QRhiMetal);
#ifdef Q_OS_MACOS
- if (m_type != Dynamic) {
+ if (!rhiD->caps.isAppleGPU && m_type != Dynamic) {
opts = MTLResourceStorageModeManaged;
d->managed = true;
}
@@ -2270,8 +3275,10 @@ bool QMetalBuffer::create()
// Static maps to on macOS) is not safe when another frame reading from the
// same buffer is still in flight.
d->slotted = !m_usage.testFlag(QRhiBuffer::StorageBuffer); // except for SSBOs written in the shader
+ // and a special case for internal work buffers
+ if (int(m_usage) == WorkBufPoolUsage)
+ d->slotted = false;
- QRHI_RES_RHI(QRhiMetal);
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
if (i == 0 || d->slotted) {
d->buf[i] = [rhiD->d->dev newBufferWithLength: roundedSize options: opts];
@@ -2286,9 +3293,6 @@ bool QMetalBuffer::create()
}
}
- QRHI_PROF;
- QRHI_PROF_F(newBuffer(this, roundedSize, d->slotted ? QMTL_FRAMES_IN_FLIGHT : 1, 0));
-
lastActiveFrameSlot = -1;
generation += 1;
rhiD->registerResource(this);
@@ -2337,11 +3341,12 @@ void QMetalBuffer::endFullDynamicBufferUpdateForCurrentFrame()
#endif
}
-static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags, const QRhiMetalData *d)
+static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QRhiTexture::Flags flags, const QRhiMetal *d)
{
#ifndef Q_OS_MACOS
Q_UNUSED(d);
#endif
+
const bool srgb = flags.testFlag(QRhiTexture::sRGB);
switch (format) {
case QRhiTexture::RGBA8:
@@ -2376,13 +3381,16 @@ static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QR
case QRhiTexture::R32F:
return MTLPixelFormatR32Float;
+ case QRhiTexture::RGB10A2:
+ return MTLPixelFormatRGB10A2Unorm;
+
#ifdef Q_OS_MACOS
case QRhiTexture::D16:
return MTLPixelFormatDepth16Unorm;
case QRhiTexture::D24:
- return [d->dev isDepth24Stencil8PixelFormatSupported] ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float;
+ return [d->d->dev isDepth24Stencil8PixelFormatSupported] ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float;
case QRhiTexture::D24S8:
- return [d->dev isDepth24Stencil8PixelFormatSupported] ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
+ return [d->d->dev isDepth24Stencil8PixelFormatSupported] ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
#else
case QRhiTexture::D16:
return MTLPixelFormatDepth32Float;
@@ -2405,7 +3413,7 @@ static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QR
return MTLPixelFormatBC4_RUnorm;
case QRhiTexture::BC5:
qWarning("QRhiMetal does not support BC5");
- return MTLPixelFormatRGBA8Unorm;
+ return MTLPixelFormatInvalid;
case QRhiTexture::BC6H:
return MTLPixelFormatBC6H_RGBUfloat;
case QRhiTexture::BC7:
@@ -2419,7 +3427,7 @@ static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QR
case QRhiTexture::BC6H:
case QRhiTexture::BC7:
qWarning("QRhiMetal: BCx compression not supported on this platform");
- return MTLPixelFormatRGBA8Unorm;
+ return MTLPixelFormatInvalid;
#endif
#ifndef Q_OS_MACOS
@@ -2460,32 +3468,129 @@ static inline MTLPixelFormat toMetalTextureFormat(QRhiTexture::Format format, QR
return srgb ? MTLPixelFormatASTC_12x12_sRGB : MTLPixelFormatASTC_12x12_LDR;
#else
case QRhiTexture::ETC2_RGB8:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatETC2_RGB8_sRGB : MTLPixelFormatETC2_RGB8;
+ }
+ qWarning("QRhiMetal: ETC2 compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ETC2_RGB8A1:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatETC2_RGB8A1_sRGB : MTLPixelFormatETC2_RGB8A1;
+ }
+ qWarning("QRhiMetal: ETC2 compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ETC2_RGBA8:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatEAC_RGBA8_sRGB : MTLPixelFormatEAC_RGBA8;
+ }
qWarning("QRhiMetal: ETC2 compression not supported on this platform");
- return MTLPixelFormatRGBA8Unorm;
-
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_4x4:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_4x4_sRGB : MTLPixelFormatASTC_4x4_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_5x4:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_5x4_sRGB : MTLPixelFormatASTC_5x4_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_5x5:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_5x5_sRGB : MTLPixelFormatASTC_5x5_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_6x5:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_6x5_sRGB : MTLPixelFormatASTC_6x5_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_6x6:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_6x6_sRGB : MTLPixelFormatASTC_6x6_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_8x5:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_8x5_sRGB : MTLPixelFormatASTC_8x5_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_8x6:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_8x6_sRGB : MTLPixelFormatASTC_8x6_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_8x8:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_8x8_sRGB : MTLPixelFormatASTC_8x8_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_10x5:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_10x5_sRGB : MTLPixelFormatASTC_10x5_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_10x6:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_10x6_sRGB : MTLPixelFormatASTC_10x6_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_10x8:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_10x8_sRGB : MTLPixelFormatASTC_10x8_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_10x10:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_10x10_sRGB : MTLPixelFormatASTC_10x10_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_12x10:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_12x10_sRGB : MTLPixelFormatASTC_12x10_LDR;
+ }
+ qWarning("QRhiMetal: ASTC compression not supported on this platform");
+ return MTLPixelFormatInvalid;
case QRhiTexture::ASTC_12x12:
+ if (d->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *))
+ return srgb ? MTLPixelFormatASTC_12x12_sRGB : MTLPixelFormatASTC_12x12_LDR;
+ }
qWarning("QRhiMetal: ASTC compression not supported on this platform");
- return MTLPixelFormatRGBA8Unorm;
+ return MTLPixelFormatInvalid;
#endif
default:
Q_UNREACHABLE();
- return MTLPixelFormatRGBA8Unorm;
+ return MTLPixelFormatInvalid;
}
}
@@ -2516,10 +3621,10 @@ void QMetalRenderBuffer::destroy()
d->tex = nil;
QRHI_RES_RHI(QRhiMetal);
- rhiD->d->releaseQueue.append(e);
- QRHI_PROF;
- QRHI_PROF_F(releaseRenderBuffer(this));
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->d->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QMetalRenderBuffer::create()
@@ -2542,16 +3647,23 @@ bool QMetalRenderBuffer::create()
desc.resourceOptions = MTLResourceStorageModePrivate;
desc.usage = MTLTextureUsageRenderTarget;
- bool transientBacking = false;
switch (m_type) {
case DepthStencil:
#ifdef Q_OS_MACOS
- desc.storageMode = MTLStorageModePrivate;
- d->format = rhiD->d->dev.depth24Stencil8PixelFormatSupported
- ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
+ if (rhiD->caps.isAppleGPU) {
+ if (@available(macOS 11.0, *)) {
+ desc.storageMode = MTLStorageModeMemoryless;
+ d->format = MTLPixelFormatDepth32Float_Stencil8;
+ } else {
+ Q_UNREACHABLE();
+ }
+ } else {
+ desc.storageMode = MTLStorageModePrivate;
+ d->format = rhiD->d->dev.depth24Stencil8PixelFormatSupported
+ ? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
+ }
#else
desc.storageMode = MTLStorageModeMemoryless;
- transientBacking = true;
d->format = MTLPixelFormatDepth32Float_Stencil8;
#endif
desc.pixelFormat = d->format;
@@ -2559,7 +3671,7 @@ bool QMetalRenderBuffer::create()
case Color:
desc.storageMode = MTLStorageModePrivate;
if (m_backingFormatHint != QRhiTexture::UnknownFormat)
- d->format = toMetalTextureFormat(m_backingFormatHint, {}, rhiD->d);
+ d->format = toMetalTextureFormat(m_backingFormatHint, {}, rhiD);
else
d->format = MTLPixelFormatRGBA8Unorm;
desc.pixelFormat = d->format;
@@ -2575,9 +3687,6 @@ bool QMetalRenderBuffer::create()
if (!m_objectName.isEmpty())
d->tex.label = [NSString stringWithUTF8String: m_objectName.constData()];
- QRHI_PROF;
- QRHI_PROF_F(newRenderBuffer(this, transientBacking, false, samples));
-
lastActiveFrameSlot = -1;
generation += 1;
rhiD->registerResource(this);
@@ -2593,8 +3702,8 @@ QRhiTexture::Format QMetalRenderBuffer::backingFormat() const
}
QMetalTexture::QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags),
+ int arraySize, int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, arraySize, sampleCount, flags),
d(new QMetalTextureData(this))
{
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
@@ -2633,10 +3742,10 @@ void QMetalTexture::destroy()
}
QRHI_RES_RHI(QRhiMetal);
- rhiD->d->releaseQueue.append(e);
- QRHI_PROF;
- QRHI_PROF_F(releaseTexture(this));
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->d->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QMetalTexture::prepareCreate(QSize *adjustedSize)
@@ -2644,13 +3753,17 @@ bool QMetalTexture::prepareCreate(QSize *adjustedSize)
if (d->tex)
destroy();
- const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
const bool isCube = m_flags.testFlag(CubeMap);
const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool isArray = m_flags.testFlag(TextureArray);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
+ const bool is1D = m_flags.testFlag(OneDimensional);
+
+ const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
+ : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
QRHI_RES_RHI(QRhiMetal);
- d->format = toMetalTextureFormat(m_format, m_flags, rhiD->d);
+ d->format = toMetalTextureFormat(m_format, m_flags, rhiD);
mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
samples = rhiD->effectiveSampleCount(m_sampleCount);
if (samples > 1) {
@@ -2671,11 +3784,30 @@ bool QMetalTexture::prepareCreate(QSize *adjustedSize)
qWarning("Texture cannot be both cube and 3D");
return false;
}
- m_depth = qMax(1, m_depth);
+ if (isArray && is3D) {
+ qWarning("Texture cannot be both array and 3D");
+ return false;
+ }
+ if (is1D && is3D) {
+ qWarning("Texture cannot be both 1D and 3D");
+ return false;
+ }
+ if (is1D && isCube) {
+ qWarning("Texture cannot be both 1D and cube");
+ return false;
+ }
if (m_depth > 1 && !is3D) {
qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
return false;
}
+ if (m_arraySize > 0 && !isArray) {
+ qWarning("Texture cannot have an array size of %d when it is not an array", m_arraySize);
+ return false;
+ }
+ if (m_arraySize < 1 && isArray) {
+ qWarning("Texture is an array but array size is %d", m_arraySize);
+ return false;
+ }
if (adjustedSize)
*adjustedSize = size;
@@ -2693,19 +3825,36 @@ bool QMetalTexture::create()
const bool isCube = m_flags.testFlag(CubeMap);
const bool is3D = m_flags.testFlag(ThreeDimensional);
- if (isCube)
+ const bool isArray = m_flags.testFlag(TextureArray);
+ const bool is1D = m_flags.testFlag(OneDimensional);
+ if (isCube) {
desc.textureType = MTLTextureTypeCube;
- else if (is3D)
+ } else if (is3D) {
desc.textureType = MTLTextureType3D;
- else
+ } else if (is1D) {
+ desc.textureType = isArray ? MTLTextureType1DArray : MTLTextureType1D;
+ } else if (isArray) {
+#ifdef Q_OS_IOS
+ if (@available(iOS 14, *)) {
+ desc.textureType = samples > 1 ? MTLTextureType2DMultisampleArray : MTLTextureType2DArray;
+ } else {
+ desc.textureType = MTLTextureType2DArray;
+ }
+#else
+ desc.textureType = samples > 1 ? MTLTextureType2DMultisampleArray : MTLTextureType2DArray;
+#endif
+ } else {
desc.textureType = samples > 1 ? MTLTextureType2DMultisample : MTLTextureType2D;
+ }
desc.pixelFormat = d->format;
desc.width = NSUInteger(size.width());
desc.height = NSUInteger(size.height());
- desc.depth = is3D ? m_depth : 1;
+ desc.depth = is3D ? qMax(1, m_depth) : 1;
desc.mipmapLevelCount = NSUInteger(mipLevelCount);
if (samples > 1)
desc.sampleCount = NSUInteger(samples);
+ if (isArray)
+ desc.arrayLength = NSUInteger(qMax(0, m_arraySize));
desc.resourceOptions = MTLResourceStorageModePrivate;
desc.storageMode = MTLStorageModePrivate;
desc.usage = MTLTextureUsageShaderRead;
@@ -2723,9 +3872,6 @@ bool QMetalTexture::create()
d->owns = true;
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, true, mipLevelCount, isCube ? 6 : 1, samples));
-
lastActiveFrameSlot = -1;
generation += 1;
rhiD->registerResource(this);
@@ -2745,9 +3891,6 @@ bool QMetalTexture::createFrom(QRhiTexture::NativeTexture src)
d->owns = false;
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, false, mipLevelCount, m_flags.testFlag(CubeMap) ? 6 : 1, samples));
-
lastActiveFrameSlot = -1;
generation += 1;
QRHI_RES_RHI(QRhiMetal);
@@ -2768,8 +3911,10 @@ id<MTLTexture> QMetalTextureData::viewForLevel(int level)
const MTLTextureType type = [tex textureType];
const bool isCube = q->m_flags.testFlag(QRhiTexture::CubeMap);
+ const bool isArray = q->m_flags.testFlag(QRhiTexture::TextureArray);
id<MTLTexture> view = [tex newTextureViewWithPixelFormat: format textureType: type
- levels: NSMakeRange(NSUInteger(level), 1) slices: NSMakeRange(0, isCube ? 6 : 1)];
+ levels: NSMakeRange(NSUInteger(level), 1)
+ slices: NSMakeRange(0, isCube ? 6 : (isArray ? qMax(0, q->m_arraySize) : 1))];
perLevelViews[level] = view;
return view;
@@ -2801,8 +3946,10 @@ void QMetalSampler::destroy()
d->samplerState = nil;
QRHI_RES_RHI(QRhiMetal);
- rhiD->d->releaseQueue.append(e);
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->d->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
static inline MTLSamplerMinMagFilter toMetalFilter(QRhiSampler::Filter f)
@@ -2902,6 +4049,7 @@ bool QMetalSampler::create()
QMetalRenderPassDescriptor::QMetalRenderPassDescriptor(QRhiImplementation *rhi)
: QRhiRenderPassDescriptor(rhi)
{
+ serializedFormatData.reserve(16);
}
QMetalRenderPassDescriptor::~QMetalRenderPassDescriptor()
@@ -2911,7 +4059,9 @@ QMetalRenderPassDescriptor::~QMetalRenderPassDescriptor()
void QMetalRenderPassDescriptor::destroy()
{
- // nothing to do here
+ QRHI_RES_RHI(QRhiMetal);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QMetalRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
@@ -2940,44 +4090,66 @@ bool QMetalRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *ot
return true;
}
+void QMetalRenderPassDescriptor::updateSerializedFormat()
+{
+ serializedFormatData.clear();
+ auto p = std::back_inserter(serializedFormatData);
+
+ *p++ = colorAttachmentCount;
+ *p++ = hasDepthStencil;
+ for (int i = 0; i < colorAttachmentCount; ++i)
+ *p++ = colorFormat[i];
+ *p++ = hasDepthStencil ? dsFormat : 0;
+}
+
QRhiRenderPassDescriptor *QMetalRenderPassDescriptor::newCompatibleRenderPassDescriptor() const
{
- QMetalRenderPassDescriptor *rp = new QMetalRenderPassDescriptor(m_rhi);
- rp->colorAttachmentCount = colorAttachmentCount;
- rp->hasDepthStencil = hasDepthStencil;
- memcpy(rp->colorFormat, colorFormat, sizeof(colorFormat));
- rp->dsFormat = dsFormat;
- return rp;
+ QMetalRenderPassDescriptor *rpD = new QMetalRenderPassDescriptor(m_rhi);
+ rpD->colorAttachmentCount = colorAttachmentCount;
+ rpD->hasDepthStencil = hasDepthStencil;
+ memcpy(rpD->colorFormat, colorFormat, sizeof(colorFormat));
+ rpD->dsFormat = dsFormat;
+
+ rpD->updateSerializedFormat();
+
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
-QMetalReferenceRenderTarget::QMetalReferenceRenderTarget(QRhiImplementation *rhi)
- : QRhiRenderTarget(rhi),
+QVector<quint32> QMetalRenderPassDescriptor::serializedFormat() const
+{
+ return serializedFormatData;
+}
+
+QMetalSwapChainRenderTarget::QMetalSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
+ : QRhiSwapChainRenderTarget(rhi, swapchain),
d(new QMetalRenderTargetData)
{
}
-QMetalReferenceRenderTarget::~QMetalReferenceRenderTarget()
+QMetalSwapChainRenderTarget::~QMetalSwapChainRenderTarget()
{
destroy();
delete d;
}
-void QMetalReferenceRenderTarget::destroy()
+void QMetalSwapChainRenderTarget::destroy()
{
// nothing to do here
}
-QSize QMetalReferenceRenderTarget::pixelSize() const
+QSize QMetalSwapChainRenderTarget::pixelSize() const
{
return d->pixelSize;
}
-float QMetalReferenceRenderTarget::devicePixelRatio() const
+float QMetalSwapChainRenderTarget::devicePixelRatio() const
{
return d->dpr;
}
-int QMetalReferenceRenderTarget::sampleCount() const
+int QMetalSwapChainRenderTarget::sampleCount() const
{
return d->sampleCount;
}
@@ -2998,12 +4170,14 @@ QMetalTextureRenderTarget::~QMetalTextureRenderTarget()
void QMetalTextureRenderTarget::destroy()
{
- // nothing to do here
+ QRHI_RES_RHI(QRhiMetal);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDescriptor()
{
- const int colorAttachmentCount = m_desc.cendColorAttachments() - m_desc.cbeginColorAttachments();
+ const int colorAttachmentCount = int(m_desc.colorAttachmentCount());
QMetalRenderPassDescriptor *rpD = new QMetalRenderPassDescriptor(m_rhi);
rpD->colorAttachmentCount = colorAttachmentCount;
rpD->hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
@@ -3020,14 +4194,17 @@ QRhiRenderPassDescriptor *QMetalTextureRenderTarget::newCompatibleRenderPassDesc
else if (m_desc.depthStencilBuffer())
rpD->dsFormat = int(QRHI_RES(QMetalRenderBuffer, m_desc.depthStencilBuffer())->d->format);
+ rpD->updateSerializedFormat();
+
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->registerResource(rpD, false);
return rpD;
}
bool QMetalTextureRenderTarget::create()
{
QRHI_RES_RHI(QRhiMetal);
- const bool hasColorAttachments = m_desc.cbeginColorAttachments() != m_desc.cendColorAttachments();
- Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
+ Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
@@ -3071,8 +4248,9 @@ bool QMetalTextureRenderTarget::create()
if (m_desc.depthTexture()) {
QMetalTexture *depthTexD = QRHI_RES(QMetalTexture, m_desc.depthTexture());
d->fb.dsTex = depthTexD->d->tex;
- d->fb.hasStencil = false;
- d->fb.depthNeedsStore = true;
+ d->fb.hasStencil = rhiD->isStencilSupportingFormat(depthTexD->format());
+ d->fb.depthNeedsStore = !m_flags.testFlag(DoNotStoreDepthStencilContents) && !m_desc.depthResolveTexture();
+ d->fb.preserveDs = m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
if (d->colorAttCount == 0) {
d->pixelSize = depthTexD->pixelSize();
d->sampleCount = depthTexD->samples;
@@ -3082,21 +4260,35 @@ bool QMetalTextureRenderTarget::create()
d->fb.dsTex = depthRbD->d->tex;
d->fb.hasStencil = true;
d->fb.depthNeedsStore = false;
+ d->fb.preserveDs = false;
if (d->colorAttCount == 0) {
d->pixelSize = depthRbD->pixelSize();
d->sampleCount = depthRbD->samples;
}
}
+ if (m_desc.depthResolveTexture()) {
+ QMetalTexture *depthResolveTexD = QRHI_RES(QMetalTexture, m_desc.depthResolveTexture());
+ d->fb.dsResolveTex = depthResolveTexD->d->tex;
+ }
d->dsAttCount = 1;
} else {
d->dsAttCount = 0;
}
+ if (d->colorAttCount > 0)
+ d->fb.preserveColor = m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
+
+ QRhiRenderTargetAttachmentTracker::updateResIdList<QMetalTexture, QMetalRenderBuffer>(m_desc, &d->currentResIdList);
+
+ rhiD->registerResource(this, false);
return true;
}
QSize QMetalTextureRenderTarget::pixelSize() const
{
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QMetalTexture, QMetalRenderBuffer>(m_desc, d->currentResIdList))
+ const_cast<QMetalTextureRenderTarget *>(this)->create();
+
return d->pixelSize;
}
@@ -3124,6 +4316,10 @@ void QMetalShaderResourceBindings::destroy()
{
sortedBindings.clear();
maxBinding = -1;
+
+ QRHI_RES_RHI(QRhiMetal);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QMetalShaderResourceBindings::create()
@@ -3138,13 +4334,9 @@ bool QMetalShaderResourceBindings::create()
rhiD->updateLayoutDesc(this);
std::copy(m_bindings.cbegin(), m_bindings.cend(), std::back_inserter(sortedBindings));
- std::sort(sortedBindings.begin(), sortedBindings.end(),
- [](const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
- {
- return a.data()->binding < b.data()->binding;
- });
+ std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
if (!sortedBindings.isEmpty())
- maxBinding = sortedBindings.last().data()->binding;
+ maxBinding = QRhiImplementation::shaderResourceBindingData(sortedBindings.last())->binding;
else
maxBinding = -1;
@@ -3154,13 +4346,29 @@ bool QMetalShaderResourceBindings::create()
memset(&bd, 0, sizeof(BoundResourceData));
generation += 1;
+ rhiD->registerResource(this, false);
return true;
}
+void QMetalShaderResourceBindings::updateResources(UpdateFlags flags)
+{
+ sortedBindings.clear();
+ std::copy(m_bindings.cbegin(), m_bindings.cend(), std::back_inserter(sortedBindings));
+ if (!flags.testFlag(BindingsAreSorted))
+ std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
+
+ for (BoundResourceData &bd : boundResourceData)
+ memset(&bd, 0, sizeof(BoundResourceData));
+
+ generation += 1;
+}
+
QMetalGraphicsPipeline::QMetalGraphicsPipeline(QRhiImplementation *rhi)
: QRhiGraphicsPipeline(rhi),
d(new QMetalGraphicsPipelineData)
{
+ d->q = this;
+ d->tess.q = d;
}
QMetalGraphicsPipeline::~QMetalGraphicsPipeline()
@@ -3171,21 +4379,48 @@ QMetalGraphicsPipeline::~QMetalGraphicsPipeline()
void QMetalGraphicsPipeline::destroy()
{
- QRHI_RES_RHI(QRhiMetal);
-
d->vs.destroy();
d->fs.destroy();
- [d->ds release];
- d->ds = nil;
+ d->tess.compVs[0].destroy();
+ d->tess.compVs[1].destroy();
+ d->tess.compVs[2].destroy();
- if (!d->ps)
+ d->tess.compTesc.destroy();
+ d->tess.vertTese.destroy();
+
+ qDeleteAll(d->extraBufMgr.deviceLocalWorkBuffers);
+ d->extraBufMgr.deviceLocalWorkBuffers.clear();
+ qDeleteAll(d->extraBufMgr.hostVisibleWorkBuffers);
+ d->extraBufMgr.hostVisibleWorkBuffers.clear();
+
+ delete d->bufferSizeBuffer;
+ d->bufferSizeBuffer = nullptr;
+
+ if (!d->ps && !d->ds
+ && !d->tess.vertexComputeState[0] && !d->tess.vertexComputeState[1] && !d->tess.vertexComputeState[2]
+ && !d->tess.tessControlComputeState)
+ {
return;
+ }
- [d->ps release];
+ QRhiMetalData::DeferredReleaseEntry e;
+ e.type = QRhiMetalData::DeferredReleaseEntry::GraphicsPipeline;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+ e.graphicsPipeline.pipelineState = d->ps;
+ e.graphicsPipeline.depthStencilState = d->ds;
+ e.graphicsPipeline.tessVertexComputeState = d->tess.vertexComputeState;
+ e.graphicsPipeline.tessTessControlComputeState = d->tess.tessControlComputeState;
d->ps = nil;
+ d->ds = nil;
+ d->tess.vertexComputeState = {};
+ d->tess.tessControlComputeState = nil;
- rhiD->unregisterResource(this);
+ QRHI_RES_RHI(QRhiMetal);
+ if (rhiD) {
+ rhiD->d->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
static inline MTLVertexFormat toMetalAttributeFormat(QRhiVertexInputAttribute::Format format)
@@ -3221,6 +4456,30 @@ static inline MTLVertexFormat toMetalAttributeFormat(QRhiVertexInputAttribute::F
return MTLVertexFormatInt2;
case QRhiVertexInputAttribute::SInt:
return MTLVertexFormatInt;
+ case QRhiVertexInputAttribute::Half4:
+ return MTLVertexFormatHalf4;
+ case QRhiVertexInputAttribute::Half3:
+ return MTLVertexFormatHalf3;
+ case QRhiVertexInputAttribute::Half2:
+ return MTLVertexFormatHalf2;
+ case QRhiVertexInputAttribute::Half:
+ return MTLVertexFormatHalf;
+ case QRhiVertexInputAttribute::UShort4:
+ return MTLVertexFormatUShort4;
+ case QRhiVertexInputAttribute::UShort3:
+ return MTLVertexFormatUShort3;
+ case QRhiVertexInputAttribute::UShort2:
+ return MTLVertexFormatUShort2;
+ case QRhiVertexInputAttribute::UShort:
+ return MTLVertexFormatUShort;
+ case QRhiVertexInputAttribute::SShort4:
+ return MTLVertexFormatShort4;
+ case QRhiVertexInputAttribute::SShort3:
+ return MTLVertexFormatShort3;
+ case QRhiVertexInputAttribute::SShort2:
+ return MTLVertexFormatShort2;
+ case QRhiVertexInputAttribute::SShort:
+ return MTLVertexFormatShort;
default:
Q_UNREACHABLE();
return MTLVertexFormatFloat4;
@@ -3376,6 +4635,24 @@ static inline MTLPrimitiveType toMetalPrimitiveType(QRhiGraphicsPipeline::Topolo
}
}
+static inline MTLPrimitiveTopologyClass toMetalPrimitiveTopologyClass(QRhiGraphicsPipeline::Topology t)
+{
+ switch (t) {
+ case QRhiGraphicsPipeline::Triangles:
+ case QRhiGraphicsPipeline::TriangleStrip:
+ case QRhiGraphicsPipeline::TriangleFan:
+ return MTLPrimitiveTopologyClassTriangle;
+ case QRhiGraphicsPipeline::Lines:
+ case QRhiGraphicsPipeline::LineStrip:
+ return MTLPrimitiveTopologyClassLine;
+ case QRhiGraphicsPipeline::Points:
+ return MTLPrimitiveTopologyClassPoint;
+ default:
+ Q_UNREACHABLE();
+ return MTLPrimitiveTopologyClassTriangle;
+ }
+}
+
static inline MTLCullMode toMetalCullMode(QRhiGraphicsPipeline::CullMode c)
{
switch (c) {
@@ -3391,15 +4668,80 @@ static inline MTLCullMode toMetalCullMode(QRhiGraphicsPipeline::CullMode c)
}
}
+static inline MTLTriangleFillMode toMetalTriangleFillMode(QRhiGraphicsPipeline::PolygonMode mode)
+{
+ switch (mode) {
+ case QRhiGraphicsPipeline::Fill:
+ return MTLTriangleFillModeFill;
+ case QRhiGraphicsPipeline::Line:
+ return MTLTriangleFillModeLines;
+ default:
+ Q_UNREACHABLE();
+ return MTLTriangleFillModeFill;
+ }
+}
+
+static inline MTLWinding toMetalTessellationWindingOrder(QShaderDescription::TessellationWindingOrder w)
+{
+ switch (w) {
+ case QShaderDescription::CwTessellationWindingOrder:
+ return MTLWindingClockwise;
+ case QShaderDescription::CcwTessellationWindingOrder:
+ return MTLWindingCounterClockwise;
+ default:
+ // this is reachable, consider a tess.eval. shader not declaring it, the value is then Unknown
+ return MTLWindingCounterClockwise;
+ }
+}
+
+static inline MTLTessellationPartitionMode toMetalTessellationPartitionMode(QShaderDescription::TessellationPartitioning p)
+{
+ switch (p) {
+ case QShaderDescription::EqualTessellationPartitioning:
+ return MTLTessellationPartitionModePow2;
+ case QShaderDescription::FractionalEvenTessellationPartitioning:
+ return MTLTessellationPartitionModeFractionalEven;
+ case QShaderDescription::FractionalOddTessellationPartitioning:
+ return MTLTessellationPartitionModeFractionalOdd;
+ default:
+ // this is reachable, consider a tess.eval. shader not declaring it, the value is then Unknown
+ return MTLTessellationPartitionModePow2;
+ }
+}
+
+static inline MTLLanguageVersion toMetalLanguageVersion(const QShaderVersion &version)
+{
+ int v = version.version();
+ return MTLLanguageVersion(((v / 10) << 16) + (v % 10));
+}
+
id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Variant shaderVariant,
QString *error, QByteArray *entryPoint, QShaderKey *activeKey)
{
- QShaderKey key = { QShader::MetalLibShader, 20, shaderVariant };
- QShaderCode mtllib = shader.shader(key);
- if (mtllib.shader().isEmpty()) {
- key.setSourceVersion(12);
- mtllib = shader.shader(key);
+ QVarLengthArray<int, 8> versions;
+ if (@available(macOS 13, iOS 16, *))
+ versions << 30;
+ if (@available(macOS 12, iOS 15, *))
+ versions << 24;
+ if (@available(macOS 11, iOS 14, *))
+ versions << 23;
+ if (@available(macOS 10.15, iOS 13, *))
+ versions << 22;
+ if (@available(macOS 10.14, iOS 12, *))
+ versions << 21;
+ versions << 20 << 12;
+
+ const QList<QShaderKey> shaders = shader.availableShaders();
+
+ QShaderKey key;
+
+ for (const int &version : versions) {
+ key = { QShader::Source::MetalLibShader, version, shaderVariant };
+ if (shaders.contains(key))
+ break;
}
+
+ QShaderCode mtllib = shader.shader(key);
if (!mtllib.shader().isEmpty()) {
dispatch_data_t data = dispatch_data_create(mtllib.shader().constData(),
size_t(mtllib.shader().size()),
@@ -3418,12 +4760,13 @@ id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Var
}
}
- key = { QShader::MslShader, 20, shaderVariant };
- QShaderCode mslSource = shader.shader(key);
- if (mslSource.shader().isEmpty()) {
- key.setSourceVersion(12);
- mslSource = shader.shader(key);
+ for (const int &version : versions) {
+ key = { QShader::Source::MslShader, version, shaderVariant };
+ if (shaders.contains(key))
+ break;
}
+
+ QShaderCode mslSource = shader.shader(key);
if (mslSource.shader().isEmpty()) {
qWarning() << "No MSL 2.0 or 1.2 code found in baked shader" << shader;
return nil;
@@ -3431,7 +4774,7 @@ id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Var
NSString *src = [NSString stringWithUTF8String: mslSource.shader().constData()];
MTLCompileOptions *opts = [[MTLCompileOptions alloc] init];
- opts.languageVersion = key.sourceVersion() == 20 ? MTLLanguageVersion2_0 : MTLLanguageVersion1_2;
+ opts.languageVersion = toMetalLanguageVersion(key.sourceVersion());
NSError *err = nil;
id<MTLLibrary> lib = [dev newLibraryWithSource: src options: opts error: &err];
[opts release];
@@ -3453,55 +4796,192 @@ id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Var
id<MTLFunction> QRhiMetalData::createMSLShaderFunction(id<MTLLibrary> lib, const QByteArray &entryPoint)
{
- NSString *name = [NSString stringWithUTF8String: entryPoint.constData()];
- id<MTLFunction> f = [lib newFunctionWithName: name];
- [name release];
- return f;
+ return [lib newFunctionWithName:[NSString stringWithUTF8String:entryPoint.constData()]];
}
-bool QMetalGraphicsPipeline::create()
+void QMetalGraphicsPipeline::setupAttachmentsInMetalRenderPassDescriptor(void *metalRpDesc, QMetalRenderPassDescriptor *rpD)
{
- if (d->ps)
- destroy();
+ MTLRenderPipelineDescriptor *rpDesc = reinterpret_cast<MTLRenderPipelineDescriptor *>(metalRpDesc);
+
+ if (rpD->colorAttachmentCount) {
+ // defaults when no targetBlends are provided
+ rpDesc.colorAttachments[0].pixelFormat = MTLPixelFormat(rpD->colorFormat[0]);
+ rpDesc.colorAttachments[0].writeMask = MTLColorWriteMaskAll;
+ rpDesc.colorAttachments[0].blendingEnabled = false;
+
+ Q_ASSERT(m_targetBlends.count() == rpD->colorAttachmentCount
+ || (m_targetBlends.isEmpty() && rpD->colorAttachmentCount == 1));
+
+ for (uint i = 0, ie = uint(m_targetBlends.count()); i != ie; ++i) {
+ const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[int(i)]);
+ rpDesc.colorAttachments[i].pixelFormat = MTLPixelFormat(rpD->colorFormat[i]);
+ rpDesc.colorAttachments[i].blendingEnabled = b.enable;
+ rpDesc.colorAttachments[i].sourceRGBBlendFactor = toMetalBlendFactor(b.srcColor);
+ rpDesc.colorAttachments[i].destinationRGBBlendFactor = toMetalBlendFactor(b.dstColor);
+ rpDesc.colorAttachments[i].rgbBlendOperation = toMetalBlendOp(b.opColor);
+ rpDesc.colorAttachments[i].sourceAlphaBlendFactor = toMetalBlendFactor(b.srcAlpha);
+ rpDesc.colorAttachments[i].destinationAlphaBlendFactor = toMetalBlendFactor(b.dstAlpha);
+ rpDesc.colorAttachments[i].alphaBlendOperation = toMetalBlendOp(b.opAlpha);
+ rpDesc.colorAttachments[i].writeMask = toMetalColorWriteMask(b.colorWrite);
+ }
+ }
+
+ if (rpD->hasDepthStencil) {
+ // Must only be set when a depth-stencil buffer will actually be bound,
+ // validation blows up otherwise.
+ MTLPixelFormat fmt = MTLPixelFormat(rpD->dsFormat);
+ rpDesc.depthAttachmentPixelFormat = fmt;
+#if defined(Q_OS_MACOS)
+ if (fmt != MTLPixelFormatDepth16Unorm && fmt != MTLPixelFormatDepth32Float)
+#else
+ if (fmt != MTLPixelFormatDepth32Float)
+#endif
+ rpDesc.stencilAttachmentPixelFormat = fmt;
+ }
QRHI_RES_RHI(QRhiMetal);
- if (!rhiD->sanityCheckGraphicsPipeline(this))
- return false;
+ rpDesc.sampleCount = NSUInteger(rhiD->effectiveSampleCount(m_sampleCount));
+}
+
+void QMetalGraphicsPipeline::setupMetalDepthStencilDescriptor(void *metalDsDesc)
+{
+ MTLDepthStencilDescriptor *dsDesc = reinterpret_cast<MTLDepthStencilDescriptor *>(metalDsDesc);
+
+ dsDesc.depthCompareFunction = m_depthTest ? toMetalCompareOp(m_depthOp) : MTLCompareFunctionAlways;
+ dsDesc.depthWriteEnabled = m_depthWrite;
+ if (m_stencilTest) {
+ dsDesc.frontFaceStencil = [[MTLStencilDescriptor alloc] init];
+ dsDesc.frontFaceStencil.stencilFailureOperation = toMetalStencilOp(m_stencilFront.failOp);
+ dsDesc.frontFaceStencil.depthFailureOperation = toMetalStencilOp(m_stencilFront.depthFailOp);
+ dsDesc.frontFaceStencil.depthStencilPassOperation = toMetalStencilOp(m_stencilFront.passOp);
+ dsDesc.frontFaceStencil.stencilCompareFunction = toMetalCompareOp(m_stencilFront.compareOp);
+ dsDesc.frontFaceStencil.readMask = m_stencilReadMask;
+ dsDesc.frontFaceStencil.writeMask = m_stencilWriteMask;
+
+ dsDesc.backFaceStencil = [[MTLStencilDescriptor alloc] init];
+ dsDesc.backFaceStencil.stencilFailureOperation = toMetalStencilOp(m_stencilBack.failOp);
+ dsDesc.backFaceStencil.depthFailureOperation = toMetalStencilOp(m_stencilBack.depthFailOp);
+ dsDesc.backFaceStencil.depthStencilPassOperation = toMetalStencilOp(m_stencilBack.passOp);
+ dsDesc.backFaceStencil.stencilCompareFunction = toMetalCompareOp(m_stencilBack.compareOp);
+ dsDesc.backFaceStencil.readMask = m_stencilReadMask;
+ dsDesc.backFaceStencil.writeMask = m_stencilWriteMask;
+ }
+}
+void QMetalGraphicsPipeline::mapStates()
+{
+ d->winding = m_frontFace == CCW ? MTLWindingCounterClockwise : MTLWindingClockwise;
+ d->cullMode = toMetalCullMode(m_cullMode);
+ d->triangleFillMode = toMetalTriangleFillMode(m_polygonMode);
+ d->depthBias = float(m_depthBias);
+ d->slopeScaledDepthBias = m_slopeScaledDepthBias;
+}
+
+void QMetalGraphicsPipelineData::setupVertexInputDescriptor(MTLVertexDescriptor *desc)
+{
// same binding space for vertex and constant buffers - work it around
- const int firstVertexBinding = QRHI_RES(QMetalShaderResourceBindings, m_shaderResourceBindings)->maxBinding + 1;
+ // should be in native resource binding not SPIR-V, but this will work anyway
+ const int firstVertexBinding = QRHI_RES(QMetalShaderResourceBindings, q->shaderResourceBindings())->maxBinding + 1;
- MTLVertexDescriptor *inputLayout = [MTLVertexDescriptor vertexDescriptor];
- for (auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes();
+ QRhiVertexInputLayout vertexInputLayout = q->vertexInputLayout();
+ for (auto it = vertexInputLayout.cbeginAttributes(), itEnd = vertexInputLayout.cendAttributes();
it != itEnd; ++it)
{
const uint loc = uint(it->location());
- inputLayout.attributes[loc].format = toMetalAttributeFormat(it->format());
- inputLayout.attributes[loc].offset = NSUInteger(it->offset());
- inputLayout.attributes[loc].bufferIndex = NSUInteger(firstVertexBinding + it->binding());
+ desc.attributes[loc].format = decltype(desc.attributes[loc].format)(toMetalAttributeFormat(it->format()));
+ desc.attributes[loc].offset = NSUInteger(it->offset());
+ desc.attributes[loc].bufferIndex = NSUInteger(firstVertexBinding + it->binding());
}
int bindingIndex = 0;
- for (auto it = m_vertexInputLayout.cbeginBindings(), itEnd = m_vertexInputLayout.cendBindings();
+ const NSUInteger viewCount = qMax<NSUInteger>(1, q->multiViewCount());
+ for (auto it = vertexInputLayout.cbeginBindings(), itEnd = vertexInputLayout.cendBindings();
it != itEnd; ++it, ++bindingIndex)
{
const uint layoutIdx = uint(firstVertexBinding + bindingIndex);
- inputLayout.layouts[layoutIdx].stepFunction =
- it->classification() == QRhiVertexInputBinding::PerInstance
- ? MTLVertexStepFunctionPerInstance : MTLVertexStepFunctionPerVertex;
- inputLayout.layouts[layoutIdx].stepRate = NSUInteger(it->instanceStepRate());
- inputLayout.layouts[layoutIdx].stride = it->stride();
+ desc.layouts[layoutIdx].stepFunction =
+ it->classification() == QRhiVertexInputBinding::PerInstance
+ ? MTLVertexStepFunctionPerInstance : MTLVertexStepFunctionPerVertex;
+ desc.layouts[layoutIdx].stepRate = NSUInteger(it->instanceStepRate());
+ if (desc.layouts[layoutIdx].stepFunction == MTLVertexStepFunctionPerInstance)
+ desc.layouts[layoutIdx].stepRate *= viewCount;
+ desc.layouts[layoutIdx].stride = it->stride();
}
+}
- MTLRenderPipelineDescriptor *rpDesc = [[MTLRenderPipelineDescriptor alloc] init];
+void QMetalGraphicsPipelineData::setupStageInputDescriptor(MTLStageInputOutputDescriptor *desc)
+{
+ // same binding space for vertex and constant buffers - work it around
+ // should be in native resource binding not SPIR-V, but this will work anyway
+ const int firstVertexBinding = QRHI_RES(QMetalShaderResourceBindings, q->shaderResourceBindings())->maxBinding + 1;
+
+ QRhiVertexInputLayout vertexInputLayout = q->vertexInputLayout();
+ for (auto it = vertexInputLayout.cbeginAttributes(), itEnd = vertexInputLayout.cendAttributes();
+ it != itEnd; ++it)
+ {
+ const uint loc = uint(it->location());
+ desc.attributes[loc].format = decltype(desc.attributes[loc].format)(toMetalAttributeFormat(it->format()));
+ desc.attributes[loc].offset = NSUInteger(it->offset());
+ desc.attributes[loc].bufferIndex = NSUInteger(firstVertexBinding + it->binding());
+ }
+ int bindingIndex = 0;
+ for (auto it = vertexInputLayout.cbeginBindings(), itEnd = vertexInputLayout.cendBindings();
+ it != itEnd; ++it, ++bindingIndex)
+ {
+ const uint layoutIdx = uint(firstVertexBinding + bindingIndex);
+ if (desc.indexBufferIndex) {
+ desc.layouts[layoutIdx].stepFunction =
+ it->classification() == QRhiVertexInputBinding::PerInstance
+ ? MTLStepFunctionThreadPositionInGridY : MTLStepFunctionThreadPositionInGridXIndexed;
+ } else {
+ desc.layouts[layoutIdx].stepFunction =
+ it->classification() == QRhiVertexInputBinding::PerInstance
+ ? MTLStepFunctionThreadPositionInGridY : MTLStepFunctionThreadPositionInGridX;
+ }
+ desc.layouts[layoutIdx].stepRate = NSUInteger(it->instanceStepRate());
+ desc.layouts[layoutIdx].stride = it->stride();
+ }
+}
- rpDesc.vertexDescriptor = inputLayout;
+void QRhiMetalData::trySeedingRenderPipelineFromBinaryArchive(MTLRenderPipelineDescriptor *rpDesc)
+{
+ if (@available(macOS 11.0, iOS 14.0, *)) {
+ if (binArch) {
+ NSArray *binArchArray = [NSArray arrayWithObjects: binArch, nil];
+ rpDesc.binaryArchives = binArchArray;
+ }
+ }
+}
- // mutability cannot be determined (slotted buffers could be set as
+void QRhiMetalData::addRenderPipelineToBinaryArchive(MTLRenderPipelineDescriptor *rpDesc)
+{
+ if (@available(macOS 11.0, iOS 14.0, *)) {
+ if (binArch) {
+ NSError *err = nil;
+ if (![binArch addRenderPipelineFunctionsWithDescriptor: rpDesc error: &err]) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ qWarning("Failed to collect render pipeline functions to binary archive: %s", qPrintable(msg));
+ }
+ }
+ }
+}
+
+bool QMetalGraphicsPipeline::createVertexFragmentPipeline()
+{
+ QRHI_RES_RHI(QRhiMetal);
+
+ MTLVertexDescriptor *vertexDesc = [MTLVertexDescriptor vertexDescriptor];
+ d->setupVertexInputDescriptor(vertexDesc);
+
+ MTLRenderPipelineDescriptor *rpDesc = [[MTLRenderPipelineDescriptor alloc] init];
+ rpDesc.vertexDescriptor = vertexDesc;
+
+ // Mutability cannot be determined (slotted buffers could be set as
// MTLMutabilityImmutable, but then we potentially need a different
// descriptor for each buffer combination as this depends on the actual
- // buffers not just the resource binding layout) so leave it at the default
+ // buffers not just the resource binding layout), so leave
+ // rpDesc.vertex/fragmentBuffers at the defaults.
- for (const QRhiShaderStage &shaderStage : qAsConst(m_shaderStages)) {
+ for (const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
auto cacheIt = rhiD->d->shaderCache.constFind(shaderStage);
if (cacheIt != rhiD->d->shaderCache.constEnd()) {
switch (shaderStage.type()) {
@@ -3547,8 +5027,9 @@ bool QMetalGraphicsPipeline::create()
case QRhiShaderStage::Vertex:
d->vs.lib = lib;
d->vs.func = func;
- if (const QShader::NativeResourceBindingMap *map = shader.nativeResourceBindingMap(activeKey))
- d->vs.nativeResourceBindingMap = *map;
+ d->vs.nativeResourceBindingMap = shader.nativeResourceBindingMap(activeKey);
+ d->vs.desc = shader.description();
+ d->vs.nativeShaderInfo = shader.nativeShaderInfo(activeKey);
rhiD->d->shaderCache.insert(shaderStage, d->vs);
[d->vs.lib retain];
[d->vs.func retain];
@@ -3557,8 +5038,9 @@ bool QMetalGraphicsPipeline::create()
case QRhiShaderStage::Fragment:
d->fs.lib = lib;
d->fs.func = func;
- if (const QShader::NativeResourceBindingMap *map = shader.nativeResourceBindingMap(activeKey))
- d->fs.nativeResourceBindingMap = *map;
+ d->fs.nativeResourceBindingMap = shader.nativeResourceBindingMap(activeKey);
+ d->fs.desc = shader.description();
+ d->fs.nativeShaderInfo = shader.nativeShaderInfo(activeKey);
rhiD->d->shaderCache.insert(shaderStage, d->fs);
[d->fs.lib retain];
[d->fs.func retain];
@@ -3573,85 +5055,838 @@ bool QMetalGraphicsPipeline::create()
}
QMetalRenderPassDescriptor *rpD = QRHI_RES(QMetalRenderPassDescriptor, m_renderPassDesc);
+ setupAttachmentsInMetalRenderPassDescriptor(rpDesc, rpD);
- if (rpD->colorAttachmentCount) {
- // defaults when no targetBlends are provided
- rpDesc.colorAttachments[0].pixelFormat = MTLPixelFormat(rpD->colorFormat[0]);
- rpDesc.colorAttachments[0].writeMask = MTLColorWriteMaskAll;
- rpDesc.colorAttachments[0].blendingEnabled = false;
+ if (m_multiViewCount >= 2)
+ rpDesc.inputPrimitiveTopology = toMetalPrimitiveTopologyClass(m_topology);
- Q_ASSERT(m_targetBlends.count() == rpD->colorAttachmentCount
- || (m_targetBlends.isEmpty() && rpD->colorAttachmentCount == 1));
+ rhiD->d->trySeedingRenderPipelineFromBinaryArchive(rpDesc);
- for (uint i = 0, ie = uint(m_targetBlends.count()); i != ie; ++i) {
- const QRhiGraphicsPipeline::TargetBlend &b(m_targetBlends[int(i)]);
- rpDesc.colorAttachments[i].pixelFormat = MTLPixelFormat(rpD->colorFormat[i]);
- rpDesc.colorAttachments[i].blendingEnabled = b.enable;
- rpDesc.colorAttachments[i].sourceRGBBlendFactor = toMetalBlendFactor(b.srcColor);
- rpDesc.colorAttachments[i].destinationRGBBlendFactor = toMetalBlendFactor(b.dstColor);
- rpDesc.colorAttachments[i].rgbBlendOperation = toMetalBlendOp(b.opColor);
- rpDesc.colorAttachments[i].sourceAlphaBlendFactor = toMetalBlendFactor(b.srcAlpha);
- rpDesc.colorAttachments[i].destinationAlphaBlendFactor = toMetalBlendFactor(b.dstAlpha);
- rpDesc.colorAttachments[i].alphaBlendOperation = toMetalBlendOp(b.opAlpha);
- rpDesc.colorAttachments[i].writeMask = toMetalColorWriteMask(b.colorWrite);
+ if (rhiD->rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
+ rhiD->d->addRenderPipelineToBinaryArchive(rpDesc);
+
+ NSError *err = nil;
+ d->ps = [rhiD->d->dev newRenderPipelineStateWithDescriptor: rpDesc error: &err];
+ [rpDesc release];
+ if (!d->ps) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ qWarning("Failed to create render pipeline state: %s", qPrintable(msg));
+ return false;
+ }
+
+ MTLDepthStencilDescriptor *dsDesc = [[MTLDepthStencilDescriptor alloc] init];
+ setupMetalDepthStencilDescriptor(dsDesc);
+ d->ds = [rhiD->d->dev newDepthStencilStateWithDescriptor: dsDesc];
+ [dsDesc release];
+
+ d->primitiveType = toMetalPrimitiveType(m_topology);
+ mapStates();
+
+ return true;
+}
+
+int QMetalGraphicsPipelineData::Tessellation::vsCompVariantToIndex(QShader::Variant vertexCompVariant)
+{
+ switch (vertexCompVariant) {
+ case QShader::NonIndexedVertexAsComputeShader:
+ return 0;
+ case QShader::UInt32IndexedVertexAsComputeShader:
+ return 1;
+ case QShader::UInt16IndexedVertexAsComputeShader:
+ return 2;
+ default:
+ break;
+ }
+ return -1;
+}
+
+id<MTLComputePipelineState> QMetalGraphicsPipelineData::Tessellation::vsCompPipeline(QRhiMetal *rhiD, QShader::Variant vertexCompVariant)
+{
+ const int varIndex = vsCompVariantToIndex(vertexCompVariant);
+ if (varIndex >= 0 && vertexComputeState[varIndex])
+ return vertexComputeState[varIndex];
+
+ id<MTLFunction> func = nil;
+ if (varIndex >= 0)
+ func = compVs[varIndex].func;
+
+ if (!func) {
+ qWarning("No compute function found for vertex shader translated for tessellation, this should not happen");
+ return nil;
+ }
+
+ const QMap<int, int> &ebb(compVs[varIndex].nativeShaderInfo.extraBufferBindings);
+ const int indexBufferBinding = ebb.value(QShaderPrivate::MslTessVertIndicesBufferBinding, -1);
+
+ MTLComputePipelineDescriptor *cpDesc = [MTLComputePipelineDescriptor new];
+ cpDesc.computeFunction = func;
+ cpDesc.threadGroupSizeIsMultipleOfThreadExecutionWidth = YES;
+ cpDesc.stageInputDescriptor = [MTLStageInputOutputDescriptor stageInputOutputDescriptor];
+ if (indexBufferBinding >= 0) {
+ if (vertexCompVariant == QShader::UInt32IndexedVertexAsComputeShader) {
+ cpDesc.stageInputDescriptor.indexType = MTLIndexTypeUInt32;
+ cpDesc.stageInputDescriptor.indexBufferIndex = indexBufferBinding;
+ } else if (vertexCompVariant == QShader::UInt16IndexedVertexAsComputeShader) {
+ cpDesc.stageInputDescriptor.indexType = MTLIndexTypeUInt16;
+ cpDesc.stageInputDescriptor.indexBufferIndex = indexBufferBinding;
}
}
+ q->setupStageInputDescriptor(cpDesc.stageInputDescriptor);
- if (rpD->hasDepthStencil) {
- // Must only be set when a depth-stencil buffer will actually be bound,
- // validation blows up otherwise.
- MTLPixelFormat fmt = MTLPixelFormat(rpD->dsFormat);
- rpDesc.depthAttachmentPixelFormat = fmt;
-#ifdef Q_OS_MACOS
- if (fmt != MTLPixelFormatDepth16Unorm && fmt != MTLPixelFormatDepth32Float)
-#else
- if (fmt != MTLPixelFormatDepth32Float)
-#endif
- rpDesc.stencilAttachmentPixelFormat = fmt;
+ rhiD->d->trySeedingComputePipelineFromBinaryArchive(cpDesc);
+
+ if (rhiD->rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
+ rhiD->d->addComputePipelineToBinaryArchive(cpDesc);
+
+ NSError *err = nil;
+ id<MTLComputePipelineState> ps = [rhiD->d->dev newComputePipelineStateWithDescriptor: cpDesc
+ options: MTLPipelineOptionNone
+ reflection: nil
+ error: &err];
+ [cpDesc release];
+ if (!ps) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ qWarning("Failed to create compute pipeline state: %s", qPrintable(msg));
+ } else {
+ vertexComputeState[varIndex] = ps;
}
+ // not retained, the only owner is vertexComputeState and so the QRhiGraphicsPipeline
+ return ps;
+}
- rpDesc.sampleCount = NSUInteger(rhiD->effectiveSampleCount(m_sampleCount));
+id<MTLComputePipelineState> QMetalGraphicsPipelineData::Tessellation::tescCompPipeline(QRhiMetal *rhiD)
+{
+ if (tessControlComputeState)
+ return tessControlComputeState;
+
+ MTLComputePipelineDescriptor *cpDesc = [MTLComputePipelineDescriptor new];
+ cpDesc.computeFunction = compTesc.func;
+
+ rhiD->d->trySeedingComputePipelineFromBinaryArchive(cpDesc);
+
+ if (rhiD->rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
+ rhiD->d->addComputePipelineToBinaryArchive(cpDesc);
NSError *err = nil;
- d->ps = [rhiD->d->dev newRenderPipelineStateWithDescriptor: rpDesc error: &err];
- if (!d->ps) {
+ id<MTLComputePipelineState> ps = [rhiD->d->dev newComputePipelineStateWithDescriptor: cpDesc
+ options: MTLPipelineOptionNone
+ reflection: nil
+ error: &err];
+ [cpDesc release];
+ if (!ps) {
const QString msg = QString::fromNSString(err.localizedDescription);
- qWarning("Failed to create render pipeline state: %s", qPrintable(msg));
- [rpDesc release];
- return false;
+ qWarning("Failed to create compute pipeline state: %s", qPrintable(msg));
+ } else {
+ tessControlComputeState = ps;
}
+ // not retained, the only owner is tessControlComputeState and so the QRhiGraphicsPipeline
+ return ps;
+}
+
+static inline bool indexTaken(quint32 index, quint64 indices)
+{
+ return (indices >> index) & 0x1;
+}
+
+static inline void takeIndex(quint32 index, quint64 &indices)
+{
+ indices |= 1 << index;
+}
+
+static inline int nextAttributeIndex(quint64 indices)
+{
+ // Maximum number of vertex attributes per vertex descriptor. There does
+ // not appear to be a way to query this from the implementation.
+ // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf indicates
+ // that all GPU families have a value of 31.
+ static const int maxVertexAttributes = 31;
+
+ for (int index = 0; index < maxVertexAttributes; ++index) {
+ if (!indexTaken(index, indices))
+ return index;
+ }
+
+ Q_UNREACHABLE_RETURN(-1);
+}
+
+static inline int aligned(quint32 offset, quint32 alignment)
+{
+ return ((offset + alignment - 1) / alignment) * alignment;
+}
+
+template<typename T>
+static void addUnusedVertexAttribute(const T &variable, QRhiMetal *rhiD, quint32 &offset, quint32 &vertexAlignment)
+{
+
+ int elements = 1;
+ for (const int dim : variable.arrayDims)
+ elements *= dim;
+
+ if (variable.type == QShaderDescription::VariableType::Struct) {
+ for (int element = 0; element < elements; ++element) {
+ for (const auto &member : variable.structMembers) {
+ addUnusedVertexAttribute(member, rhiD, offset, vertexAlignment);
+ }
+ }
+ } else {
+ const QRhiVertexInputAttribute::Format format = rhiD->shaderDescVariableFormatToVertexInputFormat(variable.type);
+ const quint32 size = rhiD->byteSizePerVertexForVertexInputFormat(format);
+
+ // MSL specification 3.0 says alignment = size for non packed scalars and vectors
+ const quint32 alignment = size;
+ vertexAlignment = std::max(vertexAlignment, alignment);
+
+ for (int element = 0; element < elements; ++element) {
+ // adjust alignment
+ offset = aligned(offset, alignment);
+ offset += size;
+ }
+ }
+}
+
+template<typename T>
+static void addVertexAttribute(const T &variable, int binding, QRhiMetal *rhiD, int &index, quint32 &offset, MTLVertexAttributeDescriptorArray *attributes, quint64 &indices, quint32 &vertexAlignment)
+{
+
+ int elements = 1;
+ for (const int dim : variable.arrayDims)
+ elements *= dim;
+
+ if (variable.type == QShaderDescription::VariableType::Struct) {
+ for (int element = 0; element < elements; ++element) {
+ for (const auto &member : variable.structMembers) {
+ addVertexAttribute(member, binding, rhiD, index, offset, attributes, indices, vertexAlignment);
+ }
+ }
+ } else {
+ const QRhiVertexInputAttribute::Format format = rhiD->shaderDescVariableFormatToVertexInputFormat(variable.type);
+ const quint32 size = rhiD->byteSizePerVertexForVertexInputFormat(format);
+
+ // MSL specification 3.0 says alignment = size for non packed scalars and vectors
+ const quint32 alignment = size;
+ vertexAlignment = std::max(vertexAlignment, alignment);
+
+ for (int element = 0; element < elements; ++element) {
+ Q_ASSERT(!indexTaken(index, indices));
+
+ // adjust alignment
+ offset = aligned(offset, alignment);
+
+ attributes[index].bufferIndex = binding;
+ attributes[index].format = toMetalAttributeFormat(format);
+ attributes[index].offset = offset;
+
+ takeIndex(index, indices);
+ index++;
+ if (indexTaken(index, indices))
+ index = nextAttributeIndex(indices);
+
+ offset += size;
+ }
+ }
+}
+
+static inline bool matches(const QList<QShaderDescription::BlockVariable> &a, const QList<QShaderDescription::BlockVariable> &b)
+{
+ if (a.size() == b.size()) {
+ bool match = true;
+ for (int i = 0; i < a.size() && match; ++i) {
+ match &= a[i].type == b[i].type
+ && a[i].arrayDims == b[i].arrayDims
+ && matches(a[i].structMembers, b[i].structMembers);
+ }
+ return match;
+ }
+
+ return false;
+}
+
+static inline bool matches(const QShaderDescription::InOutVariable &a, const QShaderDescription::InOutVariable &b)
+{
+ return a.location == b.location
+ && a.type == b.type
+ && a.perPatch == b.perPatch
+ && matches(a.structMembers, b.structMembers);
+}
+
+//
+// Create the tessellation evaluation render pipeline state
+//
+// The tesc runs as a compute shader in a compute pipeline and writes per patch and per patch
+// control point data into separate storage buffers. The tese runs as a vertex shader in a render
+// pipeline. Our task is to generate a render pipeline descriptor for the tese that pulls vertices
+// from these buffers.
+//
+// As the buffers we are pulling vertices from are written by a compute pipeline, they follow the
+// MSL alignment conventions which we must take into account when generating our
+// MTLVertexDescriptor. We must include the user defined tese input attributes, and any builtins
+// that were used.
+//
+// SPIRV-Cross generates the MSL tese shader code with input attribute indices that reflect the
+// specified GLSL locations. Interface blocks are flattened with each member having an incremented
+// attribute index. SPIRV-Cross reports an error on compilation if there are clashes in the index
+// address space.
+//
+// After the user specified attributes are processed, SPIRV-Cross places the in-use builtins at the
+// next available (lowest value) attribute index. Tese builtins are processed in the following
+// order:
+//
+// in gl_PerVertex
+// {
+// vec4 gl_Position;
+// float gl_PointSize;
+// float gl_ClipDistance[];
+// };
+//
+// patch in float gl_TessLevelOuter[4];
+// patch in float gl_TessLevelInner[2];
+//
+// Enumerations in QShaderDescription::BuiltinType are defined in this order.
+//
+// For quads, SPIRV-Cross places MTLQuadTessellationFactorsHalf per patch in the tessellation
+// factor buffer. For triangles it uses MTLTriangleTessellationFactorsHalf.
+//
+// It should be noted that SPIRV-Cross handles the following builtin inputs internally, with no
+// host side support required.
+//
+// in vec3 gl_TessCoord;
+// in int gl_PatchVerticesIn;
+// in int gl_PrimitiveID;
+//
+id<MTLRenderPipelineState> QMetalGraphicsPipelineData::Tessellation::teseFragRenderPipeline(QRhiMetal *rhiD, QMetalGraphicsPipeline *pipeline)
+{
+ if (pipeline->d->ps)
+ return pipeline->d->ps;
+
+ MTLRenderPipelineDescriptor *rpDesc = [[MTLRenderPipelineDescriptor alloc] init];
+ MTLVertexDescriptor *vertexDesc = [MTLVertexDescriptor vertexDescriptor];
+
+ // tesc output buffers
+ const QMap<int, int> &ebb(compTesc.nativeShaderInfo.extraBufferBindings);
+ const int tescOutputBufferBinding = ebb.value(QShaderPrivate::MslTessVertTescOutputBufferBinding, -1);
+ const int tescPatchOutputBufferBinding = ebb.value(QShaderPrivate::MslTessTescPatchOutputBufferBinding, -1);
+ const int tessFactorBufferBinding = ebb.value(QShaderPrivate::MslTessTescTessLevelBufferBinding, -1);
+ quint32 offsetInTescOutput = 0;
+ quint32 offsetInTescPatchOutput = 0;
+ quint32 offsetInTessFactorBuffer = 0;
+ quint32 tescOutputAlignment = 0;
+ quint32 tescPatchOutputAlignment = 0;
+ quint32 tessFactorAlignment = 0;
+ QSet<int> usedBuffers;
+
+ // tesc output variables in ascending location order
+ QMap<int, QShaderDescription::InOutVariable> tescOutVars;
+ for (const auto &tescOutVar : compTesc.desc.outputVariables())
+ tescOutVars[tescOutVar.location] = tescOutVar;
+
+ // tese input variables in ascending location order
+ QMap<int, QShaderDescription::InOutVariable> teseInVars;
+ for (const auto &teseInVar : vertTese.desc.inputVariables())
+ teseInVars[teseInVar.location] = teseInVar;
+
+ // bit mask tracking usage of vertex attribute indices
+ quint64 indices = 0;
+
+ for (QShaderDescription::InOutVariable &tescOutVar : tescOutVars) {
+
+ int index = tescOutVar.location;
+ int binding = -1;
+ quint32 *offset = nullptr;
+ quint32 *alignment = nullptr;
+
+ if (tescOutVar.perPatch) {
+ binding = tescPatchOutputBufferBinding;
+ offset = &offsetInTescPatchOutput;
+ alignment = &tescPatchOutputAlignment;
+ } else {
+ tescOutVar.arrayDims.removeLast();
+ binding = tescOutputBufferBinding;
+ offset = &offsetInTescOutput;
+ alignment = &tescOutputAlignment;
+ }
+
+ if (teseInVars.contains(index)) {
+
+ if (!matches(teseInVars[index], tescOutVar)) {
+ qWarning() << "mismatched tessellation control output -> tesssellation evaluation input at location" << index;
+ qWarning() << " tesc out:" << tescOutVar;
+ qWarning() << " tese in:" << teseInVars[index];
+ }
+
+ if (binding != -1) {
+ addVertexAttribute(tescOutVar, binding, rhiD, index, *offset, vertexDesc.attributes, indices, *alignment);
+ usedBuffers << binding;
+ } else {
+ qWarning() << "baked tessellation control shader missing output buffer binding information";
+ addUnusedVertexAttribute(tescOutVar, rhiD, *offset, *alignment);
+ }
+
+ } else {
+ qWarning() << "missing tessellation evaluation input for tessellation control output:" << tescOutVar;
+ addUnusedVertexAttribute(tescOutVar, rhiD, *offset, *alignment);
+ }
+
+ teseInVars.remove(tescOutVar.location);
+ }
+
+ for (const QShaderDescription::InOutVariable &teseInVar : teseInVars)
+ qWarning() << "missing tessellation control output for tessellation evaluation input:" << teseInVar;
+
+ // tesc output builtins in ascending location order
+ QMap<QShaderDescription::BuiltinType, QShaderDescription::BuiltinVariable> tescOutBuiltins;
+ for (const auto &tescOutBuiltin : compTesc.desc.outputBuiltinVariables())
+ tescOutBuiltins[tescOutBuiltin.type] = tescOutBuiltin;
+
+ // tese input builtins in ascending location order
+ QMap<QShaderDescription::BuiltinType, QShaderDescription::BuiltinVariable> teseInBuiltins;
+ for (const auto &teseInBuiltin : vertTese.desc.inputBuiltinVariables())
+ teseInBuiltins[teseInBuiltin.type] = teseInBuiltin;
+
+ const bool trianglesMode = vertTese.desc.tessellationMode() == QShaderDescription::TrianglesTessellationMode;
+ bool tessLevelAdded = false;
+
+ for (const QShaderDescription::BuiltinVariable &builtin : tescOutBuiltins) {
+
+ QShaderDescription::InOutVariable variable;
+ int binding = -1;
+ quint32 *offset = nullptr;
+ quint32 *alignment = nullptr;
+
+ switch (builtin.type) {
+ case QShaderDescription::BuiltinType::PositionBuiltin:
+ variable.type = QShaderDescription::VariableType::Vec4;
+ binding = tescOutputBufferBinding;
+ offset = &offsetInTescOutput;
+ alignment = &tescOutputAlignment;
+ break;
+ case QShaderDescription::BuiltinType::PointSizeBuiltin:
+ variable.type = QShaderDescription::VariableType::Float;
+ binding = tescOutputBufferBinding;
+ offset = &offsetInTescOutput;
+ alignment = &tescOutputAlignment;
+ break;
+ case QShaderDescription::BuiltinType::ClipDistanceBuiltin:
+ variable.type = QShaderDescription::VariableType::Float;
+ variable.arrayDims = builtin.arrayDims;
+ binding = tescOutputBufferBinding;
+ offset = &offsetInTescOutput;
+ alignment = &tescOutputAlignment;
+ break;
+ case QShaderDescription::BuiltinType::TessLevelOuterBuiltin:
+ variable.type = QShaderDescription::VariableType::Half4;
+ binding = tessFactorBufferBinding;
+ offset = &offsetInTessFactorBuffer;
+ tessLevelAdded = trianglesMode;
+ alignment = &tessFactorAlignment;
+ break;
+ case QShaderDescription::BuiltinType::TessLevelInnerBuiltin:
+ if (trianglesMode) {
+ if (!tessLevelAdded) {
+ variable.type = QShaderDescription::VariableType::Half4;
+ binding = tessFactorBufferBinding;
+ offsetInTessFactorBuffer = 0;
+ offset = &offsetInTessFactorBuffer;
+ alignment = &tessFactorAlignment;
+ tessLevelAdded = true;
+ } else {
+ teseInBuiltins.remove(builtin.type);
+ continue;
+ }
+ } else {
+ variable.type = QShaderDescription::VariableType::Half2;
+ binding = tessFactorBufferBinding;
+ offsetInTessFactorBuffer = 8;
+ offset = &offsetInTessFactorBuffer;
+ alignment = &tessFactorAlignment;
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ if (teseInBuiltins.contains(builtin.type)) {
+ if (binding != -1) {
+ int index = nextAttributeIndex(indices);
+ addVertexAttribute(variable, binding, rhiD, index, *offset, vertexDesc.attributes, indices, *alignment);
+ usedBuffers << binding;
+ } else {
+ qWarning() << "baked tessellation control shader missing output buffer binding information";
+ addUnusedVertexAttribute(variable, rhiD, *offset, *alignment);
+ }
+ } else {
+ addUnusedVertexAttribute(variable, rhiD, *offset, *alignment);
+ }
+
+ teseInBuiltins.remove(builtin.type);
+ }
+
+ for (const QShaderDescription::BuiltinVariable &builtin : teseInBuiltins) {
+ switch (builtin.type) {
+ case QShaderDescription::BuiltinType::PositionBuiltin:
+ case QShaderDescription::BuiltinType::PointSizeBuiltin:
+ case QShaderDescription::BuiltinType::ClipDistanceBuiltin:
+ qWarning() << "missing tessellation control output for tessellation evaluation builtin input:" << builtin;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (usedBuffers.contains(tescOutputBufferBinding)) {
+ vertexDesc.layouts[tescOutputBufferBinding].stepFunction = MTLVertexStepFunctionPerPatchControlPoint;
+ vertexDesc.layouts[tescOutputBufferBinding].stride = aligned(offsetInTescOutput, tescOutputAlignment);
+ }
+
+ if (usedBuffers.contains(tescPatchOutputBufferBinding)) {
+ vertexDesc.layouts[tescPatchOutputBufferBinding].stepFunction = MTLVertexStepFunctionPerPatch;
+ vertexDesc.layouts[tescPatchOutputBufferBinding].stride = aligned(offsetInTescPatchOutput, tescPatchOutputAlignment);
+ }
+
+ if (usedBuffers.contains(tessFactorBufferBinding)) {
+ vertexDesc.layouts[tessFactorBufferBinding].stepFunction = MTLVertexStepFunctionPerPatch;
+ vertexDesc.layouts[tessFactorBufferBinding].stride = trianglesMode ? sizeof(MTLTriangleTessellationFactorsHalf) : sizeof(MTLQuadTessellationFactorsHalf);
+ }
+
+ rpDesc.vertexDescriptor = vertexDesc;
+ rpDesc.vertexFunction = vertTese.func;
+ rpDesc.fragmentFunction = pipeline->d->fs.func;
+
+ // The portable, cross-API approach is to use CCW, the results are then
+ // identical (assuming the applied clipSpaceCorrMatrix) for all the 3D
+ // APIs. The tess.eval. GLSL shader is thus expected to specify ccw. If it
+ // doesn't, things may not work as expected.
+ rpDesc.tessellationOutputWindingOrder = toMetalTessellationWindingOrder(vertTese.desc.tessellationWindingOrder());
+
+ rpDesc.tessellationPartitionMode = toMetalTessellationPartitionMode(vertTese.desc.tessellationPartitioning());
+
+ QMetalRenderPassDescriptor *rpD = QRHI_RES(QMetalRenderPassDescriptor, pipeline->renderPassDescriptor());
+ pipeline->setupAttachmentsInMetalRenderPassDescriptor(rpDesc, rpD);
+
+ rhiD->d->trySeedingRenderPipelineFromBinaryArchive(rpDesc);
+
+ if (rhiD->rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
+ rhiD->d->addRenderPipelineToBinaryArchive(rpDesc);
+
+ NSError *err = nil;
+ id<MTLRenderPipelineState> ps = [rhiD->d->dev newRenderPipelineStateWithDescriptor: rpDesc error: &err];
[rpDesc release];
+ if (!ps) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ qWarning("Failed to create render pipeline state for tessellation: %s", qPrintable(msg));
+ } else {
+ // ps is stored in the QMetalGraphicsPipelineData so the end result in this
+ // regard is no different from what createVertexFragmentPipeline does
+ pipeline->d->ps = ps;
+ }
+ return ps;
+}
- MTLDepthStencilDescriptor *dsDesc = [[MTLDepthStencilDescriptor alloc] init];
- dsDesc.depthCompareFunction = m_depthTest ? toMetalCompareOp(m_depthOp) : MTLCompareFunctionAlways;
- dsDesc.depthWriteEnabled = m_depthWrite;
- if (m_stencilTest) {
- dsDesc.frontFaceStencil = [[MTLStencilDescriptor alloc] init];
- dsDesc.frontFaceStencil.stencilFailureOperation = toMetalStencilOp(m_stencilFront.failOp);
- dsDesc.frontFaceStencil.depthFailureOperation = toMetalStencilOp(m_stencilFront.depthFailOp);
- dsDesc.frontFaceStencil.depthStencilPassOperation = toMetalStencilOp(m_stencilFront.passOp);
- dsDesc.frontFaceStencil.stencilCompareFunction = toMetalCompareOp(m_stencilFront.compareOp);
- dsDesc.frontFaceStencil.readMask = m_stencilReadMask;
- dsDesc.frontFaceStencil.writeMask = m_stencilWriteMask;
+QMetalBuffer *QMetalGraphicsPipelineData::ExtraBufferManager::acquireWorkBuffer(QRhiMetal *rhiD, quint32 size, WorkBufType type)
+{
+ QVector<QMetalBuffer *> *workBuffers = type == WorkBufType::DeviceLocal ? &deviceLocalWorkBuffers : &hostVisibleWorkBuffers;
- dsDesc.backFaceStencil = [[MTLStencilDescriptor alloc] init];
- dsDesc.backFaceStencil.stencilFailureOperation = toMetalStencilOp(m_stencilBack.failOp);
- dsDesc.backFaceStencil.depthFailureOperation = toMetalStencilOp(m_stencilBack.depthFailOp);
- dsDesc.backFaceStencil.depthStencilPassOperation = toMetalStencilOp(m_stencilBack.passOp);
- dsDesc.backFaceStencil.stencilCompareFunction = toMetalCompareOp(m_stencilBack.compareOp);
- dsDesc.backFaceStencil.readMask = m_stencilReadMask;
- dsDesc.backFaceStencil.writeMask = m_stencilWriteMask;
+ // Check if something is reusable as-is.
+ for (QMetalBuffer *workBuf : *workBuffers) {
+ if (workBuf && workBuf->lastActiveFrameSlot == -1 && workBuf->size() >= size) {
+ workBuf->lastActiveFrameSlot = rhiD->currentFrameSlot;
+ return workBuf;
+ }
}
+ // Once the pool is above a certain threshold, see if there is something
+ // unused (but too small) and recreate that our size.
+ if (workBuffers->count() > QMTL_FRAMES_IN_FLIGHT * 8) {
+ for (QMetalBuffer *workBuf : *workBuffers) {
+ if (workBuf && workBuf->lastActiveFrameSlot == -1) {
+ workBuf->setSize(size);
+ if (workBuf->create()) {
+ workBuf->lastActiveFrameSlot = rhiD->currentFrameSlot;
+ return workBuf;
+ }
+ }
+ }
+ }
+
+ // Add a new buffer to the pool.
+ QMetalBuffer *buf;
+ if (type == WorkBufType::DeviceLocal) {
+ // for GPU->GPU data (non-slotted, not necessarily host writable)
+ buf = new QMetalBuffer(rhiD, QRhiBuffer::Static, QRhiBuffer::UsageFlags(QMetalBuffer::WorkBufPoolUsage), size);
+ } else {
+ // for CPU->GPU (non-slotted, host writable/coherent)
+ buf = new QMetalBuffer(rhiD, QRhiBuffer::Dynamic, QRhiBuffer::UsageFlags(QMetalBuffer::WorkBufPoolUsage), size);
+ }
+ if (buf->create()) {
+ buf->lastActiveFrameSlot = rhiD->currentFrameSlot;
+ workBuffers->append(buf);
+ return buf;
+ }
+
+ qWarning("Failed to acquire work buffer of size %u", size);
+ return nullptr;
+}
+
+bool QMetalGraphicsPipeline::createTessellationPipelines(const QShader &tessVert, const QShader &tesc, const QShader &tese, const QShader &tessFrag)
+{
+ QRHI_RES_RHI(QRhiMetal);
+ QString error;
+ QByteArray entryPoint;
+ QShaderKey activeKey;
+
+ const QShaderDescription tescDesc = tesc.description();
+ const QShaderDescription teseDesc = tese.description();
+ d->tess.inControlPointCount = uint(m_patchControlPointCount);
+ d->tess.outControlPointCount = tescDesc.tessellationOutputVertexCount();
+ if (!d->tess.outControlPointCount)
+ d->tess.outControlPointCount = teseDesc.tessellationOutputVertexCount();
+
+ if (!d->tess.outControlPointCount) {
+ qWarning("Failed to determine output vertex count from the tessellation control or evaluation shader, cannot tessellate");
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+
+ if (m_multiViewCount >= 2)
+ qWarning("Multiview is not supported with tessellation");
+
+ // Now the vertex shader is a compute shader.
+ // It should have three dedicated *VertexAsComputeShader variants.
+ // What the requested variant was (Standard or Batchable) plays no role here.
+ // (the Qt Quick scenegraph does not use tessellation with its materials)
+ // Create all three versions.
+
+ bool variantsPresent[3] = {};
+ const QVector<QShaderKey> tessVertKeys = tessVert.availableShaders();
+ for (const QShaderKey &k : tessVertKeys) {
+ switch (k.sourceVariant()) {
+ case QShader::NonIndexedVertexAsComputeShader:
+ variantsPresent[0] = true;
+ break;
+ case QShader::UInt32IndexedVertexAsComputeShader:
+ variantsPresent[1] = true;
+ break;
+ case QShader::UInt16IndexedVertexAsComputeShader:
+ variantsPresent[2] = true;
+ break;
+ default:
+ break;
+ }
+ }
+ if (!(variantsPresent[0] && variantsPresent[1] && variantsPresent[2])) {
+ qWarning("Vertex shader is not prepared for Metal tessellation. Cannot tessellate. "
+ "Perhaps the relevant variants (UInt32IndexedVertexAsComputeShader et al) were not generated? "
+ "Try passing --msltess to qsb.");
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+
+ int varIndex = 0; // Will map NonIndexed as 0, UInt32 as 1, UInt16 as 2. Do not change this ordering.
+ for (QShader::Variant variant : {
+ QShader::NonIndexedVertexAsComputeShader,
+ QShader::UInt32IndexedVertexAsComputeShader,
+ QShader::UInt16IndexedVertexAsComputeShader })
+ {
+ id<MTLLibrary> lib = rhiD->d->createMetalLib(tessVert, variant, &error, &entryPoint, &activeKey);
+ if (!lib) {
+ qWarning("MSL shader compilation failed for vertex-as-compute shader %d: %s", int(variant), qPrintable(error));
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+ id<MTLFunction> func = rhiD->d->createMSLShaderFunction(lib, entryPoint);
+ if (!func) {
+ qWarning("MSL function for entry point %s not found", entryPoint.constData());
+ [lib release];
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+ QMetalShader &compVs(d->tess.compVs[varIndex]);
+ compVs.lib = lib;
+ compVs.func = func;
+ compVs.desc = tessVert.description();
+ compVs.nativeResourceBindingMap = tessVert.nativeResourceBindingMap(activeKey);
+ compVs.nativeShaderInfo = tessVert.nativeShaderInfo(activeKey);
+
+ // pre-create all three MTLComputePipelineStates
+ if (!d->tess.vsCompPipeline(rhiD, variant)) {
+ qWarning("Failed to pre-generate compute pipeline for vertex compute shader (tessellation variant %d)", int(variant));
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+
+ ++varIndex;
+ }
+
+ // Pipeline #2 is a compute that runs the tessellation control (compute) shader
+ id<MTLLibrary> tessControlLib = rhiD->d->createMetalLib(tesc, QShader::StandardShader, &error, &entryPoint, &activeKey);
+ if (!tessControlLib) {
+ qWarning("MSL shader compilation failed for tessellation control compute shader: %s", qPrintable(error));
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+ id<MTLFunction> tessControlFunc = rhiD->d->createMSLShaderFunction(tessControlLib, entryPoint);
+ if (!tessControlFunc) {
+ qWarning("MSL function for entry point %s not found", entryPoint.constData());
+ [tessControlLib release];
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+ d->tess.compTesc.lib = tessControlLib;
+ d->tess.compTesc.func = tessControlFunc;
+ d->tess.compTesc.desc = tesc.description();
+ d->tess.compTesc.nativeResourceBindingMap = tesc.nativeResourceBindingMap(activeKey);
+ d->tess.compTesc.nativeShaderInfo = tesc.nativeShaderInfo(activeKey);
+ if (!d->tess.tescCompPipeline(rhiD)) {
+ qWarning("Failed to pre-generate compute pipeline for tessellation control shader");
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+
+ // Pipeline #3 is a render pipeline with the tessellation evaluation (vertex) + the fragment shader
+ id<MTLLibrary> tessEvalLib = rhiD->d->createMetalLib(tese, QShader::StandardShader, &error, &entryPoint, &activeKey);
+ if (!tessEvalLib) {
+ qWarning("MSL shader compilation failed for tessellation evaluation vertex shader: %s", qPrintable(error));
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+ id<MTLFunction> tessEvalFunc = rhiD->d->createMSLShaderFunction(tessEvalLib, entryPoint);
+ if (!tessEvalFunc) {
+ qWarning("MSL function for entry point %s not found", entryPoint.constData());
+ [tessEvalLib release];
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+ d->tess.vertTese.lib = tessEvalLib;
+ d->tess.vertTese.func = tessEvalFunc;
+ d->tess.vertTese.desc = tese.description();
+ d->tess.vertTese.nativeResourceBindingMap = tese.nativeResourceBindingMap(activeKey);
+ d->tess.vertTese.nativeShaderInfo = tese.nativeShaderInfo(activeKey);
+
+ id<MTLLibrary> fragLib = rhiD->d->createMetalLib(tessFrag, QShader::StandardShader, &error, &entryPoint, &activeKey);
+ if (!fragLib) {
+ qWarning("MSL shader compilation failed for fragment shader: %s", qPrintable(error));
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+ id<MTLFunction> fragFunc = rhiD->d->createMSLShaderFunction(fragLib, entryPoint);
+ if (!fragFunc) {
+ qWarning("MSL function for entry point %s not found", entryPoint.constData());
+ [fragLib release];
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+ d->fs.lib = fragLib;
+ d->fs.func = fragFunc;
+ d->fs.desc = tessFrag.description();
+ d->fs.nativeShaderInfo = tessFrag.nativeShaderInfo(activeKey);
+ d->fs.nativeResourceBindingMap = tessFrag.nativeResourceBindingMap(activeKey);
+
+ if (!d->tess.teseFragRenderPipeline(rhiD, this)) {
+ qWarning("Failed to pre-generate render pipeline for tessellation evaluation + fragment shader");
+ d->tess.enabled = false;
+ d->tess.failed = true;
+ return false;
+ }
+
+ MTLDepthStencilDescriptor *dsDesc = [[MTLDepthStencilDescriptor alloc] init];
+ setupMetalDepthStencilDescriptor(dsDesc);
d->ds = [rhiD->d->dev newDepthStencilStateWithDescriptor: dsDesc];
[dsDesc release];
- d->primitiveType = toMetalPrimitiveType(m_topology);
- d->winding = m_frontFace == CCW ? MTLWindingCounterClockwise : MTLWindingClockwise;
- d->cullMode = toMetalCullMode(m_cullMode);
- d->depthBias = float(m_depthBias);
- d->slopeScaledDepthBias = m_slopeScaledDepthBias;
+ // no primitiveType
+ mapStates();
+
+ return true;
+}
+bool QMetalGraphicsPipeline::create()
+{
+ destroy(); // no early test, always invoke and leave it to destroy to decide what to clean up
+
+ QRHI_RES_RHI(QRhiMetal);
+ rhiD->pipelineCreationStart();
+ if (!rhiD->sanityCheckGraphicsPipeline(this))
+ return false;
+
+ // See if tessellation is involved. Things will be very different, if so.
+ QShader tessVert;
+ QShader tesc;
+ QShader tese;
+ QShader tessFrag;
+ for (const QRhiShaderStage &shaderStage : std::as_const(m_shaderStages)) {
+ switch (shaderStage.type()) {
+ case QRhiShaderStage::Vertex:
+ tessVert = shaderStage.shader();
+ break;
+ case QRhiShaderStage::TessellationControl:
+ tesc = shaderStage.shader();
+ break;
+ case QRhiShaderStage::TessellationEvaluation:
+ tese = shaderStage.shader();
+ break;
+ case QRhiShaderStage::Fragment:
+ tessFrag = shaderStage.shader();
+ break;
+ default:
+ break;
+ }
+ }
+ d->tess.enabled = tesc.isValid() && tese.isValid() && m_topology == Patches && m_patchControlPointCount > 0;
+ d->tess.failed = false;
+
+ bool ok = d->tess.enabled ? createTessellationPipelines(tessVert, tesc, tese, tessFrag) : createVertexFragmentPipeline();
+ if (!ok)
+ return false;
+
+ // SPIRV-Cross buffer size buffers
+ int buffers = 0;
+ QVarLengthArray<QMetalShader *, 6> shaders;
+ if (d->tess.enabled) {
+ shaders.append(&d->tess.compVs[0]);
+ shaders.append(&d->tess.compVs[1]);
+ shaders.append(&d->tess.compVs[2]);
+ shaders.append(&d->tess.compTesc);
+ shaders.append(&d->tess.vertTese);
+ } else {
+ shaders.append(&d->vs);
+ }
+ shaders.append(&d->fs);
+
+ for (QMetalShader *shader : shaders) {
+ if (shader->nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)) {
+ const int binding = shader->nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding];
+ shader->nativeResourceBindingMap[binding] = qMakePair(binding, -1);
+ int maxNativeBinding = 0;
+ for (const QShaderDescription::StorageBlock &block : shader->desc.storageBlocks())
+ maxNativeBinding = qMax(maxNativeBinding, shader->nativeResourceBindingMap[block.binding].first);
+
+ // we use one buffer to hold data for all graphics shader stages, each with a different offset.
+ // buffer offsets must be 32byte aligned - adjust buffer count accordingly
+ buffers += ((maxNativeBinding + 1 + 7) / 8) * 8;
+ }
+ }
+
+ if (buffers) {
+ if (!d->bufferSizeBuffer)
+ d->bufferSizeBuffer = new QMetalBuffer(rhiD, QRhiBuffer::Static, QRhiBuffer::StorageBuffer, buffers * sizeof(int));
+
+ d->bufferSizeBuffer->setSize(buffers * sizeof(int));
+ d->bufferSizeBuffer->create();
+ }
+
+ rhiD->pipelineCreationEnd();
lastActiveFrameSlot = -1;
generation += 1;
rhiD->registerResource(this);
@@ -3672,17 +5907,48 @@ QMetalComputePipeline::~QMetalComputePipeline()
void QMetalComputePipeline::destroy()
{
- QRHI_RES_RHI(QRhiMetal);
-
d->cs.destroy();
if (!d->ps)
return;
- [d->ps release];
+ delete d->bufferSizeBuffer;
+ d->bufferSizeBuffer = nullptr;
+
+ QRhiMetalData::DeferredReleaseEntry e;
+ e.type = QRhiMetalData::DeferredReleaseEntry::ComputePipeline;
+ e.lastActiveFrameSlot = lastActiveFrameSlot;
+ e.computePipeline.pipelineState = d->ps;
d->ps = nil;
- rhiD->unregisterResource(this);
+ QRHI_RES_RHI(QRhiMetal);
+ if (rhiD) {
+ rhiD->d->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
+}
+
+void QRhiMetalData::trySeedingComputePipelineFromBinaryArchive(MTLComputePipelineDescriptor *cpDesc)
+{
+ if (@available(macOS 11.0, iOS 14.0, *)) {
+ if (binArch) {
+ NSArray *binArchArray = [NSArray arrayWithObjects: binArch, nil];
+ cpDesc.binaryArchives = binArchArray;
+ }
+ }
+}
+
+void QRhiMetalData::addComputePipelineToBinaryArchive(MTLComputePipelineDescriptor *cpDesc)
+{
+ if (@available(macOS 11.0, iOS 14.0, *)) {
+ if (binArch) {
+ NSError *err = nil;
+ if (![binArch addComputePipelineFunctionsWithDescriptor: cpDesc error: &err]) {
+ const QString msg = QString::fromNSString(err.localizedDescription);
+ qWarning("Failed to collect compute pipeline functions to binary archive: %s", qPrintable(msg));
+ }
+ }
+ }
}
bool QMetalComputePipeline::create()
@@ -3691,6 +5957,7 @@ bool QMetalComputePipeline::create()
destroy();
QRHI_RES_RHI(QRhiMetal);
+ rhiD->pipelineCreationStart();
auto cacheIt = rhiD->d->shaderCache.constFind(m_shaderStage);
if (cacheIt != rhiD->d->shaderCache.constEnd()) {
@@ -3715,8 +5982,15 @@ bool QMetalComputePipeline::create()
d->cs.lib = lib;
d->cs.func = func;
d->cs.localSize = shader.description().computeShaderLocalSize();
- if (const QShader::NativeResourceBindingMap *map = shader.nativeResourceBindingMap(activeKey))
- d->cs.nativeResourceBindingMap = *map;
+ d->cs.nativeResourceBindingMap = shader.nativeResourceBindingMap(activeKey);
+ d->cs.desc = shader.description();
+ d->cs.nativeShaderInfo = shader.nativeShaderInfo(activeKey);
+
+ // SPIRV-Cross buffer size buffers
+ if (d->cs.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)) {
+ const int binding = d->cs.nativeShaderInfo.extraBufferBindings[QShaderPrivate::MslBufferSizeBufferBinding];
+ d->cs.nativeResourceBindingMap[binding] = qMakePair(binding, -1);
+ }
if (rhiD->d->shaderCache.count() >= QRhiMetal::MAX_SHADER_CACHE_ENTRIES) {
for (QMetalShader &s : rhiD->d->shaderCache)
@@ -3731,14 +6005,42 @@ bool QMetalComputePipeline::create()
d->localSize = MTLSizeMake(d->cs.localSize[0], d->cs.localSize[1], d->cs.localSize[2]);
+ MTLComputePipelineDescriptor *cpDesc = [MTLComputePipelineDescriptor new];
+ cpDesc.computeFunction = d->cs.func;
+
+ rhiD->d->trySeedingComputePipelineFromBinaryArchive(cpDesc);
+
+ if (rhiD->rhiFlags.testFlag(QRhi::EnablePipelineCacheDataSave))
+ rhiD->d->addComputePipelineToBinaryArchive(cpDesc);
+
NSError *err = nil;
- d->ps = [rhiD->d->dev newComputePipelineStateWithFunction: d->cs.func error: &err];
+ d->ps = [rhiD->d->dev newComputePipelineStateWithDescriptor: cpDesc
+ options: MTLPipelineOptionNone
+ reflection: nil
+ error: &err];
+ [cpDesc release];
if (!d->ps) {
const QString msg = QString::fromNSString(err.localizedDescription);
- qWarning("Failed to create render pipeline state: %s", qPrintable(msg));
+ qWarning("Failed to create compute pipeline state: %s", qPrintable(msg));
return false;
}
+ // SPIRV-Cross buffer size buffers
+ if (d->cs.nativeShaderInfo.extraBufferBindings.contains(QShaderPrivate::MslBufferSizeBufferBinding)) {
+ int buffers = 0;
+ for (const QShaderDescription::StorageBlock &block : d->cs.desc.storageBlocks())
+ buffers = qMax(buffers, d->cs.nativeResourceBindingMap[block.binding].first);
+
+ buffers += 1;
+
+ if (!d->bufferSizeBuffer)
+ d->bufferSizeBuffer = new QMetalBuffer(rhiD, QRhiBuffer::Static, QRhiBuffer::StorageBuffer, buffers * sizeof(int));
+
+ d->bufferSizeBuffer->setSize(buffers * sizeof(int));
+ d->bufferSizeBuffer->create();
+ }
+
+ rhiD->pipelineCreationEnd();
lastActiveFrameSlot = -1;
generation += 1;
rhiD->registerResource(this);
@@ -3770,10 +6072,12 @@ const QRhiNativeHandles *QMetalCommandBuffer::nativeHandles()
return &nativeHandlesStruct;
}
-void QMetalCommandBuffer::resetState()
+void QMetalCommandBuffer::resetState(double lastGpuTime)
{
+ d->lastGpuTime = lastGpuTime;
d->currentRenderPassEncoder = nil;
d->currentComputePassEncoder = nil;
+ d->tessellationComputeEncoder = nil;
d->currentPassRpDesc = nil;
resetPerPassState();
}
@@ -3798,9 +6102,12 @@ void QMetalCommandBuffer::resetPerPassCachedState()
currentIndexOffset = 0;
currentIndexFormat = QRhiCommandBuffer::IndexUInt16;
currentCullMode = -1;
+ currentTriangleFillMode = -1;
currentFrontFaceWinding = -1;
currentDepthBiasValues = { 0.0f, 0.0f };
+ d->currentShaderResourceBindingState = {};
+ d->currentDepthStencilState = nil;
d->currentFirstVertexBinding = -1;
d->currentVertexInputsBuffers.clear();
d->currentVertexInputOffsets.clear();
@@ -3808,7 +6115,7 @@ void QMetalCommandBuffer::resetPerPassCachedState()
QMetalSwapChain::QMetalSwapChain(QRhiImplementation *rhi)
: QRhiSwapChain(rhi),
- rtWrapper(rhi),
+ rtWrapper(rhi, this),
cbWrapper(rhi),
d(new QMetalSwapChainData)
{
@@ -3832,8 +6139,7 @@ void QMetalSwapChain::destroy()
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
if (d->sem[i]) {
// the semaphores cannot be released if they do not have the initial value
- dispatch_semaphore_wait(d->sem[i], DISPATCH_TIME_FOREVER);
- dispatch_semaphore_signal(d->sem[i]);
+ waitUntilCompleted(i);
dispatch_release(d->sem[i]);
d->sem[i] = nullptr;
@@ -3845,18 +6151,23 @@ void QMetalSwapChain::destroy()
d->msaaTex[i] = nil;
}
+#ifdef Q_OS_MACOS
+ d->liveResizeStartObserver.remove();
+ d->liveResizeEndObserver.remove();
+ d->liveResizeObserverSet = false;
+#endif
+
d->layer = nullptr;
+ m_proxyData = {};
[d->curDrawable release];
d->curDrawable = nil;
QRHI_RES_RHI(QRhiMetal);
- rhiD->swapchains.remove(this);
-
- QRHI_PROF;
- QRHI_PROF_F(releaseSwapChain(this));
-
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->swapchains.remove(this);
+ rhiD->unregisterResource(this);
+ }
}
QRhiCommandBuffer *QMetalSwapChain::currentFrameCommandBuffer()
@@ -3869,6 +6180,9 @@ QRhiRenderTarget *QMetalSwapChain::currentFrameRenderTarget()
return &rtWrapper;
}
+// view.layer should ideally be called on the main thread, otherwise the UI
+// Thread Checker in Xcode drops a warning. Hence trying to proxy it through
+// QRhiSwapChainProxyData instead of just calling this function directly.
static inline CAMetalLayer *layerForWindow(QWindow *window)
{
Q_ASSERT(window);
@@ -3881,21 +6195,51 @@ static inline CAMetalLayer *layerForWindow(QWindow *window)
return static_cast<CAMetalLayer *>(view.layer);
}
+// If someone calls this, it is hopefully from the main thread, and they will
+// then set the returned data on the QRhiSwapChain, so it won't need to query
+// the layer on its own later on.
+QRhiSwapChainProxyData QRhiMetal::updateSwapChainProxyData(QWindow *window)
+{
+ QRhiSwapChainProxyData d;
+ d.reserved[0] = layerForWindow(window);
+ return d;
+}
+
QSize QMetalSwapChain::surfacePixelSize()
{
Q_ASSERT(m_window);
CAMetalLayer *layer = d->layer;
if (!layer)
- layer = layerForWindow(m_window);
+ layer = qrhi_objectFromProxyData<CAMetalLayer>(&m_proxyData, m_window, QRhi::Metal, 0);
+
+ Q_ASSERT(layer);
+ int height = (int)layer.bounds.size.height;
+ int width = (int)layer.bounds.size.width;
+ width *= layer.contentsScale;
+ height *= layer.contentsScale;
+ return QSize(width, height);
+}
- CGSize layerSize = layer.bounds.size;
- layerSize.width *= layer.contentsScale;
- layerSize.height *= layer.contentsScale;
- return QSizeF::fromCGSize(layerSize).toSize();
+bool QMetalSwapChain::isFormatSupported(Format f)
+{
+ if (f == HDRExtendedSrgbLinear) {
+ if (@available(macOS 10.11, iOS 16.0, *))
+ return hdrInfo().limits.colorComponentValue.maxPotentialColorComponentValue > 1.0f;
+ else
+ return false;
+ } else if (f == HDRExtendedDisplayP3Linear) {
+ if (@available(macOS 11.0, iOS 14.0, *))
+ return hdrInfo().limits.colorComponentValue.maxPotentialColorComponentValue > 1.0f;
+ else
+ return false;
+ }
+ return f == SDR;
}
QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor()
{
+ QRHI_RES_RHI(QRhiMetal);
+
chooseFormats(); // ensure colorFormat and similar are filled out
QMetalRenderPassDescriptor *rpD = new QMetalRenderPassDescriptor(m_rhi);
@@ -3906,13 +6250,15 @@ QRhiRenderPassDescriptor *QMetalSwapChain::newCompatibleRenderPassDescriptor()
#ifdef Q_OS_MACOS
// m_depthStencil may not be built yet so cannot rely on computed fields in it
- QRHI_RES_RHI(QRhiMetal);
rpD->dsFormat = rhiD->d->dev.depth24Stencil8PixelFormatSupported
? MTLPixelFormatDepth24Unorm_Stencil8 : MTLPixelFormatDepth32Float_Stencil8;
#else
rpD->dsFormat = MTLPixelFormatDepth32Float_Stencil8;
#endif
+ rpD->updateSerializedFormat();
+
+ rhiD->registerResource(rpD, false);
return rpD;
}
@@ -3921,10 +6267,26 @@ void QMetalSwapChain::chooseFormats()
QRHI_RES_RHI(QRhiMetal);
samples = rhiD->effectiveSampleCount(m_sampleCount);
// pick a format that is allowed for CAMetalLayer.pixelFormat
+ if (m_format == HDRExtendedSrgbLinear || m_format == HDRExtendedDisplayP3Linear) {
+ d->colorFormat = MTLPixelFormatRGBA16Float;
+ d->rhiColorFormat = QRhiTexture::RGBA16F;
+ return;
+ }
d->colorFormat = m_flags.testFlag(sRGB) ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm;
d->rhiColorFormat = QRhiTexture::BGRA8;
}
+void QMetalSwapChain::waitUntilCompleted(int slot)
+{
+ // wait+signal is the general pattern to ensure the commands for a
+ // given frame slot have completed (if sem is 1, we go 0 then 1; if
+ // sem is 0 we go -1, block, completion increments to 0, then us to 1)
+
+ dispatch_semaphore_t sem = d->sem[slot];
+ dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
+ dispatch_semaphore_signal(sem);
+}
+
bool QMetalSwapChain::createOrResize()
{
Q_ASSERT(m_window);
@@ -3946,13 +6308,25 @@ bool QMetalSwapChain::createOrResize()
return false;
}
- d->layer = layerForWindow(window);
+ d->layer = qrhi_objectFromProxyData<CAMetalLayer>(&m_proxyData, window, QRhi::Metal, 0);
Q_ASSERT(d->layer);
chooseFormats();
if (d->colorFormat != d->layer.pixelFormat)
d->layer.pixelFormat = d->colorFormat;
+ if (m_format == HDRExtendedSrgbLinear) {
+ if (@available(macOS 10.11, iOS 16.0, *)) {
+ d->layer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceExtendedLinearSRGB);
+ d->layer.wantsExtendedDynamicRangeContent = YES;
+ }
+ } else if (m_format == HDRExtendedDisplayP3Linear) {
+ if (@available(macOS 11.0, iOS 16.0, *)) {
+ d->layer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceExtendedLinearDisplayP3);
+ d->layer.wantsExtendedDynamicRangeContent = YES;
+ }
+ }
+
if (m_flags.testFlag(UsedAsTransferSource))
d->layer.framebufferOnly = NO;
@@ -3976,9 +6350,12 @@ bool QMetalSwapChain::createOrResize()
// Now set the layer's drawableSize which will stay set to the same value
// until the next createOrResize(), thus ensuring atomicity with regards to
// the drawable size in frames.
- CGSize layerSize = d->layer.bounds.size;
- layerSize.width *= d->layer.contentsScale;
- layerSize.height *= d->layer.contentsScale;
+ int width = (int)d->layer.bounds.size.width;
+ int height = (int)d->layer.bounds.size.height;
+ CGSize layerSize = CGSizeMake(width, height);
+ const float scaleFactor = d->layer.contentsScale;
+ layerSize.width *= scaleFactor;
+ layerSize.height *= scaleFactor;
d->layer.drawableSize = layerSize;
m_currentPixelSize = QSizeF::fromCGSize(layerSize).toSize();
@@ -3986,10 +6363,39 @@ bool QMetalSwapChain::createOrResize()
[d->layer setDevice: rhiD->d->dev];
+#ifdef Q_OS_MACOS
+ // Can only use presentsWithTransaction (to get smooth resizing) when
+ // presenting from the main (gui) thread. We predict that based on the
+ // thread this function is called on since if the QRhiSwapChain is
+ // initialied on a given thread then that's almost certainly the thread on
+ // which the QRhi renders and presents.
+ const bool canUsePresentsWithTransaction = NSThread.isMainThread;
+
+ // Have an env.var. just in case it turns out presentsWithTransaction is
+ // not desired in some specific case.
+ static bool allowPresentsWithTransaction = !qEnvironmentVariableIntValue("QT_MTL_NO_TRANSACTION");
+
+ if (allowPresentsWithTransaction && canUsePresentsWithTransaction && !d->liveResizeObserverSet) {
+ d->liveResizeObserverSet = true;
+ NSView *view = reinterpret_cast<NSView *>(window->winId());
+ NSWindow *window = view.window;
+ if (window) {
+ qCDebug(QRHI_LOG_INFO, "will set presentsWithTransaction during live resize");
+ d->liveResizeStartObserver = QMacNotificationObserver(window, NSWindowWillStartLiveResizeNotification, [this] {
+ d->layer.presentsWithTransaction = true;
+ });
+ d->liveResizeEndObserver = QMacNotificationObserver(window, NSWindowDidEndLiveResizeNotification, [this] {
+ d->layer.presentsWithTransaction = false;
+ });
+ }
+ }
+#endif
+
[d->curDrawable release];
d->curDrawable = nil;
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
+ d->lastGpuTime[i] = 0;
if (!d->sem[i])
d->sem[i] = dispatch_semaphore_create(QMTL_FRAMES_IN_FLIGHT - 1);
}
@@ -4015,13 +6421,15 @@ bool QMetalSwapChain::createOrResize()
}
}
+ rtWrapper.setRenderPassDescriptor(m_renderPassDesc); // for the public getter in QRhiRenderTarget
rtWrapper.d->pixelSize = pixelSize;
- rtWrapper.d->dpr = float(window->devicePixelRatio());
+ rtWrapper.d->dpr = scaleFactor;
rtWrapper.d->sampleCount = samples;
rtWrapper.d->colorAttCount = 1;
rtWrapper.d->dsAttCount = ds ? 1 : 0;
- qCDebug(QRHI_LOG_INFO, "got CAMetalLayer, size %dx%d", pixelSize.width(), pixelSize.height());
+ qCDebug(QRHI_LOG_INFO, "got CAMetalLayer, pixel size %dx%d (scale %.2f)",
+ pixelSize.width(), pixelSize.height(), scaleFactor);
if (samples > 1) {
MTLTextureDescriptor *desc = [[MTLTextureDescriptor alloc] init];
@@ -4040,13 +6448,39 @@ bool QMetalSwapChain::createOrResize()
[desc release];
}
- QRHI_PROF;
- QRHI_PROF_F(resizeSwapChain(this, QMTL_FRAMES_IN_FLIGHT, samples > 1 ? QMTL_FRAMES_IN_FLIGHT : 0, samples));
-
if (needsRegistration)
rhiD->registerResource(this);
return true;
}
+QRhiSwapChainHdrInfo QMetalSwapChain::hdrInfo()
+{
+ QRhiSwapChainHdrInfo info;
+ info.limitsType = QRhiSwapChainHdrInfo::ColorComponentValue;
+ info.limits.colorComponentValue.maxColorComponentValue = 1;
+ info.limits.colorComponentValue.maxPotentialColorComponentValue = 1;
+ info.luminanceBehavior = QRhiSwapChainHdrInfo::DisplayReferred; // 1.0 = SDR white
+ info.sdrWhiteLevel = 200; // typical value, but dummy (don't know the real one); won't matter due to being display-referred
+
+ if (m_window) {
+ // Must use m_window, not window, given this may be called before createOrResize().
+#if defined(Q_OS_MACOS)
+ NSView *view = reinterpret_cast<NSView *>(m_window->winId());
+ NSScreen *screen = view.window.screen;
+ info.limits.colorComponentValue.maxColorComponentValue = screen.maximumExtendedDynamicRangeColorComponentValue;
+ info.limits.colorComponentValue.maxPotentialColorComponentValue = screen.maximumPotentialExtendedDynamicRangeColorComponentValue;
+#elif defined(Q_OS_IOS)
+ if (@available(iOS 16.0, *)) {
+ UIView *view = reinterpret_cast<UIView *>(m_window->winId());
+ UIScreen *screen = view.window.windowScene.screen;
+ info.limits.colorComponentValue.maxColorComponentValue = view.window.windowScene.screen.currentEDRHeadroom;
+ info.limits.colorComponentValue.maxPotentialColorComponentValue = screen.potentialEDRHeadroom;
+ }
+#endif
+ }
+
+ return info;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhimetal_p.h b/src/gui/rhi/qrhimetal_p.h
index 58025c02f2..f539148b2c 100644
--- a/src/gui/rhi/qrhimetal_p.h
+++ b/src/gui/rhi/qrhimetal_p.h
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHIMETAL_H
-#define QRHIMETAL_H
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHIMETAL_P_H
+#define QRHIMETAL_P_H
//
// W A R N I N G
@@ -51,29 +15,494 @@
// We mean it.
//
-#include <private/qrhi_p.h>
-
-Q_FORWARD_DECLARE_OBJC_CLASS(MTLDevice);
-Q_FORWARD_DECLARE_OBJC_CLASS(MTLCommandQueue);
-Q_FORWARD_DECLARE_OBJC_CLASS(MTLCommandBuffer);
-Q_FORWARD_DECLARE_OBJC_CLASS(MTLRenderCommandEncoder);
+#include "qrhi_p.h"
+#include <QWindow>
QT_BEGIN_NAMESPACE
-struct Q_GUI_EXPORT QRhiMetalInitParams : public QRhiInitParams
+static const int QMTL_FRAMES_IN_FLIGHT = 2;
+
+// have to hide the ObjC stuff, this header cannot contain MTL* at all
+struct QMetalBufferData;
+
+struct QMetalBuffer : public QRhiBuffer
+{
+ QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
+ ~QMetalBuffer();
+ void destroy() override;
+ bool create() override;
+ QRhiBuffer::NativeBuffer nativeBuffer() override;
+ char *beginFullDynamicBufferUpdateForCurrentFrame() override;
+ void endFullDynamicBufferUpdateForCurrentFrame() override;
+
+ QMetalBufferData *d;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+ friend struct QMetalShaderResourceBindings;
+
+ static constexpr int WorkBufPoolUsage = 1 << 8;
+ static_assert(WorkBufPoolUsage > QRhiBuffer::StorageBuffer);
+};
+
+struct QMetalRenderBufferData;
+
+struct QMetalRenderBuffer : public QRhiRenderBuffer
+{
+ QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint);
+ ~QMetalRenderBuffer();
+ void destroy() override;
+ bool create() override;
+ QRhiTexture::Format backingFormat() const override;
+
+ QMetalRenderBufferData *d;
+ int samples = 1;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+};
+
+struct QMetalTextureData;
+
+struct QMetalTexture : public QRhiTexture
+{
+ QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
+ int arraySize, int sampleCount, Flags flags);
+ ~QMetalTexture();
+ void destroy() override;
+ bool create() override;
+ bool createFrom(NativeTexture src) override;
+ NativeTexture nativeTexture() override;
+
+ bool prepareCreate(QSize *adjustedSize = nullptr);
+
+ QMetalTextureData *d;
+ int mipLevelCount = 0;
+ int samples = 1;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+ friend struct QMetalShaderResourceBindings;
+ friend struct QMetalTextureData;
+};
+
+struct QMetalSamplerData;
+
+struct QMetalSampler : public QRhiSampler
+{
+ QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v, AddressMode w);
+ ~QMetalSampler();
+ void destroy() override;
+ bool create() override;
+
+ QMetalSamplerData *d;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+ friend struct QMetalShaderResourceBindings;
+};
+
+struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QMetalRenderPassDescriptor(QRhiImplementation *rhi);
+ ~QMetalRenderPassDescriptor();
+ void destroy() override;
+ bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
+ QVector<quint32> serializedFormat() const override;
+
+ void updateSerializedFormat();
+
+ // there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass()
+
+ // but the things needed for the render pipeline descriptor have to be provided
+ static const int MAX_COLOR_ATTACHMENTS = 8;
+ int colorAttachmentCount = 0;
+ bool hasDepthStencil = false;
+ int colorFormat[MAX_COLOR_ATTACHMENTS];
+ int dsFormat;
+ QVector<quint32> serializedFormatData;
+};
+
+struct QMetalRenderTargetData;
+
+struct QMetalSwapChainRenderTarget : public QRhiSwapChainRenderTarget
+{
+ QMetalSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
+ ~QMetalSwapChainRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QMetalRenderTargetData *d;
+};
+
+struct QMetalTextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QMetalTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
+ ~QMetalTextureRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool create() override;
+
+ QMetalRenderTargetData *d;
+ friend class QRhiMetal;
+};
+
+struct QMetalShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QMetalShaderResourceBindings(QRhiImplementation *rhi);
+ ~QMetalShaderResourceBindings();
+ void destroy() override;
+ bool create() override;
+ void updateResources(UpdateFlags flags) override;
+
+ QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
+ int maxBinding = -1;
+
+ struct BoundUniformBufferData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundSampledTextureData {
+ int count;
+ struct {
+ quint64 texId;
+ uint texGeneration;
+ quint64 samplerId;
+ uint samplerGeneration;
+ } d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
+ };
+ struct BoundStorageImageData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundStorageBufferData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundResourceData {
+ union {
+ BoundUniformBufferData ubuf;
+ BoundSampledTextureData stex;
+ BoundStorageImageData simage;
+ BoundStorageBufferData sbuf;
+ };
+ };
+ QVarLengthArray<BoundResourceData, 8> boundResourceData;
+
+ uint generation = 0;
+ friend class QRhiMetal;
+};
+
+struct QMetalGraphicsPipelineData;
+struct QMetalCommandBuffer;
+
+struct QMetalGraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QMetalGraphicsPipeline(QRhiImplementation *rhi);
+ ~QMetalGraphicsPipeline();
+ void destroy() override;
+ bool create() override;
+
+ void makeActiveForCurrentRenderPassEncoder(QMetalCommandBuffer *cbD);
+ void setupAttachmentsInMetalRenderPassDescriptor(void *metalRpDesc, QMetalRenderPassDescriptor *rpD);
+ void setupMetalDepthStencilDescriptor(void *metalDsDesc);
+ void mapStates();
+ bool createVertexFragmentPipeline();
+ bool createTessellationPipelines(const QShader &tessVert, const QShader &tesc, const QShader &tese, const QShader &tessFrag);
+
+ QMetalGraphicsPipelineData *d;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+};
+
+struct QMetalComputePipelineData;
+
+struct QMetalComputePipeline : public QRhiComputePipeline
+{
+ QMetalComputePipeline(QRhiImplementation *rhi);
+ ~QMetalComputePipeline();
+ void destroy() override;
+ bool create() override;
+
+ QMetalComputePipelineData *d;
+ uint generation = 0;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiMetal;
+};
+
+struct QMetalCommandBufferData;
+struct QMetalSwapChain;
+
+struct QMetalCommandBuffer : public QRhiCommandBuffer
{
+ QMetalCommandBuffer(QRhiImplementation *rhi);
+ ~QMetalCommandBuffer();
+ void destroy() override;
+
+ QMetalCommandBufferData *d = nullptr;
+ QRhiMetalCommandBufferNativeHandles nativeHandlesStruct;
+
+ enum PassType {
+ NoPass,
+ RenderPass,
+ ComputePass
+ };
+
+ // per-pass (render or compute command encoder) persistent state
+ PassType recordingPass;
+ QRhiRenderTarget *currentTarget;
+
+ // per-pass (render or compute command encoder) volatile (cached) state
+ QMetalGraphicsPipeline *currentGraphicsPipeline;
+ QMetalComputePipeline *currentComputePipeline;
+ uint currentPipelineGeneration;
+ QMetalShaderResourceBindings *currentGraphicsSrb;
+ QMetalShaderResourceBindings *currentComputeSrb;
+ uint currentSrbGeneration;
+ int currentResSlot;
+ QMetalBuffer *currentIndexBuffer;
+ quint32 currentIndexOffset;
+ QRhiCommandBuffer::IndexFormat currentIndexFormat;
+ int currentCullMode;
+ int currentTriangleFillMode;
+ int currentFrontFaceWinding;
+ QPair<float, float> currentDepthBiasValues;
+
+ const QRhiNativeHandles *nativeHandles();
+ void resetState(double lastGpuTime = 0);
+ void resetPerPassState();
+ void resetPerPassCachedState();
};
-struct Q_GUI_EXPORT QRhiMetalNativeHandles : public QRhiNativeHandles
+struct QMetalSwapChainData;
+
+struct QMetalSwapChain : public QRhiSwapChain
{
- MTLDevice *dev = nullptr;
- MTLCommandQueue *cmdQueue = nullptr;
+ QMetalSwapChain(QRhiImplementation *rhi);
+ ~QMetalSwapChain();
+ void destroy() override;
+
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+ QSize surfacePixelSize() override;
+ bool isFormatSupported(Format f) override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+
+ bool createOrResize() override;
+
+ virtual QRhiSwapChainHdrInfo hdrInfo() override;
+
+ void chooseFormats();
+ void waitUntilCompleted(int slot);
+
+ QWindow *window = nullptr;
+ QSize pixelSize;
+ int currentFrameSlot = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1
+ int frameCount = 0;
+ int samples = 1;
+ QMetalSwapChainRenderTarget rtWrapper;
+ QMetalCommandBuffer cbWrapper;
+ QMetalRenderBuffer *ds = nullptr;
+ QMetalSwapChainData *d = nullptr;
};
-struct Q_GUI_EXPORT QRhiMetalCommandBufferNativeHandles : public QRhiNativeHandles
+struct QRhiMetalData;
+
+class QRhiMetal : public QRhiImplementation
{
- MTLCommandBuffer *commandBuffer = nullptr;
- MTLRenderCommandEncoder *encoder = nullptr;
+public:
+ QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice = nullptr);
+ ~QRhiMetal();
+
+ static bool probe(QRhiMetalInitParams *params);
+ static QRhiSwapChainProxyData updateSwapChainProxyData(QWindow *window);
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiComputePipeline *createComputePipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ quint32 size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int depth,
+ int arraySize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ void beginComputePass(QRhiCommandBuffer *cb,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+ void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
+ void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+ double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
+
+ QList<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ QRhiDriverInfo driverInfo() const override;
+ QRhiStats statistics() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
+
+ QByteArray pipelineCacheData() override;
+ void setPipelineCacheData(const QByteArray &data) override;
+
+ void executeDeferredReleases(bool forced = false);
+ void finishActiveReadbacks(bool forced = false);
+ qsizetype subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
+ void enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEncPtr,
+ int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc,
+ qsizetype *curOfs);
+ void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
+ void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot);
+ void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
+ static const int SUPPORTED_STAGES = 5;
+ void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD,
+ QMetalCommandBuffer *cbD,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets,
+ bool offsetOnlyChange,
+ const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES]);
+ struct TessDrawArgs {
+ QMetalCommandBuffer *cbD;
+ enum {
+ NonIndexed,
+ U16Indexed,
+ U32Indexed
+ } type;
+ struct NonIndexedArgs {
+ quint32 vertexCount;
+ quint32 instanceCount;
+ quint32 firstVertex;
+ quint32 firstInstance;
+ };
+ struct IndexedArgs {
+ quint32 indexCount;
+ quint32 instanceCount;
+ quint32 firstIndex;
+ qint32 vertexOffset;
+ quint32 firstInstance;
+ void *indexBuffer;
+ };
+ union {
+ NonIndexedArgs draw;
+ IndexedArgs drawIndexed;
+ };
+ };
+ void tessellatedDraw(const TessDrawArgs &args);
+ void adjustForMultiViewDraw(quint32 *instanceCount, QRhiCommandBuffer *cb);
+
+ QRhi::Flags rhiFlags;
+ bool importedDevice = false;
+ bool importedCmdQueue = false;
+ QMetalSwapChain *currentSwapChain = nullptr;
+ QSet<QMetalSwapChain *> swapchains;
+ QRhiMetalNativeHandles nativeHandlesStruct;
+ QRhiDriverInfo driverInfoStruct;
+ quint32 osMajor = 0;
+ quint32 osMinor = 0;
+
+ struct {
+ int maxTextureSize = 4096;
+ bool baseVertexAndInstance = true;
+ QVector<int> supportedSampleCounts;
+ bool isAppleGPU = false;
+ int maxThreadGroupSize = 512;
+ bool multiView = false;
+ } caps;
+
+ QRhiMetalData *d = nullptr;
};
QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
deleted file mode 100644
index 3a22b76b22..0000000000
--- a/src/gui/rhi/qrhimetal_p_p.h
+++ /dev/null
@@ -1,486 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHIMETAL_P_H
-#define QRHIMETAL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qrhimetal_p.h"
-#include "qrhi_p_p.h"
-#include <QWindow>
-
-QT_BEGIN_NAMESPACE
-
-static const int QMTL_FRAMES_IN_FLIGHT = 2;
-
-// have to hide the ObjC stuff, this header cannot contain MTL* at all
-struct QMetalBufferData;
-
-struct QMetalBuffer : public QRhiBuffer
-{
- QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
- ~QMetalBuffer();
- void destroy() override;
- bool create() override;
- QRhiBuffer::NativeBuffer nativeBuffer() override;
- char *beginFullDynamicBufferUpdateForCurrentFrame() override;
- void endFullDynamicBufferUpdateForCurrentFrame() override;
-
- QMetalBufferData *d;
- uint generation = 0;
- int lastActiveFrameSlot = -1;
- friend class QRhiMetal;
- friend struct QMetalShaderResourceBindings;
-};
-
-struct QMetalRenderBufferData;
-
-struct QMetalRenderBuffer : public QRhiRenderBuffer
-{
- QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
- int sampleCount, QRhiRenderBuffer::Flags flags,
- QRhiTexture::Format backingFormatHint);
- ~QMetalRenderBuffer();
- void destroy() override;
- bool create() override;
- QRhiTexture::Format backingFormat() const override;
-
- QMetalRenderBufferData *d;
- int samples = 1;
- uint generation = 0;
- int lastActiveFrameSlot = -1;
- friend class QRhiMetal;
-};
-
-struct QMetalTextureData;
-
-struct QMetalTexture : public QRhiTexture
-{
- QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags);
- ~QMetalTexture();
- void destroy() override;
- bool create() override;
- bool createFrom(NativeTexture src) override;
- NativeTexture nativeTexture() override;
-
- bool prepareCreate(QSize *adjustedSize = nullptr);
-
- QMetalTextureData *d;
- int mipLevelCount = 0;
- int samples = 1;
- uint generation = 0;
- int lastActiveFrameSlot = -1;
- friend class QRhiMetal;
- friend struct QMetalShaderResourceBindings;
- friend struct QMetalTextureData;
-};
-
-struct QMetalSamplerData;
-
-struct QMetalSampler : public QRhiSampler
-{
- QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v, AddressMode w);
- ~QMetalSampler();
- void destroy() override;
- bool create() override;
-
- QMetalSamplerData *d;
- uint generation = 0;
- int lastActiveFrameSlot = -1;
- friend class QRhiMetal;
- friend struct QMetalShaderResourceBindings;
-};
-
-struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor
-{
- QMetalRenderPassDescriptor(QRhiImplementation *rhi);
- ~QMetalRenderPassDescriptor();
- void destroy() override;
- bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
-
- // there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass()
-
- // but the things needed for the render pipeline descriptor have to be provided
- static const int MAX_COLOR_ATTACHMENTS = 8;
- int colorAttachmentCount = 0;
- bool hasDepthStencil = false;
- int colorFormat[MAX_COLOR_ATTACHMENTS];
- int dsFormat;
-};
-
-struct QMetalRenderTargetData;
-
-struct QMetalReferenceRenderTarget : public QRhiRenderTarget
-{
- QMetalReferenceRenderTarget(QRhiImplementation *rhi);
- ~QMetalReferenceRenderTarget();
- void destroy() override;
-
- QSize pixelSize() const override;
- float devicePixelRatio() const override;
- int sampleCount() const override;
-
- QMetalRenderTargetData *d;
-};
-
-struct QMetalTextureRenderTarget : public QRhiTextureRenderTarget
-{
- QMetalTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
- ~QMetalTextureRenderTarget();
- void destroy() override;
-
- QSize pixelSize() const override;
- float devicePixelRatio() const override;
- int sampleCount() const override;
-
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
- bool create() override;
-
- QMetalRenderTargetData *d;
- friend class QRhiMetal;
-};
-
-struct QMetalShaderResourceBindings : public QRhiShaderResourceBindings
-{
- QMetalShaderResourceBindings(QRhiImplementation *rhi);
- ~QMetalShaderResourceBindings();
- void destroy() override;
- bool create() override;
-
- QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
- int maxBinding = -1;
-
- struct BoundUniformBufferData {
- quint64 id;
- uint generation;
- };
- struct BoundSampledTextureData {
- int count;
- struct {
- quint64 texId;
- uint texGeneration;
- quint64 samplerId;
- uint samplerGeneration;
- } d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
- };
- struct BoundStorageImageData {
- quint64 id;
- uint generation;
- };
- struct BoundStorageBufferData {
- quint64 id;
- uint generation;
- };
- struct BoundResourceData {
- union {
- BoundUniformBufferData ubuf;
- BoundSampledTextureData stex;
- BoundStorageImageData simage;
- BoundStorageBufferData sbuf;
- };
- };
- QVarLengthArray<BoundResourceData, 8> boundResourceData;
-
- uint generation = 0;
- friend class QRhiMetal;
-};
-
-struct QMetalGraphicsPipelineData;
-
-struct QMetalGraphicsPipeline : public QRhiGraphicsPipeline
-{
- QMetalGraphicsPipeline(QRhiImplementation *rhi);
- ~QMetalGraphicsPipeline();
- void destroy() override;
- bool create() override;
-
- QMetalGraphicsPipelineData *d;
- uint generation = 0;
- int lastActiveFrameSlot = -1;
- friend class QRhiMetal;
-};
-
-struct QMetalComputePipelineData;
-
-struct QMetalComputePipeline : public QRhiComputePipeline
-{
- QMetalComputePipeline(QRhiImplementation *rhi);
- ~QMetalComputePipeline();
- void destroy() override;
- bool create() override;
-
- QMetalComputePipelineData *d;
- uint generation = 0;
- int lastActiveFrameSlot = -1;
- friend class QRhiMetal;
-};
-
-struct QMetalCommandBufferData;
-struct QMetalSwapChain;
-
-struct QMetalCommandBuffer : public QRhiCommandBuffer
-{
- QMetalCommandBuffer(QRhiImplementation *rhi);
- ~QMetalCommandBuffer();
- void destroy() override;
-
- QMetalCommandBufferData *d = nullptr;
- QRhiMetalCommandBufferNativeHandles nativeHandlesStruct;
-
- enum PassType {
- NoPass,
- RenderPass,
- ComputePass
- };
-
- // per-pass (render or compute command encoder) persistent state
- PassType recordingPass;
- QRhiRenderTarget *currentTarget;
-
- // per-pass (render or compute command encoder) volatile (cached) state
- QRhiGraphicsPipeline *currentGraphicsPipeline;
- QRhiComputePipeline *currentComputePipeline;
- uint currentPipelineGeneration;
- QRhiShaderResourceBindings *currentGraphicsSrb;
- QRhiShaderResourceBindings *currentComputeSrb;
- uint currentSrbGeneration;
- int currentResSlot;
- QRhiBuffer *currentIndexBuffer;
- quint32 currentIndexOffset;
- QRhiCommandBuffer::IndexFormat currentIndexFormat;
- int currentCullMode;
- int currentFrontFaceWinding;
- QPair<float, float> currentDepthBiasValues;
-
- const QRhiNativeHandles *nativeHandles();
- void resetState();
- void resetPerPassState();
- void resetPerPassCachedState();
-};
-
-struct QMetalSwapChainData;
-
-struct QMetalSwapChain : public QRhiSwapChain
-{
- QMetalSwapChain(QRhiImplementation *rhi);
- ~QMetalSwapChain();
- void destroy() override;
-
- QRhiCommandBuffer *currentFrameCommandBuffer() override;
- QRhiRenderTarget *currentFrameRenderTarget() override;
- QSize surfacePixelSize() override;
-
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
-
- bool createOrResize() override;
-
- void chooseFormats();
-
- QWindow *window = nullptr;
- QSize pixelSize;
- int currentFrameSlot = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1
- int frameCount = 0;
- int samples = 1;
- QMetalReferenceRenderTarget rtWrapper;
- QMetalCommandBuffer cbWrapper;
- QMetalRenderBuffer *ds = nullptr;
- QMetalSwapChainData *d = nullptr;
-};
-
-struct QRhiMetalData;
-
-class QRhiMetal : public QRhiImplementation
-{
-public:
- QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice = nullptr);
- ~QRhiMetal();
-
- bool create(QRhi::Flags flags) override;
- void destroy() override;
-
- QRhiGraphicsPipeline *createGraphicsPipeline() override;
- QRhiComputePipeline *createComputePipeline() override;
- QRhiShaderResourceBindings *createShaderResourceBindings() override;
- QRhiBuffer *createBuffer(QRhiBuffer::Type type,
- QRhiBuffer::UsageFlags usage,
- int size) override;
- QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
- const QSize &pixelSize,
- int sampleCount,
- QRhiRenderBuffer::Flags flags,
- QRhiTexture::Format backingFormatHint) override;
- QRhiTexture *createTexture(QRhiTexture::Format format,
- const QSize &pixelSize,
- int depth,
- int sampleCount,
- QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
- QRhiSampler::Filter minFilter,
- QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u,
- QRhiSampler::AddressMode v,
- QRhiSampler::AddressMode w) override;
-
- QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
- QRhiTextureRenderTarget::Flags flags) override;
-
- QRhiSwapChain *createSwapChain() override;
- QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
- QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
- QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
- QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
- QRhi::FrameOpResult finish() override;
-
- void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
-
- void beginPass(QRhiCommandBuffer *cb,
- QRhiRenderTarget *rt,
- const QColor &colorClearValue,
- const QRhiDepthStencilClearValue &depthStencilClearValue,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) override;
- void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
-
- void setGraphicsPipeline(QRhiCommandBuffer *cb,
- QRhiGraphicsPipeline *ps) override;
-
- void setShaderResources(QRhiCommandBuffer *cb,
- QRhiShaderResourceBindings *srb,
- int dynamicOffsetCount,
- const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
-
- void setVertexInput(QRhiCommandBuffer *cb,
- int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
- QRhiBuffer *indexBuf, quint32 indexOffset,
- QRhiCommandBuffer::IndexFormat indexFormat) override;
-
- void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
- void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
- void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
- void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
-
- void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
- quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
-
- void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
- quint32 instanceCount, quint32 firstIndex,
- qint32 vertexOffset, quint32 firstInstance) override;
-
- void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
- void debugMarkEnd(QRhiCommandBuffer *cb) override;
- void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
-
- void beginComputePass(QRhiCommandBuffer *cb,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) override;
- void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
- void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
- void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
-
- const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
- void beginExternal(QRhiCommandBuffer *cb) override;
- void endExternal(QRhiCommandBuffer *cb) override;
-
- QList<int> supportedSampleCounts() const override;
- int ubufAlignment() const override;
- bool isYUpInFramebuffer() const override;
- bool isYUpInNDC() const override;
- bool isClipDepthZeroToOne() const override;
- QMatrix4x4 clipSpaceCorrMatrix() const override;
- bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
- bool isFeatureSupported(QRhi::Feature feature) const override;
- int resourceLimit(QRhi::ResourceLimit limit) const override;
- const QRhiNativeHandles *nativeHandles() override;
- QRhiDriverInfo driverInfo() const override;
- void sendVMemStatsToProfiler() override;
- bool makeThreadLocalNativeContextCurrent() override;
- void releaseCachedResources() override;
- bool isDeviceLost() const override;
-
- QByteArray pipelineCacheData() override;
- void setPipelineCacheData(const QByteArray &data) override;
-
- void executeDeferredReleases(bool forced = false);
- void finishActiveReadbacks(bool forced = false);
- qsizetype subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
- void enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEncPtr,
- int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc,
- qsizetype *curOfs);
- void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
- void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot);
- void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
- static const int SUPPORTED_STAGES = 3;
- void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD,
- QMetalCommandBuffer *cbD,
- int dynamicOffsetCount,
- const QRhiCommandBuffer::DynamicOffset *dynamicOffsets,
- bool offsetOnlyChange,
- const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES]);
- int effectiveSampleCount(int sampleCount) const;
-
- bool importedDevice = false;
- bool importedCmdQueue = false;
- QMetalSwapChain *currentSwapChain = nullptr;
- QSet<QMetalSwapChain *> swapchains;
- QRhiMetalNativeHandles nativeHandlesStruct;
- QRhiDriverInfo driverInfoStruct;
-
- struct {
- int maxTextureSize = 4096;
- } caps;
-
- QRhiMetalData *d = nullptr;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp
index d8dd77a790..566b922c1b 100644
--- a/src/gui/rhi/qrhinull.cpp
+++ b/src/gui/rhi/qrhinull.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qrhinull_p_p.h"
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhinull_p.h"
#include <qmath.h>
#include <QPainter>
@@ -45,10 +9,13 @@ QT_BEGIN_NAMESPACE
/*!
\class QRhiNullInitParams
- \internal
\inmodule QtGui
+ \since 6.6
\brief Null backend specific initialization parameters.
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
A Null QRhi needs no special parameters for initialization.
\badcode
@@ -59,15 +26,17 @@ QT_BEGIN_NAMESPACE
The Null backend does not issue any graphics calls and creates no
resources. All QRhi operations will succeed as normal so applications can
still be run, albeit potentially at an unthrottled speed, depending on
- their frame rendering strategy. The backend reports resources to
- QRhiProfiler as usual.
+ their frame rendering strategy.
*/
/*!
\class QRhiNullNativeHandles
- \internal
\inmodule QtGui
+ \since 6.6
\brief Empty.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
QRhiNull::QRhiNull(QRhiNullInitParams *params)
@@ -96,7 +65,7 @@ QRhiSwapChain *QRhiNull::createSwapChain()
return new QNullSwapChain(this);
}
-QRhiBuffer *QRhiNull::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+QRhiBuffer *QRhiNull::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
{
return new QNullBuffer(this, type, usage, size);
}
@@ -162,10 +131,17 @@ int QRhiNull::resourceLimit(QRhi::ResourceLimit limit) const
return 0;
case QRhi::MaxThreadGroupZ:
return 0;
- default:
- Q_UNREACHABLE();
- return 0;
+ case QRhi::TextureArraySizeMax:
+ return 2048;
+ case QRhi::MaxUniformBufferRange:
+ return 65536;
+ case QRhi::MaxVertexInputs:
+ return 32;
+ case QRhi::MaxVertexOutputs:
+ return 32;
}
+
+ Q_UNREACHABLE_RETURN(0);
}
const QRhiNativeHandles *QRhiNull::nativeHandles()
@@ -180,9 +156,9 @@ QRhiDriverInfo QRhiNull::driverInfo() const
return info;
}
-void QRhiNull::sendVMemStatsToProfiler()
+QRhiStats QRhiNull::statistics()
{
- // nothing to do here
+ return {};
}
bool QRhiNull::makeThreadLocalNativeContextCurrent()
@@ -219,10 +195,10 @@ QRhiRenderBuffer *QRhiNull::createRenderBuffer(QRhiRenderBuffer::Type type, cons
}
QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format,
- const QSize &pixelSize, int depth,
+ const QSize &pixelSize, int depth, int arraySize,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QNullTexture(this, format, pixelSize, depth, sampleCount, flags);
+ return new QNullTexture(this, format, pixelSize, depth, arraySize, sampleCount, flags);
}
QRhiSampler *QRhiNull::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -374,12 +350,16 @@ void QRhiNull::endExternal(QRhiCommandBuffer *cb)
Q_UNUSED(cb);
}
+double QRhiNull::lastCompletedGpuTime(QRhiCommandBuffer *cb)
+{
+ Q_UNUSED(cb);
+ return 0;
+}
+
QRhi::FrameOpResult QRhiNull::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
{
Q_UNUSED(flags);
currentSwapChain = swapChain;
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- QRHI_PROF_F(beginSwapChainFrame(swapChain));
return QRhi::FrameOpSuccess;
}
@@ -387,9 +367,6 @@ QRhi::FrameOpResult QRhiNull::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameF
{
Q_UNUSED(flags);
QNullSwapChain *swapChainD = QRHI_RES(QNullSwapChain, swapChain);
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
- QRHI_PROF_F(swapChainFrameGpuTime(swapChain, 0.000666f));
swapChainD->frameCount += 1;
currentSwapChain = nullptr;
return QRhi::FrameOpSuccess;
@@ -416,9 +393,9 @@ QRhi::FrameOpResult QRhiNull::finish()
void QRhiNull::simulateTextureUpload(const QRhiResourceUpdateBatchPrivate::TextureOp &u)
{
QNullTexture *texD = QRHI_RES(QNullTexture, u.dst);
- for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int layer = 0, maxLayer = u.subresDesc.size(); layer < maxLayer; ++layer) {
for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
- for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level])) {
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level])) {
if (!subresDesc.image().isNull()) {
const QImage src = subresDesc.image();
QPainter painter(&texD->image[layer][level]);
@@ -491,7 +468,7 @@ void QRhiNull::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *re
QNullBuffer *bufD = QRHI_RES(QNullBuffer, u.buf);
memcpy(bufD->data + u.offset, u.data.constData(), size_t(u.data.size()));
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
- QRhiBufferReadbackResult *result = u.result;
+ QRhiReadbackResult *result = u.result;
result->data.resize(u.readSize);
QNullBuffer *bufD = QRHI_RES(QNullBuffer, u.buf);
memcpy(result->data.data(), bufD->data + u.offset, size_t(u.readSize));
@@ -549,12 +526,18 @@ void QRhiNull::beginPass(QRhiCommandBuffer *cb,
QRhiResourceUpdateBatch *resourceUpdates,
QRhiCommandBuffer::BeginPassFlags flags)
{
- Q_UNUSED(rt);
Q_UNUSED(colorClearValue);
Q_UNUSED(depthStencilClearValue);
Q_UNUSED(flags);
+
if (resourceUpdates)
resourceUpdate(cb, resourceUpdates);
+
+ if (rt->resourceType() == QRhiRenderTarget::TextureRenderTarget) {
+ QNullTextureRenderTarget *rtTex = QRHI_RES(QNullTextureRenderTarget, rt);
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QNullTexture, QNullRenderBuffer>(rtTex->description(), rtTex->d.currentResIdList))
+ rtTex->create();
+ }
}
void QRhiNull::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@@ -578,7 +561,7 @@ void QRhiNull::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *re
resourceUpdate(cb, resourceUpdates);
}
-QNullBuffer::QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+QNullBuffer::QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
: QRhiBuffer(rhi, type, usage, size)
{
}
@@ -593,17 +576,22 @@ void QNullBuffer::destroy()
delete[] data;
data = nullptr;
- QRHI_PROF;
- QRHI_PROF_F(releaseBuffer(this));
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullBuffer::create()
{
+ if (data)
+ destroy();
+
data = new char[m_size];
memset(data, 0, m_size);
- QRHI_PROF;
- QRHI_PROF_F(newBuffer(this, uint(m_size), 1, 0));
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(this);
+
return true;
}
@@ -627,14 +615,24 @@ QNullRenderBuffer::~QNullRenderBuffer()
void QNullRenderBuffer::destroy()
{
- QRHI_PROF;
- QRHI_PROF_F(releaseRenderBuffer(this));
+ valid = false;
+
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullRenderBuffer::create()
{
- QRHI_PROF;
- QRHI_PROF_F(newRenderBuffer(this, false, false, 1));
+ if (valid)
+ destroy();
+
+ valid = true;
+ generation += 1;
+
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(this);
+
return true;
}
@@ -644,8 +642,8 @@ QRhiTexture::Format QNullRenderBuffer::backingFormat() const
}
QNullTexture::QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags)
+ int arraySize, int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, arraySize, sampleCount, flags)
{
}
@@ -656,20 +654,33 @@ QNullTexture::~QNullTexture()
void QNullTexture::destroy()
{
- QRHI_PROF;
- QRHI_PROF_F(releaseTexture(this));
+ valid = false;
+
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullTexture::create()
{
+ if (valid)
+ destroy();
+
+ valid = true;
+
QRHI_RES_RHI(QRhiNull);
const bool isCube = m_flags.testFlag(CubeMap);
const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool isArray = m_flags.testFlag(TextureArray);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
- QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
- m_depth = qMax(1, m_depth);
+ const bool is1D = m_flags.testFlags(OneDimensional);
+ QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
+ : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
const int mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
- const int layerCount = is3D ? m_depth : (isCube ? 6 : 1);
+ const int layerCount = is3D ? qMax(1, m_depth)
+ : (isCube ? 6
+ : (isArray ? qMax(0, m_arraySize)
+ : 1));
if (m_format == RGBA8) {
image.resize(layerCount);
@@ -682,21 +693,26 @@ bool QNullTexture::create()
}
}
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, true, mipLevelCount, layerCount, 1));
+ generation += 1;
+
+ rhiD->registerResource(this);
+
return true;
}
bool QNullTexture::createFrom(QRhiTexture::NativeTexture src)
{
Q_UNUSED(src);
+ if (valid)
+ destroy();
+
+ valid = true;
+
+ generation += 1;
+
QRHI_RES_RHI(QRhiNull);
- const bool isCube = m_flags.testFlag(CubeMap);
- const bool hasMipMaps = m_flags.testFlag(MipMapped);
- QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
- const int mipLevelCount = hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1;
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, false, mipLevelCount, isCube ? 6 : 1, 1));
+ rhiD->registerResource(this);
+
return true;
}
@@ -713,10 +729,15 @@ QNullSampler::~QNullSampler()
void QNullSampler::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullSampler::create()
{
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(this);
return true;
}
@@ -732,6 +753,9 @@ QNullRenderPassDescriptor::~QNullRenderPassDescriptor()
void QNullRenderPassDescriptor::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other) const
@@ -742,35 +766,43 @@ bool QNullRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *oth
QRhiRenderPassDescriptor *QNullRenderPassDescriptor::newCompatibleRenderPassDescriptor() const
{
- return new QNullRenderPassDescriptor(m_rhi);
+ QNullRenderPassDescriptor *rpD = new QNullRenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(rpD, false);
+ return rpD;
+}
+
+QVector<quint32> QNullRenderPassDescriptor::serializedFormat() const
+{
+ return {};
}
-QNullReferenceRenderTarget::QNullReferenceRenderTarget(QRhiImplementation *rhi)
- : QRhiRenderTarget(rhi),
+QNullSwapChainRenderTarget::QNullSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
+ : QRhiSwapChainRenderTarget(rhi, swapchain),
d(rhi)
{
}
-QNullReferenceRenderTarget::~QNullReferenceRenderTarget()
+QNullSwapChainRenderTarget::~QNullSwapChainRenderTarget()
{
destroy();
}
-void QNullReferenceRenderTarget::destroy()
+void QNullSwapChainRenderTarget::destroy()
{
}
-QSize QNullReferenceRenderTarget::pixelSize() const
+QSize QNullSwapChainRenderTarget::pixelSize() const
{
return d.pixelSize;
}
-float QNullReferenceRenderTarget::devicePixelRatio() const
+float QNullSwapChainRenderTarget::devicePixelRatio() const
{
return d.dpr;
}
-int QNullReferenceRenderTarget::sampleCount() const
+int QNullSwapChainRenderTarget::sampleCount() const
{
return 1;
}
@@ -790,11 +822,17 @@ QNullTextureRenderTarget::~QNullTextureRenderTarget()
void QNullTextureRenderTarget::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
QRhiRenderPassDescriptor *QNullTextureRenderTarget::newCompatibleRenderPassDescriptor()
{
- return new QNullRenderPassDescriptor(m_rhi);
+ QNullRenderPassDescriptor *rpD = new QNullRenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
bool QNullTextureRenderTarget::create()
@@ -811,11 +849,16 @@ bool QNullTextureRenderTarget::create()
} else if (m_desc.depthTexture()) {
d.pixelSize = m_desc.depthTexture()->pixelSize();
}
+ QRhiRenderTargetAttachmentTracker::updateResIdList<QNullTexture, QNullRenderBuffer>(m_desc, &d.currentResIdList);
+ rhiD->registerResource(this);
return true;
}
QSize QNullTextureRenderTarget::pixelSize() const
{
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QNullTexture, QNullRenderBuffer>(m_desc, d.currentResIdList))
+ const_cast<QNullTextureRenderTarget *>(this)->create();
+
return d.pixelSize;
}
@@ -841,6 +884,9 @@ QNullShaderResourceBindings::~QNullShaderResourceBindings()
void QNullShaderResourceBindings::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullShaderResourceBindings::create()
@@ -851,9 +897,15 @@ bool QNullShaderResourceBindings::create()
rhiD->updateLayoutDesc(this);
+ rhiD->registerResource(this, false);
return true;
}
+void QNullShaderResourceBindings::updateResources(UpdateFlags flags)
+{
+ Q_UNUSED(flags);
+}
+
QNullGraphicsPipeline::QNullGraphicsPipeline(QRhiImplementation *rhi)
: QRhiGraphicsPipeline(rhi)
{
@@ -866,6 +918,9 @@ QNullGraphicsPipeline::~QNullGraphicsPipeline()
void QNullGraphicsPipeline::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullGraphicsPipeline::create()
@@ -874,6 +929,7 @@ bool QNullGraphicsPipeline::create()
if (!rhiD->sanityCheckGraphicsPipeline(this))
return false;
+ rhiD->registerResource(this);
return true;
}
@@ -889,10 +945,15 @@ QNullComputePipeline::~QNullComputePipeline()
void QNullComputePipeline::destroy()
{
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
bool QNullComputePipeline::create()
{
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(this);
return true;
}
@@ -913,7 +974,7 @@ void QNullCommandBuffer::destroy()
QNullSwapChain::QNullSwapChain(QRhiImplementation *rhi)
: QRhiSwapChain(rhi),
- rt(rhi),
+ rt(rhi, this),
cb(rhi)
{
}
@@ -925,8 +986,9 @@ QNullSwapChain::~QNullSwapChain()
void QNullSwapChain::destroy()
{
- QRHI_PROF;
- QRHI_PROF_F(releaseSwapChain(this));
+ QRHI_RES_RHI(QRhiNull);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
QRhiCommandBuffer *QNullSwapChain::currentFrameCommandBuffer()
@@ -944,19 +1006,37 @@ QSize QNullSwapChain::surfacePixelSize()
return QSize(1280, 720);
}
+bool QNullSwapChain::isFormatSupported(Format f)
+{
+ return f == SDR;
+}
+
QRhiRenderPassDescriptor *QNullSwapChain::newCompatibleRenderPassDescriptor()
{
- return new QNullRenderPassDescriptor(m_rhi);
+ QNullRenderPassDescriptor *rpD = new QNullRenderPassDescriptor(m_rhi);
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(rpD, false);
+ return rpD;
}
bool QNullSwapChain::createOrResize()
{
+ const bool needsRegistration = !window || window != m_window;
+ if (window && window != m_window)
+ destroy();
+
+ window = m_window;
m_currentPixelSize = surfacePixelSize();
+ rt.setRenderPassDescriptor(m_renderPassDesc); // for the public getter in QRhiRenderTarget
rt.d.rp = QRHI_RES(QNullRenderPassDescriptor, m_renderPassDesc);
rt.d.pixelSize = m_currentPixelSize;
frameCount = 0;
- QRHI_PROF;
- QRHI_PROF_F(resizeSwapChain(this, 1, 0, 1));
+
+ if (needsRegistration) {
+ QRHI_RES_RHI(QRhiNull);
+ rhiD->registerResource(this);
+ }
+
return true;
}
diff --git a/src/gui/rhi/qrhinull_p.h b/src/gui/rhi/qrhinull_p.h
index 8b45d3b254..fc266b4f38 100644
--- a/src/gui/rhi/qrhinull_p.h
+++ b/src/gui/rhi/qrhinull_p.h
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHINULL_H
-#define QRHINULL_H
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHINULL_P_H
+#define QRHINULL_P_H
//
// W A R N I N G
@@ -51,16 +15,279 @@
// We mean it.
//
-#include <private/qrhi_p.h>
+#include "qrhi_p.h"
QT_BEGIN_NAMESPACE
-struct Q_GUI_EXPORT QRhiNullInitParams : public QRhiInitParams
+struct QNullBuffer : public QRhiBuffer
+{
+ QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
+ ~QNullBuffer();
+ void destroy() override;
+ bool create() override;
+ char *beginFullDynamicBufferUpdateForCurrentFrame() override;
+
+ char *data = nullptr;
+};
+
+struct QNullRenderBuffer : public QRhiRenderBuffer
+{
+ QNullRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint);
+ ~QNullRenderBuffer();
+ void destroy() override;
+ bool create() override;
+ QRhiTexture::Format backingFormat() const override;
+
+ bool valid = false;
+ uint generation = 0;
+};
+
+struct QNullTexture : public QRhiTexture
{
+ QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
+ int arraySize, int sampleCount, Flags flags);
+ ~QNullTexture();
+ void destroy() override;
+ bool create() override;
+ bool createFrom(NativeTexture src) override;
+
+ bool valid = false;
+ QVarLengthArray<std::array<QImage, QRhi::MAX_MIP_LEVELS>, 6> image;
+ uint generation = 0;
};
-struct Q_GUI_EXPORT QRhiNullNativeHandles : public QRhiNativeHandles
+struct QNullSampler : public QRhiSampler
{
+ QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v, AddressMode w);
+ ~QNullSampler();
+ void destroy() override;
+ bool create() override;
+};
+
+struct QNullRenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QNullRenderPassDescriptor(QRhiImplementation *rhi);
+ ~QNullRenderPassDescriptor();
+ void destroy() override;
+ bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
+ QVector<quint32> serializedFormat() const override;
+};
+
+struct QNullRenderTargetData
+{
+ QNullRenderTargetData(QRhiImplementation *) { }
+
+ QNullRenderPassDescriptor *rp = nullptr;
+ QSize pixelSize;
+ float dpr = 1;
+ QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList;
+};
+
+struct QNullSwapChainRenderTarget : public QRhiSwapChainRenderTarget
+{
+ QNullSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
+ ~QNullSwapChainRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QNullRenderTargetData d;
+};
+
+struct QNullTextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QNullTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
+ ~QNullTextureRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool create() override;
+
+ QNullRenderTargetData d;
+};
+
+struct QNullShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QNullShaderResourceBindings(QRhiImplementation *rhi);
+ ~QNullShaderResourceBindings();
+ void destroy() override;
+ bool create() override;
+ void updateResources(UpdateFlags flags) override;
+};
+
+struct QNullGraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QNullGraphicsPipeline(QRhiImplementation *rhi);
+ ~QNullGraphicsPipeline();
+ void destroy() override;
+ bool create() override;
+};
+
+struct QNullComputePipeline : public QRhiComputePipeline
+{
+ QNullComputePipeline(QRhiImplementation *rhi);
+ ~QNullComputePipeline();
+ void destroy() override;
+ bool create() override;
+};
+
+struct QNullCommandBuffer : public QRhiCommandBuffer
+{
+ QNullCommandBuffer(QRhiImplementation *rhi);
+ ~QNullCommandBuffer();
+ void destroy() override;
+};
+
+struct QNullSwapChain : public QRhiSwapChain
+{
+ QNullSwapChain(QRhiImplementation *rhi);
+ ~QNullSwapChain();
+ void destroy() override;
+
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+
+ QSize surfacePixelSize() override;
+ bool isFormatSupported(Format f) override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool createOrResize() override;
+
+ QWindow *window = nullptr;
+ QNullSwapChainRenderTarget rt;
+ QNullCommandBuffer cb;
+ int frameCount = 0;
+};
+
+class QRhiNull : public QRhiImplementation
+{
+public:
+ QRhiNull(QRhiNullInitParams *params);
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiComputePipeline *createComputePipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ quint32 size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int depth,
+ int arraySize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ void beginComputePass(QRhiCommandBuffer *cb,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+ void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
+ void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+ double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
+
+ QList<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ QRhiDriverInfo driverInfo() const override;
+ QRhiStats statistics() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
+
+ QByteArray pipelineCacheData() override;
+ void setPipelineCacheData(const QByteArray &data) override;
+
+ void simulateTextureUpload(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
+ void simulateTextureCopy(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
+ void simulateTextureGenMips(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
+
+ QRhiNullNativeHandles nativeHandlesStruct;
+ QRhiSwapChain *currentSwapChain = nullptr;
+ QNullCommandBuffer offscreenCommandBuffer;
};
QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhinull_p_p.h b/src/gui/rhi/qrhinull_p_p.h
deleted file mode 100644
index b064e7ad37..0000000000
--- a/src/gui/rhi/qrhinull_p_p.h
+++ /dev/null
@@ -1,320 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHINULL_P_H
-#define QRHINULL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qrhinull_p.h"
-#include "qrhi_p_p.h"
-
-QT_BEGIN_NAMESPACE
-
-struct QNullBuffer : public QRhiBuffer
-{
- QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
- ~QNullBuffer();
- void destroy() override;
- bool create() override;
- char *beginFullDynamicBufferUpdateForCurrentFrame() override;
-
- char *data = nullptr;
-};
-
-struct QNullRenderBuffer : public QRhiRenderBuffer
-{
- QNullRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
- int sampleCount, QRhiRenderBuffer::Flags flags,
- QRhiTexture::Format backingFormatHint);
- ~QNullRenderBuffer();
- void destroy() override;
- bool create() override;
- QRhiTexture::Format backingFormat() const override;
-};
-
-struct QNullTexture : public QRhiTexture
-{
- QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags);
- ~QNullTexture();
- void destroy() override;
- bool create() override;
- bool createFrom(NativeTexture src) override;
-
- QVarLengthArray<std::array<QImage, QRhi::MAX_MIP_LEVELS>, 6> image;
-};
-
-struct QNullSampler : public QRhiSampler
-{
- QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v, AddressMode w);
- ~QNullSampler();
- void destroy() override;
- bool create() override;
-};
-
-struct QNullRenderPassDescriptor : public QRhiRenderPassDescriptor
-{
- QNullRenderPassDescriptor(QRhiImplementation *rhi);
- ~QNullRenderPassDescriptor();
- void destroy() override;
- bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
-};
-
-struct QNullRenderTargetData
-{
- QNullRenderTargetData(QRhiImplementation *) { }
-
- QNullRenderPassDescriptor *rp = nullptr;
- QSize pixelSize;
- float dpr = 1;
-};
-
-struct QNullReferenceRenderTarget : public QRhiRenderTarget
-{
- QNullReferenceRenderTarget(QRhiImplementation *rhi);
- ~QNullReferenceRenderTarget();
- void destroy() override;
-
- QSize pixelSize() const override;
- float devicePixelRatio() const override;
- int sampleCount() const override;
-
- QNullRenderTargetData d;
-};
-
-struct QNullTextureRenderTarget : public QRhiTextureRenderTarget
-{
- QNullTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
- ~QNullTextureRenderTarget();
- void destroy() override;
-
- QSize pixelSize() const override;
- float devicePixelRatio() const override;
- int sampleCount() const override;
-
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
- bool create() override;
-
- QNullRenderTargetData d;
-};
-
-struct QNullShaderResourceBindings : public QRhiShaderResourceBindings
-{
- QNullShaderResourceBindings(QRhiImplementation *rhi);
- ~QNullShaderResourceBindings();
- void destroy() override;
- bool create() override;
-};
-
-struct QNullGraphicsPipeline : public QRhiGraphicsPipeline
-{
- QNullGraphicsPipeline(QRhiImplementation *rhi);
- ~QNullGraphicsPipeline();
- void destroy() override;
- bool create() override;
-};
-
-struct QNullComputePipeline : public QRhiComputePipeline
-{
- QNullComputePipeline(QRhiImplementation *rhi);
- ~QNullComputePipeline();
- void destroy() override;
- bool create() override;
-};
-
-struct QNullCommandBuffer : public QRhiCommandBuffer
-{
- QNullCommandBuffer(QRhiImplementation *rhi);
- ~QNullCommandBuffer();
- void destroy() override;
-};
-
-struct QNullSwapChain : public QRhiSwapChain
-{
- QNullSwapChain(QRhiImplementation *rhi);
- ~QNullSwapChain();
- void destroy() override;
-
- QRhiCommandBuffer *currentFrameCommandBuffer() override;
- QRhiRenderTarget *currentFrameRenderTarget() override;
-
- QSize surfacePixelSize() override;
-
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
- bool createOrResize() override;
-
- QNullReferenceRenderTarget rt;
- QNullCommandBuffer cb;
- int frameCount = 0;
-};
-
-class QRhiNull : public QRhiImplementation
-{
-public:
- QRhiNull(QRhiNullInitParams *params);
-
- bool create(QRhi::Flags flags) override;
- void destroy() override;
-
- QRhiGraphicsPipeline *createGraphicsPipeline() override;
- QRhiComputePipeline *createComputePipeline() override;
- QRhiShaderResourceBindings *createShaderResourceBindings() override;
- QRhiBuffer *createBuffer(QRhiBuffer::Type type,
- QRhiBuffer::UsageFlags usage,
- int size) override;
- QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
- const QSize &pixelSize,
- int sampleCount,
- QRhiRenderBuffer::Flags flags,
- QRhiTexture::Format backingFormatHint) override;
- QRhiTexture *createTexture(QRhiTexture::Format format,
- const QSize &pixelSize,
- int depth,
- int sampleCount,
- QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
- QRhiSampler::Filter minFilter,
- QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u,
- QRhiSampler::AddressMode v,
- QRhiSampler::AddressMode w) override;
-
- QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
- QRhiTextureRenderTarget::Flags flags) override;
-
- QRhiSwapChain *createSwapChain() override;
- QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
- QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
- QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
- QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
- QRhi::FrameOpResult finish() override;
-
- void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
-
- void beginPass(QRhiCommandBuffer *cb,
- QRhiRenderTarget *rt,
- const QColor &colorClearValue,
- const QRhiDepthStencilClearValue &depthStencilClearValue,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) override;
- void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
-
- void setGraphicsPipeline(QRhiCommandBuffer *cb,
- QRhiGraphicsPipeline *ps) override;
-
- void setShaderResources(QRhiCommandBuffer *cb,
- QRhiShaderResourceBindings *srb,
- int dynamicOffsetCount,
- const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
-
- void setVertexInput(QRhiCommandBuffer *cb,
- int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
- QRhiBuffer *indexBuf, quint32 indexOffset,
- QRhiCommandBuffer::IndexFormat indexFormat) override;
-
- void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
- void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
- void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
- void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
-
- void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
- quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
-
- void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
- quint32 instanceCount, quint32 firstIndex,
- qint32 vertexOffset, quint32 firstInstance) override;
-
- void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
- void debugMarkEnd(QRhiCommandBuffer *cb) override;
- void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
-
- void beginComputePass(QRhiCommandBuffer *cb,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) override;
- void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
- void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
- void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
-
- const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
- void beginExternal(QRhiCommandBuffer *cb) override;
- void endExternal(QRhiCommandBuffer *cb) override;
-
- QList<int> supportedSampleCounts() const override;
- int ubufAlignment() const override;
- bool isYUpInFramebuffer() const override;
- bool isYUpInNDC() const override;
- bool isClipDepthZeroToOne() const override;
- QMatrix4x4 clipSpaceCorrMatrix() const override;
- bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
- bool isFeatureSupported(QRhi::Feature feature) const override;
- int resourceLimit(QRhi::ResourceLimit limit) const override;
- const QRhiNativeHandles *nativeHandles() override;
- QRhiDriverInfo driverInfo() const override;
- void sendVMemStatsToProfiler() override;
- bool makeThreadLocalNativeContextCurrent() override;
- void releaseCachedResources() override;
- bool isDeviceLost() const override;
-
- QByteArray pipelineCacheData() override;
- void setPipelineCacheData(const QByteArray &data) override;
-
- void simulateTextureUpload(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
- void simulateTextureCopy(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
- void simulateTextureGenMips(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
-
- QRhiNullNativeHandles nativeHandlesStruct;
- QRhiSwapChain *currentSwapChain = nullptr;
- QNullCommandBuffer offscreenCommandBuffer;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qrhiprofiler.cpp b/src/gui/rhi/qrhiprofiler.cpp
deleted file mode 100644
index 76798dc396..0000000000
--- a/src/gui/rhi/qrhiprofiler.cpp
+++ /dev/null
@@ -1,611 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qrhiprofiler_p_p.h"
-#include "qrhi_p_p.h"
-#include <QtCore/qiodevice.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QRhiProfiler
- \internal
- \inmodule QtGui
-
- \brief Collects resource and timing information from an active QRhi.
-
- A QRhiProfiler is present for each QRhi. Query it via QRhi::profiler(). The
- profiler is active only when the QRhi was created with
- QRhi::EnableProfiling. No data is collected otherwise.
-
- \note GPU timings are only available when QRhi indicates that
- QRhi::Timestamps is supported.
-
- Besides collecting data from the QRhi implementations, some additional
- values are calculated. For example, for textures and similar resources the
- profiler gives an estimate of the complete amount of memory the resource
- needs.
-
- \section2 Output Format
-
- The output is comma-separated text. Each line has a number of
- comma-separated entries and each line ends with a comma.
-
- For example:
-
- \badcode
- 1,0,140446057946208,Triangle vbuf,type,0,usage,1,logical_size,84,effective_size,84,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
- 1,0,140446057947376,Triangle ubuf,type,2,usage,4,logical_size,68,effective_size,256,backing_gpu_buf_count,2,backing_cpu_buf_count,0,
- 1,1,140446057950416,,type,0,usage,1,logical_size,112,effective_size,112,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
- 1,1,140446057950544,,type,0,usage,2,logical_size,12,effective_size,12,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
- 1,1,140446057947440,,type,2,usage,4,logical_size,68,effective_size,256,backing_gpu_buf_count,2,backing_cpu_buf_count,0,
- 1,1,140446057984784,Cube vbuf (textured),type,0,usage,1,logical_size,720,effective_size,720,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
- 1,1,140446057982528,Cube ubuf (textured),type,2,usage,4,logical_size,68,effective_size,256,backing_gpu_buf_count,2,backing_cpu_buf_count,0,
- 7,8,140446058913648,Qt texture,width,256,height,256,format,1,owns_native_resource,1,mip_count,9,layer_count,1,effective_sample_count,1,approx_byte_size,349524,
- 1,8,140446058795856,Cube vbuf (textured with offscreen),type,0,usage,1,logical_size,720,effective_size,720,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
- 1,8,140446058947920,Cube ubuf (textured with offscreen),type,2,usage,4,logical_size,68,effective_size,256,backing_gpu_buf_count,2,backing_cpu_buf_count,0,
- 7,8,140446058794928,Texture for offscreen content,width,512,height,512,format,1,owns_native_resource,1,mip_count,1,layer_count,1,effective_sample_count,1,approx_byte_size,1048576,
- 1,8,140446058963904,Triangle vbuf,type,0,usage,1,logical_size,84,effective_size,84,backing_gpu_buf_count,1,backing_cpu_buf_count,0,
- 1,8,140446058964560,Triangle ubuf,type,2,usage,4,logical_size,68,effective_size,256,backing_gpu_buf_count,2,backing_cpu_buf_count,0,
- 5,9,140446057945392,,type,0,width,1280,height,720,effective_sample_count,1,transient_backing,0,winsys_backing,0,approx_byte_size,3686400,
- 11,9,140446057944592,,width,1280,height,720,buffer_count,2,msaa_buffer_count,0,effective_sample_count,1,approx_total_byte_size,7372800,
- 9,9,140446058913648,Qt texture,slot,0,size,262144,
- 10,9,140446058913648,Qt texture,slot,0,
- 17,2019,140446057944592,,frames_since_resize,121,min_ms_frame_delta,9,max_ms_frame_delta,33,Favg_ms_frame_delta,16.1167,
- 18,2019,140446057944592,,frames_since_resize,121,min_ms_frame_build,0,max_ms_frame_build,1,Favg_ms_frame_build,0.00833333,
- 17,4019,140446057944592,,frames_since_resize,241,min_ms_frame_delta,15,max_ms_frame_delta,17,Favg_ms_frame_delta,16.0583,
- 18,4019,140446057944592,,frames_since_resize,241,min_ms_frame_build,0,max_ms_frame_build,0,Favg_ms_frame_build,0,
- 12,5070,140446057944592,,
- 2,5079,140446057947376,Triangle ubuf,
- 2,5079,140446057946208,Triangle vbuf,
- 2,5079,140446057947440,,
- 2,5079,140446057950544,,
- 2,5079,140446057950416,,
- 8,5079,140446058913648,Qt texture,
- 2,5079,140446057982528,Cube ubuf (textured),
- 2,5079,140446057984784,Cube vbuf (textured),
- 2,5079,140446058964560,Triangle ubuf,
- 2,5079,140446058963904,Triangle vbuf,
- 8,5079,140446058794928,Texture for offscreen content,
- 2,5079,140446058947920,Cube ubuf (textured with offscreen),
- 2,5079,140446058795856,Cube vbuf (textured with offscreen),
- 6,5079,140446057945392,,
- \endcode
-
- Each line starts with \c op, \c timestamp, \c res, \c name where op is a
- value from StreamOp, timestamp is a recording timestamp in milliseconds
- (qint64), res is a number (quint64) referring to the QRhiResource the entry
- refers to, or 0 if not applicable. \c name is the value of
- QRhiResource::name() and may be empty as well. The \c name will never
- contain a comma.
-
- This is followed by any number of \c{key, value} pairs where \c key is an
- unspecified string and \c value is a number. If \c key starts with \c F, it
- indicates the value is a float. Otherwise assume that the value is a
- qint64.
- */
-
-/*!
- \enum QRhiProfiler::StreamOp
- Describes an entry in the profiler's output stream.
-
- \value NewBuffer A buffer is created
- \value ReleaseBuffer A buffer is destroyed
- \value NewBufferStagingArea A staging buffer for buffer upload is created
- \value ReleaseBufferStagingArea A staging buffer for buffer upload is destroyed
- \value NewRenderBuffer A renderbuffer is created
- \value ReleaseRenderBuffer A renderbuffer is destroyed
- \value NewTexture A texture is created
- \value ReleaseTexture A texture is destroyed
- \value NewTextureStagingArea A staging buffer for texture upload is created
- \value ReleaseTextureStagingArea A staging buffer for texture upload is destroyed
- \value ResizeSwapChain A swapchain is created or resized
- \value ReleaseSwapChain A swapchain is destroyed
- \value NewReadbackBuffer A staging buffer for readback is created
- \value ReleaseReadbackBuffer A staging buffer for readback is destroyed
- \value GpuMemAllocStats GPU memory allocator statistics
- \value GpuFrameTime GPU frame times
- \value FrameToFrameTime CPU frame-to-frame times
- \value FrameBuildTime CPU beginFrame-endFrame times
- */
-
-/*!
- \class QRhiProfiler::CpuTime
- \internal
- \inmodule QtGui
- \brief Contains CPU-side frame timings.
-
- Once sufficient number of frames have been rendered, the minimum, maximum,
- and average values (in milliseconds) from various measurements are made
- available in this struct queriable from QRhiProfiler::frameToFrameTimes()
- and QRhiProfiler::frameBuildTimes().
-
- \sa QRhiProfiler::setFrameTimingWriteInterval()
- */
-
-/*!
- \class QRhiProfiler::GpuTime
- \internal
- \inmodule QtGui
- \brief Contains GPU-side frame timings.
-
- Once sufficient number of frames have been rendered, the minimum, maximum,
- and average values (in milliseconds) calculated from GPU command buffer
- timestamps are made available in this struct queriable from
- QRhiProfiler::gpuFrameTimes().
-
- \sa QRhiProfiler::setFrameTimingWriteInterval()
- */
-
-/*!
- \internal
- */
-QRhiProfiler::QRhiProfiler()
- : d(new QRhiProfilerPrivate)
-{
- d->ts.start();
-}
-
-/*!
- Destructor.
- */
-QRhiProfiler::~QRhiProfiler()
-{
- // Flush because there is a high chance we have writes that were made since
- // the event loop last ran. (esp. relevant for network devices like QTcpSocket)
- if (d->outputDevice)
- d->outputDevice->waitForBytesWritten(1000);
-
- delete d;
-}
-
-/*!
- Sets the output \a device.
-
- \note No output will be generated when QRhi::EnableProfiling was not set.
- */
-void QRhiProfiler::setDevice(QIODevice *device)
-{
- d->outputDevice = device;
-}
-
-/*!
- Requests writing a GpuMemAllocStats entry into the output, when applicable.
- Backends that do not support this will ignore the request. This is an
- explicit request since getting the allocator status and statistics may be
- an expensive operation.
- */
-void QRhiProfiler::addVMemAllocatorStats()
-{
- if (d->rhiDWhenEnabled)
- d->rhiDWhenEnabled->sendVMemStatsToProfiler();
-}
-
-/*!
- \return the currently set frame timing writeout interval.
- */
-int QRhiProfiler::frameTimingWriteInterval() const
-{
- return d->frameTimingWriteInterval;
-}
-
-/*!
- Sets the number of frames that need to be rendered before the collected CPU
- and GPU timings are processed (min, max, average are calculated) to \a
- frameCount.
-
- The default value is 120.
- */
-void QRhiProfiler::setFrameTimingWriteInterval(int frameCount)
-{
- if (frameCount > 0)
- d->frameTimingWriteInterval = frameCount;
-}
-
-/*!
- \return min, max, and avg in milliseconds for the time that elapsed between two
- QRhi::endFrame() calls.
-
- \note The values are all 0 until at least frameTimingWriteInterval() frames
- have been rendered.
- */
-QRhiProfiler::CpuTime QRhiProfiler::frameToFrameTimes(QRhiSwapChain *sc) const
-{
- auto it = d->swapchains.constFind(sc);
- if (it != d->swapchains.constEnd())
- return it->frameToFrameTime;
-
- return QRhiProfiler::CpuTime();
-}
-
-/*!
- \return min, max, and avg in milliseconds for the time that elapsed between
- a QRhi::beginFrame() and QRhi::endFrame().
-
- \note The values are all 0 until at least frameTimingWriteInterval() frames
- have been rendered.
- */
-QRhiProfiler::CpuTime QRhiProfiler::frameBuildTimes(QRhiSwapChain *sc) const
-{
- auto it = d->swapchains.constFind(sc);
- if (it != d->swapchains.constEnd())
- return it->beginToEndFrameTime;
-
- return QRhiProfiler::CpuTime();
-}
-
-/*!
- \return min, max, and avg in milliseconds for the GPU time that is spent on
- one frame.
-
- \note The values are all 0 until at least frameTimingWriteInterval() frames
- have been rendered.
-
- The GPU times should only be compared between runs on the same GPU of the
- same system with the same backend. Comparing times for different graphics
- cards or for different backends can give misleading results. The numbers are
- not meant to be comparable that way.
-
- \note Some backends have no support for this, and even for those that have,
- it is not guaranteed that the driver will support it at run time. Support
- can be checked via QRhi::Timestamps.
- */
-QRhiProfiler::GpuTime QRhiProfiler::gpuFrameTimes(QRhiSwapChain *sc) const
-{
- auto it = d->swapchains.constFind(sc);
- if (it != d->swapchains.constEnd())
- return it->gpuFrameTime;
-
- return QRhiProfiler::GpuTime();
-}
-
-void QRhiProfilerPrivate::startEntry(QRhiProfiler::StreamOp op, qint64 timestamp, QRhiResource *res)
-{
- buf.clear();
- buf.append(QByteArray::number(op));
- buf.append(',');
- buf.append(QByteArray::number(timestamp));
- buf.append(',');
- buf.append(QByteArray::number(quint64(quintptr(res))));
- buf.append(',');
- if (res)
- buf.append(res->name());
- buf.append(',');
-}
-
-void QRhiProfilerPrivate::writeInt(const char *key, qint64 v)
-{
- Q_ASSERT(key[0] != 'F');
- buf.append(key);
- buf.append(',');
- buf.append(QByteArray::number(v));
- buf.append(',');
-}
-
-void QRhiProfilerPrivate::writeFloat(const char *key, float f)
-{
- Q_ASSERT(key[0] == 'F');
- buf.append(key);
- buf.append(',');
- buf.append(QByteArray::number(double(f)));
- buf.append(',');
-}
-
-void QRhiProfilerPrivate::endEntry()
-{
- buf.append('\n');
- outputDevice->write(buf);
-}
-
-void QRhiProfilerPrivate::newBuffer(QRhiBuffer *buf, quint32 realSize, int backingGpuBufCount, int backingCpuBufCount)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::NewBuffer, ts.elapsed(), buf);
- writeInt("type", buf->type());
- writeInt("usage", buf->usage());
- writeInt("logical_size", buf->size());
- writeInt("effective_size", realSize);
- writeInt("backing_gpu_buf_count", backingGpuBufCount);
- writeInt("backing_cpu_buf_count", backingCpuBufCount);
- endEntry();
-}
-
-void QRhiProfilerPrivate::releaseBuffer(QRhiBuffer *buf)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::ReleaseBuffer, ts.elapsed(), buf);
- endEntry();
-}
-
-void QRhiProfilerPrivate::newBufferStagingArea(QRhiBuffer *buf, int slot, quint32 size)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::NewBufferStagingArea, ts.elapsed(), buf);
- writeInt("slot", slot);
- writeInt("size", size);
- endEntry();
-}
-
-void QRhiProfilerPrivate::releaseBufferStagingArea(QRhiBuffer *buf, int slot)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::ReleaseBufferStagingArea, ts.elapsed(), buf);
- writeInt("slot", slot);
- endEntry();
-}
-
-void QRhiProfilerPrivate::newRenderBuffer(QRhiRenderBuffer *rb, bool transientBacking, bool winSysBacking, int sampleCount)
-{
- if (!outputDevice)
- return;
-
- const QRhiRenderBuffer::Type type = rb->type();
- const QSize sz = rb->pixelSize();
- // just make up something, ds is likely D24S8 while color is RGBA8 or similar
- const QRhiTexture::Format assumedFormat = type == QRhiRenderBuffer::DepthStencil ? QRhiTexture::D32F : QRhiTexture::RGBA8;
- quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(assumedFormat, sz, 1, 1, 1);
- if (sampleCount > 1)
- byteSize *= uint(sampleCount);
-
- startEntry(QRhiProfiler::NewRenderBuffer, ts.elapsed(), rb);
- writeInt("type", type);
- writeInt("width", sz.width());
- writeInt("height", sz.height());
- writeInt("effective_sample_count", sampleCount);
- writeInt("transient_backing", transientBacking);
- writeInt("winsys_backing", winSysBacking);
- writeInt("approx_byte_size", byteSize);
- endEntry();
-}
-
-void QRhiProfilerPrivate::releaseRenderBuffer(QRhiRenderBuffer *rb)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::ReleaseRenderBuffer, ts.elapsed(), rb);
- endEntry();
-}
-
-void QRhiProfilerPrivate::newTexture(QRhiTexture *tex, bool owns, int mipCount, int layerCount, int sampleCount)
-{
- if (!outputDevice)
- return;
-
- const QRhiTexture::Format format = tex->format();
- const QSize sz = tex->pixelSize();
- const int depth = tex->depth();
- quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(format, sz, depth, mipCount, layerCount);
- if (sampleCount > 1)
- byteSize *= uint(sampleCount);
-
- startEntry(QRhiProfiler::NewTexture, ts.elapsed(), tex);
- writeInt("width", sz.width());
- writeInt("height", sz.height());
- writeInt("format", format);
- writeInt("owns_native_resource", owns);
- writeInt("mip_count", mipCount);
- writeInt("layer_count", layerCount);
- writeInt("effective_sample_count", sampleCount);
- writeInt("approx_byte_size", byteSize);
- endEntry();
-}
-
-void QRhiProfilerPrivate::releaseTexture(QRhiTexture *tex)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::ReleaseTexture, ts.elapsed(), tex);
- endEntry();
-}
-
-void QRhiProfilerPrivate::newTextureStagingArea(QRhiTexture *tex, int slot, quint32 size)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::NewTextureStagingArea, ts.elapsed(), tex);
- writeInt("slot", slot);
- writeInt("size", size);
- endEntry();
-}
-
-void QRhiProfilerPrivate::releaseTextureStagingArea(QRhiTexture *tex, int slot)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::ReleaseTextureStagingArea, ts.elapsed(), tex);
- writeInt("slot", slot);
- endEntry();
-}
-
-void QRhiProfilerPrivate::resizeSwapChain(QRhiSwapChain *sc, int bufferCount, int msaaBufferCount, int sampleCount)
-{
- if (!outputDevice)
- return;
-
- const QSize sz = sc->currentPixelSize();
- quint32 byteSize = rhiDWhenEnabled->approxByteSizeForTexture(QRhiTexture::BGRA8, sz, 1, 1, 1);
- byteSize = byteSize * uint(bufferCount) + byteSize * uint(msaaBufferCount) * uint(sampleCount);
-
- startEntry(QRhiProfiler::ResizeSwapChain, ts.elapsed(), sc);
- writeInt("width", sz.width());
- writeInt("height", sz.height());
- writeInt("buffer_count", bufferCount);
- writeInt("msaa_buffer_count", msaaBufferCount);
- writeInt("effective_sample_count", sampleCount);
- writeInt("approx_total_byte_size", byteSize);
- endEntry();
-}
-
-void QRhiProfilerPrivate::releaseSwapChain(QRhiSwapChain *sc)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::ReleaseSwapChain, ts.elapsed(), sc);
- endEntry();
-}
-
-template<typename T>
-void calcTiming(QList<T> *vec, T *minDelta, T *maxDelta, float *avgDelta)
-{
- if (vec->isEmpty())
- return;
-
- *minDelta = *maxDelta = 0;
- float totalDelta = 0;
- for (T delta : qAsConst(*vec)) {
- totalDelta += float(delta);
- if (*minDelta == 0 || delta < *minDelta)
- *minDelta = delta;
- if (*maxDelta == 0 || delta > *maxDelta)
- *maxDelta = delta;
- }
- *avgDelta = totalDelta / vec->count();
-
- vec->clear();
-}
-
-void QRhiProfilerPrivate::beginSwapChainFrame(QRhiSwapChain *sc)
-{
- Sc &scd(swapchains[sc]);
- scd.beginToEndTimer.start();
-}
-
-void QRhiProfilerPrivate::endSwapChainFrame(QRhiSwapChain *sc, int frameCount)
-{
- Sc &scd(swapchains[sc]);
- if (!scd.frameToFrameRunning) {
- scd.frameToFrameTimer.start();
- scd.frameToFrameRunning = true;
- return;
- }
-
- scd.frameToFrameSamples.append(scd.frameToFrameTimer.restart());
- if (scd.frameToFrameSamples.count() >= frameTimingWriteInterval) {
- calcTiming(&scd.frameToFrameSamples,
- &scd.frameToFrameTime.minTime, &scd.frameToFrameTime.maxTime, &scd.frameToFrameTime.avgTime);
- if (outputDevice) {
- startEntry(QRhiProfiler::FrameToFrameTime, ts.elapsed(), sc);
- writeInt("frames_since_resize", frameCount);
- writeInt("min_ms_frame_delta", scd.frameToFrameTime.minTime);
- writeInt("max_ms_frame_delta", scd.frameToFrameTime.maxTime);
- writeFloat("Favg_ms_frame_delta", scd.frameToFrameTime.avgTime);
- endEntry();
- }
- }
-
- scd.beginToEndSamples.append(scd.beginToEndTimer.elapsed());
- if (scd.beginToEndSamples.count() >= frameTimingWriteInterval) {
- calcTiming(&scd.beginToEndSamples,
- &scd.beginToEndFrameTime.minTime, &scd.beginToEndFrameTime.maxTime, &scd.beginToEndFrameTime.avgTime);
- if (outputDevice) {
- startEntry(QRhiProfiler::FrameBuildTime, ts.elapsed(), sc);
- writeInt("frames_since_resize", frameCount);
- writeInt("min_ms_frame_build", scd.beginToEndFrameTime.minTime);
- writeInt("max_ms_frame_build", scd.beginToEndFrameTime.maxTime);
- writeFloat("Favg_ms_frame_build", scd.beginToEndFrameTime.avgTime);
- endEntry();
- }
- }
-}
-
-void QRhiProfilerPrivate::swapChainFrameGpuTime(QRhiSwapChain *sc, float gpuTime)
-{
- Sc &scd(swapchains[sc]);
- scd.gpuFrameSamples.append(gpuTime);
- if (scd.gpuFrameSamples.count() >= frameTimingWriteInterval) {
- calcTiming(&scd.gpuFrameSamples,
- &scd.gpuFrameTime.minTime, &scd.gpuFrameTime.maxTime, &scd.gpuFrameTime.avgTime);
- if (outputDevice) {
- startEntry(QRhiProfiler::GpuFrameTime, ts.elapsed(), sc);
- writeFloat("Fmin_ms_gpu_frame_time", scd.gpuFrameTime.minTime);
- writeFloat("Fmax_ms_gpu_frame_time", scd.gpuFrameTime.maxTime);
- writeFloat("Favg_ms_gpu_frame_time", scd.gpuFrameTime.avgTime);
- endEntry();
- }
- }
-}
-
-void QRhiProfilerPrivate::newReadbackBuffer(qint64 id, QRhiResource *src, quint32 size)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::NewReadbackBuffer, ts.elapsed(), src);
- writeInt("id", id);
- writeInt("size", size);
- endEntry();
-}
-
-void QRhiProfilerPrivate::releaseReadbackBuffer(qint64 id)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::ReleaseReadbackBuffer, ts.elapsed(), nullptr);
- writeInt("id", id);
- endEntry();
-}
-
-void QRhiProfilerPrivate::vmemStat(uint realAllocCount, uint subAllocCount, quint32 totalSize, quint32 unusedSize)
-{
- if (!outputDevice)
- return;
-
- startEntry(QRhiProfiler::GpuMemAllocStats, ts.elapsed(), nullptr);
- writeInt("real_alloc_count", realAllocCount);
- writeInt("sub_alloc_count", subAllocCount);
- writeInt("total_size", totalSize);
- writeInt("unused_size", unusedSize);
- endEntry();
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhiprofiler_p.h b/src/gui/rhi/qrhiprofiler_p.h
deleted file mode 100644
index 9707fb5972..0000000000
--- a/src/gui/rhi/qrhiprofiler_p.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHIPROFILER_H
-#define QRHIPROFILER_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qrhi_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QRhiProfilerPrivate;
-class QIODevice;
-
-class Q_GUI_EXPORT QRhiProfiler
-{
-public:
- enum StreamOp {
- NewBuffer = 1,
- ReleaseBuffer,
- NewBufferStagingArea,
- ReleaseBufferStagingArea,
- NewRenderBuffer,
- ReleaseRenderBuffer,
- NewTexture,
- ReleaseTexture,
- NewTextureStagingArea,
- ReleaseTextureStagingArea,
- ResizeSwapChain,
- ReleaseSwapChain,
- NewReadbackBuffer,
- ReleaseReadbackBuffer,
- GpuMemAllocStats,
- GpuFrameTime,
- FrameToFrameTime,
- FrameBuildTime
- };
-
- ~QRhiProfiler();
-
- void setDevice(QIODevice *device);
-
- void addVMemAllocatorStats();
-
- int frameTimingWriteInterval() const;
- void setFrameTimingWriteInterval(int frameCount);
-
- struct CpuTime {
- qint64 minTime = 0;
- qint64 maxTime = 0;
- float avgTime = 0;
- };
-
- struct GpuTime {
- float minTime = 0;
- float maxTime = 0;
- float avgTime = 0;
- };
-
- CpuTime frameToFrameTimes(QRhiSwapChain *sc) const;
- CpuTime frameBuildTimes(QRhiSwapChain *sc) const; // beginFrame - endFrame
- GpuTime gpuFrameTimes(QRhiSwapChain *sc) const;
-
-private:
- Q_DISABLE_COPY(QRhiProfiler)
- QRhiProfiler();
- QRhiProfilerPrivate *d;
- friend class QRhiImplementation;
- friend class QRhiProfilerPrivate;
-};
-
-Q_DECLARE_TYPEINFO(QRhiProfiler::CpuTime, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QRhiProfiler::GpuTime, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qrhiprofiler_p_p.h b/src/gui/rhi/qrhiprofiler_p_p.h
deleted file mode 100644
index 7d0eec8614..0000000000
--- a/src/gui/rhi/qrhiprofiler_p_p.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHIPROFILER_P_H
-#define QRHIPROFILER_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qrhiprofiler_p.h"
-#include <QElapsedTimer>
-#include <QHash>
-
-QT_BEGIN_NAMESPACE
-
-class QRhiProfilerPrivate
-{
-public:
- static QRhiProfilerPrivate *get(QRhiProfiler *p) { return p->d; }
-
- void newBuffer(QRhiBuffer *buf, quint32 realSize, int backingGpuBufCount, int backingCpuBufCount);
- void releaseBuffer(QRhiBuffer *buf);
- void newBufferStagingArea(QRhiBuffer *buf, int slot, quint32 size);
- void releaseBufferStagingArea(QRhiBuffer *buf, int slot);
-
- void newRenderBuffer(QRhiRenderBuffer *rb, bool transientBacking, bool winSysBacking, int sampleCount);
- void releaseRenderBuffer(QRhiRenderBuffer *rb);
-
- void newTexture(QRhiTexture *tex, bool owns, int mipCount, int layerCount, int sampleCount);
- void releaseTexture(QRhiTexture *tex);
- void newTextureStagingArea(QRhiTexture *tex, int slot, quint32 size);
- void releaseTextureStagingArea(QRhiTexture *tex, int slot);
-
- void resizeSwapChain(QRhiSwapChain *sc, int bufferCount, int msaaBufferCount, int sampleCount);
- void releaseSwapChain(QRhiSwapChain *sc);
-
- void beginSwapChainFrame(QRhiSwapChain *sc);
- void endSwapChainFrame(QRhiSwapChain *sc, int frameCount);
- void swapChainFrameGpuTime(QRhiSwapChain *sc, float gpuTimeMs);
-
- void newReadbackBuffer(qint64 id, QRhiResource *src, quint32 size);
- void releaseReadbackBuffer(qint64 id);
-
- void vmemStat(uint realAllocCount, uint subAllocCount, quint32 totalSize, quint32 unusedSize);
-
- void startEntry(QRhiProfiler::StreamOp op, qint64 timestamp, QRhiResource *res);
- void writeInt(const char *key, qint64 v);
- void writeFloat(const char *key, float f);
- void endEntry();
-
- QRhiImplementation *rhiDWhenEnabled = nullptr;
- QIODevice *outputDevice = nullptr;
- QElapsedTimer ts;
- QByteArray buf;
- static const int DEFAULT_FRAME_TIMING_WRITE_INTERVAL = 120; // frames
- int frameTimingWriteInterval = DEFAULT_FRAME_TIMING_WRITE_INTERVAL;
- struct Sc {
- Sc() {
- frameToFrameSamples.reserve(DEFAULT_FRAME_TIMING_WRITE_INTERVAL);
- beginToEndSamples.reserve(DEFAULT_FRAME_TIMING_WRITE_INTERVAL);
- gpuFrameSamples.reserve(DEFAULT_FRAME_TIMING_WRITE_INTERVAL);
- }
- QElapsedTimer frameToFrameTimer;
- bool frameToFrameRunning = false;
- QElapsedTimer beginToEndTimer;
- QList<qint64> frameToFrameSamples;
- QList<qint64> beginToEndSamples;
- QList<float> gpuFrameSamples;
- QRhiProfiler::CpuTime frameToFrameTime;
- QRhiProfiler::CpuTime beginToEndFrameTime;
- QRhiProfiler::GpuTime gpuFrameTime;
- };
- QHash<QRhiSwapChain *, Sc> swapchains;
-};
-
-Q_DECLARE_TYPEINFO(QRhiProfilerPrivate::Sc, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index 64b979b8c7..f0b51146cc 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qrhivulkan_p_p.h"
-#include "qrhivulkanext_p.h"
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qrhivulkan_p.h"
+#include <qpa/qplatformvulkaninstance.h>
#define VMA_IMPLEMENTATION
+#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_RECORDING_ENABLED 0
#define VMA_DEDICATED_ALLOCATION 0
@@ -49,12 +14,16 @@
#endif
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wsuggest-override")
+#if defined(Q_CC_CLANG) && Q_CC_CLANG >= 1100
+QT_WARNING_DISABLE_CLANG("-Wdeprecated-copy")
+#endif
#include "vk_mem_alloc.h"
QT_WARNING_POP
#include <qmath.h>
#include <QVulkanFunctions>
#include <QtGui/qwindow.h>
+#include <optional>
QT_BEGIN_NAMESPACE
@@ -90,10 +59,13 @@ QT_BEGIN_NAMESPACE
/*!
\class QRhiVulkanInitParams
- \internal
\inmodule QtGui
+ \since 6.6
\brief Vulkan specific initialization parameters.
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
+
A Vulkan-based QRhi needs at minimum a valid QVulkanInstance. It is up to
the user to ensure this is available and initialized. This is typically
done in main() similarly to the following:
@@ -196,34 +168,121 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \variable QRhiVulkanInitParams::inst
+
+ The QVulkanInstance that has already been successfully
+ \l{QVulkanInstance::create()}{created}, required.
+*/
+
+/*!
+ \variable QRhiVulkanInitParams::window
+
+ Optional, but recommended when targeting a QWindow.
+*/
+
+/*!
+ \variable QRhiVulkanInitParams::deviceExtensions
+
+ Optional, empty by default. The list of Vulkan device extensions to enable.
+ Unsupported extensions are ignored gracefully.
+*/
+
+/*!
\class QRhiVulkanNativeHandles
- \internal
\inmodule QtGui
+ \since 6.6
\brief Collects device, queue, and other Vulkan objects that are used by the QRhi.
\note Ownership of the Vulkan objects is never transferred.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
+ \variable QRhiVulkanNativeHandles::physDev
+
+ When different from \nullptr, specifies the Vulkan physical device to use.
+*/
+
+/*!
+ \variable QRhiVulkanNativeHandles::dev
+
+ When wanting to import not just a physical device, but also use an already
+ existing VkDevice, set this and the graphics queue index and family index.
+*/
+
+/*!
+ \variable QRhiVulkanNativeHandles::gfxQueueFamilyIdx
+
+ Graphics queue family index.
+*/
+
+/*!
+ \variable QRhiVulkanNativeHandles::gfxQueueIdx
+
+ Graphics queue index.
+*/
+
+/*!
+ \variable QRhiVulkanNativeHandles::vmemAllocator
+
+ Relevant only when importing an existing memory allocator object,
+ leave it set to \nullptr otherwise.
+*/
+
+/*!
+ \variable QRhiVulkanNativeHandles::gfxQueue
+
+ Output only, not used by QRhi::create(), only set by the
+ QRhi::nativeHandles() accessor. The graphics VkQueue used by the QRhi.
+*/
+
+/*!
+ \variable QRhiVulkanNativeHandles::inst
+
+ Output only, not used by QRhi::create(), only set by the
+ QRhi::nativeHandles() accessor. The QVulkanInstance used by the QRhi.
+*/
+
+/*!
\class QRhiVulkanCommandBufferNativeHandles
- \internal
\inmodule QtGui
+ \since 6.6
\brief Holds the Vulkan command buffer object that is backing a QRhiCommandBuffer.
\note The Vulkan command buffer object is only guaranteed to be valid, and
in recording state, while recording a frame. That is, between a
\l{QRhi::beginFrame()}{beginFrame()} - \l{QRhi::endFrame()}{endFrame()} or
\l{QRhi::beginOffscreenFrame()}{beginOffscreenFrame()} -
- \l{QRhi::endOffsrceenFrame()}{endOffscreenFrame()} pair.
+ \l{QRhi::endOffscreenFrame()}{endOffscreenFrame()} pair.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
/*!
+ \variable QRhiVulkanCommandBufferNativeHandles::commandBuffer
+
+ The VkCommandBuffer object.
+*/
+
+/*!
\class QRhiVulkanRenderPassNativeHandles
- \internal
\inmodule QtGui
+ \since 6.6
\brief Holds the Vulkan render pass object backing a QRhiRenderPassDescriptor.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QRhi
+ for details.
*/
+/*!
+ \variable QRhiVulkanRenderPassNativeHandles::renderPass
+
+ The VkRenderPass object.
+*/
+
template <class Int>
inline Int aligned(Int v, Int byteAlign)
{
@@ -232,84 +291,14 @@ inline Int aligned(Int v, Int byteAlign)
static QVulkanInstance *globalVulkanInstance;
-static void VKAPI_PTR wrap_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties)
-{
- globalVulkanInstance->functions()->vkGetPhysicalDeviceProperties(physicalDevice, pProperties);
-}
-
-static void VKAPI_PTR wrap_vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties)
-{
- globalVulkanInstance->functions()->vkGetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
-}
-
-static VkResult VKAPI_PTR wrap_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory)
+static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL wrap_vkGetInstanceProcAddr(VkInstance, const char *pName)
{
- return globalVulkanInstance->deviceFunctions(device)->vkAllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
+ return globalVulkanInstance->getInstanceProcAddr(pName);
}
-void VKAPI_PTR wrap_vkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator)
+static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL wrap_vkGetDeviceProcAddr(VkDevice device, const char *pName)
{
- globalVulkanInstance->deviceFunctions(device)->vkFreeMemory(device, memory, pAllocator);
-}
-
-VkResult VKAPI_PTR wrap_vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData)
-{
- return globalVulkanInstance->deviceFunctions(device)->vkMapMemory(device, memory, offset, size, flags, ppData);
-}
-
-void VKAPI_PTR wrap_vkUnmapMemory(VkDevice device, VkDeviceMemory memory)
-{
- globalVulkanInstance->deviceFunctions(device)->vkUnmapMemory(device, memory);
-}
-
-VkResult VKAPI_PTR wrap_vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges)
-{
- return globalVulkanInstance->deviceFunctions(device)->vkFlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
-}
-
-VkResult VKAPI_PTR wrap_vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges)
-{
- return globalVulkanInstance->deviceFunctions(device)->vkInvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
-}
-
-VkResult VKAPI_PTR wrap_vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset)
-{
- return globalVulkanInstance->deviceFunctions(device)->vkBindBufferMemory(device, buffer, memory, memoryOffset);
-}
-
-VkResult VKAPI_PTR wrap_vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset)
-{
- return globalVulkanInstance->deviceFunctions(device)->vkBindImageMemory(device, image, memory, memoryOffset);
-}
-
-void VKAPI_PTR wrap_vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements)
-{
- globalVulkanInstance->deviceFunctions(device)->vkGetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
-}
-
-void VKAPI_PTR wrap_vkGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements)
-{
- globalVulkanInstance->deviceFunctions(device)->vkGetImageMemoryRequirements(device, image, pMemoryRequirements);
-}
-
-VkResult VKAPI_PTR wrap_vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer)
-{
- return globalVulkanInstance->deviceFunctions(device)->vkCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
-}
-
-void VKAPI_PTR wrap_vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator)
-{
- globalVulkanInstance->deviceFunctions(device)->vkDestroyBuffer(device, buffer, pAllocator);
-}
-
-VkResult VKAPI_PTR wrap_vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage)
-{
- return globalVulkanInstance->deviceFunctions(device)->vkCreateImage(device, pCreateInfo, pAllocator, pImage);
-}
-
-void VKAPI_PTR wrap_vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator)
-{
- globalVulkanInstance->deviceFunctions(device)->vkDestroyImage(device, image, pAllocator);
+ return globalVulkanInstance->functions()->vkGetDeviceProcAddr(device, pName);
}
static inline VmaAllocation toVmaAllocation(QVkAlloc a)
@@ -322,6 +311,13 @@ static inline VmaAllocator toVmaAllocator(QVkAllocator a)
return reinterpret_cast<VmaAllocator>(a);
}
+/*!
+ \return the list of instance extensions that are expected to be enabled on
+ the QVulkanInstance that is used for the Vulkan-based QRhi.
+
+ The returned list can be safely passed to QVulkanInstance::setExtensions()
+ as-is, because unsupported extensions are filtered out automatically.
+ */
QByteArrayList QRhiVulkanInitParams::preferredInstanceExtensions()
{
return {
@@ -329,12 +325,18 @@ QByteArrayList QRhiVulkanInitParams::preferredInstanceExtensions()
};
}
+/*!
+ \return the list of device extensions that are expected to be enabled on the
+ \c VkDevice when creating a Vulkan-based QRhi with an externally created
+ \c VkDevice object.
+ */
QByteArrayList QRhiVulkanInitParams::preferredExtensionsForImportedDevice()
{
return {
QByteArrayLiteral("VK_KHR_swapchain"),
- QByteArrayLiteral("VK_EXT_debug_marker"),
- QByteArrayLiteral("VK_EXT_vertex_attribute_divisor")
+ QByteArrayLiteral("VK_EXT_vertex_attribute_divisor"),
+ QByteArrayLiteral("VK_KHR_create_renderpass2"),
+ QByteArrayLiteral("VK_KHR_depth_stencil_resolve")
};
}
@@ -361,20 +363,19 @@ QRhiVulkan::QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *im
}
}
-static bool qvk_debug_filter(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object,
- size_t location, int32_t messageCode, const char *pLayerPrefix, const char *pMessage)
+static bool qvk_debug_filter(QVulkanInstance::DebugMessageSeverityFlags severity,
+ QVulkanInstance::DebugMessageTypeFlags type,
+ const void *callbackData)
{
- Q_UNUSED(flags);
- Q_UNUSED(objectType);
- Q_UNUSED(object);
- Q_UNUSED(location);
- Q_UNUSED(messageCode);
- Q_UNUSED(pLayerPrefix);
+ Q_UNUSED(severity);
+ Q_UNUSED(type);
+#ifdef VK_EXT_debug_utils
+ const VkDebugUtilsMessengerCallbackDataEXT *d = static_cast<const VkDebugUtilsMessengerCallbackDataEXT *>(callbackData);
// Filter out certain misleading validation layer messages, as per
// VulkanMemoryAllocator documentation.
- if (strstr(pMessage, "Mapping an image with layout")
- && strstr(pMessage, "can result in undefined behavior if this memory is used by the device"))
+ if (strstr(d->pMessage, "Mapping an image with layout")
+ && strstr(d->pMessage, "can result in undefined behavior if this memory is used by the device"))
{
return true;
}
@@ -385,9 +386,11 @@ static bool qvk_debug_filter(VkDebugReportFlagsEXT flags, VkDebugReportObjectTyp
// then move on to another pool. If there is a real error, a qWarning
// message is shown by allocateDescriptorSet(), so the validation warning
// does not have any value and is just noise.
- if (strstr(pMessage, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307"))
+ if (strstr(d->pMessage, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307"))
return true;
-
+#else
+ Q_UNUSED(callbackData);
+#endif
return false;
}
@@ -417,11 +420,19 @@ bool QRhiVulkan::create(QRhi::Flags flags)
return false;
}
- globalVulkanInstance = inst; // assume this will not change during the lifetime of the entire application
+ rhiFlags = flags;
+ qCDebug(QRHI_LOG_INFO, "Initializing QRhi Vulkan backend %p with flags %d", this, int(rhiFlags));
+ globalVulkanInstance = inst; // used for function resolving in vkmemalloc callbacks
f = inst->functions();
+ if (QRHI_LOG_INFO().isEnabled(QtDebugMsg)) {
+ qCDebug(QRHI_LOG_INFO, "Enabled instance extensions:");
+ for (const char *ext : inst->extensions())
+ qCDebug(QRHI_LOG_INFO, " %s", ext);
+ }
- rhiFlags = flags;
+ caps = {};
+ caps.debugUtils = inst->extensions().contains(QByteArrayLiteral("VK_EXT_debug_utils"));
QList<VkQueueFamilyProperties> queueFamilyProps;
auto queryQueueFamilyProps = [this, &queueFamilyProps] {
@@ -502,50 +513,125 @@ bool QRhiVulkan::create(QRhi::Flags flags)
physDevProperties.deviceType);
}
+ caps.apiVersion = inst->apiVersion();
+
+ // Check the physical device API version against the instance API version,
+ // they do not have to match, which means whatever version was set in the
+ // QVulkanInstance may not be legally used with a given device if the
+ // physical device has a lower version.
+ const QVersionNumber physDevApiVersion(VK_VERSION_MAJOR(physDevProperties.apiVersion),
+ VK_VERSION_MINOR(physDevProperties.apiVersion)); // patch version left out intentionally
+ if (physDevApiVersion < caps.apiVersion) {
+ qCDebug(QRHI_LOG_INFO) << "Instance has api version" << caps.apiVersion
+ << "whereas the chosen physical device has" << physDevApiVersion
+ << "- restricting to the latter";
+ caps.apiVersion = physDevApiVersion;
+ }
+
driverInfoStruct.deviceName = QByteArray(physDevProperties.deviceName);
driverInfoStruct.deviceId = physDevProperties.deviceID;
driverInfoStruct.vendorId = physDevProperties.vendorID;
driverInfoStruct.deviceType = toRhiDeviceType(physDevProperties.deviceType);
- f->vkGetPhysicalDeviceFeatures(physDev, &physDevFeatures);
+ bool featuresQueried = false;
+#ifdef VK_VERSION_1_1
+ VkPhysicalDeviceFeatures2 physDevFeaturesChainable = {};
+ physDevFeaturesChainable.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+#endif
+
+ // Vulkan >=1.2 headers at build time, >=1.2 implementation at run time
+#ifdef VK_VERSION_1_2
+ if (!featuresQueried) {
+ // Vulkan11Features, Vulkan12Features, etc. are only in Vulkan 1.2 and newer.
+ if (caps.apiVersion >= QVersionNumber(1, 2)) {
+ physDevFeatures11IfApi12OrNewer = {};
+ physDevFeatures11IfApi12OrNewer.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
+ physDevFeatures12 = {};
+ physDevFeatures12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
+#ifdef VK_VERSION_1_3
+ physDevFeatures13 = {};
+ physDevFeatures13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
+#endif
+ physDevFeaturesChainable.pNext = &physDevFeatures11IfApi12OrNewer;
+ physDevFeatures11IfApi12OrNewer.pNext = &physDevFeatures12;
+#ifdef VK_VERSION_1_3
+ if (caps.apiVersion >= QVersionNumber(1, 3))
+ physDevFeatures12.pNext = &physDevFeatures13;
+#endif
+ f->vkGetPhysicalDeviceFeatures2(physDev, &physDevFeaturesChainable);
+ memcpy(&physDevFeatures, &physDevFeaturesChainable.features, sizeof(VkPhysicalDeviceFeatures));
+ featuresQueried = true;
+ }
+ }
+#endif // VK_VERSION_1_2
+
+ // Vulkan >=1.1 headers at build time, 1.1 implementation at run time
+#ifdef VK_VERSION_1_1
+ if (!featuresQueried) {
+ // Vulkan versioning nightmares: if the runtime API version is 1.1,
+ // there is no Vulkan11Features (introduced in 1.2+, the headers might
+ // have the types and structs, but the Vulkan implementation version at
+ // run time is what matters). But there are individual feature structs.
+ // For multiview, it is important to get this right since at the time of
+ // writing Quest 3 Android is a Vulkan 1.1 implementation at run time on
+ // the headset.
+ if (caps.apiVersion == QVersionNumber(1, 1)) {
+ multiviewFeaturesIfApi11 = {};
+ multiviewFeaturesIfApi11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES;
+ physDevFeaturesChainable.pNext = &multiviewFeaturesIfApi11;
+ f->vkGetPhysicalDeviceFeatures2(physDev, &physDevFeaturesChainable);
+ memcpy(&physDevFeatures, &physDevFeaturesChainable.features, sizeof(VkPhysicalDeviceFeatures));
+ featuresQueried = true;
+ }
+ }
+#endif
+
+ if (!featuresQueried) {
+ // If the API version at run time is 1.0 (or we are building with
+ // ancient 1.0 headers), then do the Vulkan 1.0 query.
+ f->vkGetPhysicalDeviceFeatures(physDev, &physDevFeatures);
+ featuresQueried = true;
+ }
// Choose queue and create device, unless the device was specified in importParams.
if (!importedDevice) {
// We only support combined graphics+present queues. When it comes to
// compute, only combined graphics+compute queue is used, compute gets
// disabled otherwise.
- gfxQueueFamilyIdx = -1;
- int computelessGfxQueueCandidateIdx = -1;
+ std::optional<uint32_t> gfxQueueFamilyIdxOpt;
+ std::optional<uint32_t> computelessGfxQueueCandidateIdxOpt;
queryQueueFamilyProps();
- for (int i = 0; i < queueFamilyProps.count(); ++i) {
- qCDebug(QRHI_LOG_INFO, "queue family %d: flags=0x%x count=%d",
+ const uint32_t queueFamilyCount = uint32_t(queueFamilyProps.size());
+ for (uint32_t i = 0; i < queueFamilyCount; ++i) {
+ qCDebug(QRHI_LOG_INFO, "queue family %u: flags=0x%x count=%u",
i, queueFamilyProps[i].queueFlags, queueFamilyProps[i].queueCount);
- if (gfxQueueFamilyIdx == -1
+ if (!gfxQueueFamilyIdxOpt.has_value()
&& (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
- && (!maybeWindow || inst->supportsPresent(physDev, uint32_t(i), maybeWindow)))
+ && (!maybeWindow || inst->supportsPresent(physDev, i, maybeWindow)))
{
if (queueFamilyProps[i].queueFlags & VK_QUEUE_COMPUTE_BIT)
- gfxQueueFamilyIdx = i;
- else if (computelessGfxQueueCandidateIdx == -1)
- computelessGfxQueueCandidateIdx = i;
+ gfxQueueFamilyIdxOpt = i;
+ else if (!computelessGfxQueueCandidateIdxOpt.has_value())
+ computelessGfxQueueCandidateIdxOpt = i;
}
}
- if (gfxQueueFamilyIdx == -1) {
- if (computelessGfxQueueCandidateIdx != -1) {
- gfxQueueFamilyIdx = computelessGfxQueueCandidateIdx;
+ if (gfxQueueFamilyIdxOpt.has_value()) {
+ gfxQueueFamilyIdx = gfxQueueFamilyIdxOpt.value();
+ } else {
+ if (computelessGfxQueueCandidateIdxOpt.has_value()) {
+ gfxQueueFamilyIdx = computelessGfxQueueCandidateIdxOpt.value();
} else {
qWarning("No graphics (or no graphics+present) queue family found");
return false;
}
}
- VkDeviceQueueCreateInfo queueInfo[2];
+ VkDeviceQueueCreateInfo queueInfo = {};
const float prio[] = { 0 };
- memset(queueInfo, 0, sizeof(queueInfo));
- queueInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- queueInfo[0].queueFamilyIndex = uint32_t(gfxQueueFamilyIdx);
- queueInfo[0].queueCount = 1;
- queueInfo[0].pQueuePriorities = prio;
+ queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueInfo.queueFamilyIndex = gfxQueueFamilyIdx;
+ queueInfo.queueCount = 1;
+ queueInfo.pQueuePriorities = prio;
QList<const char *> devLayers;
if (inst->layers().contains("VK_LAYER_KHRONOS_validation"))
@@ -557,44 +643,69 @@ bool QRhiVulkan::create(QRhi::Flags flags)
if (devExtCount) {
QList<VkExtensionProperties> extProps(devExtCount);
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, extProps.data());
- for (const VkExtensionProperties &p : qAsConst(extProps))
+ for (const VkExtensionProperties &p : std::as_const(extProps))
devExts.append({ p.extensionName, p.specVersion });
}
- qCDebug(QRHI_LOG_INFO, "%d device extensions available", int(devExts.count()));
+ qCDebug(QRHI_LOG_INFO, "%d device extensions available", int(devExts.size()));
QList<const char *> requestedDevExts;
requestedDevExts.append("VK_KHR_swapchain");
- caps.debugMarkers = false;
- if (devExts.contains(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
- requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
- caps.debugMarkers = true;
+ const bool hasPhysDevProp2 = inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"));
+
+ if (devExts.contains(QByteArrayLiteral("VK_KHR_portability_subset"))) {
+ if (hasPhysDevProp2) {
+ requestedDevExts.append("VK_KHR_portability_subset");
+ } else {
+ qWarning("VK_KHR_portability_subset should be enabled on the device "
+ "but the instance does not have VK_KHR_get_physical_device_properties2 enabled. "
+ "Expect problems.");
+ }
}
- caps.vertexAttribDivisor = false;
+#ifdef VK_EXT_vertex_attribute_divisor
if (devExts.contains(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
- if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
+ if (hasPhysDevProp2) {
requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
caps.vertexAttribDivisor = true;
}
}
+#endif
+
+#ifdef VK_KHR_create_renderpass2
+ if (devExts.contains(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)) {
+ requestedDevExts.append(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
+ caps.renderPass2KHR = true;
+ }
+#endif
+
+#ifdef VK_KHR_depth_stencil_resolve
+ if (devExts.contains(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME)) {
+ requestedDevExts.append(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
+ caps.depthStencilResolveKHR = true;
+ }
+#endif
for (const QByteArray &ext : requestedDeviceExtensions) {
- if (!ext.isEmpty()) {
- if (devExts.contains(ext))
+ if (!ext.isEmpty() && !requestedDevExts.contains(ext)) {
+ if (devExts.contains(ext)) {
requestedDevExts.append(ext.constData());
- else
- qWarning("Device extension %s is not supported", ext.constData());
+ } else {
+ qWarning("Device extension %s requested in QRhiVulkanInitParams 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))
+ if (devExts.contains(ext)) {
requestedDevExts.append(ext.constData());
- else
- qWarning("Device extension %s is not supported", ext.constData());
+ } else {
+ qWarning("Device extension %s requested in QT_VULKAN_DEVICE_EXTENSIONS is not supported",
+ ext.constData());
+ }
}
}
@@ -604,29 +715,50 @@ bool QRhiVulkan::create(QRhi::Flags flags)
qCDebug(QRHI_LOG_INFO, " %s", ext);
}
- VkDeviceCreateInfo devInfo;
- memset(&devInfo, 0, sizeof(devInfo));
+ VkDeviceCreateInfo devInfo = {};
devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
devInfo.queueCreateInfoCount = 1;
- devInfo.pQueueCreateInfos = queueInfo;
- devInfo.enabledLayerCount = uint32_t(devLayers.count());
+ devInfo.pQueueCreateInfos = &queueInfo;
+ devInfo.enabledLayerCount = uint32_t(devLayers.size());
devInfo.ppEnabledLayerNames = devLayers.constData();
- devInfo.enabledExtensionCount = uint32_t(requestedDevExts.count());
+ devInfo.enabledExtensionCount = uint32_t(requestedDevExts.size());
devInfo.ppEnabledExtensionNames = requestedDevExts.constData();
- VkPhysicalDeviceFeatures features;
- memset(&features, 0, sizeof(features));
- if (physDevFeatures.wideLines)
- features.wideLines = VK_TRUE;
- if (physDevFeatures.largePoints)
- features.largePoints = VK_TRUE;
- if (physDevFeatures.textureCompressionETC2)
- features.textureCompressionETC2 = VK_TRUE;
- if (physDevFeatures.textureCompressionASTC_LDR)
- features.textureCompressionASTC_LDR = VK_TRUE;
- if (physDevFeatures.textureCompressionBC)
- features.textureCompressionBC = VK_TRUE;
- devInfo.pEnabledFeatures = &features;
+ // Enable all features that are reported as supported, except
+ // robustness because that potentially affects performance.
+ //
+ // Enabling all features mainly serves third-party renderers that may
+ // use the VkDevice created here. For the record, the backend here
+ // optionally relies on the following features, meaning just for our
+ // (QRhi/Quick/Quick 3D) purposes it would be sufficient to
+ // enable-if-supported only the following:
+ //
+ // wideLines, largePoints, fillModeNonSolid,
+ // tessellationShader, geometryShader
+ // textureCompressionETC2, textureCompressionASTC_LDR, textureCompressionBC
+
+#ifdef VK_VERSION_1_1
+ physDevFeaturesChainable.features.robustBufferAccess = VK_FALSE;
+#endif
+#ifdef VK_VERSION_1_3
+ physDevFeatures13.robustImageAccess = VK_FALSE;
+#endif
+
+#ifdef VK_VERSION_1_1
+ if (caps.apiVersion >= QVersionNumber(1, 1)) {
+ // For a >=1.2 implementation at run time, this will enable all
+ // (1.0-1.3) features reported as supported, except the ones we turn
+ // off explicitly above. For a 1.1 implementation at run time, this
+ // only enables the 1.0 and multiview features reported as
+ // supported. We will not be bothering with the Vulkan 1.1
+ // individual feature struct nonsense.
+ devInfo.pNext = &physDevFeaturesChainable;
+ } else
+#endif
+ {
+ physDevFeatures.robustBufferAccess = VK_FALSE;
+ devInfo.pEnabledFeatures = &physDevFeatures;
+ }
VkResult err = f->vkCreateDevice(physDev, &devInfo, nullptr, &dev);
if (err != VK_SUCCESS) {
@@ -635,14 +767,27 @@ bool QRhiVulkan::create(QRhi::Flags flags)
}
} else {
qCDebug(QRHI_LOG_INFO, "Using imported device %p", dev);
+
+ // Here we have no way to tell if the extensions got enabled or not.
+ // Pretend it's all there and supported. If getProcAddress fails, we'll
+ // handle that gracefully.
+ caps.vertexAttribDivisor = true;
+ caps.renderPass2KHR = true;
+ caps.depthStencilResolveKHR = true;
}
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
+ inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
+ vkGetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
+ inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfaceFormatsKHR"));
+ vkGetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(
+ inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfacePresentModesKHR"));
+
df = inst->deviceFunctions(dev);
- VkCommandPoolCreateInfo poolInfo;
- memset(&poolInfo, 0, sizeof(poolInfo));
+ VkCommandPoolCreateInfo poolInfo = {};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- poolInfo.queueFamilyIndex = uint32_t(gfxQueueFamilyIdx);
+ poolInfo.queueFamilyIndex = gfxQueueFamilyIdx;
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
VkResult err = df->vkCreateCommandPool(dev, &poolInfo, nullptr, &cmdPool[i]);
if (err != VK_SUCCESS) {
@@ -651,13 +796,10 @@ bool QRhiVulkan::create(QRhi::Flags flags)
}
}
- if (gfxQueueFamilyIdx < 0) {
- // this is when importParams is faulty and did not specify the queue family index
- qWarning("No queue family index provided");
- return false;
- }
+ qCDebug(QRHI_LOG_INFO, "Using queue family index %u and queue index %u",
+ gfxQueueFamilyIdx, gfxQueueIdx);
- df->vkGetDeviceQueue(dev, uint32_t(gfxQueueFamilyIdx), gfxQueueIdx, &gfxQueue);
+ df->vkGetDeviceQueue(dev, gfxQueueFamilyIdx, gfxQueueIdx, &gfxQueue);
if (queueFamilyProps.isEmpty())
queryQueueFamilyProps();
@@ -672,35 +814,51 @@ bool QRhiVulkan::create(QRhi::Flags flags)
caps.wideLines = physDevFeatures.wideLines;
- caps.texture3DSliceAs2D = inst->apiVersion() >= QVersionNumber(1, 1);
+ caps.texture3DSliceAs2D = caps.apiVersion >= QVersionNumber(1, 1);
+
+ caps.tessellation = physDevFeatures.tessellationShader;
+ caps.geometryShader = physDevFeatures.geometryShader;
+
+ caps.nonFillPolygonMode = physDevFeatures.fillModeNonSolid;
+
+#ifdef VK_VERSION_1_2
+ if (caps.apiVersion >= QVersionNumber(1, 2))
+ caps.multiView = physDevFeatures11IfApi12OrNewer.multiview;
+#endif
+
+#ifdef VK_VERSION_1_1
+ if (caps.apiVersion == QVersionNumber(1, 1))
+ caps.multiView = multiviewFeaturesIfApi11.multiview;
+#endif
+
+ // With Vulkan 1.2 renderpass2 and depth_stencil_resolve are core, but we
+ // have to support the case of 1.1 + extensions, in particular for the Quest
+ // 3 (Android, Vulkan 1.1 at the time of writing). Therefore, always rely on
+ // the KHR extension for now.
+#ifdef VK_KHR_create_renderpass2
+ if (caps.renderPass2KHR) {
+ vkCreateRenderPass2KHR = reinterpret_cast<PFN_vkCreateRenderPass2KHR>(f->vkGetDeviceProcAddr(dev, "vkCreateRenderPass2KHR"));
+ if (!vkCreateRenderPass2KHR) // handle it gracefully, the caps flag may be incorrect when using an imported VkDevice
+ caps.renderPass2KHR = false;
+ }
+#endif
if (!importedAllocator) {
- VmaVulkanFunctions afuncs;
- afuncs.vkGetPhysicalDeviceProperties = wrap_vkGetPhysicalDeviceProperties;
- afuncs.vkGetPhysicalDeviceMemoryProperties = wrap_vkGetPhysicalDeviceMemoryProperties;
- afuncs.vkAllocateMemory = wrap_vkAllocateMemory;
- afuncs.vkFreeMemory = wrap_vkFreeMemory;
- afuncs.vkMapMemory = wrap_vkMapMemory;
- afuncs.vkUnmapMemory = wrap_vkUnmapMemory;
- afuncs.vkFlushMappedMemoryRanges = wrap_vkFlushMappedMemoryRanges;
- afuncs.vkInvalidateMappedMemoryRanges = wrap_vkInvalidateMappedMemoryRanges;
- afuncs.vkBindBufferMemory = wrap_vkBindBufferMemory;
- afuncs.vkBindImageMemory = wrap_vkBindImageMemory;
- afuncs.vkGetBufferMemoryRequirements = wrap_vkGetBufferMemoryRequirements;
- afuncs.vkGetImageMemoryRequirements = wrap_vkGetImageMemoryRequirements;
- afuncs.vkCreateBuffer = wrap_vkCreateBuffer;
- afuncs.vkDestroyBuffer = wrap_vkDestroyBuffer;
- afuncs.vkCreateImage = wrap_vkCreateImage;
- afuncs.vkDestroyImage = wrap_vkDestroyImage;
-
- VmaAllocatorCreateInfo allocatorInfo;
- memset(&allocatorInfo, 0, sizeof(allocatorInfo));
+ VmaVulkanFunctions funcs = {};
+ funcs.vkGetInstanceProcAddr = wrap_vkGetInstanceProcAddr;
+ funcs.vkGetDeviceProcAddr = wrap_vkGetDeviceProcAddr;
+
+ VmaAllocatorCreateInfo allocatorInfo = {};
// A QRhi is supposed to be used from one single thread only. Disable
// the allocator's own mutexes. This gives a performance boost.
allocatorInfo.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
allocatorInfo.physicalDevice = physDev;
allocatorInfo.device = dev;
- allocatorInfo.pVulkanFunctions = &afuncs;
+ allocatorInfo.pVulkanFunctions = &funcs;
+ allocatorInfo.instance = inst->vkInstance();
+ allocatorInfo.vulkanApiVersion = VK_MAKE_VERSION(caps.apiVersion.majorVersion(),
+ caps.apiVersion.minorVersion(),
+ caps.apiVersion.microVersion());
VmaAllocator vmaallocator;
VkResult err = vmaCreateAllocator(&allocatorInfo, &vmaallocator);
if (err != VK_SUCCESS) {
@@ -719,8 +877,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
else
qWarning("Failed to create initial descriptor pool: %d", err);
- VkQueryPoolCreateInfo timestampQueryPoolInfo;
- memset(&timestampQueryPoolInfo, 0, sizeof(timestampQueryPoolInfo));
+ VkQueryPoolCreateInfo timestampQueryPoolInfo = {};
timestampQueryPoolInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
timestampQueryPoolInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;
timestampQueryPoolInfo.queryCount = QVK_MAX_ACTIVE_TIMESTAMP_PAIRS * 2;
@@ -732,12 +889,14 @@ bool QRhiVulkan::create(QRhi::Flags flags)
timestampQueryPoolMap.resize(QVK_MAX_ACTIVE_TIMESTAMP_PAIRS); // 1 bit per pair
timestampQueryPoolMap.fill(false);
- if (caps.debugMarkers) {
- vkCmdDebugMarkerBegin = reinterpret_cast<PFN_vkCmdDebugMarkerBeginEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerBeginEXT"));
- vkCmdDebugMarkerEnd = reinterpret_cast<PFN_vkCmdDebugMarkerEndEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerEndEXT"));
- vkCmdDebugMarkerInsert = reinterpret_cast<PFN_vkCmdDebugMarkerInsertEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdDebugMarkerInsertEXT"));
- vkDebugMarkerSetObjectName = reinterpret_cast<PFN_vkDebugMarkerSetObjectNameEXT>(f->vkGetDeviceProcAddr(dev, "vkDebugMarkerSetObjectNameEXT"));
+#ifdef VK_EXT_debug_utils
+ if (caps.debugUtils) {
+ vkSetDebugUtilsObjectNameEXT = reinterpret_cast<PFN_vkSetDebugUtilsObjectNameEXT>(f->vkGetDeviceProcAddr(dev, "vkSetDebugUtilsObjectNameEXT"));
+ vkCmdBeginDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdBeginDebugUtilsLabelEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdBeginDebugUtilsLabelEXT"));
+ vkCmdEndDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdEndDebugUtilsLabelEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdEndDebugUtilsLabelEXT"));
+ vkCmdInsertDebugUtilsLabelEXT = reinterpret_cast<PFN_vkCmdInsertDebugUtilsLabelEXT>(f->vkGetDeviceProcAddr(dev, "vkCmdInsertDebugUtilsLabelEXT"));
}
+#endif
deviceLost = false;
@@ -747,6 +906,7 @@ bool QRhiVulkan::create(QRhi::Flags flags)
nativeHandlesStruct.gfxQueueIdx = gfxQueueIdx;
nativeHandlesStruct.gfxQueue = gfxQueue;
nativeHandlesStruct.vmemAllocator = allocator;
+ nativeHandlesStruct.inst = inst;
return true;
}
@@ -815,8 +975,7 @@ VkResult QRhiVulkan::createDescriptorPool(VkDescriptorPool *pool)
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, QVK_STORAGE_BUFFERS_PER_POOL },
{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, QVK_STORAGE_IMAGES_PER_POOL }
};
- VkDescriptorPoolCreateInfo descPoolInfo;
- memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ VkDescriptorPoolCreateInfo descPoolInfo = {};
descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
// Do not enable vkFreeDescriptorSets - sets are never freed on their own
// (good so no trouble with fragmentation), they just deref their pool
@@ -838,7 +997,7 @@ bool QRhiVulkan::allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, V
return r;
};
- int lastPoolIdx = descriptorPools.count() - 1;
+ int lastPoolIdx = descriptorPools.size() - 1;
for (int i = lastPoolIdx; i >= 0; --i) {
if (descriptorPools[i].refCount == 0) {
df->vkResetDescriptorPool(dev, descriptorPools[i].pool, 0);
@@ -858,7 +1017,7 @@ bool QRhiVulkan::allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, V
VkResult poolErr = createDescriptorPool(&newPool);
if (poolErr == VK_SUCCESS) {
descriptorPools.append(newPool);
- lastPoolIdx = descriptorPools.count() - 1;
+ lastPoolIdx = descriptorPools.size() - 1;
VkResult err = tryAllocate(lastPoolIdx);
if (err != VK_SUCCESS) {
qWarning("Failed to allocate descriptor set from new pool too, giving up: %d", err);
@@ -901,6 +1060,10 @@ static inline VkFormat toVkTextureFormat(QRhiTexture::Format format, QRhiTexture
case QRhiTexture::R32F:
return VK_FORMAT_R32_SFLOAT;
+ case QRhiTexture::RGB10A2:
+ // intentionally A2B10G10R10, not A2R10G10B10
+ return VK_FORMAT_A2B10G10R10_UNORM_PACK32;
+
case QRhiTexture::D16:
return VK_FORMAT_D16_UNORM;
case QRhiTexture::D24:
@@ -962,12 +1125,11 @@ static inline VkFormat toVkTextureFormat(QRhiTexture::Format format, QRhiTexture
return srgb ? VK_FORMAT_ASTC_12x12_SRGB_BLOCK : VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
default:
- Q_UNREACHABLE();
- return VK_FORMAT_R8G8B8A8_UNORM;
+ Q_UNREACHABLE_RETURN(VK_FORMAT_R8G8B8A8_UNORM);
}
}
-static inline QRhiTexture::Format colorTextureFormatFromVkFormat(VkFormat format, QRhiTexture::Flags *flags)
+static inline QRhiTexture::Format swapchainReadbackTextureFormat(VkFormat format, QRhiTexture::Flags *flags)
{
switch (format) {
case VK_FORMAT_R8G8B8A8_UNORM:
@@ -982,24 +1144,14 @@ static inline QRhiTexture::Format colorTextureFormatFromVkFormat(VkFormat format
if (flags)
(*flags) |= QRhiTexture::sRGB;
return QRhiTexture::BGRA8;
- case VK_FORMAT_R8_UNORM:
- return QRhiTexture::R8;
- case VK_FORMAT_R8G8_UNORM:
- return QRhiTexture::RG8;
- case VK_FORMAT_R8_SRGB:
- if (flags)
- (*flags) |= QRhiTexture::sRGB;
- return QRhiTexture::R8;
- case VK_FORMAT_R8G8_SRGB:
- if (flags)
- (*flags) |= QRhiTexture::sRGB;
- return QRhiTexture::RG8;
- case VK_FORMAT_R16_UNORM:
- return QRhiTexture::R16;
- case VK_FORMAT_R16G16_UNORM:
- return QRhiTexture::RG16;
- default: // this cannot assert, must warn and return unknown
- qWarning("VkFormat %d is not a recognized uncompressed color format", format);
+ case VK_FORMAT_R16G16B16A16_SFLOAT:
+ return QRhiTexture::RGBA16F;
+ case VK_FORMAT_R32G32B32A32_SFLOAT:
+ return QRhiTexture::RGBA32F;
+ case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
+ return QRhiTexture::RGB10A2;
+ default:
+ qWarning("VkFormat %d cannot be read back", format);
break;
}
return QRhiTexture::UnknownFormat;
@@ -1075,8 +1227,7 @@ bool QRhiVulkan::createTransientImage(VkFormat format,
VkResult err;
for (int i = 0; i < count; ++i) {
- VkImageCreateInfo imgInfo;
- memset(&imgInfo, 0, sizeof(imgInfo));
+ VkImageCreateInfo imgInfo = {};
imgInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imgInfo.imageType = VK_IMAGE_TYPE_2D;
imgInfo.format = format;
@@ -1101,8 +1252,7 @@ bool QRhiVulkan::createTransientImage(VkFormat format,
df->vkGetImageMemoryRequirements(dev, images[i], &memReq);
}
- VkMemoryAllocateInfo memInfo;
- memset(&memInfo, 0, sizeof(memInfo));
+ VkMemoryAllocateInfo memInfo = {};
memInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memInfo.allocationSize = aligned(memReq.size, memReq.alignment) * VkDeviceSize(count);
@@ -1130,8 +1280,7 @@ bool QRhiVulkan::createTransientImage(VkFormat format,
}
ofs += aligned(memReq.size, memReq.alignment);
- VkImageViewCreateInfo imgViewInfo;
- memset(&imgViewInfo, 0, sizeof(imgViewInfo));
+ VkImageViewCreateInfo imgViewInfo = {};
imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imgViewInfo.image = images[i];
imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
@@ -1185,18 +1334,18 @@ static void fillRenderPassCreateInfo(VkRenderPassCreateInfo *rpInfo,
{
memset(subpassDesc, 0, sizeof(VkSubpassDescription));
subpassDesc->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
- subpassDesc->colorAttachmentCount = uint32_t(rpD->colorRefs.count());
+ subpassDesc->colorAttachmentCount = uint32_t(rpD->colorRefs.size());
subpassDesc->pColorAttachments = !rpD->colorRefs.isEmpty() ? rpD->colorRefs.constData() : nullptr;
subpassDesc->pDepthStencilAttachment = rpD->hasDepthStencil ? &rpD->dsRef : nullptr;
subpassDesc->pResolveAttachments = !rpD->resolveRefs.isEmpty() ? rpD->resolveRefs.constData() : nullptr;
memset(rpInfo, 0, sizeof(VkRenderPassCreateInfo));
rpInfo->sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
- rpInfo->attachmentCount = uint32_t(rpD->attDescs.count());
+ rpInfo->attachmentCount = uint32_t(rpD->attDescs.size());
rpInfo->pAttachments = rpD->attDescs.constData();
rpInfo->subpassCount = 1;
rpInfo->pSubpasses = subpassDesc;
- rpInfo->dependencyCount = uint32_t(rpD->subpassDeps.count());
+ rpInfo->dependencyCount = uint32_t(rpD->subpassDeps.size());
rpInfo->pDependencies = !rpD->subpassDeps.isEmpty() ? rpD->subpassDeps.constData() : nullptr;
}
@@ -1204,8 +1353,7 @@ bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasD
{
// attachment list layout is color (1), ds (0-1), resolve (0-1)
- VkAttachmentDescription attDesc;
- memset(&attDesc, 0, sizeof(attDesc));
+ VkAttachmentDescription attDesc = {};
attDesc.format = colorFormat;
attDesc.samples = samples;
attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
@@ -1219,6 +1367,8 @@ bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasD
rpD->colorRefs.append({ 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL });
rpD->hasDepthStencil = hasDepthStencil;
+ rpD->hasDepthStencilResolve = false;
+ rpD->multiViewCount = 0;
if (hasDepthStencil) {
// clear on load + no store + lazy alloc + transient image should play
@@ -1253,8 +1403,7 @@ bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasD
}
// Replace the first implicit dep (TOP_OF_PIPE / ALL_COMMANDS) with our own.
- VkSubpassDependency subpassDep;
- memset(&subpassDep, 0, sizeof(subpassDep));
+ VkSubpassDependency subpassDep = {};
subpassDep.srcSubpass = VK_SUBPASS_EXTERNAL;
subpassDep.dstSubpass = 0;
subpassDep.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
@@ -1289,29 +1438,190 @@ bool QRhiVulkan::createDefaultRenderPass(QVkRenderPassDescriptor *rpD, bool hasD
return true;
}
+struct MultiViewRenderPassSetupHelper
+{
+ bool prepare(VkRenderPassCreateInfo *rpInfo, int multiViewCount, bool multiViewCap)
+ {
+ if (multiViewCount < 2)
+ return true;
+ if (!multiViewCap) {
+ qWarning("Cannot create multiview render pass without support for the Vulkan 1.1 multiview feature");
+ return false;
+ }
+#ifdef VK_VERSION_1_1
+ uint32_t allViewsMask = 0;
+ for (uint32_t i = 0; i < uint32_t(multiViewCount); ++i)
+ allViewsMask |= (1 << i);
+ multiViewMask = allViewsMask;
+ multiViewCorrelationMask = allViewsMask;
+ multiViewInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO;
+ multiViewInfo.subpassCount = 1;
+ multiViewInfo.pViewMasks = &multiViewMask;
+ multiViewInfo.correlationMaskCount = 1;
+ multiViewInfo.pCorrelationMasks = &multiViewCorrelationMask;
+ rpInfo->pNext = &multiViewInfo;
+#endif
+ return true;
+ }
+
+#ifdef VK_VERSION_1_1
+ VkRenderPassMultiviewCreateInfo multiViewInfo = {};
+ uint32_t multiViewMask = 0;
+ uint32_t multiViewCorrelationMask = 0;
+#endif
+};
+
+#ifdef VK_KHR_create_renderpass2
+// Effectively converts a VkRenderPassCreateInfo into a VkRenderPassCreateInfo2,
+// adding depth-stencil resolve support. Assumes a single subpass and no subpass
+// dependencies.
+struct RenderPass2SetupHelper
+{
+ bool prepare(VkRenderPassCreateInfo2 *rpInfo2, const VkRenderPassCreateInfo *rpInfo, const QVkRenderPassDescriptor *rpD, int multiViewCount) {
+ *rpInfo2 = {};
+
+ viewMask = 0;
+ if (multiViewCount >= 2) {
+ for (uint32_t i = 0; i < uint32_t(multiViewCount); ++i)
+ viewMask |= (1 << i);
+ }
+
+ attDescs2.resize(rpInfo->attachmentCount);
+ for (qsizetype i = 0; i < attDescs2.count(); ++i) {
+ VkAttachmentDescription2KHR &att2(attDescs2[i]);
+ const VkAttachmentDescription &att(rpInfo->pAttachments[i]);
+ att2 = {};
+ att2.sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
+ att2.flags = att.flags;
+ att2.format = att.format;
+ att2.samples = att.samples;
+ att2.loadOp = att.loadOp;
+ att2.storeOp = att.storeOp;
+ att2.stencilLoadOp = att.stencilLoadOp;
+ att2.stencilStoreOp = att.stencilStoreOp;
+ att2.initialLayout = att.initialLayout;
+ att2.finalLayout = att.finalLayout;
+ }
+
+ attRefs2.clear();
+ subpass2 = {};
+ subpass2.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR;
+ const VkSubpassDescription &subpassDesc(rpInfo->pSubpasses[0]);
+ subpass2.flags = subpassDesc.flags;
+ subpass2.pipelineBindPoint = subpassDesc.pipelineBindPoint;
+ if (multiViewCount >= 2)
+ subpass2.viewMask = viewMask;
+
+ // color attachment refs
+ qsizetype startIndex = attRefs2.count();
+ for (uint32_t j = 0; j < subpassDesc.colorAttachmentCount; ++j) {
+ attRefs2.append({});
+ VkAttachmentReference2KHR &attref2(attRefs2.last());
+ const VkAttachmentReference &attref(subpassDesc.pColorAttachments[j]);
+ attref2.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
+ attref2.attachment = attref.attachment;
+ attref2.layout = attref.layout;
+ attref2.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+ subpass2.colorAttachmentCount = subpassDesc.colorAttachmentCount;
+ subpass2.pColorAttachments = attRefs2.constData() + startIndex;
+
+ // color resolve refs
+ if (subpassDesc.pResolveAttachments) {
+ startIndex = attRefs2.count();
+ for (uint32_t j = 0; j < subpassDesc.colorAttachmentCount; ++j) {
+ attRefs2.append({});
+ VkAttachmentReference2KHR &attref2(attRefs2.last());
+ const VkAttachmentReference &attref(subpassDesc.pResolveAttachments[j]);
+ attref2.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
+ attref2.attachment = attref.attachment;
+ attref2.layout = attref.layout;
+ attref2.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ }
+ subpass2.pResolveAttachments = attRefs2.constData() + startIndex;
+ }
+
+ // depth-stencil ref
+ if (subpassDesc.pDepthStencilAttachment) {
+ startIndex = attRefs2.count();
+ attRefs2.append({});
+ VkAttachmentReference2KHR &attref2(attRefs2.last());
+ const VkAttachmentReference &attref(*subpassDesc.pDepthStencilAttachment);
+ attref2.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
+ attref2.attachment = attref.attachment;
+ attref2.layout = attref.layout;
+ attref2.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ subpass2.pDepthStencilAttachment = attRefs2.constData() + startIndex;
+ }
+
+ // depth-stencil resolve ref
+#ifdef VK_KHR_depth_stencil_resolve
+ dsResolveDesc = {};
+ if (rpD->hasDepthStencilResolve) {
+ startIndex = attRefs2.count();
+ attRefs2.append({});
+ VkAttachmentReference2KHR &attref2(attRefs2.last());
+ attref2.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR;
+ attref2.attachment = rpD->dsResolveRef.attachment;
+ attref2.layout = rpD->dsResolveRef.layout;
+ attref2.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ dsResolveDesc.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR;
+ dsResolveDesc.depthResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
+ dsResolveDesc.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
+ dsResolveDesc.pDepthStencilResolveAttachment = attRefs2.constData() + startIndex;
+ subpass2.pNext = &dsResolveDesc;
+ }
+#endif
+
+ rpInfo2->sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR;
+ rpInfo2->pNext = nullptr; // the 1.1 VkRenderPassMultiviewCreateInfo is part of the '2' structs
+ rpInfo2->flags = rpInfo->flags;
+ rpInfo2->attachmentCount = rpInfo->attachmentCount;
+ rpInfo2->pAttachments = attDescs2.constData();
+ rpInfo2->subpassCount = 1;
+ rpInfo2->pSubpasses = &subpass2;
+ if (multiViewCount >= 2) {
+ rpInfo2->correlatedViewMaskCount = 1;
+ rpInfo2->pCorrelatedViewMasks = &viewMask;
+ }
+ return true;
+ }
+
+ QVarLengthArray<VkAttachmentDescription2KHR, 8> attDescs2;
+ QVarLengthArray<VkAttachmentReference2KHR, 8> attRefs2;
+ VkSubpassDescription2KHR subpass2;
+#ifdef VK_KHR_depth_stencil_resolve
+ VkSubpassDescriptionDepthStencilResolveKHR dsResolveDesc;
+#endif
+ uint32_t viewMask;
+};
+#endif // VK_KHR_create_renderpass2
+
bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
const QRhiColorAttachment *firstColorAttachment,
const QRhiColorAttachment *lastColorAttachment,
bool preserveColor,
bool preserveDs,
+ bool storeDs,
QRhiRenderBuffer *depthStencilBuffer,
- QRhiTexture *depthTexture)
+ QRhiTexture *depthTexture,
+ QRhiTexture *depthResolveTexture)
{
- // attachment list layout is color (0-8), ds (0-1), resolve (0-8)
+ // attachment list layout is color (0-8), ds (0-1), resolve (0-8), ds resolve (0-1)
+ int multiViewCount = 0;
for (auto it = firstColorAttachment; it != lastColorAttachment; ++it) {
QVkTexture *texD = QRHI_RES(QVkTexture, it->texture());
QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, it->renderBuffer());
Q_ASSERT(texD || rbD);
- const VkFormat vkformat = texD ? texD->vkformat : rbD->vkformat;
+ const VkFormat vkformat = texD ? texD->viewFormat : rbD->vkformat;
const VkSampleCountFlagBits samples = texD ? texD->samples : rbD->samples;
- VkAttachmentDescription attDesc;
- memset(&attDesc, 0, sizeof(attDesc));
+ VkAttachmentDescription attDesc = {};
attDesc.format = vkformat;
attDesc.samples = samples;
attDesc.loadOp = preserveColor ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
- attDesc.storeOp = it->resolveTexture() ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
+ attDesc.storeOp = (it->resolveTexture() && !preserveColor) ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
attDesc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
// this has to interact correctly with activateTextureRenderTarget(), hence leaving in COLOR_ATT
@@ -1319,31 +1629,41 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
rpD->attDescs.append(attDesc);
- const VkAttachmentReference ref = { uint32_t(rpD->attDescs.count() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
+ const VkAttachmentReference ref = { uint32_t(rpD->attDescs.size() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
rpD->colorRefs.append(ref);
+
+ if (it->multiViewCount() >= 2) {
+ if (multiViewCount > 0 && multiViewCount != it->multiViewCount())
+ qWarning("Inconsistent multiViewCount in color attachment set");
+ else
+ multiViewCount = it->multiViewCount();
+ } else if (multiViewCount > 0) {
+ qWarning("Mixing non-multiview color attachments within a multiview render pass");
+ }
}
+ Q_ASSERT(multiViewCount == 0 || multiViewCount >= 2);
+ rpD->multiViewCount = uint32_t(multiViewCount);
rpD->hasDepthStencil = depthStencilBuffer || depthTexture;
if (rpD->hasDepthStencil) {
- const VkFormat dsFormat = depthTexture ? QRHI_RES(QVkTexture, depthTexture)->vkformat
+ const VkFormat dsFormat = depthTexture ? QRHI_RES(QVkTexture, depthTexture)->viewFormat
: QRHI_RES(QVkRenderBuffer, depthStencilBuffer)->vkformat;
const VkSampleCountFlagBits samples = depthTexture ? QRHI_RES(QVkTexture, depthTexture)->samples
: QRHI_RES(QVkRenderBuffer, depthStencilBuffer)->samples;
const VkAttachmentLoadOp loadOp = preserveDs ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
- const VkAttachmentStoreOp storeOp = depthTexture ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
- VkAttachmentDescription attDesc;
- memset(&attDesc, 0, sizeof(attDesc));
+ const VkAttachmentStoreOp storeOp = storeDs ? VK_ATTACHMENT_STORE_OP_STORE : VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ VkAttachmentDescription attDesc = {};
attDesc.format = dsFormat;
attDesc.samples = samples;
attDesc.loadOp = loadOp;
attDesc.storeOp = storeOp;
attDesc.stencilLoadOp = loadOp;
attDesc.stencilStoreOp = storeOp;
- attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc.initialLayout = preserveDs ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
attDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
rpD->attDescs.append(attDesc);
}
- rpD->dsRef = { uint32_t(rpD->attDescs.count() - 1), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
+ rpD->dsRef = { uint32_t(rpD->attDescs.size() - 1), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
for (auto it = firstColorAttachment; it != lastColorAttachment; ++it) {
if (it->resolveTexture()) {
@@ -1363,9 +1683,8 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
int(srcFormat), int(dstFormat));
}
- VkAttachmentDescription attDesc;
- memset(&attDesc, 0, sizeof(attDesc));
- attDesc.format = dstFormat;
+ VkAttachmentDescription attDesc = {};
+ attDesc.format = rtexD->viewFormat;
attDesc.samples = VK_SAMPLE_COUNT_1_BIT;
attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // ignored
attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
@@ -1375,14 +1694,39 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
attDesc.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
rpD->attDescs.append(attDesc);
- const VkAttachmentReference ref = { uint32_t(rpD->attDescs.count() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
+ const VkAttachmentReference ref = { uint32_t(rpD->attDescs.size() - 1), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
rpD->resolveRefs.append(ref);
} else {
const VkAttachmentReference ref = { VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
rpD->resolveRefs.append(ref);
}
}
- Q_ASSERT(rpD->colorRefs.count() == rpD->resolveRefs.count());
+ Q_ASSERT(rpD->colorRefs.size() == rpD->resolveRefs.size());
+
+ rpD->hasDepthStencilResolve = rpD->hasDepthStencil && depthResolveTexture;
+ if (rpD->hasDepthStencilResolve) {
+ QVkTexture *rtexD = QRHI_RES(QVkTexture, depthResolveTexture);
+ if (rtexD->samples > VK_SAMPLE_COUNT_1_BIT)
+ qWarning("Resolving into a multisample depth texture is not supported");
+
+ QVkTexture *texD = QRHI_RES(QVkTexture, depthResolveTexture);
+ if (texD->vkformat != rtexD->vkformat) {
+ qWarning("Multisample resolve between different depth-stencil formats (%d and %d) is not supported.",
+ int(texD->vkformat), int(rtexD->vkformat));
+ }
+
+ VkAttachmentDescription attDesc = {};
+ attDesc.format = rtexD->viewFormat;
+ attDesc.samples = VK_SAMPLE_COUNT_1_BIT;
+ attDesc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // ignored
+ attDesc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attDesc.stencilLoadOp = attDesc.loadOp;
+ attDesc.stencilStoreOp = attDesc.storeOp;
+ attDesc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ rpD->attDescs.append(attDesc);
+ }
+ rpD->dsResolveRef = { uint32_t(rpD->attDescs.size() - 1), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
// rpD->subpassDeps stays empty: don't yet know the correct initial/final
// access and stage stuff for the implicit deps at this point, so leave it
@@ -1393,10 +1737,35 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
VkSubpassDescription subpassDesc;
fillRenderPassCreateInfo(&rpInfo, &subpassDesc, rpD);
- VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp);
- if (err != VK_SUCCESS) {
- qWarning("Failed to create renderpass: %d", err);
+ MultiViewRenderPassSetupHelper multiViewHelper;
+ if (!multiViewHelper.prepare(&rpInfo, multiViewCount, caps.multiView))
return false;
+
+#ifdef VK_KHR_create_renderpass2
+ if (rpD->hasDepthStencilResolve && caps.renderPass2KHR) {
+ // Use the KHR extension, not the 1.2 core API, in order to support Vulkan 1.1.
+ VkRenderPassCreateInfo2KHR rpInfo2;
+ RenderPass2SetupHelper rp2Helper;
+ if (!rp2Helper.prepare(&rpInfo2, &rpInfo, rpD, multiViewCount))
+ return false;
+
+ VkResult err = vkCreateRenderPass2KHR(dev, &rpInfo2, nullptr, &rpD->rp);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create renderpass (using VkRenderPassCreateInfo2KHR): %d", err);
+ return false;
+ }
+ } else
+#endif
+ {
+ if (rpD->hasDepthStencilResolve) {
+ qWarning("Resolving multisample depth-stencil buffers is not supported without "
+ "VK_KHR_depth_stencil_resolve and VK_KHR_create_renderpass2");
+ }
+ VkResult err = df->vkCreateRenderPass(dev, &rpInfo, nullptr, &rpD->rp);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create renderpass: %d", err);
+ return false;
+ }
}
return true;
@@ -1437,21 +1806,45 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain)
? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
: surfaceCaps.currentTransform;
+ // This looks odd but matches how platforms work in practice.
+ //
+ // On Windows with NVIDIA for example, the only supportedCompositeAlpha
+ // value reported is OPAQUE, nothing else. Yet transparency works
+ // regardless, as long as the native window is set up correctly, so that's
+ // not something we need to handle here.
+ //
+ // On Linux with Intel and Mesa and running on xcb reports, on one
+ // particular system, INHERIT+PRE_MULTIPLIED. Tranparency works, regardless,
+ // presumably due to setting INHERIT.
+ //
+ // On the same setup with Wayland instead of xcb we see
+ // OPAQUE+PRE_MULTIPLIED reported. Here transparency won't work unless
+ // PRE_MULTIPLIED is set.
+ //
+ // Therefore our rules are:
+ // - Prefer INHERIT over OPAQUE.
+ // - Then based on the request, try the requested alpha mode, but if
+ // that's not reported as supported, try also the other (PRE/POST,
+ // POST/PRE) as that is better than nothing. This is not different from
+ // some other backends, e.g. D3D11 with DirectComposition there is also
+ // no control over being straight or pre-multiplied. Whereas with
+ // WGL/GLX/EGL we never had that sort of control.
+
VkCompositeAlphaFlagBitsKHR compositeAlpha =
(surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
: VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- if (swapChainD->m_flags.testFlag(QRhiSwapChain::SurfaceHasPreMulAlpha)
- && (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR))
- {
- compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
- }
-
- if (swapChainD->m_flags.testFlag(QRhiSwapChain::SurfaceHasNonPreMulAlpha)
- && (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR))
- {
- compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
+ if (swapChainD->m_flags.testFlag(QRhiSwapChain::SurfaceHasPreMulAlpha)) {
+ if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
+ compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
+ else if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
+ compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
+ } else if (swapChainD->m_flags.testFlag(QRhiSwapChain::SurfaceHasNonPreMulAlpha)) {
+ if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
+ compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
+ else if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
+ compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
}
VkImageUsageFlags usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
@@ -1459,9 +1852,16 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain)
if (swapChainD->supportsReadback && swapChainD->m_flags.testFlag(QRhiSwapChain::UsedAsTransferSource))
usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+ const bool stereo = bool(swapChainD->m_window) && (swapChainD->m_window->format().stereo())
+ && surfaceCaps.maxImageArrayLayers > 1;
+ swapChainD->stereo = stereo;
+
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
if (swapChainD->m_flags.testFlag(QRhiSwapChain::NoVSync)) {
- if (swapChainD->supportedPresentationModes.contains(VK_PRESENT_MODE_MAILBOX_KHR))
+ // Stereo has a weird bug, when using VK_PRESENT_MODE_MAILBOX_KHR,
+ // black screen is shown, but there is no validation error.
+ // Detected on Windows, with NVidia RTX A series (at least 4000 and 6000) driver 535.98
+ if (swapChainD->supportedPresentationModes.contains(VK_PRESENT_MODE_MAILBOX_KHR) && !stereo)
presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
else if (swapChainD->supportedPresentationModes.contains(VK_PRESENT_MODE_IMMEDIATE_KHR))
presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
@@ -1478,15 +1878,14 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain)
reuseExisting ? "recycled" : "new",
reqBufferCount, swapChainD->pixelSize.width(), swapChainD->pixelSize.height(), presentMode);
- VkSwapchainCreateInfoKHR swapChainInfo;
- memset(&swapChainInfo, 0, sizeof(swapChainInfo));
+ VkSwapchainCreateInfoKHR swapChainInfo = {};
swapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapChainInfo.surface = swapChainD->surface;
swapChainInfo.minImageCount = reqBufferCount;
swapChainInfo.imageFormat = swapChainD->colorFormat;
swapChainInfo.imageColorSpace = swapChainD->colorSpace;
swapChainInfo.imageExtent = VkExtent2D { uint32_t(swapChainD->pixelSize.width()), uint32_t(swapChainD->pixelSize.height()) };
- swapChainInfo.imageArrayLayers = 1;
+ swapChainInfo.imageArrayLayers = stereo ? 2u : 1u;
swapChainInfo.imageUsage = usage;
swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapChainInfo.preTransform = preTransform;
@@ -1544,12 +1943,13 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain)
}
}
- VkFenceCreateInfo fenceInfo;
- memset(&fenceInfo, 0, sizeof(fenceInfo));
+ VkFenceCreateInfo fenceInfo = {};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
- swapChainD->imageRes.resize(swapChainD->bufferCount);
+ // Double up for stereo
+ swapChainD->imageRes.resize(swapChainD->bufferCount * (stereo ? 2u : 1u));
+
for (int i = 0; i < swapChainD->bufferCount; ++i) {
QVkSwapChain::ImageResources &image(swapChainD->imageRes[i]);
image.image = swapChainImages[i];
@@ -1558,8 +1958,7 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain)
image.msaaImageView = msaaViews[i];
}
- VkImageViewCreateInfo imgViewInfo;
- memset(&imgViewInfo, 0, sizeof(imgViewInfo));
+ VkImageViewCreateInfo imgViewInfo = {};
imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imgViewInfo.image = swapChainImages[i];
imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
@@ -1578,11 +1977,40 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain)
image.lastUse = QVkSwapChain::ImageResources::ScImageUseNone;
}
+ if (stereo) {
+ for (int i = 0; i < swapChainD->bufferCount; ++i) {
+ QVkSwapChain::ImageResources &image(swapChainD->imageRes[i + swapChainD->bufferCount]);
+ image.image = swapChainImages[i];
+ if (swapChainD->samples > VK_SAMPLE_COUNT_1_BIT) {
+ image.msaaImage = msaaImages[i];
+ image.msaaImageView = msaaViews[i];
+ }
+
+ VkImageViewCreateInfo imgViewInfo = {};
+ imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ imgViewInfo.image = swapChainImages[i];
+ imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ imgViewInfo.format = swapChainD->colorFormat;
+ imgViewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ imgViewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ imgViewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ imgViewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ imgViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ imgViewInfo.subresourceRange.baseArrayLayer = 1;
+ imgViewInfo.subresourceRange.levelCount = imgViewInfo.subresourceRange.layerCount = 1;
+ err = df->vkCreateImageView(dev, &imgViewInfo, nullptr, &image.imageView);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create swapchain image view %d: %d", i, err);
+ return false;
+ }
+
+ image.lastUse = QVkSwapChain::ImageResources::ScImageUseNone;
+ }
+ }
swapChainD->currentImageIndex = 0;
- VkSemaphoreCreateInfo semInfo;
- memset(&semInfo, 0, sizeof(semInfo));
+ VkSemaphoreCreateInfo semInfo = {};
semInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
@@ -1646,7 +2074,7 @@ void QRhiVulkan::releaseSwapChainResources(QRhiSwapChain *swapChain)
}
}
- for (int i = 0; i < swapChainD->bufferCount; ++i) {
+ for (int i = 0; i < swapChainD->bufferCount * (swapChainD->stereo ? 2 : 1); ++i) {
QVkSwapChain::ImageResources &image(swapChainD->imageRes[i]);
if (image.fb) {
df->vkDestroyFramebuffer(dev, image.fb, nullptr);
@@ -1688,7 +2116,25 @@ void QRhiVulkan::ensureCommandPoolForNewFrame()
flags |= VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT;
// put all command buffers allocated from this slot's pool to initial state
- df->vkResetCommandPool(dev, cmdPool[currentFrameSlot], 0);
+ df->vkResetCommandPool(dev, cmdPool[currentFrameSlot], flags);
+}
+
+double QRhiVulkan::elapsedSecondsFromTimestamp(quint64 timestamp[2], bool *ok)
+{
+ quint64 mask = 0;
+ for (quint64 i = 0; i < timestampValidBits; i += 8)
+ mask |= 0xFFULL << i;
+ const quint64 ts0 = timestamp[0] & mask;
+ const quint64 ts1 = timestamp[1] & mask;
+ const float nsecsPerTick = physDevProperties.limits.timestampPeriod;
+ if (!qFuzzyIsNull(nsecsPerTick)) {
+ const float elapsedMs = float(ts1 - ts0) * nsecsPerTick / 1000000.0f;
+ const double elapsedSec = elapsedMs / 1000.0;
+ *ok = true;
+ return elapsedSec;
+ }
+ *ok = false;
+ return 0;
}
QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags)
@@ -1696,7 +2142,8 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
const int frameResIndex = swapChainD->bufferCount > 1 ? swapChainD->currentFrameSlot : 0;
QVkSwapChain::FrameResources &frame(swapChainD->frameRes[frameResIndex]);
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
+
+ inst->handle()->beginFrame(swapChainD->window);
if (!frame.imageAcquired) {
// Wait if we are too far ahead, i.e. the thread gets throttled based on the presentation rate
@@ -1741,32 +2188,6 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
// mess up A's in-flight commands (as they are not in flight anymore).
waitCommandCompletion(frameResIndex);
- // Now is the time to read the timestamps for the previous frame for this slot.
- if (frame.timestampQueryIndex >= 0) {
- quint64 timestamp[2] = { 0, 0 };
- VkResult err = df->vkGetQueryPoolResults(dev, timestampQueryPool, uint32_t(frame.timestampQueryIndex), 2,
- 2 * sizeof(quint64), timestamp, sizeof(quint64),
- VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
- timestampQueryPoolMap.clearBit(frame.timestampQueryIndex / 2);
- frame.timestampQueryIndex = -1;
- if (err == VK_SUCCESS) {
- quint64 mask = 0;
- for (quint64 i = 0; i < timestampValidBits; i += 8)
- mask |= 0xFFULL << i;
- const quint64 ts0 = timestamp[0] & mask;
- const quint64 ts1 = timestamp[1] & mask;
- const float nsecsPerTick = physDevProperties.limits.timestampPeriod;
- if (!qFuzzyIsNull(nsecsPerTick)) {
- const float elapsedMs = float(ts1 - ts0) * nsecsPerTick / 1000000.0f;
- // now we have the gpu time for the previous frame for this slot, report it
- // (does not matter that it is not for this frame)
- QRHI_PROF_F(swapChainFrameGpuTime(swapChain, elapsedMs));
- }
- } else {
- qWarning("Failed to query timestamp: %d", err);
- }
- }
-
currentFrameSlot = int(swapChainD->currentFrameSlot);
currentSwapChain = swapChainD;
if (swapChainD->ds)
@@ -1780,34 +2201,56 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
if (cbres != QRhi::FrameOpSuccess)
return cbres;
- // when profiling is enabled, pick a free query (pair) from the pool
- int timestampQueryIdx = -1;
- if (profilerPrivateOrNull() && swapChainD->bufferCount > 1) { // no timestamps if not having at least 2 frames in flight
- for (int i = 0; i < timestampQueryPoolMap.count(); ++i) {
- if (!timestampQueryPoolMap.testBit(i)) {
- timestampQueryPoolMap.setBit(i);
- timestampQueryIdx = i * 2;
- break;
- }
- }
- }
- if (timestampQueryIdx >= 0) {
- df->vkCmdResetQueryPool(frame.cmdBuf, timestampQueryPool, uint32_t(timestampQueryIdx), 2);
- // record timestamp at the start of the command buffer
- df->vkCmdWriteTimestamp(frame.cmdBuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
- timestampQueryPool, uint32_t(timestampQueryIdx));
- frame.timestampQueryIndex = timestampQueryIdx;
- }
-
swapChainD->cbWrapper.cb = frame.cmdBuf;
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
swapChainD->rtWrapper.d.fb = image.fb;
- QRHI_PROF_F(beginSwapChainFrame(swapChain));
+ if (swapChainD->stereo) {
+ QVkSwapChain::ImageResources &image(
+ swapChainD->imageRes[swapChainD->currentImageIndex + swapChainD->bufferCount]);
+ swapChainD->rtWrapperRight.d.fb = image.fb;
+ }
prepareNewFrame(&swapChainD->cbWrapper);
+ // Read the timestamps for the previous frame for this slot.
+ if (frame.timestampQueryIndex >= 0) {
+ quint64 timestamp[2] = { 0, 0 };
+ VkResult err = df->vkGetQueryPoolResults(dev, timestampQueryPool, uint32_t(frame.timestampQueryIndex), 2,
+ 2 * sizeof(quint64), timestamp, sizeof(quint64),
+ VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
+ timestampQueryPoolMap.clearBit(frame.timestampQueryIndex / 2);
+ frame.timestampQueryIndex = -1;
+ if (err == VK_SUCCESS) {
+ bool ok = false;
+ const double elapsedSec = elapsedSecondsFromTimestamp(timestamp, &ok);
+ if (ok)
+ swapChainD->cbWrapper.lastGpuTime = elapsedSec;
+ } else {
+ qWarning("Failed to query timestamp: %d", err);
+ }
+ }
+
+ // No timestamps if the client did not opt in, or when not having at least 2 frames in flight.
+ if (rhiFlags.testFlag(QRhi::EnableTimestamps) && swapChainD->bufferCount > 1) {
+ int timestampQueryIdx = -1;
+ for (int i = 0; i < timestampQueryPoolMap.size(); ++i) {
+ if (!timestampQueryPoolMap.testBit(i)) {
+ timestampQueryPoolMap.setBit(i);
+ timestampQueryIdx = i * 2;
+ break;
+ }
+ }
+ if (timestampQueryIdx >= 0) {
+ df->vkCmdResetQueryPool(frame.cmdBuf, timestampQueryPool, uint32_t(timestampQueryIdx), 2);
+ // record timestamp at the start of the command buffer
+ df->vkCmdWriteTimestamp(frame.cmdBuf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ timestampQueryPool, uint32_t(timestampQueryIdx));
+ frame.timestampQueryIndex = timestampQueryIdx;
+ }
+ }
+
return QRhi::FrameOpSuccess;
}
@@ -1816,6 +2259,10 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
Q_ASSERT(currentSwapChain == swapChainD);
+ auto cleanup = qScopeGuard([this, swapChainD] {
+ inst->handle()->endFrame(swapChainD->window);
+ });
+
recordPrimaryCommandBuffer(&swapChainD->cbWrapper);
int frameResIndex = swapChainD->bufferCount > 1 ? swapChainD->currentFrameSlot : 0;
@@ -1823,8 +2270,7 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
if (image.lastUse != QVkSwapChain::ImageResources::ScImageUseRender) {
- VkImageMemoryBarrier presTrans;
- memset(&presTrans, 0, sizeof(presTrans));
+ VkImageMemoryBarrier presTrans = {};
presTrans.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
presTrans.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
presTrans.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
@@ -1871,14 +2317,9 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram
frame.imageSemWaitable = false;
frame.cmdFenceWaitable = true;
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- // this must be done before the Present
- QRHI_PROF_F(endSwapChainFrame(swapChain, swapChainD->frameCount + 1));
-
if (needsPresent) {
// add the Present to the queue
- VkPresentInfoKHR presInfo;
- memset(&presInfo, 0, sizeof(presInfo));
+ VkPresentInfoKHR presInfo = {};
presInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presInfo.swapchainCount = 1;
presInfo.pSwapchains = &swapChainD->sc;
@@ -1931,8 +2372,8 @@ void QRhiVulkan::prepareNewFrame(QRhiCommandBuffer *cb)
//
// With multiple swapchains on the same QRhi things get more convoluted
// (and currentFrameSlot strictly alternating is not true anymore) but
- // beginNonWrapperFrame() solves that by blocking as necessary so the rest
- // here is safe regardless.
+ // begin(Offscreen)Frame() blocks anyway waiting for its current frame
+ // slot's previous commands to complete so this here is safe regardless.
executeDeferredReleases();
@@ -1946,8 +2387,7 @@ void QRhiVulkan::prepareNewFrame(QRhiCommandBuffer *cb)
QRhi::FrameOpResult QRhiVulkan::startPrimaryCommandBuffer(VkCommandBuffer *cb)
{
if (!*cb) {
- VkCommandBufferAllocateInfo cmdBufInfo;
- memset(&cmdBufInfo, 0, sizeof(cmdBufInfo));
+ VkCommandBufferAllocateInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cmdBufInfo.commandPool = cmdPool[currentFrameSlot];
cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
@@ -1965,8 +2405,7 @@ QRhi::FrameOpResult QRhiVulkan::startPrimaryCommandBuffer(VkCommandBuffer *cb)
}
}
- VkCommandBufferBeginInfo cmdBufBeginInfo;
- memset(&cmdBufBeginInfo, 0, sizeof(cmdBufBeginInfo));
+ VkCommandBufferBeginInfo cmdBufBeginInfo = {};
cmdBufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
VkResult err = df->vkBeginCommandBuffer(*cb, &cmdBufBeginInfo);
@@ -1997,8 +2436,7 @@ QRhi::FrameOpResult QRhiVulkan::endAndSubmitPrimaryCommandBuffer(VkCommandBuffer
return QRhi::FrameOpError;
}
- VkSubmitInfo submitInfo;
- memset(&submitInfo, 0, sizeof(submitInfo));
+ VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &cb;
@@ -2029,7 +2467,7 @@ QRhi::FrameOpResult QRhiVulkan::endAndSubmitPrimaryCommandBuffer(VkCommandBuffer
void QRhiVulkan::waitCommandCompletion(int frameSlot)
{
- for (QVkSwapChain *sc : qAsConst(swapchains)) {
+ for (QVkSwapChain *sc : std::as_const(swapchains)) {
const int frameResIndex = sc->bufferCount > 1 ? frameSlot : 0;
QVkSwapChain::FrameResources &frame(sc->frameRes[frameResIndex]);
if (frame.cmdFenceWaitable) {
@@ -2043,17 +2481,17 @@ void QRhiVulkan::waitCommandCompletion(int frameSlot)
QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags)
{
// Switch to the next slot manually. Swapchains do not know about this
- // which is good. So for example a - unusual but possible - onscreen,
- // onscreen, offscreen, onscreen, onscreen, onscreen sequence of
- // begin/endFrame leads to 0, 1, 0, 0, 1, 0. This works because the
- // offscreen frame is synchronous in the sense that we wait for execution
- // to complete in endFrame, and so no resources used in that frame are busy
+ // which is good. So for example an onscreen, onscreen, offscreen,
+ // onscreen, onscreen, onscreen sequence of frames leads to 0, 1, 0, 0, 1,
+ // 0. (no strict alternation anymore) But this is not different from what
+ // happens when multiple swapchains are involved. Offscreen frames are
+ // synchronous anyway in the sense that they wait for execution to complete
+ // in endOffscreenFrame, so no resources used in that frame are busy
// anymore in the next frame.
+
currentFrameSlot = (currentFrameSlot + 1) % QVK_FRAMES_IN_FLIGHT;
- // except that this gets complicated with multiple swapchains so make sure
- // any pending commands have finished for the frame slot we are going to use
- if (swapchains.count() > 1)
- waitCommandCompletion(currentFrameSlot);
+
+ waitCommandCompletion(currentFrameSlot);
ensureCommandPoolForNewFrame();
@@ -2065,6 +2503,24 @@ QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi
prepareNewFrame(cbWrapper);
ofr.active = true;
+ if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
+ int timestampQueryIdx = -1;
+ for (int i = 0; i < timestampQueryPoolMap.size(); ++i) {
+ if (!timestampQueryPoolMap.testBit(i)) {
+ timestampQueryPoolMap.setBit(i);
+ timestampQueryIdx = i * 2;
+ break;
+ }
+ }
+ if (timestampQueryIdx >= 0) {
+ df->vkCmdResetQueryPool(cbWrapper->cb, timestampQueryPool, uint32_t(timestampQueryIdx), 2);
+ // record timestamp at the start of the command buffer
+ df->vkCmdWriteTimestamp(cbWrapper->cb, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ timestampQueryPool, uint32_t(timestampQueryIdx));
+ ofr.timestampQueryIndex = timestampQueryIdx;
+ }
+ }
+
*cb = cbWrapper;
return QRhi::FrameOpSuccess;
}
@@ -2078,9 +2534,14 @@ QRhi::FrameOpResult QRhiVulkan::endOffscreenFrame(QRhi::EndFrameFlags flags)
QVkCommandBuffer *cbWrapper(ofr.cbWrapper[currentFrameSlot]);
recordPrimaryCommandBuffer(cbWrapper);
+ // record another timestamp, when enabled
+ if (ofr.timestampQueryIndex >= 0) {
+ df->vkCmdWriteTimestamp(cbWrapper->cb, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ timestampQueryPool, uint32_t(ofr.timestampQueryIndex + 1));
+ }
+
if (!ofr.cmdFence) {
- VkFenceCreateInfo fenceInfo;
- memset(&fenceInfo, 0, sizeof(fenceInfo));
+ VkFenceCreateInfo fenceInfo = {};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
VkResult err = df->vkCreateFence(dev, &fenceInfo, nullptr, &ofr.cmdFence);
if (err != VK_SUCCESS) {
@@ -2101,6 +2562,24 @@ QRhi::FrameOpResult QRhiVulkan::endOffscreenFrame(QRhi::EndFrameFlags flags)
// previous) frame is safe since we waited for completion above.
finishActiveReadbacks(true);
+ // Read the timestamps, if we wrote them.
+ if (ofr.timestampQueryIndex >= 0) {
+ quint64 timestamp[2] = { 0, 0 };
+ VkResult err = df->vkGetQueryPoolResults(dev, timestampQueryPool, uint32_t(ofr.timestampQueryIndex), 2,
+ 2 * sizeof(quint64), timestamp, sizeof(quint64),
+ VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
+ timestampQueryPoolMap.clearBit(ofr.timestampQueryIndex / 2);
+ ofr.timestampQueryIndex = -1;
+ if (err == VK_SUCCESS) {
+ bool ok = false;
+ const double elapsedSec = elapsedSecondsFromTimestamp(timestamp, &ok);
+ if (ok)
+ cbWrapper->lastGpuTime = elapsedSec;
+ } else {
+ qWarning("Failed to query timestamp: %d", err);
+ }
+ }
+
return QRhi::FrameOpSuccess;
}
@@ -2172,6 +2651,9 @@ static inline QRhiPassResourceTracker::UsageState toPassTrackerUsageState(const
void QRhiVulkan::activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRenderTarget *rtD)
{
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QVkTexture, QVkRenderBuffer>(rtD->description(), rtD->d.currentResIdList))
+ rtD->create();
+
rtD->lastActiveFrameSlot = currentFrameSlot;
rtD->d.rp->lastActiveFrameSlot = currentFrameSlot;
QRhiPassResourceTracker &passResTracker(cbD->passResTrackers[cbD->currentPassResTrackerIndex]);
@@ -2215,6 +2697,13 @@ void QRhiVulkan::activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRe
QRhiPassResourceTracker::TexDepthOutputStage);
depthTexD->lastActiveFrameSlot = currentFrameSlot;
}
+ if (rtD->m_desc.depthResolveTexture()) {
+ QVkTexture *depthResolveTexD = QRHI_RES(QVkTexture, rtD->m_desc.depthResolveTexture());
+ trackedRegisterTexture(&passResTracker, depthResolveTexD,
+ QRhiPassResourceTracker::TexDepthOutput,
+ QRhiPassResourceTracker::TexDepthOutputStage);
+ depthResolveTexD->lastActiveFrameSlot = currentFrameSlot;
+ }
}
void QRhiVulkan::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@@ -2233,8 +2722,7 @@ VkCommandBuffer QRhiVulkan::startSecondaryCommandBuffer(QVkRenderTargetData *rtD
secondaryCb = freeSecondaryCbs[currentFrameSlot].last();
freeSecondaryCbs[currentFrameSlot].removeLast();
} else {
- VkCommandBufferAllocateInfo cmdBufInfo;
- memset(&cmdBufInfo, 0, sizeof(cmdBufInfo));
+ VkCommandBufferAllocateInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cmdBufInfo.commandPool = cmdPool[currentFrameSlot];
cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
@@ -2247,12 +2735,10 @@ VkCommandBuffer QRhiVulkan::startSecondaryCommandBuffer(QVkRenderTargetData *rtD
}
}
- VkCommandBufferBeginInfo cmdBufBeginInfo;
- memset(&cmdBufBeginInfo, 0, sizeof(cmdBufBeginInfo));
+ VkCommandBufferBeginInfo cmdBufBeginInfo = {};
cmdBufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufBeginInfo.flags = rtD ? VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT : 0;
- VkCommandBufferInheritanceInfo cmdBufInheritInfo;
- memset(&cmdBufInheritInfo, 0, sizeof(cmdBufInheritInfo));
+ VkCommandBufferInheritanceInfo cmdBufInheritInfo = {};
cmdBufInheritInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
cmdBufInheritInfo.subpass = 0;
if (rtD) {
@@ -2308,8 +2794,8 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
QVkRenderTargetData *rtD = nullptr;
switch (rt->resourceType()) {
- case QRhiResource::RenderTarget:
- rtD = &QRHI_RES(QVkReferenceRenderTarget, rt)->d;
+ case QRhiResource::SwapChainRenderTarget:
+ rtD = &QRHI_RES(QVkSwapChainRenderTarget, rt)->d;
rtD->rp->lastActiveFrameSlot = currentFrameSlot;
Q_ASSERT(currentSwapChain);
currentSwapChain->imageRes[currentSwapChain->currentImageIndex].lastUse =
@@ -2334,8 +2820,7 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
// No copy operations or image layout transitions allowed after this point
// (up until endPass) as we are going to begin the renderpass.
- VkRenderPassBeginInfo rpBeginInfo;
- memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ VkRenderPassBeginInfo rpBeginInfo = {};
rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rpBeginInfo.renderPass = rtD->rp->rp;
rpBeginInfo.framebuffer = rtD->fb;
@@ -2360,17 +2845,24 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
float(colorClearValue.alphaF()) } };
cvs.append(cv);
}
- rpBeginInfo.clearValueCount = uint32_t(cvs.count());
+ for (int i = 0; i < rtD->dsResolveAttCount; ++i) {
+ VkClearValue cv;
+ cv.depthStencil = { depthStencilClearValue.depthClearValue(), depthStencilClearValue.stencilClearValue() };
+ cvs.append(cv);
+ }
+ rpBeginInfo.clearValueCount = uint32_t(cvs.size());
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::BeginRenderPass;
cmd.args.beginRenderPass.desc = rpBeginInfo;
- cmd.args.beginRenderPass.clearValueIndex = cbD->pools.clearValue.count();
+ cmd.args.beginRenderPass.clearValueIndex = cbD->pools.clearValue.size();
cmd.args.beginRenderPass.useSecondaryCb = cbD->passUsesSecondaryCb;
- cbD->pools.clearValue.append(cvs.constData(), cvs.count());
+ cbD->pools.clearValue.append(cvs.constData(), cvs.size());
if (cbD->passUsesSecondaryCb)
cbD->activeSecondaryCbStack.append(startSecondaryCommandBuffer(rtD));
+
+ cbD->resetCachedState();
}
void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@@ -2382,7 +2874,6 @@ void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourc
VkCommandBuffer secondaryCb = cbD->activeSecondaryCbStack.last();
cbD->activeSecondaryCbStack.removeLast();
endAndEnqueueSecondaryCommandBuffer(secondaryCb, cbD);
- cbD->resetCachedState();
}
QVkCommandBuffer::Command &cmd(cbD->commands.get());
@@ -2414,6 +2905,8 @@ void QRhiVulkan::beginComputePass(QRhiCommandBuffer *cb,
if (cbD->passUsesSecondaryCb)
cbD->activeSecondaryCbStack.append(startSecondaryCommandBuffer());
+
+ cbD->resetCachedState();
}
void QRhiVulkan::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@@ -2425,7 +2918,6 @@ void QRhiVulkan::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *
VkCommandBuffer secondaryCb = cbD->activeSecondaryCbStack.last();
cbD->activeSecondaryCbStack.removeLast();
endAndEnqueueSecondaryCommandBuffer(secondaryCb, cbD);
- cbD->resetCachedState();
}
cbD->recordingPass = QVkCommandBuffer::NoPass;
@@ -2496,9 +2988,9 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
accessAndIsNewFlag = { 0, false };
QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, cbD->currentComputeSrb);
- const int bindingCount = srbD->m_bindings.count();
+ const int bindingCount = srbD->m_bindings.size();
for (int i = 0; i < bindingCount; ++i) {
- const QRhiShaderResourceBinding::Data *b = srbD->m_bindings.at(i).data();
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->m_bindings.at(i));
switch (b->type) {
case QRhiShaderResourceBinding::ImageLoad:
case QRhiShaderResourceBinding::ImageStore:
@@ -2531,8 +3023,7 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
if (accessInThisDispatch && !isNewInThisDispatch) {
if (it.key()->resourceType() == QRhiResource::Texture) {
QVkTexture *texD = QRHI_RES(QVkTexture, it.key());
- VkImageMemoryBarrier barrier;
- memset(&barrier, 0, sizeof(barrier));
+ VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
// won't care about subresources, pretend the whole resource was written
@@ -2548,8 +3039,7 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
imageBarriers.append(barrier);
} else {
QVkBuffer *bufD = QRHI_RES(QVkBuffer, it.key());
- VkBufferMemoryBarrier barrier;
- memset(&barrier, 0, sizeof(barrier));
+ VkBufferMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@@ -2576,12 +3066,12 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
df->vkCmdPipelineBarrier(secondaryCb, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, 0, nullptr,
0, nullptr,
- imageBarriers.count(), imageBarriers.constData());
+ imageBarriers.size(), imageBarriers.constData());
}
if (!bufferBarriers.isEmpty()) {
df->vkCmdPipelineBarrier(secondaryCb, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, 0, nullptr,
- bufferBarriers.count(), bufferBarriers.constData(),
+ bufferBarriers.size(), bufferBarriers.constData(),
0, nullptr);
}
df->vkCmdDispatch(secondaryCb, uint32_t(x), uint32_t(y), uint32_t(z));
@@ -2591,18 +3081,18 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
cmd.cmd = QVkCommandBuffer::Command::ImageBarrier;
cmd.args.imageBarrier.srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
cmd.args.imageBarrier.dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- cmd.args.imageBarrier.count = imageBarriers.count();
- cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count();
- cbD->pools.imageBarrier.append(imageBarriers.constData(), imageBarriers.count());
+ cmd.args.imageBarrier.count = imageBarriers.size();
+ cmd.args.imageBarrier.index = cbD->pools.imageBarrier.size();
+ cbD->pools.imageBarrier.append(imageBarriers.constData(), imageBarriers.size());
}
if (!bufferBarriers.isEmpty()) {
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::BufferBarrier;
cmd.args.bufferBarrier.srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
cmd.args.bufferBarrier.dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- cmd.args.bufferBarrier.count = bufferBarriers.count();
- cmd.args.bufferBarrier.index = cbD->pools.bufferBarrier.count();
- cbD->pools.bufferBarrier.append(bufferBarriers.constData(), bufferBarriers.count());
+ cmd.args.bufferBarrier.count = bufferBarriers.size();
+ cmd.args.bufferBarrier.index = cbD->pools.bufferBarrier.size();
+ cbD->pools.bufferBarrier.append(bufferBarriers.constData(), bufferBarriers.size());
}
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::Dispatch;
@@ -2614,8 +3104,7 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
VkShaderModule QRhiVulkan::createShader(const QByteArray &spirv)
{
- VkShaderModuleCreateInfo shaderInfo;
- memset(&shaderInfo, 0, sizeof(shaderInfo));
+ VkShaderModuleCreateInfo shaderInfo = {};
shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shaderInfo.codeSize = size_t(spirv.size());
shaderInfo.pCode = reinterpret_cast<const quint32 *>(spirv.constData());
@@ -2633,8 +3122,7 @@ bool QRhiVulkan::ensurePipelineCache(const void *initialData, size_t initialData
if (pipelineCache)
return true;
- VkPipelineCacheCreateInfo pipelineCacheInfo;
- memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ VkPipelineCacheCreateInfo pipelineCacheInfo = {};
pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
pipelineCacheInfo.initialDataSize = initialDataSize;
pipelineCacheInfo.pInitialData = initialData;
@@ -2659,12 +3147,11 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
const bool updateAll = descSetIdx < 0;
int frameSlot = updateAll ? 0 : descSetIdx;
while (frameSlot < (updateAll ? QVK_FRAMES_IN_FLIGHT : descSetIdx + 1)) {
- for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
- const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data();
+ for (int i = 0, ie = srbD->sortedBindings.size(); i != ie; ++i) {
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings.at(i));
QVkShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[frameSlot][i]);
- VkWriteDescriptorSet writeInfo;
- memset(&writeInfo, 0, sizeof(writeInfo));
+ VkWriteDescriptorSet writeInfo = {};
writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writeInfo.dstSet = srbD->descSets[frameSlot];
writeInfo.dstBinding = uint32_t(b->binding);
@@ -2684,17 +3171,17 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
bd.ubuf.generation = bufD->generation;
VkDescriptorBufferInfo bufInfo;
bufInfo.buffer = bufD->m_type == QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0];
- bufInfo.offset = VkDeviceSize(b->u.ubuf.offset);
- bufInfo.range = VkDeviceSize(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size);
+ bufInfo.offset = b->u.ubuf.offset;
+ bufInfo.range = b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size;
// be nice and assert when we know the vulkan device would die a horrible death due to non-aligned reads
Q_ASSERT(aligned(bufInfo.offset, ubufAlign) == bufInfo.offset);
- bufferInfoIndex = bufferInfos.count();
+ bufferInfoIndex = bufferInfos.size();
bufferInfos.append(bufInfo);
}
break;
case QRhiShaderResourceBinding::SampledTexture:
{
- const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
+ const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
writeInfo.descriptorCount = data->count; // arrays of combined image samplers are supported
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
ArrayOfImageDesc imageInfo(data->count);
@@ -2710,7 +3197,44 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
imageInfo[elem].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
bd.stex.count = data->count;
- imageInfoIndex = imageInfos.count();
+ imageInfoIndex = imageInfos.size();
+ imageInfos.append(imageInfo);
+ }
+ break;
+ case QRhiShaderResourceBinding::Texture:
+ {
+ const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
+ writeInfo.descriptorCount = data->count; // arrays of (separate) images are supported
+ writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ ArrayOfImageDesc imageInfo(data->count);
+ for (int elem = 0; elem < data->count; ++elem) {
+ QVkTexture *texD = QRHI_RES(QVkTexture, data->texSamplers[elem].tex);
+ bd.stex.d[elem].texId = texD->m_id;
+ bd.stex.d[elem].texGeneration = texD->generation;
+ bd.stex.d[elem].samplerId = 0;
+ bd.stex.d[elem].samplerGeneration = 0;
+ imageInfo[elem].sampler = VK_NULL_HANDLE;
+ imageInfo[elem].imageView = texD->imageView;
+ imageInfo[elem].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ }
+ bd.stex.count = data->count;
+ imageInfoIndex = imageInfos.size();
+ imageInfos.append(imageInfo);
+ }
+ break;
+ case QRhiShaderResourceBinding::Sampler:
+ {
+ QVkSampler *samplerD = QRHI_RES(QVkSampler, b->u.stex.texSamplers[0].sampler);
+ writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
+ bd.stex.d[0].texId = 0;
+ bd.stex.d[0].texGeneration = 0;
+ bd.stex.d[0].samplerId = samplerD->m_id;
+ bd.stex.d[0].samplerGeneration = samplerD->generation;
+ ArrayOfImageDesc imageInfo(1);
+ imageInfo[0].sampler = samplerD->sampler;
+ imageInfo[0].imageView = VK_NULL_HANDLE;
+ imageInfo[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+ imageInfoIndex = imageInfos.size();
imageInfos.append(imageInfo);
}
break;
@@ -2719,7 +3243,7 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
case QRhiShaderResourceBinding::ImageLoadStore:
{
QVkTexture *texD = QRHI_RES(QVkTexture, b->u.simage.tex);
- VkImageView view = texD->imageViewForLevel(b->u.simage.level);
+ VkImageView view = texD->perLevelImageViewForLoadStore(b->u.simage.level);
if (view) {
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
bd.simage.id = texD->m_id;
@@ -2728,7 +3252,7 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
imageInfo[0].sampler = VK_NULL_HANDLE;
imageInfo[0].imageView = view;
imageInfo[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
- imageInfoIndex = imageInfos.count();
+ imageInfoIndex = imageInfos.size();
imageInfos.append(imageInfo);
}
}
@@ -2743,9 +3267,9 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
bd.sbuf.generation = bufD->generation;
VkDescriptorBufferInfo bufInfo;
bufInfo.buffer = bufD->m_type == QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0];
- bufInfo.offset = VkDeviceSize(b->u.ubuf.offset);
- bufInfo.range = VkDeviceSize(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size);
- bufferInfoIndex = bufferInfos.count();
+ bufInfo.offset = b->u.ubuf.offset;
+ bufInfo.range = b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size;
+ bufferInfoIndex = bufferInfos.size();
bufferInfos.append(bufInfo);
}
break;
@@ -2759,7 +3283,7 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
++frameSlot;
}
- for (int i = 0, writeInfoCount = writeInfos.count(); i < writeInfoCount; ++i) {
+ for (int i = 0, writeInfoCount = writeInfos.size(); i < writeInfoCount; ++i) {
const int bufferInfoIndex = infoIndices[i].first;
const int imageInfoIndex = infoIndices[i].second;
if (bufferInfoIndex >= 0)
@@ -2768,7 +3292,7 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
writeInfos[i].pImageInfo = imageInfos[imageInfoIndex].constData();
}
- df->vkUpdateDescriptorSets(dev, uint32_t(writeInfos.count()), writeInfos.constData(), 0, nullptr);
+ df->vkUpdateDescriptorSets(dev, uint32_t(writeInfos.size()), writeInfos.constData(), 0, nullptr);
}
static inline bool accessIsWrite(VkAccessFlags access)
@@ -2800,8 +3324,7 @@ void QRhiVulkan::trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, in
return;
}
- VkBufferMemoryBarrier bufMemBarrier;
- memset(&bufMemBarrier, 0, sizeof(bufMemBarrier));
+ VkBufferMemoryBarrier bufMemBarrier = {};
bufMemBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@@ -2815,7 +3338,7 @@ void QRhiVulkan::trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, in
cmd.args.bufferBarrier.srcStageMask = s.stage;
cmd.args.bufferBarrier.dstStageMask = stage;
cmd.args.bufferBarrier.count = 1;
- cmd.args.bufferBarrier.index = cbD->pools.bufferBarrier.count();
+ cmd.args.bufferBarrier.index = cbD->pools.bufferBarrier.size();
cbD->pools.bufferBarrier.append(bufMemBarrier);
s.access = access;
@@ -2833,8 +3356,7 @@ void QRhiVulkan::trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD,
return;
}
- VkImageMemoryBarrier barrier;
- memset(&barrier, 0, sizeof(barrier));
+ VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.subresourceRange.aspectMask = aspectMaskForTextureFormat(texD->m_format);
barrier.subresourceRange.baseMipLevel = 0;
@@ -2857,7 +3379,7 @@ void QRhiVulkan::trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD,
cmd.args.imageBarrier.srcStageMask = srcStage;
cmd.args.imageBarrier.dstStageMask = stage;
cmd.args.imageBarrier.count = 1;
- cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count();
+ cmd.args.imageBarrier.index = cbD->pools.imageBarrier.size();
cbD->pools.imageBarrier.append(barrier);
s.layout = layout;
@@ -2869,8 +3391,7 @@ void QRhiVulkan::depthStencilExplicitBarrier(QVkCommandBuffer *cbD, QVkRenderBuf
{
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass);
- VkImageMemoryBarrier barrier;
- memset(&barrier, 0, sizeof(barrier));
+ VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
barrier.subresourceRange.baseMipLevel = 0;
@@ -2892,7 +3413,7 @@ void QRhiVulkan::depthStencilExplicitBarrier(QVkCommandBuffer *cbD, QVkRenderBuf
cmd.args.imageBarrier.srcStageMask = stages;
cmd.args.imageBarrier.dstStageMask = stages;
cmd.args.imageBarrier.count = 1;
- cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count();
+ cmd.args.imageBarrier.index = cbD->pools.imageBarrier.size();
cbD->pools.imageBarrier.append(barrier);
}
@@ -2904,8 +3425,7 @@ void QRhiVulkan::subresourceBarrier(QVkCommandBuffer *cbD, VkImage image,
int startLevel, int levelCount)
{
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass);
- VkImageMemoryBarrier barrier;
- memset(&barrier, 0, sizeof(barrier));
+ VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = uint32_t(startLevel);
@@ -2923,7 +3443,7 @@ void QRhiVulkan::subresourceBarrier(QVkCommandBuffer *cbD, VkImage image,
cmd.args.imageBarrier.srcStageMask = srcStage;
cmd.args.imageBarrier.dstStageMask = dstStage;
cmd.args.imageBarrier.count = 1;
- cmd.args.imageBarrier.index = cbD->pools.imageBarrier.count();
+ cmd.args.imageBarrier.index = cbD->pools.imageBarrier.size();
cbD->pools.imageBarrier.append(barrier);
}
@@ -2946,9 +3466,9 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
qsizetype imageSizeBytes = 0;
const void *src = nullptr;
const bool is3D = texD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
+ const bool is1D = texD->m_flags.testFlag(QRhiTexture::OneDimensional);
- VkBufferImageCopy copyInfo;
- memset(&copyInfo, 0, sizeof(copyInfo));
+ VkBufferImageCopy copyInfo = {};
copyInfo.bufferOffset = *curOfs;
copyInfo.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copyInfo.imageSubresource.mipLevel = uint32_t(level);
@@ -2957,6 +3477,8 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
copyInfo.imageExtent.depth = 1;
if (is3D)
copyInfo.imageOffset.z = uint32_t(layer);
+ if (is1D)
+ copyInfo.imageOffset.y = uint32_t(layer);
const QByteArray rawData = subresDesc.data();
const QPoint dp = subresDesc.destinationTopLeft();
@@ -3043,10 +3565,15 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
}
}
+void QRhiVulkan::printExtraErrorInfo(VkResult err)
+{
+ if (err == VK_ERROR_OUT_OF_DEVICE_MEMORY)
+ qWarning() << "Out of device memory, current allocator statistics are" << statistics();
+}
+
void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates)
{
QRhiResourceUpdateBatchPrivate *ud = QRhiResourceUpdateBatchPrivate::get(resourceUpdates);
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
for (int opIdx = 0; opIdx < ud->activeBufferOpCount; ++opIdx) {
const QRhiResourceUpdateBatchPrivate::BufferOp &u(ud->bufferOps[opIdx]);
@@ -3064,16 +3591,14 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
Q_ASSERT(u.offset + u.data.size() <= bufD->m_size);
if (!bufD->stagingBuffers[currentFrameSlot]) {
- VkBufferCreateInfo bufferInfo;
- memset(&bufferInfo, 0, sizeof(bufferInfo));
+ VkBufferCreateInfo bufferInfo = {};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
// must cover the entire buffer - this way multiple, partial updates per frame
// are supported even when the staging buffer is reused (Static)
- bufferInfo.size = VkDeviceSize(bufD->m_size);
+ bufferInfo.size = bufD->m_size;
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- VmaAllocationCreateInfo allocInfo;
- memset(&allocInfo, 0, sizeof(allocInfo));
+ VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
VmaAllocation allocation;
@@ -3081,9 +3606,9 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
&bufD->stagingBuffers[currentFrameSlot], &allocation, nullptr);
if (err == VK_SUCCESS) {
bufD->stagingAllocations[currentFrameSlot] = allocation;
- QRHI_PROF_F(newBufferStagingArea(bufD, currentFrameSlot, quint32(bufD->m_size)));
} else {
- qWarning("Failed to create staging buffer of size %d: %d", bufD->m_size, err);
+ qWarning("Failed to create staging buffer of size %u: %d", bufD->m_size, err);
+ printExtraErrorInfo(err);
continue;
}
}
@@ -3095,18 +3620,17 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
qWarning("Failed to map buffer: %d", err);
continue;
}
- memcpy(static_cast<uchar *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
+ memcpy(static_cast<uchar *>(p) + u.offset, u.data.constData(), u.data.size());
+ vmaFlushAllocation(toVmaAllocator(allocator), a, u.offset, u.data.size());
vmaUnmapMemory(toVmaAllocator(allocator), a);
- vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(u.offset), VkDeviceSize(u.data.size()));
trackedBufferBarrier(cbD, bufD, 0,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- VkBufferCopy copyInfo;
- memset(&copyInfo, 0, sizeof(copyInfo));
- copyInfo.srcOffset = VkDeviceSize(u.offset);
- copyInfo.dstOffset = VkDeviceSize(u.offset);
- copyInfo.size = VkDeviceSize(u.data.size());
+ VkBufferCopy copyInfo = {};
+ copyInfo.srcOffset = u.offset;
+ copyInfo.dstOffset = u.offset;
+ copyInfo.size = u.data.size();
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::CopyBuffer;
@@ -3132,7 +3656,6 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
bufD->stagingBuffers[currentFrameSlot] = VK_NULL_HANDLE;
bufD->stagingAllocations[currentFrameSlot] = nullptr;
releaseQueue.append(e);
- QRHI_PROF_F(releaseBufferStagingArea(bufD, currentFrameSlot));
}
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
@@ -3143,7 +3666,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p);
if (err == VK_SUCCESS) {
u.result->data.resize(u.readSize);
- memcpy(u.result->data.data(), reinterpret_cast<char *>(p) + u.offset, size_t(u.readSize));
+ memcpy(u.result->data.data(), reinterpret_cast<char *>(p) + u.offset, u.readSize);
vmaUnmapMemory(toVmaAllocator(allocator), a);
}
if (u.result->completed)
@@ -3160,32 +3683,29 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
readback.result = u.result;
readback.byteSize = u.readSize;
- VkBufferCreateInfo bufferInfo;
- memset(&bufferInfo, 0, sizeof(bufferInfo));
+ VkBufferCreateInfo bufferInfo = {};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- bufferInfo.size = VkDeviceSize(readback.byteSize);
+ bufferInfo.size = readback.byteSize;
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- VmaAllocationCreateInfo allocInfo;
- memset(&allocInfo, 0, sizeof(allocInfo));
+ VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
VmaAllocation allocation;
VkResult err = vmaCreateBuffer(toVmaAllocator(allocator), &bufferInfo, &allocInfo, &readback.stagingBuf, &allocation, nullptr);
if (err == VK_SUCCESS) {
readback.stagingAlloc = allocation;
- QRHI_PROF_F(newReadbackBuffer(qint64(readback.stagingBuf), bufD, uint(readback.byteSize)));
} else {
qWarning("Failed to create readback buffer of size %u: %d", readback.byteSize, err);
+ printExtraErrorInfo(err);
continue;
}
trackedBufferBarrier(cbD, bufD, 0, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
- VkBufferCopy copyInfo;
- memset(&copyInfo, 0, sizeof(copyInfo));
- copyInfo.srcOffset = VkDeviceSize(u.offset);
- copyInfo.size = VkDeviceSize(u.readSize);
+ VkBufferCopy copyInfo = {};
+ copyInfo.srcOffset = u.offset;
+ copyInfo.size = u.readSize;
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::CopyBuffer;
@@ -3206,22 +3726,20 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
QVkTexture *utexD = QRHI_RES(QVkTexture, u.dst);
// batch into a single staging buffer and a single CopyBufferToImage with multiple copyInfos
VkDeviceSize stagingSize = 0;
- for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int layer = 0, maxLayer = u.subresDesc.size(); layer < maxLayer; ++layer) {
for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
- for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(u.subresDesc[layer][level]))
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(u.subresDesc[layer][level]))
stagingSize += subresUploadByteSize(subresDesc);
}
}
Q_ASSERT(!utexD->stagingBuffers[currentFrameSlot]);
- VkBufferCreateInfo bufferInfo;
- memset(&bufferInfo, 0, sizeof(bufferInfo));
+ VkBufferCreateInfo bufferInfo = {};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = stagingSize;
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- VmaAllocationCreateInfo allocInfo;
- memset(&allocInfo, 0, sizeof(allocInfo));
+ VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
VmaAllocation allocation;
@@ -3229,10 +3747,10 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
&utexD->stagingBuffers[currentFrameSlot], &allocation, nullptr);
if (err != VK_SUCCESS) {
qWarning("Failed to create image staging buffer of size %d: %d", int(stagingSize), err);
+ printExtraErrorInfo(err);
continue;
}
utexD->stagingAllocations[currentFrameSlot] = allocation;
- QRHI_PROF_F(newTextureStagingArea(utexD, currentFrameSlot, quint32(stagingSize)));
BufferImageCopyList copyInfos;
size_t curOfs = 0;
@@ -3244,19 +3762,19 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
continue;
}
- for (int layer = 0, maxLayer = u.subresDesc.count(); layer < maxLayer; ++layer) {
+ for (int layer = 0, maxLayer = u.subresDesc.size(); layer < maxLayer; ++layer) {
for (int level = 0; level < QRhi::MAX_MIP_LEVELS; ++level) {
const QList<QRhiTextureSubresourceUploadDescription> &srd(u.subresDesc[layer][level]);
if (srd.isEmpty())
continue;
- for (const QRhiTextureSubresourceUploadDescription &subresDesc : qAsConst(srd)) {
+ for (const QRhiTextureSubresourceUploadDescription &subresDesc : std::as_const(srd)) {
prepareUploadSubres(utexD, layer, level,
subresDesc, &curOfs, mp, &copyInfos);
}
}
}
- vmaUnmapMemory(toVmaAllocator(allocator), a);
vmaFlushAllocation(toVmaAllocator(allocator), a, 0, stagingSize);
+ vmaUnmapMemory(toVmaAllocator(allocator), a);
trackedImageBarrier(cbD, utexD, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
@@ -3266,9 +3784,9 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
cmd.args.copyBufferToImage.src = utexD->stagingBuffers[currentFrameSlot];
cmd.args.copyBufferToImage.dst = utexD->image;
cmd.args.copyBufferToImage.dstLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- cmd.args.copyBufferToImage.count = copyInfos.count();
- cmd.args.copyBufferToImage.bufferImageCopyIndex = cbD->pools.bufferImageCopy.count();
- cbD->pools.bufferImageCopy.append(copyInfos.constData(), copyInfos.count());
+ cmd.args.copyBufferToImage.count = copyInfos.size();
+ cmd.args.copyBufferToImage.bufferImageCopyIndex = cbD->pools.bufferImageCopy.size();
+ cbD->pools.bufferImageCopy.append(copyInfos.constData(), copyInfos.size());
// no reuse of staging, this is intentional
QRhiVulkan::DeferredReleaseEntry e;
@@ -3279,7 +3797,6 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
utexD->stagingBuffers[currentFrameSlot] = VK_NULL_HANDLE;
utexD->stagingAllocations[currentFrameSlot] = nullptr;
releaseQueue.append(e);
- QRHI_PROF_F(releaseTextureStagingArea(utexD, currentFrameSlot));
// Similarly to buffers, transitioning away from DST is done later,
// when a renderpass using the texture is encountered.
@@ -3296,9 +3813,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
const bool srcIs3D = srcD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
const bool dstIs3D = dstD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
- VkImageCopy region;
- memset(&region, 0, sizeof(region));
-
+ VkImageCopy region = {};
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.srcSubresource.mipLevel = uint32_t(u.desc.sourceLevel());
region.srcSubresource.baseArrayLayer = srcIs3D ? 0 : uint32_t(u.desc.sourceLayer());
@@ -3365,7 +3880,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
continue;
}
readback.pixelSize = swapChainD->pixelSize;
- readback.format = colorTextureFormatFromVkFormat(swapChainD->colorFormat, nullptr);
+ readback.format = swapchainReadbackTextureFormat(swapChainD->colorFormat, nullptr);
if (readback.format == QRhiTexture::UnknownFormat)
continue;
@@ -3375,31 +3890,26 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
textureFormatInfo(readback.format, readback.pixelSize, nullptr, &readback.byteSize, nullptr);
// Create a host visible readback buffer.
- VkBufferCreateInfo bufferInfo;
- memset(&bufferInfo, 0, sizeof(bufferInfo));
+ VkBufferCreateInfo bufferInfo = {};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = readback.byteSize;
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- VmaAllocationCreateInfo allocInfo;
- memset(&allocInfo, 0, sizeof(allocInfo));
+ VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
VmaAllocation allocation;
VkResult err = vmaCreateBuffer(toVmaAllocator(allocator), &bufferInfo, &allocInfo, &readback.stagingBuf, &allocation, nullptr);
if (err == VK_SUCCESS) {
readback.stagingAlloc = allocation;
- QRHI_PROF_F(newReadbackBuffer(qint64(readback.stagingBuf),
- texD ? static_cast<QRhiResource *>(texD) : static_cast<QRhiResource *>(swapChainD),
- readback.byteSize));
} else {
qWarning("Failed to create readback buffer of size %u: %d", readback.byteSize, err);
+ printExtraErrorInfo(err);
continue;
}
// Copy from the (optimal and not host visible) image into the buffer.
- VkBufferImageCopy copyDesc;
- memset(&copyDesc, 0, sizeof(copyDesc));
+ VkBufferImageCopy copyDesc = {};
copyDesc.bufferOffset = 0;
copyDesc.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copyDesc.imageSubresource.mipLevel = uint32_t(u.rb.level());
@@ -3451,6 +3961,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
QVkTexture *utexD = QRHI_RES(QVkTexture, u.dst);
Q_ASSERT(utexD->m_flags.testFlag(QRhiTexture::UsedWithGenerateMips));
const bool isCube = utexD->m_flags.testFlag(QRhiTexture::CubeMap);
+ const bool isArray = utexD->m_flags.testFlag(QRhiTexture::TextureArray);
const bool is3D = utexD->m_flags.testFlag(QRhiTexture::ThreeDimensional);
VkImageLayout origLayout = utexD->usageState.layout;
@@ -3459,10 +3970,10 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
if (!origStage)
origStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- for (int layer = 0; layer < (isCube ? 6 : 1); ++layer) {
+ for (int layer = 0; layer < (isCube ? 6 : (isArray ? qMax(0, utexD->m_arraySize) : 1)); ++layer) {
int w = utexD->m_pixelSize.width();
int h = utexD->m_pixelSize.height();
- int depth = is3D ? utexD->m_depth : 1;
+ int depth = is3D ? qMax(1, utexD->m_depth) : 1;
for (int level = 1; level < int(utexD->mipLevelCount); ++level) {
if (level == 1) {
subresourceBarrier(cbD, utexD->image,
@@ -3487,9 +3998,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
layer, 1,
level, 1);
- VkImageBlit region;
- memset(&region, 0, sizeof(region));
-
+ VkImageBlit region = {};
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.srcSubresource.mipLevel = uint32_t(level) - 1;
region.srcSubresource.baseArrayLayer = uint32_t(layer);
@@ -3560,18 +4069,18 @@ void QRhiVulkan::executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot)
qWarning("Failed to map buffer: %d", err);
return;
}
- int changeBegin = -1;
- int changeEnd = -1;
- for (const QVkBuffer::DynamicUpdate &u : qAsConst(bufD->pendingDynamicUpdates[slot])) {
- memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
- if (changeBegin == -1 || u.offset < changeBegin)
+ quint32 changeBegin = UINT32_MAX;
+ quint32 changeEnd = 0;
+ for (const QVkBuffer::DynamicUpdate &u : std::as_const(bufD->pendingDynamicUpdates[slot])) {
+ memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), u.data.size());
+ if (u.offset < changeBegin)
changeBegin = u.offset;
- if (changeEnd == -1 || u.offset + u.data.size() > changeEnd)
+ if (u.offset + u.data.size() > changeEnd)
changeEnd = u.offset + u.data.size();
}
+ if (changeBegin < UINT32_MAX && changeBegin < changeEnd)
+ vmaFlushAllocation(toVmaAllocator(allocator), a, changeBegin, changeEnd - changeBegin);
vmaUnmapMemory(toVmaAllocator(allocator), a);
- if (changeBegin >= 0)
- vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(changeBegin), VkDeviceSize(changeEnd - changeBegin));
bufD->pendingDynamicUpdates[slot].clear();
}
@@ -3610,7 +4119,7 @@ static void qrhivk_releaseSampler(const QRhiVulkan::DeferredReleaseEntry &e, VkD
void QRhiVulkan::executeDeferredReleases(bool forced)
{
- for (int i = releaseQueue.count() - 1; i >= 0; --i) {
+ for (int i = releaseQueue.size() - 1; i >= 0; --i) {
const QRhiVulkan::DeferredReleaseEntry &e(releaseQueue[i]);
if (forced || currentFrameSlot == e.lastActiveFrameSlot || e.lastActiveFrameSlot < 0) {
switch (e.type) {
@@ -3643,6 +4152,8 @@ void QRhiVulkan::executeDeferredReleases(bool forced)
df->vkDestroyImageView(dev, e.textureRenderTarget.rtv[att], nullptr);
df->vkDestroyImageView(dev, e.textureRenderTarget.resrtv[att], nullptr);
}
+ df->vkDestroyImageView(dev, e.textureRenderTarget.dsv, nullptr);
+ df->vkDestroyImageView(dev, e.textureRenderTarget.resdsv, nullptr);
break;
case QRhiVulkan::DeferredReleaseEntry::RenderPass:
df->vkDestroyRenderPass(dev, e.renderPass.rp, nullptr);
@@ -3665,9 +4176,8 @@ void QRhiVulkan::executeDeferredReleases(bool forced)
void QRhiVulkan::finishActiveReadbacks(bool forced)
{
QVarLengthArray<std::function<void()>, 4> completedCallbacks;
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- for (int i = activeTextureReadbacks.count() - 1; i >= 0; --i) {
+ for (int i = activeTextureReadbacks.size() - 1; i >= 0; --i) {
const QRhiVulkan::TextureReadback &readback(activeTextureReadbacks[i]);
if (forced || currentFrameSlot == readback.activeFrameSlot || readback.activeFrameSlot < 0) {
readback.result->format = readback.format;
@@ -3684,7 +4194,6 @@ void QRhiVulkan::finishActiveReadbacks(bool forced)
}
vmaDestroyBuffer(toVmaAllocator(allocator), readback.stagingBuf, a);
- QRHI_PROF_F(releaseReadbackBuffer(qint64(readback.stagingBuf)));
if (readback.result->completed)
completedCallbacks.append(readback.result->completed);
@@ -3693,7 +4202,7 @@ void QRhiVulkan::finishActiveReadbacks(bool forced)
}
}
- for (int i = activeBufferReadbacks.count() - 1; i >= 0; --i) {
+ for (int i = activeBufferReadbacks.size() - 1; i >= 0; --i) {
const QRhiVulkan::BufferReadback &readback(activeBufferReadbacks[i]);
if (forced || currentFrameSlot == readback.activeFrameSlot || readback.activeFrameSlot < 0) {
VmaAllocation a = toVmaAllocation(readback.stagingAlloc);
@@ -3701,14 +4210,13 @@ void QRhiVulkan::finishActiveReadbacks(bool forced)
VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p);
if (err == VK_SUCCESS && p) {
readback.result->data.resize(readback.byteSize);
- memcpy(readback.result->data.data(), p, size_t(readback.byteSize));
+ memcpy(readback.result->data.data(), p, readback.byteSize);
vmaUnmapMemory(toVmaAllocator(allocator), a);
} else {
qWarning("Failed to map buffer readback buffer of size %d: %d", readback.byteSize, err);
}
vmaDestroyBuffer(toVmaAllocator(allocator), readback.stagingBuf, a);
- QRHI_PROF_F(releaseReadbackBuffer(qint64(readback.stagingBuf)));
if (readback.result->completed)
completedCallbacks.append(readback.result->completed);
@@ -3755,33 +4263,26 @@ QList<int> QRhiVulkan::supportedSampleCounts() const
return result;
}
-VkSampleCountFlagBits QRhiVulkan::effectiveSampleCount(int sampleCount)
+VkSampleCountFlagBits QRhiVulkan::effectiveSampleCountBits(int sampleCount)
{
- // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
- sampleCount = qBound(1, sampleCount, 64);
-
- if (!supportedSampleCounts().contains(sampleCount)) {
- qWarning("Attempted to set unsupported sample count %d", sampleCount);
- return VK_SAMPLE_COUNT_1_BIT;
- }
+ const int s = effectiveSampleCount(sampleCount);
for (const auto &qvk_sampleCount : qvk_sampleCounts) {
- if (qvk_sampleCount.count == sampleCount)
+ if (qvk_sampleCount.count == s)
return qvk_sampleCount.mask;
}
- Q_UNREACHABLE();
- return VK_SAMPLE_COUNT_1_BIT;
+ Q_UNREACHABLE_RETURN(VK_SAMPLE_COUNT_1_BIT);
}
void QRhiVulkan::enqueueTransitionPassResources(QVkCommandBuffer *cbD)
{
cbD->passResTrackers.append(QRhiPassResourceTracker());
- cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1;
+ cbD->currentPassResTrackerIndex = cbD->passResTrackers.size() - 1;
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::TransitionPassResources;
- cmd.args.transitionResources.trackerIndex = cbD->passResTrackers.count() - 1;
+ cmd.args.transitionResources.trackerIndex = cbD->passResTrackers.size() - 1;
}
void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD)
@@ -3884,17 +4385,23 @@ void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD)
cmd.args.drawIndexed.firstInstance);
break;
case QVkCommandBuffer::Command::DebugMarkerBegin:
- cmd.args.debugMarkerBegin.marker.pMarkerName =
- cbD->pools.debugMarkerData[cmd.args.debugMarkerBegin.markerNameIndex].constData();
- vkCmdDebugMarkerBegin(cbD->cb, &cmd.args.debugMarkerBegin.marker);
+#ifdef VK_EXT_debug_utils
+ cmd.args.debugMarkerBegin.label.pLabelName =
+ cbD->pools.debugMarkerData[cmd.args.debugMarkerBegin.labelNameIndex].constData();
+ vkCmdBeginDebugUtilsLabelEXT(cbD->cb, &cmd.args.debugMarkerBegin.label);
+#endif
break;
case QVkCommandBuffer::Command::DebugMarkerEnd:
- vkCmdDebugMarkerEnd(cbD->cb);
+#ifdef VK_EXT_debug_utils
+ vkCmdEndDebugUtilsLabelEXT(cbD->cb);
+#endif
break;
case QVkCommandBuffer::Command::DebugMarkerInsert:
- cmd.args.debugMarkerInsert.marker.pMarkerName =
- cbD->pools.debugMarkerData[cmd.args.debugMarkerInsert.markerNameIndex].constData();
- vkCmdDebugMarkerInsert(cbD->cb, &cmd.args.debugMarkerInsert.marker);
+#ifdef VK_EXT_debug_utils
+ cmd.args.debugMarkerInsert.label.pLabelName =
+ cbD->pools.debugMarkerData[cmd.args.debugMarkerInsert.labelNameIndex].constData();
+ vkCmdInsertDebugUtilsLabelEXT(cbD->cb, &cmd.args.debugMarkerInsert.label);
+#endif
break;
case QVkCommandBuffer::Command::TransitionPassResources:
recordTransitionPassResources(cbD, cbD->passResTrackers[cmd.args.transitionResources.trackerIndex]);
@@ -3940,10 +4447,16 @@ static inline VkPipelineStageFlags toVkPipelineStage(QRhiPassResourceTracker::Bu
return VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
case QRhiPassResourceTracker::BufVertexStage:
return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
+ case QRhiPassResourceTracker::BufTCStage:
+ return VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT;
+ case QRhiPassResourceTracker::BufTEStage:
+ return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
case QRhiPassResourceTracker::BufFragmentStage:
return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
case QRhiPassResourceTracker::BufComputeStage:
return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ case QRhiPassResourceTracker::BufGeometryStage:
+ return VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
default:
Q_UNREACHABLE();
break;
@@ -4006,6 +4519,10 @@ static inline VkPipelineStageFlags toVkPipelineStage(QRhiPassResourceTracker::Te
switch (stage) {
case QRhiPassResourceTracker::TexVertexStage:
return VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
+ case QRhiPassResourceTracker::TexTCStage:
+ return VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT;
+ case QRhiPassResourceTracker::TexTEStage:
+ return VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT;
case QRhiPassResourceTracker::TexFragmentStage:
return VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
case QRhiPassResourceTracker::TexColorOutputStage:
@@ -4014,6 +4531,8 @@ static inline VkPipelineStageFlags toVkPipelineStage(QRhiPassResourceTracker::Te
return VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
case QRhiPassResourceTracker::TexComputeStage:
return VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+ case QRhiPassResourceTracker::TexGeometryStage:
+ return VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
default:
Q_UNREACHABLE();
break;
@@ -4083,8 +4602,7 @@ void QRhiVulkan::recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhi
if (!accessIsWrite(access))
continue;
}
- VkBufferMemoryBarrier bufMemBarrier;
- memset(&bufMemBarrier, 0, sizeof(bufMemBarrier));
+ VkBufferMemoryBarrier bufMemBarrier = {};
bufMemBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
@@ -4108,8 +4626,7 @@ void QRhiVulkan::recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhi
if (!accessIsWrite(access))
continue;
}
- VkImageMemoryBarrier barrier;
- memset(&barrier, 0, sizeof(barrier));
+ VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.subresourceRange.aspectMask = aspectMaskForTextureFormat(texD->m_format);
barrier.subresourceRange.baseMipLevel = 0;
@@ -4134,10 +4651,18 @@ void QRhiVulkan::recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhi
QRhiSwapChain *QRhiVulkan::createSwapChain()
{
+ if (!vkGetPhysicalDeviceSurfaceCapabilitiesKHR
+ || !vkGetPhysicalDeviceSurfaceFormatsKHR
+ || !vkGetPhysicalDeviceSurfacePresentModesKHR)
+ {
+ qWarning("Physical device surface queries not available");
+ return nullptr;
+ }
+
return new QVkSwapChain(this);
}
-QRhiBuffer *QRhiVulkan::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, int size)
+QRhiBuffer *QRhiVulkan::createBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
{
return new QVkBuffer(this, type, usage, size);
}
@@ -4211,7 +4736,7 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
case QRhi::MultisampleRenderBuffer:
return true;
case QRhi::DebugMarkers:
- return caps.debugMarkers;
+ return caps.debugUtils;
case QRhi::Timestamps:
return timestampValidBits != 0;
case QRhi::Instancing:
@@ -4266,9 +4791,34 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const
return true;
case QRhi::RenderTo3DTextureSlice:
return caps.texture3DSliceAs2D;
+ case QRhi::TextureArrays:
+ return true;
+ case QRhi::Tessellation:
+ return caps.tessellation;
+ case QRhi::GeometryShader:
+ return caps.geometryShader;
+ case QRhi::TextureArrayRange:
+ return true;
+ case QRhi::NonFillPolygonMode:
+ return caps.nonFillPolygonMode;
+ case QRhi::OneDimensionalTextures:
+ return true;
+ case QRhi::OneDimensionalTextureMipmaps:
+ return true;
+ case QRhi::HalfAttributes:
+ return true;
+ case QRhi::RenderToOneDimensionalTexture:
+ return true;
+ case QRhi::ThreeDimensionalTextureMipmaps:
+ return true;
+ case QRhi::MultiView:
+ return caps.multiView;
+ case QRhi::TextureViewFormat:
+ return true;
+ case QRhi::ResolveDepthStencil:
+ return caps.renderPass2KHR && caps.depthStencilResolveKHR;
default:
- Q_UNREACHABLE();
- return false;
+ Q_UNREACHABLE_RETURN(false);
}
}
@@ -4297,9 +4847,16 @@ int QRhiVulkan::resourceLimit(QRhi::ResourceLimit limit) const
return int(physDevProperties.limits.maxComputeWorkGroupSize[1]);
case QRhi::MaxThreadGroupZ:
return int(physDevProperties.limits.maxComputeWorkGroupSize[2]);
+ case QRhi::TextureArraySizeMax:
+ return int(physDevProperties.limits.maxImageArrayLayers);
+ case QRhi::MaxUniformBufferRange:
+ return int(qMin<uint32_t>(INT_MAX, physDevProperties.limits.maxUniformBufferRange));
+ case QRhi::MaxVertexInputs:
+ return physDevProperties.limits.maxVertexInputAttributes;
+ case QRhi::MaxVertexOutputs:
+ return physDevProperties.limits.maxVertexOutputComponents / 4;
default:
- Q_UNREACHABLE();
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
}
@@ -4313,16 +4870,24 @@ QRhiDriverInfo QRhiVulkan::driverInfo() const
return driverInfoStruct;
}
-void QRhiVulkan::sendVMemStatsToProfiler()
+QRhiStats QRhiVulkan::statistics()
{
- QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
- if (!rhiP)
- return;
+ QRhiStats result;
+ result.totalPipelineCreationTime = totalPipelineCreationTime();
+
+ VmaBudget budgets[VK_MAX_MEMORY_HEAPS];
+ vmaGetHeapBudgets(toVmaAllocator(allocator), budgets);
- VmaStats stats;
- vmaCalculateStats(toVmaAllocator(allocator), &stats);
- QRHI_PROF_F(vmemStat(stats.total.blockCount, stats.total.allocationCount,
- quint32(stats.total.usedBytes), quint32(stats.total.unusedBytes)));
+ uint32_t count = toVmaAllocator(allocator)->GetMemoryHeapCount();
+ for (uint32_t i = 0; i < count; ++i) {
+ const VmaStatistics &stats(budgets[i].statistics);
+ result.blockCount += stats.blockCount;
+ result.allocCount += stats.allocationCount;
+ result.usedBytes += stats.allocationBytes;
+ result.unusedBytes += stats.blockBytes - stats.allocationBytes;
+ }
+
+ return result;
}
bool QRhiVulkan::makeThreadLocalNativeContextCurrent()
@@ -4364,7 +4929,7 @@ QByteArray QRhiVulkan::pipelineCacheData()
size_t dataSize = 0;
VkResult err = df->vkGetPipelineCacheData(dev, pipelineCache, &dataSize, nullptr);
if (err != VK_SUCCESS) {
- qWarning("Failed to get pipeline cache data size: %d", err);
+ qCDebug(QRHI_LOG_INFO, "Failed to get pipeline cache data size: %d", err);
return QByteArray();
}
const size_t headerSize = sizeof(QVkPipelineCacheDataHeader);
@@ -4372,7 +4937,7 @@ QByteArray QRhiVulkan::pipelineCacheData()
data.resize(dataOffset + dataSize);
err = df->vkGetPipelineCacheData(dev, pipelineCache, &dataSize, data.data() + dataOffset);
if (err != VK_SUCCESS) {
- qWarning("Failed to get pipeline cache data of %d bytes: %d", int(dataSize), err);
+ qCDebug(QRHI_LOG_INFO, "Failed to get pipeline cache data of %d bytes: %d", int(dataSize), err);
return QByteArray();
}
@@ -4384,6 +4949,7 @@ QByteArray QRhiVulkan::pipelineCacheData()
header.deviceId = physDevProperties.deviceID;
header.dataSize = quint32(dataSize);
header.uuidSize = VK_UUID_SIZE;
+ header.reserved = 0;
memcpy(data.data(), &header, headerSize);
memcpy(data.data() + headerSize, physDevProperties.pipelineCacheUUID, VK_UUID_SIZE);
@@ -4397,7 +4963,7 @@ void QRhiVulkan::setPipelineCacheData(const QByteArray &data)
const size_t headerSize = sizeof(QVkPipelineCacheDataHeader);
if (data.size() < qsizetype(headerSize)) {
- qWarning("setPipelineCacheData: Invalid blob size");
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Invalid blob size");
return;
}
QVkPipelineCacheDataHeader header;
@@ -4405,49 +4971,49 @@ void QRhiVulkan::setPipelineCacheData(const QByteArray &data)
const quint32 rhiId = pipelineCacheRhiId();
if (header.rhiId != rhiId) {
- qWarning("setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
- rhiId, header.rhiId);
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: The data is for a different QRhi version or backend (%u, %u)",
+ rhiId, header.rhiId);
return;
}
const quint32 arch = quint32(sizeof(void*));
if (header.arch != arch) {
- qWarning("setPipelineCacheData: Architecture does not match (%u, %u)",
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Architecture does not match (%u, %u)",
arch, header.arch);
return;
}
if (header.driverVersion != physDevProperties.driverVersion) {
- qWarning("setPipelineCacheData: driverVersion does not match (%u, %u)",
- physDevProperties.driverVersion, header.driverVersion);
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: driverVersion does not match (%u, %u)",
+ physDevProperties.driverVersion, header.driverVersion);
return;
}
if (header.vendorId != physDevProperties.vendorID) {
- qWarning("setPipelineCacheData: vendorID does not match (%u, %u)",
- physDevProperties.vendorID, header.vendorId);
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: vendorID does not match (%u, %u)",
+ physDevProperties.vendorID, header.vendorId);
return;
}
if (header.deviceId != physDevProperties.deviceID) {
- qWarning("setPipelineCacheData: deviceID does not match (%u, %u)",
- physDevProperties.deviceID, header.deviceId);
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: deviceID does not match (%u, %u)",
+ physDevProperties.deviceID, header.deviceId);
return;
}
if (header.uuidSize != VK_UUID_SIZE) {
- qWarning("setPipelineCacheData: VK_UUID_SIZE does not match (%u, %u)",
- quint32(VK_UUID_SIZE), header.uuidSize);
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: VK_UUID_SIZE does not match (%u, %u)",
+ quint32(VK_UUID_SIZE), header.uuidSize);
return;
}
if (data.size() < qsizetype(headerSize + VK_UUID_SIZE)) {
- qWarning("setPipelineCacheData: Invalid blob, no uuid");
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Invalid blob, no uuid");
return;
}
if (memcmp(data.constData() + headerSize, physDevProperties.pipelineCacheUUID, VK_UUID_SIZE)) {
- qWarning("setPipelineCacheData: pipelineCacheUUID does not match");
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: pipelineCacheUUID does not match");
return;
}
const size_t dataOffset = headerSize + VK_UUID_SIZE;
if (data.size() < qsizetype(dataOffset + header.dataSize)) {
- qWarning("setPipelineCacheData: Invalid blob, data missing");
+ qCDebug(QRHI_LOG_INFO, "setPipelineCacheData: Invalid blob, data missing");
return;
}
@@ -4460,7 +5026,7 @@ void QRhiVulkan::setPipelineCacheData(const QByteArray &data)
qCDebug(QRHI_LOG_INFO, "Created pipeline cache with initial data of %d bytes",
int(header.dataSize));
} else {
- qWarning("Failed to create pipeline cache with initial data specified");
+ qCDebug(QRHI_LOG_INFO, "Failed to create pipeline cache with initial data specified");
}
}
@@ -4472,10 +5038,10 @@ QRhiRenderBuffer *QRhiVulkan::createRenderBuffer(QRhiRenderBuffer::Type type, co
}
QRhiTexture *QRhiVulkan::createTexture(QRhiTexture::Format format,
- const QSize &pixelSize, int depth,
+ const QSize &pixelSize, int depth, int arraySize,
int sampleCount, QRhiTexture::Flags flags)
{
- return new QVkTexture(this, format, pixelSize, depth, sampleCount, flags);
+ return new QVkTexture(this, format, pixelSize, depth, arraySize, sampleCount, flags);
}
QRhiSampler *QRhiVulkan::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
@@ -4555,8 +5121,8 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
// Do host writes and mark referenced shader resources as in-use.
// Also prepare to ensure the descriptor set we are going to bind refers to up-to-date Vk objects.
- for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
- const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings[i].data();
+ for (int i = 0, ie = srbD->sortedBindings.size(); i != ie; ++i) {
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(srbD->sortedBindings[i]);
QVkShaderResourceBindings::BoundResourceData &bd(descSetBd[i]);
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
@@ -4584,8 +5150,10 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
}
break;
case QRhiShaderResourceBinding::SampledTexture:
+ case QRhiShaderResourceBinding::Texture:
+ case QRhiShaderResourceBinding::Sampler:
{
- const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
+ const QRhiShaderResourceBinding::Data::TextureAndOrSamplerData *data = &b->u.stex;
if (bd.stex.count != data->count) {
bd.stex.count = data->count;
rewriteDescSet = true;
@@ -4593,21 +5161,32 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
for (int elem = 0; elem < data->count; ++elem) {
QVkTexture *texD = QRHI_RES(QVkTexture, data->texSamplers[elem].tex);
QVkSampler *samplerD = QRHI_RES(QVkSampler, data->texSamplers[elem].sampler);
- texD->lastActiveFrameSlot = currentFrameSlot;
- samplerD->lastActiveFrameSlot = currentFrameSlot;
- trackedRegisterTexture(&passResTracker, texD,
- QRhiPassResourceTracker::TexSample,
- QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage));
- if (texD->generation != bd.stex.d[elem].texGeneration
- || texD->m_id != bd.stex.d[elem].texId
- || samplerD->generation != bd.stex.d[elem].samplerGeneration
- || samplerD->m_id != bd.stex.d[elem].samplerId)
+ // We use the same code path for both combined and separate
+ // images and samplers, so tex or sampler (but not both) can be
+ // null here.
+ Q_ASSERT(texD || samplerD);
+ if (texD) {
+ texD->lastActiveFrameSlot = currentFrameSlot;
+ trackedRegisterTexture(&passResTracker, texD,
+ QRhiPassResourceTracker::TexSample,
+ QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage));
+ }
+ if (samplerD)
+ samplerD->lastActiveFrameSlot = currentFrameSlot;
+ const quint64 texId = texD ? texD->m_id : 0;
+ const uint texGen = texD ? texD->generation : 0;
+ const quint64 samplerId = samplerD ? samplerD->m_id : 0;
+ const uint samplerGen = samplerD ? samplerD->generation : 0;
+ if (texGen != bd.stex.d[elem].texGeneration
+ || texId != bd.stex.d[elem].texId
+ || samplerGen != bd.stex.d[elem].samplerGeneration
+ || samplerId != bd.stex.d[elem].samplerId)
{
rewriteDescSet = true;
- bd.stex.d[elem].texId = texD->m_id;
- bd.stex.d[elem].texGeneration = texD->generation;
- bd.stex.d[elem].samplerId = samplerD->m_id;
- bd.stex.d[elem].samplerGeneration = samplerD->generation;
+ bd.stex.d[elem].texId = texId;
+ bd.stex.d[elem].texGeneration = texGen;
+ bd.stex.d[elem].samplerId = samplerId;
+ bd.stex.d[elem].samplerGeneration = samplerGen;
}
}
}
@@ -4689,8 +5268,8 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
// because dynOfs has to be ordered based on the binding numbers,
// and neither srb nor dynamicOffsets has any such ordering
// requirement.
- for (const QRhiShaderResourceBinding &binding : qAsConst(srbD->sortedBindings)) {
- const QRhiShaderResourceBinding::Data *b = binding.data();
+ for (const QRhiShaderResourceBinding &binding : std::as_const(srbD->sortedBindings)) {
+ const QRhiShaderResourceBinding::Data *b = shaderResourceBindingData(binding);
if (b->type == QRhiShaderResourceBinding::UniformBuffer && b->u.ubuf.hasDynamicOffset) {
uint32_t offset = 0;
for (int i = 0; i < dynamicOffsetCount; ++i) {
@@ -4710,8 +5289,8 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
gfxPsD ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE,
gfxPsD ? gfxPsD->layout : compPsD->layout,
0, 1, &srbD->descSets[descSetIdx],
- uint32_t(dynOfs.count()),
- dynOfs.count() ? dynOfs.constData() : nullptr);
+ uint32_t(dynOfs.size()),
+ dynOfs.size() ? dynOfs.constData() : nullptr);
} else {
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::BindDescriptorSet;
@@ -4719,9 +5298,9 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
: VK_PIPELINE_BIND_POINT_COMPUTE;
cmd.args.bindDescriptorSet.pipelineLayout = gfxPsD ? gfxPsD->layout : compPsD->layout;
cmd.args.bindDescriptorSet.descSet = srbD->descSets[descSetIdx];
- cmd.args.bindDescriptorSet.dynamicOffsetCount = dynOfs.count();
- cmd.args.bindDescriptorSet.dynamicOffsetIndex = cbD->pools.dynamicOffset.count();
- cbD->pools.dynamicOffset.append(dynOfs.constData(), dynOfs.count());
+ cmd.args.bindDescriptorSet.dynamicOffsetCount = dynOfs.size();
+ cmd.args.bindDescriptorSet.dynamicOffsetIndex = cbD->pools.dynamicOffset.size();
+ cbD->pools.dynamicOffset.append(dynOfs.constData(), dynOfs.size());
}
if (gfxPsD) {
@@ -4780,16 +5359,16 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
if (cbD->passUsesSecondaryCb) {
df->vkCmdBindVertexBuffers(cbD->activeSecondaryCbStack.last(), uint32_t(startBinding),
- uint32_t(bufs.count()), bufs.constData(), ofs.constData());
+ uint32_t(bufs.size()), bufs.constData(), ofs.constData());
} else {
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::BindVertexBuffer;
cmd.args.bindVertexBuffer.startBinding = startBinding;
- cmd.args.bindVertexBuffer.count = bufs.count();
- cmd.args.bindVertexBuffer.vertexBufferIndex = cbD->pools.vertexBuffer.count();
- cbD->pools.vertexBuffer.append(bufs.constData(), bufs.count());
- cmd.args.bindVertexBuffer.vertexBufferOffsetIndex = cbD->pools.vertexBufferOffset.count();
- cbD->pools.vertexBufferOffset.append(ofs.constData(), ofs.count());
+ cmd.args.bindVertexBuffer.count = bufs.size();
+ cmd.args.bindVertexBuffer.vertexBufferIndex = cbD->pools.vertexBuffer.size();
+ cbD->pools.vertexBuffer.append(bufs.constData(), bufs.size());
+ cmd.args.bindVertexBuffer.vertexBufferOffsetIndex = cbD->pools.vertexBufferOffset.size();
+ cbD->pools.vertexBufferOffset.append(ofs.constData(), ofs.size());
}
}
@@ -4838,7 +5417,7 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport
// x,y is top-left in VkViewport but bottom-left in QRhiViewport
float x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, viewport.viewport(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<UnBounded>(outputSize, viewport.viewport(), &x, &y, &w, &h))
return;
QVkCommandBuffer::Command &cmd(cbD->commands.get());
@@ -4857,9 +5436,12 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport
cmd.cmd = QVkCommandBuffer::Command::SetViewport;
}
- if (!QRHI_RES(QVkGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
+ if (cbD->currentGraphicsPipeline
+ && !QRHI_RES(QVkGraphicsPipeline, cbD->currentGraphicsPipeline)
+ ->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
QVkCommandBuffer::Command &cmd(cbD->commands.get());
VkRect2D *s = &cmd.args.setScissor.scissor;
+ qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, viewport.viewport(), &x, &y, &w, &h);
s->offset.x = int32_t(x);
s->offset.y = int32_t(y);
s->extent.width = uint32_t(w);
@@ -4882,7 +5464,7 @@ void QRhiVulkan::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
// x,y is top-left in VkRect2D but bottom-left in QRhiScissor
int x, y, w, h;
- if (!qrhi_toTopLeftRenderTargetRect(outputSize, scissor.scissor(), &x, &y, &w, &h))
+ if (!qrhi_toTopLeftRenderTargetRect<Bounded>(outputSize, scissor.scissor(), &x, &y, &w, &h))
return;
QVkCommandBuffer::Command &cmd(cbD->commands.get());
@@ -4972,60 +5554,72 @@ void QRhiVulkan::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
{
- if (!debugMarkers || !caps.debugMarkers)
+#ifdef VK_EXT_debug_utils
+ if (!debugMarkers || !caps.debugUtils)
return;
- VkDebugMarkerMarkerInfoEXT marker;
- memset(&marker, 0, sizeof(marker));
- marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
+ VkDebugUtilsLabelEXT label = {};
+ label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) {
- marker.pMarkerName = name.constData();
- vkCmdDebugMarkerBegin(cbD->activeSecondaryCbStack.last(), &marker);
+ label.pLabelName = name.constData();
+ vkCmdBeginDebugUtilsLabelEXT(cbD->activeSecondaryCbStack.last(), &label);
} else {
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerBegin;
- cmd.args.debugMarkerBegin.marker = marker;
- cmd.args.debugMarkerBegin.markerNameIndex = cbD->pools.debugMarkerData.count();
+ cmd.args.debugMarkerBegin.label = label;
+ cmd.args.debugMarkerBegin.labelNameIndex = cbD->pools.debugMarkerData.size();
cbD->pools.debugMarkerData.append(name);
}
+#else
+ Q_UNUSED(cb);
+ Q_UNUSED(name);
+#endif
}
void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb)
{
- if (!debugMarkers || !caps.debugMarkers)
+#ifdef VK_EXT_debug_utils
+ if (!debugMarkers || !caps.debugUtils)
return;
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) {
- vkCmdDebugMarkerEnd(cbD->activeSecondaryCbStack.last());
+ vkCmdEndDebugUtilsLabelEXT(cbD->activeSecondaryCbStack.last());
} else {
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerEnd;
}
+#else
+ Q_UNUSED(cb);
+#endif
}
void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
{
- if (!debugMarkers || !caps.debugMarkers)
+#ifdef VK_EXT_debug_utils
+ if (!debugMarkers || !caps.debugUtils)
return;
- VkDebugMarkerMarkerInfoEXT marker;
- memset(&marker, 0, sizeof(marker));
- marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
+ VkDebugUtilsLabelEXT label = {};
+ label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->passUsesSecondaryCb) {
- marker.pMarkerName = msg.constData();
- vkCmdDebugMarkerInsert(cbD->activeSecondaryCbStack.last(), &marker);
+ label.pLabelName = msg.constData();
+ vkCmdInsertDebugUtilsLabelEXT(cbD->activeSecondaryCbStack.last(), &label);
} else {
QVkCommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerInsert;
- cmd.args.debugMarkerInsert.marker = marker;
- cmd.args.debugMarkerInsert.markerNameIndex = cbD->pools.debugMarkerData.count();
+ cmd.args.debugMarkerInsert.label = label;
+ cmd.args.debugMarkerInsert.labelNameIndex = cbD->pools.debugMarkerData.size();
cbD->pools.debugMarkerData.append(msg);
}
+#else
+ Q_UNUSED(cb);
+ Q_UNUSED(msg);
+#endif
}
const QRhiNativeHandles *QRhiVulkan::nativeHandles(QRhiCommandBuffer *cb)
@@ -5039,8 +5633,8 @@ static inline QVkRenderTargetData *maybeRenderTargetData(QVkCommandBuffer *cbD)
QVkRenderTargetData *rtD = nullptr;
if (cbD->recordingPass == QVkCommandBuffer::RenderPass) {
switch (cbD->currentTarget->resourceType()) {
- case QRhiResource::RenderTarget:
- rtD = &QRHI_RES(QVkReferenceRenderTarget, cbD->currentTarget)->d;
+ case QRhiResource::SwapChainRenderTarget:
+ rtD = &QRHI_RES(QVkSwapChainRenderTarget, cbD->currentTarget)->d;
break;
case QRhiResource::TextureRenderTarget:
rtD = &QRHI_RES(QVkTextureRenderTarget, cbD->currentTarget)->d;
@@ -5106,23 +5700,35 @@ void QRhiVulkan::endExternal(QRhiCommandBuffer *cb)
cbD->resetCachedState();
}
-void QRhiVulkan::setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot)
+double QRhiVulkan::lastCompletedGpuTime(QRhiCommandBuffer *cb)
+{
+ QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
+ return cbD->lastGpuTime;
+}
+
+void QRhiVulkan::setObjectName(uint64_t object, VkObjectType type, const QByteArray &name, int slot)
{
- if (!debugMarkers || !caps.debugMarkers || name.isEmpty())
+#ifdef VK_EXT_debug_utils
+ if (!debugMarkers || !caps.debugUtils || name.isEmpty())
return;
- VkDebugMarkerObjectNameInfoEXT nameInfo;
- memset(&nameInfo, 0, sizeof(nameInfo));
- nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
+ VkDebugUtilsObjectNameInfoEXT nameInfo = {};
+ nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
nameInfo.objectType = type;
- nameInfo.object = object;
+ nameInfo.objectHandle = object;
QByteArray decoratedName = name;
if (slot >= 0) {
decoratedName += '/';
decoratedName += QByteArray::number(slot);
}
nameInfo.pObjectName = decoratedName.constData();
- vkDebugMarkerSetObjectName(dev, &nameInfo);
+ vkSetDebugUtilsObjectNameEXT(dev, &nameInfo);
+#else
+ Q_UNUSED(object);
+ Q_UNUSED(type);
+ Q_UNUSED(name);
+ Q_UNUSED(slot);
+#endif
}
static inline VkBufferUsageFlagBits toVkBufferUsage(QRhiBuffer::UsageFlags usage)
@@ -5147,8 +5753,7 @@ static inline VkFilter toVkFilter(QRhiSampler::Filter f)
case QRhiSampler::Linear:
return VK_FILTER_LINEAR;
default:
- Q_UNREACHABLE();
- return VK_FILTER_NEAREST;
+ Q_UNREACHABLE_RETURN(VK_FILTER_NEAREST);
}
}
@@ -5162,8 +5767,7 @@ static inline VkSamplerMipmapMode toVkMipmapMode(QRhiSampler::Filter f)
case QRhiSampler::Linear:
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
default:
- Q_UNREACHABLE();
- return VK_SAMPLER_MIPMAP_MODE_NEAREST;
+ Q_UNREACHABLE_RETURN(VK_SAMPLER_MIPMAP_MODE_NEAREST);
}
}
@@ -5177,8 +5781,7 @@ static inline VkSamplerAddressMode toVkAddressMode(QRhiSampler::AddressMode m)
case QRhiSampler::Mirror:
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
default:
- Q_UNREACHABLE();
- return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ Q_UNREACHABLE_RETURN(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
}
}
@@ -5187,13 +5790,18 @@ static inline VkShaderStageFlagBits toVkShaderStage(QRhiShaderStage::Type type)
switch (type) {
case QRhiShaderStage::Vertex:
return VK_SHADER_STAGE_VERTEX_BIT;
+ case QRhiShaderStage::TessellationControl:
+ return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
+ case QRhiShaderStage::TessellationEvaluation:
+ return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
case QRhiShaderStage::Fragment:
return VK_SHADER_STAGE_FRAGMENT_BIT;
case QRhiShaderStage::Compute:
return VK_SHADER_STAGE_COMPUTE_BIT;
+ case QRhiShaderStage::Geometry:
+ return VK_SHADER_STAGE_GEOMETRY_BIT;
default:
- Q_UNREACHABLE();
- return VK_SHADER_STAGE_VERTEX_BIT;
+ Q_UNREACHABLE_RETURN(VK_SHADER_STAGE_VERTEX_BIT);
}
}
@@ -5230,9 +5838,32 @@ static inline VkFormat toVkAttributeFormat(QRhiVertexInputAttribute::Format form
return VK_FORMAT_R32G32_SINT;
case QRhiVertexInputAttribute::SInt:
return VK_FORMAT_R32_SINT;
+ case QRhiVertexInputAttribute::Half4:
+ return VK_FORMAT_R16G16B16A16_SFLOAT;
+ case QRhiVertexInputAttribute::Half3:
+ return VK_FORMAT_R16G16B16_SFLOAT;
+ case QRhiVertexInputAttribute::Half2:
+ return VK_FORMAT_R16G16_SFLOAT;
+ case QRhiVertexInputAttribute::Half:
+ return VK_FORMAT_R16_SFLOAT;
+ case QRhiVertexInputAttribute::UShort4:
+ return VK_FORMAT_R16G16B16A16_UINT;
+ case QRhiVertexInputAttribute::UShort3:
+ return VK_FORMAT_R16G16B16_UINT;
+ case QRhiVertexInputAttribute::UShort2:
+ return VK_FORMAT_R16G16_UINT;
+ case QRhiVertexInputAttribute::UShort:
+ return VK_FORMAT_R16_UINT;
+ case QRhiVertexInputAttribute::SShort4:
+ return VK_FORMAT_R16G16B16A16_SINT;
+ case QRhiVertexInputAttribute::SShort3:
+ return VK_FORMAT_R16G16B16_SINT;
+ case QRhiVertexInputAttribute::SShort2:
+ return VK_FORMAT_R16G16_SINT;
+ case QRhiVertexInputAttribute::SShort:
+ return VK_FORMAT_R16_SINT;
default:
- Q_UNREACHABLE();
- return VK_FORMAT_R32G32B32A32_SFLOAT;
+ Q_UNREACHABLE_RETURN(VK_FORMAT_R32G32B32A32_SFLOAT);
}
}
@@ -5251,9 +5882,10 @@ static inline VkPrimitiveTopology toVkTopology(QRhiGraphicsPipeline::Topology t)
return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
case QRhiGraphicsPipeline::Points:
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
+ case QRhiGraphicsPipeline::Patches:
+ return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
default:
- Q_UNREACHABLE();
- return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ Q_UNREACHABLE_RETURN(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
}
}
@@ -5267,8 +5899,7 @@ static inline VkCullModeFlags toVkCullMode(QRhiGraphicsPipeline::CullMode c)
case QRhiGraphicsPipeline::Back:
return VK_CULL_MODE_BACK_BIT;
default:
- Q_UNREACHABLE();
- return VK_CULL_MODE_NONE;
+ Q_UNREACHABLE_RETURN(VK_CULL_MODE_NONE);
}
}
@@ -5280,8 +5911,7 @@ static inline VkFrontFace toVkFrontFace(QRhiGraphicsPipeline::FrontFace f)
case QRhiGraphicsPipeline::CW:
return VK_FRONT_FACE_CLOCKWISE;
default:
- Q_UNREACHABLE();
- return VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ Q_UNREACHABLE_RETURN(VK_FRONT_FACE_COUNTER_CLOCKWISE);
}
}
@@ -5341,8 +5971,7 @@ static inline VkBlendFactor toVkBlendFactor(QRhiGraphicsPipeline::BlendFactor f)
case QRhiGraphicsPipeline::OneMinusSrc1Alpha:
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
default:
- Q_UNREACHABLE();
- return VK_BLEND_FACTOR_ZERO;
+ Q_UNREACHABLE_RETURN(VK_BLEND_FACTOR_ZERO);
}
}
@@ -5360,8 +5989,7 @@ static inline VkBlendOp toVkBlendOp(QRhiGraphicsPipeline::BlendOp op)
case QRhiGraphicsPipeline::Max:
return VK_BLEND_OP_MAX;
default:
- Q_UNREACHABLE();
- return VK_BLEND_OP_ADD;
+ Q_UNREACHABLE_RETURN(VK_BLEND_OP_ADD);
}
}
@@ -5385,8 +6013,7 @@ static inline VkCompareOp toVkCompareOp(QRhiGraphicsPipeline::CompareOp op)
case QRhiGraphicsPipeline::Always:
return VK_COMPARE_OP_ALWAYS;
default:
- Q_UNREACHABLE();
- return VK_COMPARE_OP_ALWAYS;
+ Q_UNREACHABLE_RETURN(VK_COMPARE_OP_ALWAYS);
}
}
@@ -5410,8 +6037,19 @@ static inline VkStencilOp toVkStencilOp(QRhiGraphicsPipeline::StencilOp op)
case QRhiGraphicsPipeline::DecrementAndWrap:
return VK_STENCIL_OP_DECREMENT_AND_WRAP;
default:
- Q_UNREACHABLE();
- return VK_STENCIL_OP_KEEP;
+ Q_UNREACHABLE_RETURN(VK_STENCIL_OP_KEEP);
+ }
+}
+
+static inline VkPolygonMode toVkPolygonMode(QRhiGraphicsPipeline::PolygonMode mode)
+{
+ switch (mode) {
+ case QRhiGraphicsPipeline::Fill:
+ return VK_POLYGON_MODE_FILL;
+ case QRhiGraphicsPipeline::Line:
+ return VK_POLYGON_MODE_LINE;
+ default:
+ Q_UNREACHABLE_RETURN(VK_POLYGON_MODE_FILL);
}
}
@@ -5433,6 +6071,12 @@ static inline VkDescriptorType toVkDescriptorType(const QRhiShaderResourceBindin
case QRhiShaderResourceBinding::SampledTexture:
return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ case QRhiShaderResourceBinding::Texture:
+ return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+
+ case QRhiShaderResourceBinding::Sampler:
+ return VK_DESCRIPTOR_TYPE_SAMPLER;
+
case QRhiShaderResourceBinding::ImageLoad:
case QRhiShaderResourceBinding::ImageStore:
case QRhiShaderResourceBinding::ImageLoadStore:
@@ -5444,8 +6088,7 @@ static inline VkDescriptorType toVkDescriptorType(const QRhiShaderResourceBindin
return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
default:
- Q_UNREACHABLE();
- return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ Q_UNREACHABLE_RETURN(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
}
}
@@ -5458,6 +6101,12 @@ static inline VkShaderStageFlags toVkShaderStageFlags(QRhiShaderResourceBinding:
s |= VK_SHADER_STAGE_FRAGMENT_BIT;
if (stage.testFlag(QRhiShaderResourceBinding::ComputeStage))
s |= VK_SHADER_STAGE_COMPUTE_BIT;
+ if (stage.testFlag(QRhiShaderResourceBinding::TessellationControlStage))
+ s |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
+ if (stage.testFlag(QRhiShaderResourceBinding::TessellationEvaluationStage))
+ s |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
+ if (stage.testFlag(QRhiShaderResourceBinding::GeometryStage))
+ s |= VK_SHADER_STAGE_GEOMETRY_BIT;
return VkShaderStageFlags(s);
}
@@ -5481,12 +6130,11 @@ static inline VkCompareOp toVkTextureCompareOp(QRhiSampler::CompareOp op)
case QRhiSampler::Always:
return VK_COMPARE_OP_ALWAYS;
default:
- Q_UNREACHABLE();
- return VK_COMPARE_OP_NEVER;
+ Q_UNREACHABLE_RETURN(VK_COMPARE_OP_NEVER);
}
}
-QVkBuffer::QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size)
+QVkBuffer::QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size)
: QRhiBuffer(rhi, type, usage, size)
{
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
@@ -5523,12 +6171,13 @@ void QVkBuffer::destroy()
}
QRHI_RES_RHI(QRhiVulkan);
- rhiD->releaseQueue.append(e);
-
- QRHI_PROF;
- QRHI_PROF_F(releaseBuffer(this));
-
- rhiD->unregisterResource(this);
+ // destroy() implementations, unlike other functions, are expected to test
+ // for m_rhi being null, to allow surviving in case one attempts to destroy
+ // a (leaked) resource after the QRhi.
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QVkBuffer::create()
@@ -5541,16 +6190,14 @@ bool QVkBuffer::create()
return false;
}
- const int nonZeroSize = m_size <= 0 ? 256 : m_size;
+ const quint32 nonZeroSize = m_size <= 0 ? 256 : m_size;
- VkBufferCreateInfo bufferInfo;
- memset(&bufferInfo, 0, sizeof(bufferInfo));
+ VkBufferCreateInfo bufferInfo = {};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- bufferInfo.size = uint32_t(nonZeroSize);
+ bufferInfo.size = nonZeroSize;
bufferInfo.usage = toVkBufferUsage(m_usage);
- VmaAllocationCreateInfo allocInfo;
- memset(&allocInfo, 0, sizeof(allocInfo));
+ VmaAllocationCreateInfo allocInfo = {};
if (m_type == Dynamic) {
#ifndef Q_OS_DARWIN // not for MoltenVK
@@ -5578,19 +6225,17 @@ bool QVkBuffer::create()
if (err != VK_SUCCESS)
break;
allocations[i] = allocation;
- rhiD->setObjectName(uint64_t(buffers[i]), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, m_objectName,
+ rhiD->setObjectName(uint64_t(buffers[i]), VK_OBJECT_TYPE_BUFFER, m_objectName,
m_type == Dynamic ? i : -1);
}
}
if (err != VK_SUCCESS) {
- qWarning("Failed to create buffer: %d", err);
+ qWarning("Failed to create buffer of size %u: %d", nonZeroSize, err);
+ rhiD->printExtraErrorInfo(err);
return false;
}
- QRHI_PROF;
- QRHI_PROF_F(newBuffer(this, uint(nonZeroSize), m_type != Dynamic ? 1 : QVK_FRAMES_IN_FLIGHT, 0));
-
lastActiveFrameSlot = -1;
generation += 1;
rhiD->registerResource(this);
@@ -5639,8 +6284,8 @@ void QVkBuffer::endFullDynamicBufferUpdateForCurrentFrame()
QRHI_RES_RHI(QRhiVulkan);
const int slot = rhiD->currentFrameSlot;
VmaAllocation a = toVmaAllocation(allocations[slot]);
- vmaUnmapMemory(toVmaAllocator(rhiD->allocator), a);
vmaFlushAllocation(toVmaAllocator(rhiD->allocator), a, 0, m_size);
+ vmaUnmapMemory(toVmaAllocator(rhiD->allocator), a);
}
QVkRenderBuffer::QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
@@ -5680,12 +6325,10 @@ void QVkRenderBuffer::destroy()
}
QRHI_RES_RHI(QRhiVulkan);
- rhiD->releaseQueue.append(e);
-
- QRHI_PROF;
- QRHI_PROF_F(releaseRenderBuffer(this));
-
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QVkRenderBuffer::create()
@@ -5697,8 +6340,7 @@ bool QVkRenderBuffer::create()
return false;
QRHI_RES_RHI(QRhiVulkan);
- QRHI_PROF;
- samples = rhiD->effectiveSampleCount(m_sampleCount);
+ samples = rhiD->effectiveSampleCountBits(m_sampleCount);
switch (m_type) {
case QRhiRenderBuffer::Color:
@@ -5707,6 +6349,7 @@ bool QVkRenderBuffer::create()
backingTexture = QRHI_RES(QVkTexture, rhiD->createTexture(backingFormat(),
m_pixelSize,
1,
+ 0,
m_sampleCount,
QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
} else {
@@ -5717,7 +6360,6 @@ bool QVkRenderBuffer::create()
if (!backingTexture->create())
return false;
vkformat = backingTexture->vkformat;
- QRHI_PROF_F(newRenderBuffer(this, false, false, samples));
}
break;
case QRhiRenderBuffer::DepthStencil:
@@ -5734,8 +6376,7 @@ bool QVkRenderBuffer::create()
{
return false;
}
- rhiD->setObjectName(uint64_t(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, m_objectName);
- QRHI_PROF_F(newRenderBuffer(this, true, false, samples));
+ rhiD->setObjectName(uint64_t(image), VK_OBJECT_TYPE_IMAGE, m_objectName);
break;
default:
Q_UNREACHABLE();
@@ -5743,6 +6384,7 @@ bool QVkRenderBuffer::create()
}
lastActiveFrameSlot = -1;
+ generation += 1;
rhiD->registerResource(this);
return true;
}
@@ -5756,8 +6398,8 @@ QRhiTexture::Format QVkRenderBuffer::backingFormat() const
}
QVkTexture::QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags)
- : QRhiTexture(rhi, format, pixelSize, depth, sampleCount, flags)
+ int arraySize, int sampleCount, Flags flags)
+ : QRhiTexture(rhi, format, pixelSize, depth, arraySize, sampleCount, flags)
{
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
stagingBuffers[i] = VK_NULL_HANDLE;
@@ -5803,12 +6445,10 @@ void QVkTexture::destroy()
imageAlloc = nullptr;
QRHI_RES_RHI(QRhiVulkan);
- rhiD->releaseQueue.append(e);
-
- QRHI_PROF;
- QRHI_PROF_F(releaseTexture(this));
-
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QVkTexture::prepareCreate(QSize *adjustedSize)
@@ -5818,6 +6458,15 @@ bool QVkTexture::prepareCreate(QSize *adjustedSize)
QRHI_RES_RHI(QRhiVulkan);
vkformat = toVkTextureFormat(m_format, m_flags);
+ if (m_writeViewFormat.format != UnknownFormat)
+ viewFormat = toVkTextureFormat(m_writeViewFormat.format, m_writeViewFormat.srgb ? sRGB : Flags());
+ else
+ viewFormat = vkformat;
+ if (m_readViewFormat.format != UnknownFormat)
+ viewFormatForSampling = toVkTextureFormat(m_readViewFormat.format, m_readViewFormat.srgb ? sRGB : Flags());
+ else
+ viewFormatForSampling = vkformat;
+
VkFormatProperties props;
rhiD->f->vkGetPhysicalDeviceFormatProperties(rhiD->physDev, vkformat, &props);
const bool canSampleOptimal = (props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
@@ -5826,18 +6475,22 @@ bool QVkTexture::prepareCreate(QSize *adjustedSize)
return false;
}
- const QSize size = m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize;
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool isArray = m_flags.testFlag(TextureArray);
const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool is1D = m_flags.testFlag(OneDimensional);
const bool hasMipMaps = m_flags.testFlag(MipMapped);
+ const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
+ : (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
+
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
const int maxLevels = QRhi::MAX_MIP_LEVELS;
if (mipLevelCount > maxLevels) {
qWarning("Too many mip levels (%d, max is %d), truncating mip chain", mipLevelCount, maxLevels);
mipLevelCount = maxLevels;
}
- samples = rhiD->effectiveSampleCount(m_sampleCount);
+ samples = rhiD->effectiveSampleCountBits(m_sampleCount);
if (samples > VK_SAMPLE_COUNT_1_BIT) {
if (isCube) {
qWarning("Cubemap texture cannot be multisample");
@@ -5856,11 +6509,30 @@ bool QVkTexture::prepareCreate(QSize *adjustedSize)
qWarning("Texture cannot be both cube and 3D");
return false;
}
- m_depth = qMax(1, m_depth);
+ if (isArray && is3D) {
+ qWarning("Texture cannot be both array and 3D");
+ return false;
+ }
+ if (isCube && is1D) {
+ qWarning("Texture cannot be both cube and 1D");
+ return false;
+ }
+ if (is1D && is3D) {
+ qWarning("Texture cannot be both 1D and 3D");
+ return false;
+ }
if (m_depth > 1 && !is3D) {
qWarning("Texture cannot have a depth of %d when it is not 3D", m_depth);
return false;
}
+ if (m_arraySize > 0 && !isArray) {
+ qWarning("Texture cannot have an array size of %d when it is not an array", m_arraySize);
+ return false;
+ }
+ if (m_arraySize < 1 && isArray) {
+ qWarning("Texture is an array but array size is %d", m_arraySize);
+ return false;
+ }
usageState.layout = VK_IMAGE_LAYOUT_PREINITIALIZED;
usageState.access = 0;
@@ -5878,21 +6550,31 @@ bool QVkTexture::finishCreate()
const auto aspectMask = aspectMaskForTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool isArray = m_flags.testFlag(TextureArray);
const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool is1D = m_flags.testFlag(OneDimensional);
- VkImageViewCreateInfo viewInfo;
- memset(&viewInfo, 0, sizeof(viewInfo));
+ VkImageViewCreateInfo viewInfo = {};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
- viewInfo.viewType = isCube ? VK_IMAGE_VIEW_TYPE_CUBE : (is3D ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D);
- viewInfo.format = vkformat;
+ viewInfo.viewType = isCube
+ ? VK_IMAGE_VIEW_TYPE_CUBE
+ : (is3D ? VK_IMAGE_VIEW_TYPE_3D
+ : (is1D ? (isArray ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D)
+ : (isArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D)));
+ viewInfo.format = viewFormatForSampling;
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
viewInfo.subresourceRange.aspectMask = aspectMask;
viewInfo.subresourceRange.levelCount = mipLevelCount;
- viewInfo.subresourceRange.layerCount = isCube ? 6 : 1;
+ if (isArray && m_arrayRangeStart >= 0 && m_arrayRangeLength >= 0) {
+ viewInfo.subresourceRange.baseArrayLayer = uint32_t(m_arrayRangeStart);
+ viewInfo.subresourceRange.layerCount = uint32_t(m_arrayRangeLength);
+ } else {
+ viewInfo.subresourceRange.layerCount = isCube ? 6 : (isArray ? qMax(0, m_arraySize) : 1);
+ }
VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &imageView);
if (err != VK_SUCCESS) {
@@ -5916,10 +6598,11 @@ bool QVkTexture::create()
const bool isRenderTarget = m_flags.testFlag(QRhiTexture::RenderTarget);
const bool isDepth = isDepthTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool isArray = m_flags.testFlag(TextureArray);
const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool is1D = m_flags.testFlag(OneDimensional);
- VkImageCreateInfo imageInfo;
- memset(&imageInfo, 0, sizeof(imageInfo));
+ VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.flags = 0;
if (isCube)
@@ -5940,13 +6623,13 @@ bool QVkTexture::create()
#endif
}
- imageInfo.imageType = is3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
+ imageInfo.imageType = is1D ? VK_IMAGE_TYPE_1D : is3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
imageInfo.format = vkformat;
imageInfo.extent.width = uint32_t(size.width());
imageInfo.extent.height = uint32_t(size.height());
- imageInfo.extent.depth = is3D ? m_depth : 1;
+ imageInfo.extent.depth = is3D ? qMax(1, m_depth) : 1;
imageInfo.mipLevels = mipLevelCount;
- imageInfo.arrayLayers = isCube ? 6 : 1;
+ imageInfo.arrayLayers = isCube ? 6 : (isArray ? qMax(0, m_arraySize) : 1);
imageInfo.samples = samples;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
@@ -5965,14 +6648,20 @@ bool QVkTexture::create()
if (m_flags.testFlag(QRhiTexture::UsedWithLoadStore))
imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
- VmaAllocationCreateInfo allocInfo;
- memset(&allocInfo, 0, sizeof(allocInfo));
+ VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
VmaAllocation allocation;
VkResult err = vmaCreateImage(toVmaAllocator(rhiD->allocator), &imageInfo, &allocInfo, &image, &allocation, nullptr);
if (err != VK_SUCCESS) {
- qWarning("Failed to create image: %d", err);
+ qWarning("Failed to create image (with VkImageCreateInfo %ux%u depth %u vkformat 0x%X mips %u layers %u vksamples 0x%X): %d",
+ imageInfo.extent.width, imageInfo.extent.height, imageInfo.extent.depth,
+ int(imageInfo.format),
+ imageInfo.mipLevels,
+ imageInfo.arrayLayers,
+ int(imageInfo.samples),
+ err);
+ rhiD->printExtraErrorInfo(err);
return false;
}
imageAlloc = allocation;
@@ -5980,10 +6669,7 @@ bool QVkTexture::create()
if (!finishCreate())
return false;
- rhiD->setObjectName(uint64_t(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, m_objectName);
-
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, true, int(mipLevelCount), isCube ? 6 : 1, samples));
+ rhiD->setObjectName(uint64_t(image), VK_OBJECT_TYPE_IMAGE, m_objectName);
owns = true;
rhiD->registerResource(this);
@@ -6004,9 +6690,6 @@ bool QVkTexture::createFrom(QRhiTexture::NativeTexture src)
if (!finishCreate())
return false;
- QRHI_PROF;
- QRHI_PROF_F(newTexture(this, false, int(mipLevelCount), m_flags.testFlag(CubeMap) ? 6 : 1, samples));
-
usageState.layout = VkImageLayout(src.layout);
owns = false;
@@ -6025,7 +6708,7 @@ void QVkTexture::setNativeLayout(int layout)
usageState.layout = VkImageLayout(layout);
}
-VkImageView QVkTexture::imageViewForLevel(int level)
+VkImageView QVkTexture::perLevelImageViewForLoadStore(int level)
{
Q_ASSERT(level >= 0 && level < int(mipLevelCount));
if (perLevelImageViews[level] != VK_NULL_HANDLE)
@@ -6033,14 +6716,19 @@ VkImageView QVkTexture::imageViewForLevel(int level)
const VkImageAspectFlags aspectMask = aspectMaskForTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
+ const bool isArray = m_flags.testFlag(TextureArray);
const bool is3D = m_flags.testFlag(ThreeDimensional);
+ const bool is1D = m_flags.testFlag(OneDimensional);
- VkImageViewCreateInfo viewInfo;
- memset(&viewInfo, 0, sizeof(viewInfo));
+ VkImageViewCreateInfo viewInfo = {};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = image;
- viewInfo.viewType = isCube ? VK_IMAGE_VIEW_TYPE_CUBE : (is3D ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D);
- viewInfo.format = vkformat;
+ viewInfo.viewType = isCube
+ ? VK_IMAGE_VIEW_TYPE_CUBE
+ : (is3D ? VK_IMAGE_VIEW_TYPE_3D
+ : (is1D ? (isArray ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D)
+ : (isArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D)));
+ viewInfo.format = viewFormat; // this is writeViewFormat, regardless of Load, Store, or LoadStore; intentional
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
@@ -6049,7 +6737,7 @@ VkImageView QVkTexture::imageViewForLevel(int level)
viewInfo.subresourceRange.baseMipLevel = uint32_t(level);
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
- viewInfo.subresourceRange.layerCount = isCube ? 6 : 1;
+ viewInfo.subresourceRange.layerCount = isCube ? 6 : (isArray ? qMax(0, m_arraySize) : 1);
VkImageView v = VK_NULL_HANDLE;
QRHI_RES_RHI(QRhiVulkan);
@@ -6087,8 +6775,10 @@ void QVkSampler::destroy()
sampler = VK_NULL_HANDLE;
QRHI_RES_RHI(QRhiVulkan);
- rhiD->releaseQueue.append(e);
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QVkSampler::create()
@@ -6096,8 +6786,7 @@ bool QVkSampler::create()
if (sampler)
destroy();
- VkSamplerCreateInfo samplerInfo;
- memset(&samplerInfo, 0, sizeof(samplerInfo));
+ VkSamplerCreateInfo samplerInfo = {};
samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
samplerInfo.magFilter = toVkFilter(m_magFilter);
samplerInfo.minFilter = toVkFilter(m_minFilter);
@@ -6126,6 +6815,7 @@ bool QVkSampler::create()
QVkRenderPassDescriptor::QVkRenderPassDescriptor(QRhiImplementation *rhi)
: QRhiRenderPassDescriptor(rhi)
{
+ serializedFormatData.reserve(64);
}
QVkRenderPassDescriptor::~QVkRenderPassDescriptor()
@@ -6152,9 +6842,10 @@ void QVkRenderPassDescriptor::destroy()
rp = VK_NULL_HANDLE;
QRHI_RES_RHI(QRhiVulkan);
- rhiD->releaseQueue.append(e);
-
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
static inline bool attachmentDescriptionEquals(const VkAttachmentDescription &a, const VkAttachmentDescription &b)
@@ -6179,16 +6870,20 @@ bool QVkRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other
const QVkRenderPassDescriptor *o = QRHI_RES(const QVkRenderPassDescriptor, other);
- if (attDescs.count() != o->attDescs.count())
+ if (attDescs.size() != o->attDescs.size())
return false;
- if (colorRefs.count() != o->colorRefs.count())
+ if (colorRefs.size() != o->colorRefs.size())
return false;
- if (resolveRefs.count() != o->resolveRefs.count())
+ if (resolveRefs.size() != o->resolveRefs.size())
return false;
if (hasDepthStencil != o->hasDepthStencil)
return false;
+ if (hasDepthStencilResolve != o->hasDepthStencilResolve)
+ return false;
+ if (multiViewCount != o->multiViewCount)
+ return false;
- for (int i = 0, ie = colorRefs.count(); i != ie; ++i) {
+ for (int i = 0, ie = colorRefs.size(); i != ie; ++i) {
const uint32_t attIdx = colorRefs[i].attachment;
if (attIdx != o->colorRefs[i].attachment)
return false;
@@ -6204,7 +6899,7 @@ bool QVkRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other
return false;
}
- for (int i = 0, ie = resolveRefs.count(); i != ie; ++i) {
+ for (int i = 0, ie = resolveRefs.size(); i != ie; ++i) {
const uint32_t attIdx = resolveRefs[i].attachment;
if (attIdx != o->resolveRefs[i].attachment)
return false;
@@ -6212,11 +6907,69 @@ bool QVkRenderPassDescriptor::isCompatible(const QRhiRenderPassDescriptor *other
return false;
}
+ if (hasDepthStencilResolve) {
+ const uint32_t attIdx = dsResolveRef.attachment;
+ if (attIdx != o->dsResolveRef.attachment)
+ return false;
+ if (attIdx != VK_ATTACHMENT_UNUSED && !attachmentDescriptionEquals(attDescs[attIdx], o->attDescs[attIdx]))
+ return false;
+ }
+
// subpassDeps is not included
return true;
}
+void QVkRenderPassDescriptor::updateSerializedFormat()
+{
+ serializedFormatData.clear();
+ auto p = std::back_inserter(serializedFormatData);
+
+ *p++ = attDescs.size();
+ *p++ = colorRefs.size();
+ *p++ = resolveRefs.size();
+ *p++ = hasDepthStencil;
+ *p++ = hasDepthStencilResolve;
+ *p++ = multiViewCount;
+
+ auto serializeAttachmentData = [this, &p](uint32_t attIdx) {
+ const bool used = attIdx != VK_ATTACHMENT_UNUSED;
+ const VkAttachmentDescription *a = used ? &attDescs[attIdx] : nullptr;
+ *p++ = used ? a->format : 0;
+ *p++ = used ? a->samples : 0;
+ *p++ = used ? a->loadOp : 0;
+ *p++ = used ? a->storeOp : 0;
+ *p++ = used ? a->stencilLoadOp : 0;
+ *p++ = used ? a->stencilStoreOp : 0;
+ *p++ = used ? a->initialLayout : 0;
+ *p++ = used ? a->finalLayout : 0;
+ };
+
+ for (int i = 0, ie = colorRefs.size(); i != ie; ++i) {
+ const uint32_t attIdx = colorRefs[i].attachment;
+ *p++ = attIdx;
+ serializeAttachmentData(attIdx);
+ }
+
+ if (hasDepthStencil) {
+ const uint32_t attIdx = dsRef.attachment;
+ *p++ = attIdx;
+ serializeAttachmentData(attIdx);
+ }
+
+ for (int i = 0, ie = resolveRefs.size(); i != ie; ++i) {
+ const uint32_t attIdx = resolveRefs[i].attachment;
+ *p++ = attIdx;
+ serializeAttachmentData(attIdx);
+ }
+
+ if (hasDepthStencilResolve) {
+ const uint32_t attIdx = dsResolveRef.attachment;
+ *p++ = attIdx;
+ serializeAttachmentData(attIdx);
+ }
+}
+
QRhiRenderPassDescriptor *QVkRenderPassDescriptor::newCompatibleRenderPassDescriptor() const
{
QVkRenderPassDescriptor *rpD = new QVkRenderPassDescriptor(m_rhi);
@@ -6227,13 +6980,22 @@ QRhiRenderPassDescriptor *QVkRenderPassDescriptor::newCompatibleRenderPassDescri
rpD->resolveRefs = resolveRefs;
rpD->subpassDeps = subpassDeps;
rpD->hasDepthStencil = hasDepthStencil;
+ rpD->hasDepthStencilResolve = hasDepthStencilResolve;
+ rpD->multiViewCount = multiViewCount;
rpD->dsRef = dsRef;
+ rpD->dsResolveRef = dsResolveRef;
VkRenderPassCreateInfo rpInfo;
VkSubpassDescription subpassDesc;
fillRenderPassCreateInfo(&rpInfo, &subpassDesc, rpD);
QRHI_RES_RHI(QRhiVulkan);
+ MultiViewRenderPassSetupHelper multiViewHelper;
+ if (!multiViewHelper.prepare(&rpInfo, multiViewCount, rhiD->caps.multiView)) {
+ delete rpD;
+ return nullptr;
+ }
+
VkResult err = rhiD->df->vkCreateRenderPass(rhiD->dev, &rpInfo, nullptr, &rpD->rp);
if (err != VK_SUCCESS) {
qWarning("Failed to create renderpass: %d", err);
@@ -6241,42 +7003,48 @@ QRhiRenderPassDescriptor *QVkRenderPassDescriptor::newCompatibleRenderPassDescri
return nullptr;
}
+ rpD->updateSerializedFormat();
rhiD->registerResource(rpD);
return rpD;
}
+QVector<quint32> QVkRenderPassDescriptor::serializedFormat() const
+{
+ return serializedFormatData;
+}
+
const QRhiNativeHandles *QVkRenderPassDescriptor::nativeHandles()
{
nativeHandlesStruct.renderPass = rp;
return &nativeHandlesStruct;
}
-QVkReferenceRenderTarget::QVkReferenceRenderTarget(QRhiImplementation *rhi)
- : QRhiRenderTarget(rhi)
+QVkSwapChainRenderTarget::QVkSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain)
+ : QRhiSwapChainRenderTarget(rhi, swapchain)
{
}
-QVkReferenceRenderTarget::~QVkReferenceRenderTarget()
+QVkSwapChainRenderTarget::~QVkSwapChainRenderTarget()
{
destroy();
}
-void QVkReferenceRenderTarget::destroy()
+void QVkSwapChainRenderTarget::destroy()
{
// nothing to do here
}
-QSize QVkReferenceRenderTarget::pixelSize() const
+QSize QVkSwapChainRenderTarget::pixelSize() const
{
return d.pixelSize;
}
-float QVkReferenceRenderTarget::devicePixelRatio() const
+float QVkSwapChainRenderTarget::devicePixelRatio() const
{
return d.dpr;
}
-int QVkReferenceRenderTarget::sampleCount() const
+int QVkSwapChainRenderTarget::sampleCount() const
{
return d.sampleCount;
}
@@ -6316,10 +7084,16 @@ void QVkTextureRenderTarget::destroy()
resrtv[att] = VK_NULL_HANDLE;
}
- QRHI_RES_RHI(QRhiVulkan);
- rhiD->releaseQueue.append(e);
+ e.textureRenderTarget.dsv = dsv;
+ dsv = VK_NULL_HANDLE;
+ e.textureRenderTarget.resdsv = resdsv;
+ resdsv = VK_NULL_HANDLE;
- rhiD->unregisterResource(this);
+ QRHI_RES_RHI(QRhiVulkan);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
QRhiRenderPassDescriptor *QVkTextureRenderTarget::newCompatibleRenderPassDescriptor()
@@ -6333,14 +7107,17 @@ QRhiRenderPassDescriptor *QVkTextureRenderTarget::newCompatibleRenderPassDescrip
m_desc.cendColorAttachments(),
m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents),
m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents),
+ m_desc.depthTexture() && !m_flags.testFlag(DoNotStoreDepthStencilContents) && !m_desc.depthResolveTexture(),
m_desc.depthStencilBuffer(),
- m_desc.depthTexture()))
+ m_desc.depthTexture(),
+ m_desc.depthResolveTexture()))
{
delete rp;
return nullptr;
}
rp->ownsRp = true;
+ rp->updateSerializedFormat();
rhiD->registerResource(rp);
return rp;
}
@@ -6350,13 +7127,13 @@ bool QVkTextureRenderTarget::create()
if (d.fb)
destroy();
- const bool hasColorAttachments = m_desc.cbeginColorAttachments() != m_desc.cendColorAttachments();
- Q_ASSERT(hasColorAttachments || m_desc.depthTexture());
+ Q_ASSERT(m_desc.colorAttachmentCount() > 0 || m_desc.depthTexture());
Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
QRHI_RES_RHI(QRhiVulkan);
QVarLengthArray<VkImageView, 8> views;
+ d.multiViewCount = 0;
d.colorAttCount = 0;
int attIndex = 0;
@@ -6367,12 +7144,17 @@ bool QVkTextureRenderTarget::create()
Q_ASSERT(texD || rbD);
if (texD) {
Q_ASSERT(texD->flags().testFlag(QRhiTexture::RenderTarget));
- VkImageViewCreateInfo viewInfo;
- memset(&viewInfo, 0, sizeof(viewInfo));
+ const bool is1D = texD->flags().testFlag(QRhiTexture::OneDimensional);
+ const bool isMultiView = it->multiViewCount() >= 2;
+ if (isMultiView && d.multiViewCount == 0)
+ d.multiViewCount = it->multiViewCount();
+ VkImageViewCreateInfo viewInfo = {};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = texD->image;
- viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- viewInfo.format = texD->vkformat;
+ viewInfo.viewType = is1D ? VK_IMAGE_VIEW_TYPE_1D
+ : (isMultiView ? VK_IMAGE_VIEW_TYPE_2D_ARRAY
+ : VK_IMAGE_VIEW_TYPE_2D);
+ viewInfo.format = texD->viewFormat;
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
@@ -6381,7 +7163,7 @@ bool QVkTextureRenderTarget::create()
viewInfo.subresourceRange.baseMipLevel = uint32_t(it->level());
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = uint32_t(it->layer());
- viewInfo.subresourceRange.layerCount = 1;
+ viewInfo.subresourceRange.layerCount = uint32_t(isMultiView ? it->multiViewCount() : 1);
VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &rtv[attIndex]);
if (err != VK_SUCCESS) {
qWarning("Failed to create render target image view: %d", err);
@@ -6406,7 +7188,25 @@ bool QVkTextureRenderTarget::create()
if (hasDepthStencil) {
if (m_desc.depthTexture()) {
QVkTexture *depthTexD = QRHI_RES(QVkTexture, m_desc.depthTexture());
- views.append(depthTexD->imageView);
+ // need a dedicated view just because viewFormat may differ from vkformat
+ VkImageViewCreateInfo viewInfo = {};
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.image = depthTexD->image;
+ viewInfo.viewType = d.multiViewCount > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = depthTexD->viewFormat;
+ viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ viewInfo.subresourceRange.levelCount = 1;
+ viewInfo.subresourceRange.layerCount = qMax<uint32_t>(1, d.multiViewCount);
+ VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &dsv);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create depth-stencil image view for rt: %d", err);
+ return false;
+ }
+ views.append(dsv);
if (d.colorAttCount == 0) {
d.pixelSize = depthTexD->pixelSize();
d.sampleCount = depthTexD->samples;
@@ -6426,18 +7226,19 @@ bool QVkTextureRenderTarget::create()
d.resolveAttCount = 0;
attIndex = 0;
+ Q_ASSERT(d.multiViewCount == 0 || d.multiViewCount >= 2);
for (auto it = m_desc.cbeginColorAttachments(), itEnd = m_desc.cendColorAttachments(); it != itEnd; ++it, ++attIndex) {
if (it->resolveTexture()) {
QVkTexture *resTexD = QRHI_RES(QVkTexture, it->resolveTexture());
Q_ASSERT(resTexD->flags().testFlag(QRhiTexture::RenderTarget));
d.resolveAttCount += 1;
- VkImageViewCreateInfo viewInfo;
- memset(&viewInfo, 0, sizeof(viewInfo));
+ VkImageViewCreateInfo viewInfo = {};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.image = resTexD->image;
- viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
- viewInfo.format = resTexD->vkformat;
+ viewInfo.viewType = d.multiViewCount ? VK_IMAGE_VIEW_TYPE_2D_ARRAY
+ : VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = resTexD->viewFormat;
viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
@@ -6446,7 +7247,7 @@ bool QVkTextureRenderTarget::create()
viewInfo.subresourceRange.baseMipLevel = uint32_t(it->resolveLevel());
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = uint32_t(it->resolveLayer());
- viewInfo.subresourceRange.layerCount = 1;
+ viewInfo.subresourceRange.layerCount = qMax<uint32_t>(1, d.multiViewCount);
VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &resrtv[attIndex]);
if (err != VK_SUCCESS) {
qWarning("Failed to create render target resolve image view: %d", err);
@@ -6456,17 +7257,46 @@ bool QVkTextureRenderTarget::create()
}
}
+ if (m_desc.depthResolveTexture()) {
+ QVkTexture *resTexD = QRHI_RES(QVkTexture, m_desc.depthResolveTexture());
+ Q_ASSERT(resTexD->flags().testFlag(QRhiTexture::RenderTarget));
+
+ VkImageViewCreateInfo viewInfo = {};
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.image = resTexD->image;
+ viewInfo.viewType = d.multiViewCount ? VK_IMAGE_VIEW_TYPE_2D_ARRAY
+ : VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = resTexD->viewFormat;
+ viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ viewInfo.subresourceRange.baseMipLevel = 0;
+ viewInfo.subresourceRange.levelCount = 1;
+ viewInfo.subresourceRange.baseArrayLayer = 0;
+ viewInfo.subresourceRange.layerCount = qMax<uint32_t>(1, d.multiViewCount);
+ VkResult err = rhiD->df->vkCreateImageView(rhiD->dev, &viewInfo, nullptr, &resdsv);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create render target depth resolve image view: %d", err);
+ return false;
+ }
+ views.append(resdsv);
+ d.dsResolveAttCount = 1;
+ } else {
+ d.dsResolveAttCount = 0;
+ }
+
if (!m_renderPassDesc)
qWarning("QVkTextureRenderTarget: No renderpass descriptor set. See newCompatibleRenderPassDescriptor() and setRenderPassDescriptor().");
d.rp = QRHI_RES(QVkRenderPassDescriptor, m_renderPassDesc);
Q_ASSERT(d.rp && d.rp->rp);
- VkFramebufferCreateInfo fbInfo;
- memset(&fbInfo, 0, sizeof(fbInfo));
+ VkFramebufferCreateInfo fbInfo = {};
fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fbInfo.renderPass = d.rp->rp;
- fbInfo.attachmentCount = uint32_t(d.colorAttCount + d.dsAttCount + d.resolveAttCount);
+ fbInfo.attachmentCount = uint32_t(d.colorAttCount + d.dsAttCount + d.resolveAttCount + d.dsResolveAttCount);
fbInfo.pAttachments = views.constData();
fbInfo.width = uint32_t(d.pixelSize.width());
fbInfo.height = uint32_t(d.pixelSize.height());
@@ -6478,6 +7308,8 @@ bool QVkTextureRenderTarget::create()
return false;
}
+ QRhiRenderTargetAttachmentTracker::updateResIdList<QVkTexture, QVkRenderBuffer>(m_desc, &d.currentResIdList);
+
lastActiveFrameSlot = -1;
rhiD->registerResource(this);
return true;
@@ -6485,6 +7317,9 @@ bool QVkTextureRenderTarget::create()
QSize QVkTextureRenderTarget::pixelSize() const
{
+ if (!QRhiRenderTargetAttachmentTracker::isUpToDate<QVkTexture, QVkRenderBuffer>(m_desc, d.currentResIdList))
+ const_cast<QVkTextureRenderTarget *>(this)->create();
+
return d.pixelSize;
}
@@ -6528,9 +7363,10 @@ void QVkShaderResourceBindings::destroy()
descSets[i] = VK_NULL_HANDLE;
QRHI_RES_RHI(QRhiVulkan);
- rhiD->releaseQueue.append(e);
-
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QVkShaderResourceBindings::create()
@@ -6549,16 +7385,12 @@ bool QVkShaderResourceBindings::create()
sortedBindings.clear();
std::copy(m_bindings.cbegin(), m_bindings.cend(), std::back_inserter(sortedBindings));
- std::sort(sortedBindings.begin(), sortedBindings.end(),
- [](const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
- {
- return a.data()->binding < b.data()->binding;
- });
+ std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
hasSlottedResource = false;
hasDynamicOffset = false;
- for (const QRhiShaderResourceBinding &binding : qAsConst(sortedBindings)) {
- const QRhiShaderResourceBinding::Data *b = binding.data();
+ for (const QRhiShaderResourceBinding &binding : std::as_const(sortedBindings)) {
+ const QRhiShaderResourceBinding::Data *b = QRhiImplementation::shaderResourceBindingData(binding);
if (b->type == QRhiShaderResourceBinding::UniformBuffer && b->u.ubuf.buf) {
if (QRHI_RES(QVkBuffer, b->u.ubuf.buf)->type() == QRhiBuffer::Dynamic)
hasSlottedResource = true;
@@ -6568,13 +7400,12 @@ bool QVkShaderResourceBindings::create()
}
QVarLengthArray<VkDescriptorSetLayoutBinding, 4> vkbindings;
- for (const QRhiShaderResourceBinding &binding : qAsConst(sortedBindings)) {
- const QRhiShaderResourceBinding::Data *b = binding.data();
- VkDescriptorSetLayoutBinding vkbinding;
- memset(&vkbinding, 0, sizeof(vkbinding));
+ for (const QRhiShaderResourceBinding &binding : std::as_const(sortedBindings)) {
+ const QRhiShaderResourceBinding::Data *b = QRhiImplementation::shaderResourceBindingData(binding);
+ VkDescriptorSetLayoutBinding vkbinding = {};
vkbinding.binding = uint32_t(b->binding);
vkbinding.descriptorType = toVkDescriptorType(b);
- if (b->type == QRhiShaderResourceBinding::SampledTexture)
+ if (b->type == QRhiShaderResourceBinding::SampledTexture || b->type == QRhiShaderResourceBinding::Texture)
vkbinding.descriptorCount = b->u.stex.count;
else
vkbinding.descriptorCount = 1;
@@ -6582,10 +7413,9 @@ bool QVkShaderResourceBindings::create()
vkbindings.append(vkbinding);
}
- VkDescriptorSetLayoutCreateInfo layoutInfo;
- memset(&layoutInfo, 0, sizeof(layoutInfo));
+ VkDescriptorSetLayoutCreateInfo layoutInfo = {};
layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
- layoutInfo.bindingCount = uint32_t(vkbindings.count());
+ layoutInfo.bindingCount = uint32_t(vkbindings.size());
layoutInfo.pBindings = vkbindings.constData();
VkResult err = rhiD->df->vkCreateDescriptorSetLayout(rhiD->dev, &layoutInfo, nullptr, &layout);
@@ -6594,8 +7424,7 @@ bool QVkShaderResourceBindings::create()
return false;
}
- VkDescriptorSetAllocateInfo allocInfo;
- memset(&allocInfo, 0, sizeof(allocInfo));
+ VkDescriptorSetAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorSetCount = QVK_FRAMES_IN_FLIGHT;
VkDescriptorSetLayout layouts[QVK_FRAMES_IN_FLIGHT];
@@ -6606,7 +7435,7 @@ bool QVkShaderResourceBindings::create()
return false;
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
- boundResourceData[i].resize(sortedBindings.count());
+ boundResourceData[i].resize(sortedBindings.size());
for (BoundResourceData &bd : boundResourceData[i])
memset(&bd, 0, sizeof(BoundResourceData));
}
@@ -6617,6 +7446,31 @@ bool QVkShaderResourceBindings::create()
return true;
}
+void QVkShaderResourceBindings::updateResources(UpdateFlags flags)
+{
+ sortedBindings.clear();
+ std::copy(m_bindings.cbegin(), m_bindings.cend(), std::back_inserter(sortedBindings));
+ if (!flags.testFlag(BindingsAreSorted))
+ std::sort(sortedBindings.begin(), sortedBindings.end(), QRhiImplementation::sortedBindingLessThan);
+
+ // Reset the state tracking table too - it can deal with assigning a
+ // different QRhiBuffer/Texture/Sampler for a binding point, but it cannot
+ // detect changes in the associated data, such as the buffer offset. And
+ // just like after a create(), a call to updateResources() may lead to now
+ // specifying a different offset for the same QRhiBuffer for a given binding
+ // point. The same applies to other type of associated data that is not part
+ // of the layout, such as the mip level for a StorageImage. Instead of
+ // complicating the checks in setShaderResources(), reset the table here
+ // just like we do in create().
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
+ Q_ASSERT(boundResourceData[i].size() == sortedBindings.size());
+ for (BoundResourceData &bd : boundResourceData[i])
+ memset(&bd, 0, sizeof(BoundResourceData));
+ }
+
+ generation += 1;
+}
+
QVkGraphicsPipeline::QVkGraphicsPipeline(QRhiImplementation *rhi)
: QRhiGraphicsPipeline(rhi)
{
@@ -6643,9 +7497,10 @@ void QVkGraphicsPipeline::destroy()
layout = VK_NULL_HANDLE;
QRHI_RES_RHI(QRhiVulkan);
- rhiD->releaseQueue.append(e);
-
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QVkGraphicsPipeline::create()
@@ -6654,14 +7509,14 @@ bool QVkGraphicsPipeline::create()
destroy();
QRHI_RES_RHI(QRhiVulkan);
+ rhiD->pipelineCreationStart();
if (!rhiD->sanityCheckGraphicsPipeline(this))
return false;
if (!rhiD->ensurePipelineCache())
return false;
- VkPipelineLayoutCreateInfo pipelineLayoutInfo;
- memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, m_shaderResourceBindings);
@@ -6673,8 +7528,7 @@ bool QVkGraphicsPipeline::create()
return false;
}
- VkGraphicsPipelineCreateInfo pipelineInfo;
- memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ VkGraphicsPipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
QVarLengthArray<VkShaderModule, 4> shaders;
@@ -6689,8 +7543,7 @@ bool QVkGraphicsPipeline::create()
VkShaderModule shader = rhiD->createShader(spirv.shader());
if (shader) {
shaders.append(shader);
- VkPipelineShaderStageCreateInfo shaderInfo;
- memset(&shaderInfo, 0, sizeof(shaderInfo));
+ VkPipelineShaderStageCreateInfo shaderInfo = {};
shaderInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderInfo.stage = toVkShaderStage(shaderStage.type());
shaderInfo.module = shader;
@@ -6698,11 +7551,13 @@ bool QVkGraphicsPipeline::create()
shaderStageCreateInfos.append(shaderInfo);
}
}
- pipelineInfo.stageCount = uint32_t(shaderStageCreateInfos.count());
+ pipelineInfo.stageCount = uint32_t(shaderStageCreateInfos.size());
pipelineInfo.pStages = shaderStageCreateInfos.constData();
QVarLengthArray<VkVertexInputBindingDescription, 4> vertexBindings;
+#ifdef VK_EXT_vertex_attribute_divisor
QVarLengthArray<VkVertexInputBindingDivisorDescriptionEXT> nonOneStepRates;
+#endif
int bindingIndex = 0;
for (auto it = m_vertexInputLayout.cbeginBindings(), itEnd = m_vertexInputLayout.cendBindings();
it != itEnd; ++it, ++bindingIndex)
@@ -6714,9 +7569,12 @@ bool QVkGraphicsPipeline::create()
? VK_VERTEX_INPUT_RATE_VERTEX : VK_VERTEX_INPUT_RATE_INSTANCE
};
if (it->classification() == QRhiVertexInputBinding::PerInstance && it->instanceStepRate() != 1) {
+#ifdef VK_EXT_vertex_attribute_divisor
if (rhiD->caps.vertexAttribDivisor) {
- nonOneStepRates.append({ uint32_t(bindingIndex), uint32_t(it->instanceStepRate()) });
- } else {
+ nonOneStepRates.append({ uint32_t(bindingIndex), it->instanceStepRate() });
+ } else
+#endif
+ {
qWarning("QRhiVulkan: Instance step rates other than 1 not supported without "
"VK_EXT_vertex_attribute_divisor on the device and "
"VK_KHR_get_physical_device_properties2 on the instance");
@@ -6736,21 +7594,21 @@ bool QVkGraphicsPipeline::create()
};
vertexAttributes.append(attributeInfo);
}
- VkPipelineVertexInputStateCreateInfo vertexInputInfo;
- memset(&vertexInputInfo, 0, sizeof(vertexInputInfo));
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
- vertexInputInfo.vertexBindingDescriptionCount = uint32_t(vertexBindings.count());
+ vertexInputInfo.vertexBindingDescriptionCount = uint32_t(vertexBindings.size());
vertexInputInfo.pVertexBindingDescriptions = vertexBindings.constData();
- vertexInputInfo.vertexAttributeDescriptionCount = uint32_t(vertexAttributes.count());
+ vertexInputInfo.vertexAttributeDescriptionCount = uint32_t(vertexAttributes.size());
vertexInputInfo.pVertexAttributeDescriptions = vertexAttributes.constData();
- VkPipelineVertexInputDivisorStateCreateInfoEXT divisorInfo;
+#ifdef VK_EXT_vertex_attribute_divisor
+ VkPipelineVertexInputDivisorStateCreateInfoEXT divisorInfo = {};
if (!nonOneStepRates.isEmpty()) {
- memset(&divisorInfo, 0, sizeof(divisorInfo));
- divisorInfo.sType = VkStructureType(1000190001); // VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT
- divisorInfo.vertexBindingDivisorCount = uint32_t(nonOneStepRates.count());
+ divisorInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
+ divisorInfo.vertexBindingDivisorCount = uint32_t(nonOneStepRates.size());
divisorInfo.pVertexBindingDivisors = nonOneStepRates.constData();
vertexInputInfo.pNext = &divisorInfo;
}
+#endif
pipelineInfo.pVertexInputState = &vertexInputInfo;
QVarLengthArray<VkDynamicState, 8> dynEnable;
@@ -6761,28 +7619,52 @@ bool QVkGraphicsPipeline::create()
if (m_flags.testFlag(QRhiGraphicsPipeline::UsesStencilRef))
dynEnable << VK_DYNAMIC_STATE_STENCIL_REFERENCE;
- VkPipelineDynamicStateCreateInfo dynamicInfo;
- memset(&dynamicInfo, 0, sizeof(dynamicInfo));
+ VkPipelineDynamicStateCreateInfo dynamicInfo = {};
dynamicInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
- dynamicInfo.dynamicStateCount = uint32_t(dynEnable.count());
+ dynamicInfo.dynamicStateCount = uint32_t(dynEnable.size());
dynamicInfo.pDynamicStates = dynEnable.constData();
pipelineInfo.pDynamicState = &dynamicInfo;
- VkPipelineViewportStateCreateInfo viewportInfo;
- memset(&viewportInfo, 0, sizeof(viewportInfo));
+ VkPipelineViewportStateCreateInfo viewportInfo = {};
viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportInfo.viewportCount = viewportInfo.scissorCount = 1;
pipelineInfo.pViewportState = &viewportInfo;
- VkPipelineInputAssemblyStateCreateInfo inputAsmInfo;
- memset(&inputAsmInfo, 0, sizeof(inputAsmInfo));
+ VkPipelineInputAssemblyStateCreateInfo inputAsmInfo = {};
inputAsmInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
inputAsmInfo.topology = toVkTopology(m_topology);
inputAsmInfo.primitiveRestartEnable = (m_topology == TriangleStrip || m_topology == LineStrip);
pipelineInfo.pInputAssemblyState = &inputAsmInfo;
- VkPipelineRasterizationStateCreateInfo rastInfo;
- memset(&rastInfo, 0, sizeof(rastInfo));
+ VkPipelineTessellationStateCreateInfo tessInfo = {};
+#ifdef VK_VERSION_1_1
+ VkPipelineTessellationDomainOriginStateCreateInfo originInfo = {};
+#endif
+ if (m_topology == Patches) {
+ tessInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
+ tessInfo.patchControlPoints = uint32_t(qMax(1, m_patchControlPointCount));
+
+ // To be able to use the same tess.evaluation shader with both OpenGL
+ // and Vulkan, flip the tessellation domain origin to be lower left.
+ // This allows declaring the winding order in the shader to be CCW and
+ // still have it working with both APIs. This requires Vulkan 1.1 (or
+ // VK_KHR_maintenance2 but don't bother with that).
+#ifdef VK_VERSION_1_1
+ if (rhiD->caps.apiVersion >= QVersionNumber(1, 1)) {
+ originInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO;
+ originInfo.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
+ tessInfo.pNext = &originInfo;
+ } else {
+ qWarning("Proper tessellation support requires Vulkan 1.1 or newer, leaving domain origin unset");
+ }
+#else
+ qWarning("QRhi was built without Vulkan 1.1 headers, this is not sufficient for proper tessellation support");
+#endif
+
+ pipelineInfo.pTessellationState = &tessInfo;
+ }
+
+ VkPipelineRasterizationStateCreateInfo rastInfo = {};
rastInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rastInfo.cullMode = toVkCullMode(m_cullMode);
rastInfo.frontFace = toVkFrontFace(m_frontFace);
@@ -6792,16 +7674,15 @@ bool QVkGraphicsPipeline::create()
rastInfo.depthBiasSlopeFactor = m_slopeScaledDepthBias;
}
rastInfo.lineWidth = rhiD->caps.wideLines ? m_lineWidth : 1.0f;
+ rastInfo.polygonMode = toVkPolygonMode(m_polygonMode);
pipelineInfo.pRasterizationState = &rastInfo;
- VkPipelineMultisampleStateCreateInfo msInfo;
- memset(&msInfo, 0, sizeof(msInfo));
+ VkPipelineMultisampleStateCreateInfo msInfo = {};
msInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- msInfo.rasterizationSamples = rhiD->effectiveSampleCount(m_sampleCount);
+ msInfo.rasterizationSamples = rhiD->effectiveSampleCountBits(m_sampleCount);
pipelineInfo.pMultisampleState = &msInfo;
- VkPipelineDepthStencilStateCreateInfo dsInfo;
- memset(&dsInfo, 0, sizeof(dsInfo));
+ VkPipelineDepthStencilStateCreateInfo dsInfo = {};
dsInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
dsInfo.depthTestEnable = m_depthTest;
dsInfo.depthWriteEnable = m_depthWrite;
@@ -6817,13 +7698,11 @@ bool QVkGraphicsPipeline::create()
}
pipelineInfo.pDepthStencilState = &dsInfo;
- VkPipelineColorBlendStateCreateInfo blendInfo;
- memset(&blendInfo, 0, sizeof(blendInfo));
+ VkPipelineColorBlendStateCreateInfo blendInfo = {};
blendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
QVarLengthArray<VkPipelineColorBlendAttachmentState, 4> vktargetBlends;
- for (const QRhiGraphicsPipeline::TargetBlend &b : qAsConst(m_targetBlends)) {
- VkPipelineColorBlendAttachmentState blend;
- memset(&blend, 0, sizeof(blend));
+ for (const QRhiGraphicsPipeline::TargetBlend &b : std::as_const(m_targetBlends)) {
+ VkPipelineColorBlendAttachmentState blend = {};
blend.blendEnable = b.enable;
blend.srcColorBlendFactor = toVkBlendFactor(b.srcColor);
blend.dstColorBlendFactor = toVkBlendFactor(b.dstColor);
@@ -6835,13 +7714,12 @@ bool QVkGraphicsPipeline::create()
vktargetBlends.append(blend);
}
if (vktargetBlends.isEmpty()) {
- VkPipelineColorBlendAttachmentState blend;
- memset(&blend, 0, sizeof(blend));
+ VkPipelineColorBlendAttachmentState blend = {};
blend.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT
| VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
vktargetBlends.append(blend);
}
- blendInfo.attachmentCount = uint32_t(vktargetBlends.count());
+ blendInfo.attachmentCount = uint32_t(vktargetBlends.size());
blendInfo.pAttachments = vktargetBlends.constData();
pipelineInfo.pColorBlendState = &blendInfo;
@@ -6860,6 +7738,7 @@ bool QVkGraphicsPipeline::create()
return false;
}
+ rhiD->pipelineCreationEnd();
lastActiveFrameSlot = -1;
generation += 1;
rhiD->registerResource(this);
@@ -6892,9 +7771,10 @@ void QVkComputePipeline::destroy()
layout = VK_NULL_HANDLE;
QRHI_RES_RHI(QRhiVulkan);
- rhiD->releaseQueue.append(e);
-
- rhiD->unregisterResource(this);
+ if (rhiD) {
+ rhiD->releaseQueue.append(e);
+ rhiD->unregisterResource(this);
+ }
}
bool QVkComputePipeline::create()
@@ -6903,11 +7783,11 @@ bool QVkComputePipeline::create()
destroy();
QRHI_RES_RHI(QRhiVulkan);
+ rhiD->pipelineCreationStart();
if (!rhiD->ensurePipelineCache())
return false;
- VkPipelineLayoutCreateInfo pipelineLayoutInfo;
- memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, m_shaderResourceBindings);
@@ -6919,8 +7799,7 @@ bool QVkComputePipeline::create()
return false;
}
- VkComputePipelineCreateInfo pipelineInfo;
- memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ VkComputePipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
pipelineInfo.layout = layout;
@@ -6939,8 +7818,7 @@ bool QVkComputePipeline::create()
return false;
}
VkShaderModule shader = rhiD->createShader(spirv.shader());
- VkPipelineShaderStageCreateInfo shaderInfo;
- memset(&shaderInfo, 0, sizeof(shaderInfo));
+ VkPipelineShaderStageCreateInfo shaderInfo = {};
shaderInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
shaderInfo.module = shader;
@@ -6954,6 +7832,7 @@ bool QVkComputePipeline::create()
return false;
}
+ rhiD->pipelineCreationEnd();
lastActiveFrameSlot = -1;
generation += 1;
rhiD->registerResource(this);
@@ -6998,7 +7877,8 @@ const QRhiNativeHandles *QVkCommandBuffer::nativeHandles()
QVkSwapChain::QVkSwapChain(QRhiImplementation *rhi)
: QRhiSwapChain(rhi),
- rtWrapper(rhi),
+ rtWrapper(rhi, this),
+ rtWrapperRight(rhi, this),
cbWrapper(rhi)
{
}
@@ -7014,8 +7894,10 @@ void QVkSwapChain::destroy()
return;
QRHI_RES_RHI(QRhiVulkan);
- rhiD->swapchains.remove(this);
- rhiD->releaseSwapChainResources(this);
+ if (rhiD) {
+ rhiD->swapchains.remove(this);
+ rhiD->releaseSwapChainResources(this);
+ }
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
QVkSwapChain::FrameResources &frame(frameRes[i]);
@@ -7025,10 +7907,8 @@ void QVkSwapChain::destroy()
surface = lastConnectedSurface = VK_NULL_HANDLE;
- QRHI_PROF;
- QRHI_PROF_F(releaseSwapChain(this));
-
- rhiD->unregisterResource(this);
+ if (rhiD)
+ rhiD->unregisterResource(this);
}
QRhiCommandBuffer *QVkSwapChain::currentFrameCommandBuffer()
@@ -7041,6 +7921,11 @@ QRhiRenderTarget *QVkSwapChain::currentFrameRenderTarget()
return &rtWrapper;
}
+QRhiRenderTarget *QVkSwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
+{
+ return !stereo || targetBuffer == StereoTargetBuffer::LeftBuffer ? &rtWrapper : &rtWrapperRight;
+}
+
QSize QVkSwapChain::surfacePixelSize()
{
if (!ensureSurface())
@@ -7048,8 +7933,7 @@ QSize QVkSwapChain::surfacePixelSize()
// The size from the QWindow may not exactly match the surface... so if a
// size is reported from the surface, use that.
- VkSurfaceCapabilitiesKHR surfaceCaps;
- memset(&surfaceCaps, 0, sizeof(surfaceCaps));
+ VkSurfaceCapabilitiesKHR surfaceCaps = {};
QRHI_RES_RHI(QRhiVulkan);
rhiD->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(rhiD->physDev, surface, &surfaceCaps);
VkExtent2D bufferSize = surfaceCaps.currentExtent;
@@ -7060,6 +7944,52 @@ QSize QVkSwapChain::surfacePixelSize()
return QSize(int(bufferSize.width), int(bufferSize.height));
}
+static inline bool hdrFormatMatchesVkSurfaceFormat(QRhiSwapChain::Format f, const VkSurfaceFormatKHR &s)
+{
+ switch (f) {
+ case QRhiSwapChain::HDRExtendedSrgbLinear:
+ return s.format == VK_FORMAT_R16G16B16A16_SFLOAT
+ && s.colorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT;
+ case QRhiSwapChain::HDR10:
+ return (s.format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 || s.format == VK_FORMAT_A2R10G10B10_UNORM_PACK32)
+ && s.colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT;
+ case QRhiSwapChain::HDRExtendedDisplayP3Linear:
+ return s.format == VK_FORMAT_R16G16B16A16_SFLOAT
+ && s.colorSpace == VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool QVkSwapChain::isFormatSupported(Format f)
+{
+ if (f == SDR)
+ return true;
+
+ if (!m_window) {
+ qWarning("Attempted to call isFormatSupported() without a window set");
+ return false;
+ }
+
+ // we may be called before create so query the surface
+ VkSurfaceKHR surf = QVulkanInstance::surfaceForWindow(m_window);
+
+ QRHI_RES_RHI(QRhiVulkan);
+ uint32_t formatCount = 0;
+ rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR(rhiD->physDev, surf, &formatCount, nullptr);
+ QVarLengthArray<VkSurfaceFormatKHR, 8> formats(formatCount);
+ if (formatCount) {
+ rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR(rhiD->physDev, surf, &formatCount, formats.data());
+ for (uint32_t i = 0; i < formatCount; ++i) {
+ if (hdrFormatMatchesVkSurfaceFormat(f, formats[i]))
+ return true;
+ }
+ }
+
+ return false;
+}
+
QRhiRenderPassDescriptor *QVkSwapChain::newCompatibleRenderPassDescriptor()
{
// not yet built so cannot rely on data computed in createOrResize()
@@ -7079,6 +8009,7 @@ QRhiRenderPassDescriptor *QVkSwapChain::newCompatibleRenderPassDescriptor()
}
rp->ownsRp = true;
+ rp->updateSerializedFormat();
rhiD->registerResource(rp);
return rp;
}
@@ -7118,27 +8049,9 @@ bool QVkSwapChain::ensureSurface()
surface = surf;
QRHI_RES_RHI(QRhiVulkan);
- if (rhiD->gfxQueueFamilyIdx != -1) {
- if (!rhiD->inst->supportsPresent(rhiD->physDev, uint32_t(rhiD->gfxQueueFamilyIdx), m_window)) {
- qWarning("Presenting not supported on this window");
- return false;
- }
- }
-
- if (!rhiD->vkGetPhysicalDeviceSurfaceCapabilitiesKHR) {
- rhiD->vkGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
- rhiD->inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
- rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
- rhiD->inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfaceFormatsKHR"));
- rhiD->vkGetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(
- rhiD->inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfacePresentModesKHR"));
- if (!rhiD->vkGetPhysicalDeviceSurfaceCapabilitiesKHR
- || !rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR
- || !rhiD->vkGetPhysicalDeviceSurfacePresentModesKHR)
- {
- qWarning("Physical device surface queries not available");
- return false;
- }
+ if (!rhiD->inst->supportsPresent(rhiD->physDev, rhiD->gfxQueueFamilyIdx, m_window)) {
+ qWarning("Presenting not supported on this window");
+ return false;
}
quint32 formatCount = 0;
@@ -7147,16 +8060,23 @@ bool QVkSwapChain::ensureSurface()
if (formatCount)
rhiD->vkGetPhysicalDeviceSurfaceFormatsKHR(rhiD->physDev, surface, &formatCount, formats.data());
+ // See if there is a better match than the default BGRA8 format. (but if
+ // not, we will stick to the default)
const bool srgbRequested = m_flags.testFlag(sRGB);
for (int i = 0; i < int(formatCount); ++i) {
- if (formats[i].format != VK_FORMAT_UNDEFINED && srgbRequested == isSrgbFormat(formats[i].format)) {
- colorFormat = formats[i].format;
- colorSpace = formats[i].colorSpace;
- break;
+ if (formats[i].format != VK_FORMAT_UNDEFINED) {
+ bool ok = srgbRequested == isSrgbFormat(formats[i].format);
+ if (m_format != SDR)
+ ok &= hdrFormatMatchesVkSurfaceFormat(m_format, formats[i]);
+ if (ok) {
+ colorFormat = formats[i].format;
+ colorSpace = formats[i].colorSpace;
+ break;
+ }
}
}
- samples = rhiD->effectiveSampleCount(m_sampleCount);
+ samples = rhiD->effectiveSampleCountBits(m_sampleCount);
quint32 presModeCount = 0;
rhiD->vkGetPhysicalDeviceSurfacePresentModesKHR(rhiD->physDev, surface, &presModeCount, nullptr);
@@ -7212,6 +8132,7 @@ bool QVkSwapChain::createOrResize()
if (!m_renderPassDesc)
qWarning("QVkSwapChain: No renderpass descriptor set. See newCompatibleRenderPassDescriptor() and setRenderPassDescriptor().");
+ rtWrapper.setRenderPassDescriptor(m_renderPassDesc); // for the public getter in QRhiRenderTarget
rtWrapper.d.rp = QRHI_RES(QVkRenderPassDescriptor, m_renderPassDesc);
Q_ASSERT(rtWrapper.d.rp && rtWrapper.d.rp->rp);
@@ -7226,6 +8147,7 @@ bool QVkSwapChain::createOrResize()
rtWrapper.d.dsAttCount = 0;
ds = nullptr;
}
+ rtWrapper.d.dsResolveAttCount = 0;
if (samples > VK_SAMPLE_COUNT_1_BIT)
rtWrapper.d.resolveAttCount = 1;
else
@@ -7239,11 +8161,10 @@ bool QVkSwapChain::createOrResize()
samples > VK_SAMPLE_COUNT_1_BIT ? image.imageView : VK_NULL_HANDLE
};
- VkFramebufferCreateInfo fbInfo;
- memset(&fbInfo, 0, sizeof(fbInfo));
+ VkFramebufferCreateInfo fbInfo = {};
fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fbInfo.renderPass = rtWrapper.d.rp->rp;
- fbInfo.attachmentCount = uint32_t(rtWrapper.d.colorAttCount + rtWrapper.d.dsAttCount + rtWrapper.d.resolveAttCount);
+ fbInfo.attachmentCount = uint32_t(rtWrapper.d.colorAttCount + rtWrapper.d.dsAttCount + rtWrapper.d.resolveAttCount + rtWrapper.d.dsResolveAttCount);
fbInfo.pAttachments = views;
fbInfo.width = uint32_t(pixelSize.width());
fbInfo.height = uint32_t(pixelSize.height());
@@ -7256,10 +8177,57 @@ bool QVkSwapChain::createOrResize()
}
}
- frameCount = 0;
+ if (stereo) {
+ rtWrapperRight.setRenderPassDescriptor(
+ m_renderPassDesc); // for the public getter in QRhiRenderTarget
+ rtWrapperRight.d.rp = QRHI_RES(QVkRenderPassDescriptor, m_renderPassDesc);
+ Q_ASSERT(rtWrapperRight.d.rp && rtWrapperRight.d.rp->rp);
- QRHI_PROF;
- QRHI_PROF_F(resizeSwapChain(this, QVK_FRAMES_IN_FLIGHT, samples > VK_SAMPLE_COUNT_1_BIT ? QVK_FRAMES_IN_FLIGHT : 0, samples));
+ rtWrapperRight.d.pixelSize = pixelSize;
+ rtWrapperRight.d.dpr = float(window->devicePixelRatio());
+ rtWrapperRight.d.sampleCount = samples;
+ rtWrapperRight.d.colorAttCount = 1;
+ if (m_depthStencil) {
+ rtWrapperRight.d.dsAttCount = 1;
+ ds = QRHI_RES(QVkRenderBuffer, m_depthStencil);
+ } else {
+ rtWrapperRight.d.dsAttCount = 0;
+ ds = nullptr;
+ }
+ rtWrapperRight.d.dsResolveAttCount = 0;
+ if (samples > VK_SAMPLE_COUNT_1_BIT)
+ rtWrapperRight.d.resolveAttCount = 1;
+ else
+ rtWrapperRight.d.resolveAttCount = 0;
+
+ for (int i = 0; i < bufferCount; ++i) {
+ QVkSwapChain::ImageResources &image(imageRes[i + bufferCount]);
+ VkImageView views[3] = {
+ // color, ds, resolve
+ samples > VK_SAMPLE_COUNT_1_BIT ? image.msaaImageView : image.imageView,
+ ds ? ds->imageView : VK_NULL_HANDLE,
+ samples > VK_SAMPLE_COUNT_1_BIT ? image.imageView : VK_NULL_HANDLE
+ };
+
+ VkFramebufferCreateInfo fbInfo = {};
+ fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fbInfo.renderPass = rtWrapperRight.d.rp->rp;
+ fbInfo.attachmentCount = uint32_t(rtWrapperRight.d.colorAttCount + rtWrapperRight.d.dsAttCount
+ + rtWrapperRight.d.resolveAttCount + rtWrapperRight.d.dsResolveAttCount);
+ fbInfo.pAttachments = views;
+ fbInfo.width = uint32_t(pixelSize.width());
+ fbInfo.height = uint32_t(pixelSize.height());
+ fbInfo.layers = 1;
+
+ VkResult err = rhiD->df->vkCreateFramebuffer(rhiD->dev, &fbInfo, nullptr, &image.fb);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create framebuffer: %d", err);
+ return false;
+ }
+ }
+ }
+
+ frameCount = 0;
if (needsRegistration)
rhiD->registerResource(this);
diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h
index 4d20b93911..ad8687de5d 100644
--- a/src/gui/rhi/qrhivulkan_p.h
+++ b/src/gui/rhi/qrhivulkan_p.h
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHIVULKAN_H
-#define QRHIVULKAN_H
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QRHIVULKAN_P_H
+#define QRHIVULKAN_P_H
//
// W A R N I N G
@@ -51,44 +15,1025 @@
// We mean it.
//
-#include <private/qrhi_p.h>
-#include <QtGui/qvulkaninstance.h> // this is where vulkan.h gets pulled in
+#include "qrhi_p.h"
QT_BEGIN_NAMESPACE
-struct Q_GUI_EXPORT QRhiVulkanInitParams : public QRhiInitParams
+class QVulkanFunctions;
+class QVulkanDeviceFunctions;
+
+static const int QVK_FRAMES_IN_FLIGHT = 2;
+
+static const int QVK_DESC_SETS_PER_POOL = 128;
+static const int QVK_UNIFORM_BUFFERS_PER_POOL = 256;
+static const int QVK_COMBINED_IMAGE_SAMPLERS_PER_POOL = 256;
+static const int QVK_STORAGE_BUFFERS_PER_POOL = 128;
+static const int QVK_STORAGE_IMAGES_PER_POOL = 128;
+
+static const int QVK_MAX_ACTIVE_TIMESTAMP_PAIRS = 16;
+
+// no vk_mem_alloc.h available here, void* is good enough
+typedef void * QVkAlloc;
+typedef void * QVkAllocator;
+
+struct QVkBuffer : public QRhiBuffer
{
- QVulkanInstance *inst = nullptr;
- QWindow *window = nullptr;
- QByteArrayList deviceExtensions;
+ QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
+ ~QVkBuffer();
+ void destroy() override;
+ bool create() override;
+ QRhiBuffer::NativeBuffer nativeBuffer() override;
+ char *beginFullDynamicBufferUpdateForCurrentFrame() override;
+ void endFullDynamicBufferUpdateForCurrentFrame() override;
- static QByteArrayList preferredInstanceExtensions();
- static QByteArrayList preferredExtensionsForImportedDevice();
+ VkBuffer buffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];
+ struct DynamicUpdate {
+ quint32 offset;
+ QRhiBufferData data;
+ };
+ QVarLengthArray<DynamicUpdate, 16> pendingDynamicUpdates[QVK_FRAMES_IN_FLIGHT];
+ VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
+ struct UsageState {
+ VkAccessFlags access = 0;
+ VkPipelineStageFlags stage = 0;
+ };
+ UsageState usageState[QVK_FRAMES_IN_FLIGHT];
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+ friend class QRhiVulkan;
};
-struct Q_GUI_EXPORT QRhiVulkanNativeHandles : public QRhiNativeHandles
+Q_DECLARE_TYPEINFO(QVkBuffer::DynamicUpdate, Q_RELOCATABLE_TYPE);
+
+struct QVkTexture;
+
+struct QVkRenderBuffer : public QRhiRenderBuffer
{
- // to import a physical device (always required)
- VkPhysicalDevice physDev = VK_NULL_HANDLE;
- // to import a device and queue
- VkDevice dev = VK_NULL_HANDLE;
- int gfxQueueFamilyIdx = -1;
- int gfxQueueIdx = 0;
- VkQueue gfxQueue = VK_NULL_HANDLE;
- // and optionally, the mem allocator
- void *vmemAllocator = nullptr;
+ QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
+ int sampleCount, Flags flags,
+ QRhiTexture::Format backingFormatHint);
+ ~QVkRenderBuffer();
+ void destroy() override;
+ bool create() override;
+ QRhiTexture::Format backingFormat() const override;
+
+ VkDeviceMemory memory = VK_NULL_HANDLE;
+ VkImage image = VK_NULL_HANDLE;
+ VkImageView imageView = VK_NULL_HANDLE;
+ VkSampleCountFlagBits samples;
+ QVkTexture *backingTexture = nullptr;
+ VkFormat vkformat;
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+ friend class QRhiVulkan;
+};
+
+struct QVkTexture : public QRhiTexture
+{
+ QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
+ int arraySize, int sampleCount, Flags flags);
+ ~QVkTexture();
+ void destroy() override;
+ bool create() override;
+ bool createFrom(NativeTexture src) override;
+ NativeTexture nativeTexture() override;
+ void setNativeLayout(int layout) override;
+
+ bool prepareCreate(QSize *adjustedSize = nullptr);
+ bool finishCreate();
+ VkImageView perLevelImageViewForLoadStore(int level);
+
+ VkImage image = VK_NULL_HANDLE;
+ VkImageView imageView = VK_NULL_HANDLE;
+ QVkAlloc imageAlloc = nullptr;
+ VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
+ VkImageView perLevelImageViews[QRhi::MAX_MIP_LEVELS];
+ bool owns = true;
+ struct UsageState {
+ // no tracking of subresource layouts (some operations can keep
+ // subresources in different layouts for some time, but that does not
+ // need to be kept track of)
+ VkImageLayout layout;
+ VkAccessFlags access;
+ VkPipelineStageFlags stage;
+ };
+ UsageState usageState;
+ VkFormat vkformat;
+ uint mipLevelCount = 0;
+ VkSampleCountFlagBits samples;
+ VkFormat viewFormat;
+ VkFormat viewFormatForSampling;
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+ friend class QRhiVulkan;
+};
+
+struct QVkSampler : public QRhiSampler
+{
+ QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
+ AddressMode u, AddressMode v, AddressMode w);
+ ~QVkSampler();
+ void destroy() override;
+ bool create() override;
+
+ VkSampler sampler = VK_NULL_HANDLE;
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+ friend class QRhiVulkan;
+};
+
+struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor
+{
+ QVkRenderPassDescriptor(QRhiImplementation *rhi);
+ ~QVkRenderPassDescriptor();
+ void destroy() override;
+ bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
+ QVector<quint32> serializedFormat() const override;
+ const QRhiNativeHandles *nativeHandles() override;
+
+ void updateSerializedFormat();
+
+ VkRenderPass rp = VK_NULL_HANDLE;
+ bool ownsRp = false;
+ QVarLengthArray<VkAttachmentDescription, 8> attDescs;
+ QVarLengthArray<VkAttachmentReference, 8> colorRefs;
+ QVarLengthArray<VkAttachmentReference, 8> resolveRefs;
+ QVarLengthArray<VkSubpassDependency, 2> subpassDeps;
+ bool hasDepthStencil = false;
+ bool hasDepthStencilResolve = false;
+ uint32_t multiViewCount = 0;
+ VkAttachmentReference dsRef;
+ VkAttachmentReference dsResolveRef;
+ QVector<quint32> serializedFormatData;
+ QRhiVulkanRenderPassNativeHandles nativeHandlesStruct;
+ int lastActiveFrameSlot = -1;
+};
+
+struct QVkRenderTargetData
+{
+ VkFramebuffer fb = VK_NULL_HANDLE;
+ QVkRenderPassDescriptor *rp = nullptr;
+ QSize pixelSize;
+ float dpr = 1;
+ int sampleCount = 1;
+ int colorAttCount = 0;
+ int dsAttCount = 0;
+ int resolveAttCount = 0;
+ int dsResolveAttCount = 0;
+ int multiViewCount = 0;
+ QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList;
+ static const int MAX_COLOR_ATTACHMENTS = 8;
+};
+
+struct QVkSwapChainRenderTarget : public QRhiSwapChainRenderTarget
+{
+ QVkSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
+ ~QVkSwapChainRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QVkRenderTargetData d;
+};
+
+struct QVkTextureRenderTarget : public QRhiTextureRenderTarget
+{
+ QVkTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
+ ~QVkTextureRenderTarget();
+ void destroy() override;
+
+ QSize pixelSize() const override;
+ float devicePixelRatio() const override;
+ int sampleCount() const override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool create() override;
+
+ QVkRenderTargetData d;
+ VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
+ VkImageView dsv = VK_NULL_HANDLE;
+ VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
+ VkImageView resdsv = VK_NULL_HANDLE;
+ int lastActiveFrameSlot = -1;
+ friend class QRhiVulkan;
+};
+
+struct QVkShaderResourceBindings : public QRhiShaderResourceBindings
+{
+ QVkShaderResourceBindings(QRhiImplementation *rhi);
+ ~QVkShaderResourceBindings();
+ void destroy() override;
+ bool create() override;
+ void updateResources(UpdateFlags flags) override;
+
+ QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
+ bool hasSlottedResource = false;
+ bool hasDynamicOffset = false;
+ int poolIndex = -1;
+ VkDescriptorSetLayout layout = VK_NULL_HANDLE;
+ VkDescriptorSet descSets[QVK_FRAMES_IN_FLIGHT]; // multiple sets to support dynamic buffers
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+
+ // Keep track of the generation number of each referenced QRhi* to be able
+ // to detect that the underlying descriptor set became out of date and they
+ // need to be written again with the up-to-date VkBuffer etc. objects.
+ struct BoundUniformBufferData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundSampledTextureData {
+ int count;
+ struct {
+ quint64 texId;
+ uint texGeneration;
+ quint64 samplerId;
+ uint samplerGeneration;
+ } d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
+ };
+ struct BoundStorageImageData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundStorageBufferData {
+ quint64 id;
+ uint generation;
+ };
+ struct BoundResourceData {
+ union {
+ BoundUniformBufferData ubuf;
+ BoundSampledTextureData stex;
+ BoundStorageImageData simage;
+ BoundStorageBufferData sbuf;
+ };
+ };
+ QVarLengthArray<BoundResourceData, 8> boundResourceData[QVK_FRAMES_IN_FLIGHT];
+
+ friend class QRhiVulkan;
+};
+
+Q_DECLARE_TYPEINFO(QVkShaderResourceBindings::BoundResourceData, Q_RELOCATABLE_TYPE);
+
+struct QVkGraphicsPipeline : public QRhiGraphicsPipeline
+{
+ QVkGraphicsPipeline(QRhiImplementation *rhi);
+ ~QVkGraphicsPipeline();
+ void destroy() override;
+ bool create() override;
+
+ VkPipelineLayout layout = VK_NULL_HANDLE;
+ VkPipeline pipeline = VK_NULL_HANDLE;
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+ friend class QRhiVulkan;
+};
+
+struct QVkComputePipeline : public QRhiComputePipeline
+{
+ QVkComputePipeline(QRhiImplementation *rhi);
+ ~QVkComputePipeline();
+ void destroy() override;
+ bool create() override;
+
+ VkPipelineLayout layout = VK_NULL_HANDLE;
+ VkPipeline pipeline = VK_NULL_HANDLE;
+ int lastActiveFrameSlot = -1;
+ uint generation = 0;
+ friend class QRhiVulkan;
+};
+
+struct QVkCommandBuffer : public QRhiCommandBuffer
+{
+ QVkCommandBuffer(QRhiImplementation *rhi);
+ ~QVkCommandBuffer();
+ void destroy() override;
+
+ const QRhiNativeHandles *nativeHandles();
+
+ VkCommandBuffer cb = VK_NULL_HANDLE; // primary
+ QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct;
+
+ enum PassType {
+ NoPass,
+ RenderPass,
+ ComputePass
+ };
+
+ void resetState() {
+ recordingPass = NoPass;
+ passUsesSecondaryCb = false;
+ lastGpuTime = 0;
+ currentTarget = nullptr;
+ activeSecondaryCbStack.clear();
+ resetCommands();
+ resetCachedState();
+ }
+
+ void resetCachedState() {
+ currentGraphicsPipeline = nullptr;
+ currentComputePipeline = nullptr;
+ currentPipelineGeneration = 0;
+ currentGraphicsSrb = nullptr;
+ currentComputeSrb = nullptr;
+ currentSrbGeneration = 0;
+ currentDescSetSlot = -1;
+ currentIndexBuffer = VK_NULL_HANDLE;
+ currentIndexOffset = 0;
+ currentIndexFormat = VK_INDEX_TYPE_UINT16;
+ memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
+ memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
+ inExternal = false;
+ }
+
+ PassType recordingPass;
+ bool passUsesSecondaryCb;
+ double lastGpuTime = 0;
+ QRhiRenderTarget *currentTarget;
+ QRhiGraphicsPipeline *currentGraphicsPipeline;
+ QRhiComputePipeline *currentComputePipeline;
+ uint currentPipelineGeneration;
+ QRhiShaderResourceBindings *currentGraphicsSrb;
+ QRhiShaderResourceBindings *currentComputeSrb;
+ uint currentSrbGeneration;
+ int currentDescSetSlot;
+ VkBuffer currentIndexBuffer;
+ quint32 currentIndexOffset;
+ VkIndexType currentIndexFormat;
+ static const int VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32;
+ VkBuffer currentVertexBuffers[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ quint32 currentVertexOffsets[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ QVarLengthArray<VkCommandBuffer, 4> activeSecondaryCbStack;
+ bool inExternal;
+
+ struct {
+ QHash<QRhiResource *, QPair<VkAccessFlags, bool> > writtenResources;
+ void reset() {
+ writtenResources.clear();
+ }
+ } computePassState;
+
+ struct Command {
+ enum Cmd {
+ CopyBuffer,
+ CopyBufferToImage,
+ CopyImage,
+ CopyImageToBuffer,
+ ImageBarrier,
+ BufferBarrier,
+ BlitImage,
+ BeginRenderPass,
+ EndRenderPass,
+ BindPipeline,
+ BindDescriptorSet,
+ BindVertexBuffer,
+ BindIndexBuffer,
+ SetViewport,
+ SetScissor,
+ SetBlendConstants,
+ SetStencilRef,
+ Draw,
+ DrawIndexed,
+ DebugMarkerBegin,
+ DebugMarkerEnd,
+ DebugMarkerInsert,
+ TransitionPassResources,
+ Dispatch,
+ ExecuteSecondary
+ };
+ Cmd cmd;
+
+ union Args {
+ struct {
+ VkBuffer src;
+ VkBuffer dst;
+ VkBufferCopy desc;
+ } copyBuffer;
+ struct {
+ VkBuffer src;
+ VkImage dst;
+ VkImageLayout dstLayout;
+ int count;
+ int bufferImageCopyIndex;
+ } copyBufferToImage;
+ struct {
+ VkImage src;
+ VkImageLayout srcLayout;
+ VkImage dst;
+ VkImageLayout dstLayout;
+ VkImageCopy desc;
+ } copyImage;
+ struct {
+ VkImage src;
+ VkImageLayout srcLayout;
+ VkBuffer dst;
+ VkBufferImageCopy desc;
+ } copyImageToBuffer;
+ struct {
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
+ int count;
+ int index;
+ } imageBarrier;
+ struct {
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
+ int count;
+ int index;
+ } bufferBarrier;
+ struct {
+ VkImage src;
+ VkImageLayout srcLayout;
+ VkImage dst;
+ VkImageLayout dstLayout;
+ VkFilter filter;
+ VkImageBlit desc;
+ } blitImage;
+ struct {
+ VkRenderPassBeginInfo desc;
+ int clearValueIndex;
+ bool useSecondaryCb;
+ } beginRenderPass;
+ struct {
+ } endRenderPass;
+ struct {
+ VkPipelineBindPoint bindPoint;
+ VkPipeline pipeline;
+ } bindPipeline;
+ struct {
+ VkPipelineBindPoint bindPoint;
+ VkPipelineLayout pipelineLayout;
+ VkDescriptorSet descSet;
+ int dynamicOffsetCount;
+ int dynamicOffsetIndex;
+ } bindDescriptorSet;
+ struct {
+ int startBinding;
+ int count;
+ int vertexBufferIndex;
+ int vertexBufferOffsetIndex;
+ } bindVertexBuffer;
+ struct {
+ VkBuffer buf;
+ VkDeviceSize ofs;
+ VkIndexType type;
+ } bindIndexBuffer;
+ struct {
+ VkViewport viewport;
+ } setViewport;
+ struct {
+ VkRect2D scissor;
+ } setScissor;
+ struct {
+ float c[4];
+ } setBlendConstants;
+ struct {
+ uint32_t ref;
+ } setStencilRef;
+ struct {
+ uint32_t vertexCount;
+ uint32_t instanceCount;
+ uint32_t firstVertex;
+ uint32_t firstInstance;
+ } draw;
+ struct {
+ uint32_t indexCount;
+ uint32_t instanceCount;
+ uint32_t firstIndex;
+ int32_t vertexOffset;
+ uint32_t firstInstance;
+ } drawIndexed;
+ struct {
+#ifdef VK_EXT_debug_utils
+ VkDebugUtilsLabelEXT label;
+ int labelNameIndex;
+#endif
+ } debugMarkerBegin;
+ struct {
+ } debugMarkerEnd;
+ struct {
+#ifdef VK_EXT_debug_utils
+ VkDebugUtilsLabelEXT label;
+ int labelNameIndex;
+#endif
+ } debugMarkerInsert;
+ struct {
+ int trackerIndex;
+ } transitionResources;
+ struct {
+ int x, y, z;
+ } dispatch;
+ struct {
+ VkCommandBuffer cb;
+ } executeSecondary;
+ } args;
+ };
+
+ QRhiBackendCommandList<Command> commands;
+ QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers;
+ int currentPassResTrackerIndex;
+
+ void resetCommands() {
+ commands.reset();
+ resetPools();
+
+ passResTrackers.clear();
+ currentPassResTrackerIndex = -1;
+ }
+
+ void resetPools() {
+ pools.clearValue.clear();
+ pools.bufferImageCopy.clear();
+ pools.dynamicOffset.clear();
+ pools.vertexBuffer.clear();
+ pools.vertexBufferOffset.clear();
+ pools.debugMarkerData.clear();
+ pools.imageBarrier.clear();
+ pools.bufferBarrier.clear();
+ }
+
+ struct {
+ QVarLengthArray<VkClearValue, 4> clearValue;
+ QVarLengthArray<VkBufferImageCopy, 16> bufferImageCopy;
+ QVarLengthArray<uint32_t, 4> dynamicOffset;
+ QVarLengthArray<VkBuffer, 4> vertexBuffer;
+ QVarLengthArray<VkDeviceSize, 4> vertexBufferOffset;
+ QVarLengthArray<QByteArray, 4> debugMarkerData;
+ QVarLengthArray<VkImageMemoryBarrier, 8> imageBarrier;
+ QVarLengthArray<VkBufferMemoryBarrier, 8> bufferBarrier;
+ } pools;
+
+ friend class QRhiVulkan;
};
-struct Q_GUI_EXPORT QRhiVulkanCommandBufferNativeHandles : public QRhiNativeHandles
+struct QVkSwapChain : public QRhiSwapChain
{
- VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
+ QVkSwapChain(QRhiImplementation *rhi);
+ ~QVkSwapChain();
+ void destroy() override;
+
+ QRhiCommandBuffer *currentFrameCommandBuffer() override;
+ QRhiRenderTarget *currentFrameRenderTarget() override;
+ QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override;
+
+ QSize surfacePixelSize() override;
+ bool isFormatSupported(Format f) override;
+
+ QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
+ bool createOrResize() override;
+
+ bool ensureSurface();
+
+ static const quint32 EXPECTED_MAX_BUFFER_COUNT = 4;
+
+ QWindow *window = nullptr;
+ QSize pixelSize;
+ bool supportsReadback = false;
+ bool stereo = false;
+ VkSwapchainKHR sc = VK_NULL_HANDLE;
+ int bufferCount = 0;
+ VkSurfaceKHR surface = VK_NULL_HANDLE;
+ VkSurfaceKHR lastConnectedSurface = VK_NULL_HANDLE;
+ VkFormat colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
+ VkColorSpaceKHR colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
+ QVkRenderBuffer *ds = nullptr;
+ VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
+ QVarLengthArray<VkPresentModeKHR, 8> supportedPresentationModes;
+ VkDeviceMemory msaaImageMem = VK_NULL_HANDLE;
+ QVkSwapChainRenderTarget rtWrapper;
+ QVkSwapChainRenderTarget rtWrapperRight;
+ QVkCommandBuffer cbWrapper;
+
+ struct ImageResources {
+ VkImage image = VK_NULL_HANDLE;
+ VkImageView imageView = VK_NULL_HANDLE;
+ VkFramebuffer fb = VK_NULL_HANDLE;
+ VkImage msaaImage = VK_NULL_HANDLE;
+ VkImageView msaaImageView = VK_NULL_HANDLE;
+ enum LastUse {
+ ScImageUseNone,
+ ScImageUseRender,
+ ScImageUseTransferSource
+ };
+ LastUse lastUse = ScImageUseNone;
+ };
+ QVarLengthArray<ImageResources, EXPECTED_MAX_BUFFER_COUNT> imageRes;
+
+ struct FrameResources {
+ VkFence imageFence = VK_NULL_HANDLE;
+ bool imageFenceWaitable = false;
+ VkSemaphore imageSem = VK_NULL_HANDLE;
+ VkSemaphore drawSem = VK_NULL_HANDLE;
+ bool imageAcquired = false;
+ bool imageSemWaitable = false;
+ VkFence cmdFence = VK_NULL_HANDLE;
+ bool cmdFenceWaitable = false;
+ VkCommandBuffer cmdBuf = VK_NULL_HANDLE; // primary
+ int timestampQueryIndex = -1;
+ } frameRes[QVK_FRAMES_IN_FLIGHT];
+
+ quint32 currentImageIndex = 0; // index in imageRes
+ quint32 currentFrameSlot = 0; // index in frameRes
+ int frameCount = 0;
+
+ friend class QRhiVulkan;
};
-struct Q_GUI_EXPORT QRhiVulkanRenderPassNativeHandles : public QRhiNativeHandles
+class QRhiVulkan : public QRhiImplementation
{
- VkRenderPass renderPass = VK_NULL_HANDLE;
+public:
+ QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *importParams = nullptr);
+
+ bool create(QRhi::Flags flags) override;
+ void destroy() override;
+
+ QRhiGraphicsPipeline *createGraphicsPipeline() override;
+ QRhiComputePipeline *createComputePipeline() override;
+ QRhiShaderResourceBindings *createShaderResourceBindings() override;
+ QRhiBuffer *createBuffer(QRhiBuffer::Type type,
+ QRhiBuffer::UsageFlags usage,
+ quint32 size) override;
+ QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
+ const QSize &pixelSize,
+ int sampleCount,
+ QRhiRenderBuffer::Flags flags,
+ QRhiTexture::Format backingFormatHint) override;
+ QRhiTexture *createTexture(QRhiTexture::Format format,
+ const QSize &pixelSize,
+ int depth,
+ int arraySize,
+ int sampleCount,
+ QRhiTexture::Flags flags) override;
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
+ QRhiSampler::Filter mipmapMode,
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
+
+ QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
+ QRhiTextureRenderTarget::Flags flags) override;
+
+ QRhiSwapChain *createSwapChain() override;
+ QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
+ QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
+ QRhi::FrameOpResult finish() override;
+
+ void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void beginPass(QRhiCommandBuffer *cb,
+ QRhiRenderTarget *rt,
+ const QColor &colorClearValue,
+ const QRhiDepthStencilClearValue &depthStencilClearValue,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+
+ void setGraphicsPipeline(QRhiCommandBuffer *cb,
+ QRhiGraphicsPipeline *ps) override;
+
+ void setShaderResources(QRhiCommandBuffer *cb,
+ QRhiShaderResourceBindings *srb,
+ int dynamicOffsetCount,
+ const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
+
+ void setVertexInput(QRhiCommandBuffer *cb,
+ int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
+ QRhiBuffer *indexBuf, quint32 indexOffset,
+ QRhiCommandBuffer::IndexFormat indexFormat) override;
+
+ void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
+ void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
+ void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
+ void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
+
+ void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
+ quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
+
+ void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
+ quint32 instanceCount, quint32 firstIndex,
+ qint32 vertexOffset, quint32 firstInstance) override;
+
+ void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
+ void debugMarkEnd(QRhiCommandBuffer *cb) override;
+ void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
+
+ void beginComputePass(QRhiCommandBuffer *cb,
+ QRhiResourceUpdateBatch *resourceUpdates,
+ QRhiCommandBuffer::BeginPassFlags flags) override;
+ void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
+ void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
+ void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
+
+ const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
+ void beginExternal(QRhiCommandBuffer *cb) override;
+ void endExternal(QRhiCommandBuffer *cb) override;
+ double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
+
+ QList<int> supportedSampleCounts() const override;
+ int ubufAlignment() const override;
+ bool isYUpInFramebuffer() const override;
+ bool isYUpInNDC() const override;
+ bool isClipDepthZeroToOne() const override;
+ QMatrix4x4 clipSpaceCorrMatrix() const override;
+ bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
+ bool isFeatureSupported(QRhi::Feature feature) const override;
+ int resourceLimit(QRhi::ResourceLimit limit) const override;
+ const QRhiNativeHandles *nativeHandles() override;
+ QRhiDriverInfo driverInfo() const override;
+ QRhiStats statistics() override;
+ bool makeThreadLocalNativeContextCurrent() override;
+ void releaseCachedResources() override;
+ bool isDeviceLost() const override;
+
+ QByteArray pipelineCacheData() override;
+ void setPipelineCacheData(const QByteArray &data) override;
+
+ VkResult createDescriptorPool(VkDescriptorPool *pool);
+ bool allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, VkDescriptorSet *result, int *resultPoolIndex);
+ uint32_t chooseTransientImageMemType(VkImage img, uint32_t startIndex);
+ bool createTransientImage(VkFormat format, const QSize &pixelSize, VkImageUsageFlags usage,
+ VkImageAspectFlags aspectMask, VkSampleCountFlagBits samples,
+ VkDeviceMemory *mem, VkImage *images, VkImageView *views, int count);
+
+ bool recreateSwapChain(QRhiSwapChain *swapChain);
+ void releaseSwapChainResources(QRhiSwapChain *swapChain);
+
+ VkFormat optimalDepthStencilFormat();
+ VkSampleCountFlagBits effectiveSampleCountBits(int sampleCount);
+ bool createDefaultRenderPass(QVkRenderPassDescriptor *rpD,
+ bool hasDepthStencil,
+ VkSampleCountFlagBits samples,
+ VkFormat colorFormat);
+ bool createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
+ const QRhiColorAttachment *firstColorAttachment,
+ const QRhiColorAttachment *lastColorAttachment,
+ bool preserveColor,
+ bool preserveDs,
+ bool storeDs,
+ QRhiRenderBuffer *depthStencilBuffer,
+ QRhiTexture *depthTexture,
+ QRhiTexture *depthResolveTexture);
+ bool ensurePipelineCache(const void *initialData = nullptr, size_t initialDataSize = 0);
+ VkShaderModule createShader(const QByteArray &spirv);
+
+ void prepareNewFrame(QRhiCommandBuffer *cb);
+ VkCommandBuffer startSecondaryCommandBuffer(QVkRenderTargetData *rtD = nullptr);
+ void endAndEnqueueSecondaryCommandBuffer(VkCommandBuffer cb, QVkCommandBuffer *cbD);
+ QRhi::FrameOpResult startPrimaryCommandBuffer(VkCommandBuffer *cb);
+ QRhi::FrameOpResult endAndSubmitPrimaryCommandBuffer(VkCommandBuffer cb, VkFence cmdFence,
+ VkSemaphore *waitSem, VkSemaphore *signalSem);
+ void waitCommandCompletion(int frameSlot);
+ VkDeviceSize subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
+ using BufferImageCopyList = QVarLengthArray<VkBufferImageCopy, 16>;
+ void prepareUploadSubres(QVkTexture *texD, int layer, int level,
+ const QRhiTextureSubresourceUploadDescription &subresDesc,
+ size_t *curOfs, void *mp,
+ BufferImageCopyList *copyInfos);
+ void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates);
+ void executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot);
+ void enqueueTransitionPassResources(QVkCommandBuffer *cbD);
+ void recordPrimaryCommandBuffer(QVkCommandBuffer *cbD);
+ void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
+ QVkBuffer *bufD,
+ int slot,
+ QRhiPassResourceTracker::BufferAccess access,
+ QRhiPassResourceTracker::BufferStage stage);
+ void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker,
+ QVkTexture *texD,
+ QRhiPassResourceTracker::TextureAccess access,
+ QRhiPassResourceTracker::TextureStage stage);
+ void recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhiPassResourceTracker &tracker);
+ void activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRenderTarget *rtD);
+ void executeDeferredReleases(bool forced = false);
+ void finishActiveReadbacks(bool forced = false);
+
+ void setObjectName(uint64_t object, VkObjectType type, const QByteArray &name, int slot = -1);
+ void trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, int slot,
+ VkAccessFlags access, VkPipelineStageFlags stage);
+ void trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD,
+ VkImageLayout layout, VkAccessFlags access, VkPipelineStageFlags stage);
+ void depthStencilExplicitBarrier(QVkCommandBuffer *cbD, QVkRenderBuffer *rbD);
+ void subresourceBarrier(QVkCommandBuffer *cbD, VkImage image,
+ VkImageLayout oldLayout, VkImageLayout newLayout,
+ VkAccessFlags srcAccess, VkAccessFlags dstAccess,
+ VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage,
+ int startLayer, int layerCount,
+ int startLevel, int levelCount);
+ void updateShaderResourceBindings(QRhiShaderResourceBindings *srb, int descSetIdx = -1);
+ void ensureCommandPoolForNewFrame();
+ double elapsedSecondsFromTimestamp(quint64 timestamp[2], bool *ok);
+ void printExtraErrorInfo(VkResult err);
+
+ QVulkanInstance *inst = nullptr;
+ QWindow *maybeWindow = nullptr;
+ QByteArrayList requestedDeviceExtensions;
+ bool importedDevice = false;
+ VkPhysicalDevice physDev = VK_NULL_HANDLE;
+ VkDevice dev = VK_NULL_HANDLE;
+ VkCommandPool cmdPool[QVK_FRAMES_IN_FLIGHT] = {};
+ quint32 gfxQueueFamilyIdx = 0;
+ quint32 gfxQueueIdx = 0;
+ VkQueue gfxQueue = VK_NULL_HANDLE;
+ quint32 timestampValidBits = 0;
+ bool importedAllocator = false;
+ QVkAllocator allocator = nullptr;
+ QVulkanFunctions *f = nullptr;
+ QVulkanDeviceFunctions *df = nullptr;
+ QRhi::Flags rhiFlags;
+ VkPhysicalDeviceFeatures physDevFeatures;
+#ifdef VK_VERSION_1_1
+ VkPhysicalDeviceMultiviewFeatures multiviewFeaturesIfApi11;
+#endif
+#ifdef VK_VERSION_1_2
+ VkPhysicalDeviceVulkan11Features physDevFeatures11IfApi12OrNewer;
+ VkPhysicalDeviceVulkan12Features physDevFeatures12;
+#endif
+#ifdef VK_VERSION_1_3
+ VkPhysicalDeviceVulkan13Features physDevFeatures13;
+#endif
+ VkPhysicalDeviceProperties physDevProperties;
+ VkDeviceSize ubufAlign;
+ VkDeviceSize texbufAlign;
+ bool deviceLost = false;
+ bool releaseCachedResourcesCalledBeforeFrameStart = false;
+
+#ifdef VK_EXT_debug_utils
+ PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr;
+ PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT = nullptr;
+ PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT = nullptr;
+ PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT = nullptr;
+#endif
+
+ PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr;
+ PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
+ PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
+ PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
+ PFN_vkQueuePresentKHR vkQueuePresentKHR;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
+ PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
+
+#ifdef VK_KHR_create_renderpass2
+ PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR = nullptr;
+#endif
+
+ struct {
+ bool compute = false;
+ bool wideLines = false;
+ bool debugUtils = false;
+ bool vertexAttribDivisor = false;
+ bool texture3DSliceAs2D = false;
+ bool tessellation = false;
+ bool geometryShader = false;
+ bool nonFillPolygonMode = false;
+ bool multiView = false;
+ bool renderPass2KHR = false;
+ bool depthStencilResolveKHR = false;
+ QVersionNumber apiVersion;
+ } caps;
+
+ VkPipelineCache pipelineCache = VK_NULL_HANDLE;
+ struct DescriptorPoolData {
+ DescriptorPoolData() { }
+ DescriptorPoolData(VkDescriptorPool pool_)
+ : pool(pool_)
+ { }
+ VkDescriptorPool pool = VK_NULL_HANDLE;
+ int refCount = 0;
+ int allocedDescSets = 0;
+ };
+ QVarLengthArray<DescriptorPoolData, 8> descriptorPools;
+ QVarLengthArray<VkCommandBuffer, 4> freeSecondaryCbs[QVK_FRAMES_IN_FLIGHT];
+
+ VkQueryPool timestampQueryPool = VK_NULL_HANDLE;
+ QBitArray timestampQueryPoolMap;
+
+ VkFormat optimalDsFormat = VK_FORMAT_UNDEFINED;
+ QMatrix4x4 clipCorrectMatrix;
+
+ QVkSwapChain *currentSwapChain = nullptr;
+ QSet<QVkSwapChain *> swapchains;
+ QRhiVulkanNativeHandles nativeHandlesStruct;
+ QRhiDriverInfo driverInfoStruct;
+
+ struct OffscreenFrame {
+ OffscreenFrame(QRhiImplementation *rhi)
+ {
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
+ cbWrapper[i] = new QVkCommandBuffer(rhi);
+ }
+ ~OffscreenFrame()
+ {
+ for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
+ delete cbWrapper[i];
+ }
+ bool active = false;
+ QVkCommandBuffer *cbWrapper[QVK_FRAMES_IN_FLIGHT];
+ VkFence cmdFence = VK_NULL_HANDLE;
+ int timestampQueryIndex = -1;
+ } ofr;
+
+ struct TextureReadback {
+ int activeFrameSlot = -1;
+ QRhiReadbackDescription desc;
+ QRhiReadbackResult *result;
+ VkBuffer stagingBuf;
+ QVkAlloc stagingAlloc;
+ quint32 byteSize;
+ QSize pixelSize;
+ QRhiTexture::Format format;
+ };
+ QVarLengthArray<TextureReadback, 2> activeTextureReadbacks;
+ struct BufferReadback {
+ int activeFrameSlot = -1;
+ QRhiReadbackResult *result;
+ quint32 byteSize;
+ VkBuffer stagingBuf;
+ QVkAlloc stagingAlloc;
+ };
+ QVarLengthArray<BufferReadback, 2> activeBufferReadbacks;
+
+ struct DeferredReleaseEntry {
+ enum Type {
+ Pipeline,
+ ShaderResourceBindings,
+ Buffer,
+ RenderBuffer,
+ Texture,
+ Sampler,
+ TextureRenderTarget,
+ RenderPass,
+ StagingBuffer,
+ SecondaryCommandBuffer
+ };
+ Type type;
+ int lastActiveFrameSlot; // -1 if not used otherwise 0..FRAMES_IN_FLIGHT-1
+ union {
+ struct {
+ VkPipeline pipeline;
+ VkPipelineLayout layout;
+ } pipelineState;
+ struct {
+ int poolIndex;
+ VkDescriptorSetLayout layout;
+ } shaderResourceBindings;
+ struct {
+ VkBuffer buffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];
+ VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
+ } buffer;
+ struct {
+ VkDeviceMemory memory;
+ VkImage image;
+ VkImageView imageView;
+ } renderBuffer;
+ struct {
+ VkImage image;
+ VkImageView imageView;
+ QVkAlloc allocation;
+ VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
+ QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
+ VkImageView extraImageViews[QRhi::MAX_MIP_LEVELS];
+ } texture;
+ struct {
+ VkSampler sampler;
+ } sampler;
+ struct {
+ VkFramebuffer fb;
+ VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
+ VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
+ VkImageView dsv;
+ VkImageView resdsv;
+ } textureRenderTarget;
+ struct {
+ VkRenderPass rp;
+ } renderPass;
+ struct {
+ VkBuffer stagingBuffer;
+ QVkAlloc stagingAllocation;
+ } stagingBuffer;
+ struct {
+ VkCommandBuffer cb;
+ } secondaryCommandBuffer;
+ };
+ };
+ QList<DeferredReleaseEntry> releaseQueue;
};
+Q_DECLARE_TYPEINFO(QRhiVulkan::DescriptorPoolData, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiVulkan::DeferredReleaseEntry, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiVulkan::TextureReadback, Q_RELOCATABLE_TYPE);
+Q_DECLARE_TYPEINFO(QRhiVulkan::BufferReadback, Q_RELOCATABLE_TYPE);
+
QT_END_NAMESPACE
#endif
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
deleted file mode 100644
index af647bb508..0000000000
--- a/src/gui/rhi/qrhivulkan_p_p.h
+++ /dev/null
@@ -1,1018 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHIVULKAN_P_H
-#define QRHIVULKAN_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qrhivulkan_p.h"
-#include "qrhi_p_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QVulkanFunctions;
-class QVulkanDeviceFunctions;
-
-static const int QVK_FRAMES_IN_FLIGHT = 2;
-
-static const int QVK_DESC_SETS_PER_POOL = 128;
-static const int QVK_UNIFORM_BUFFERS_PER_POOL = 256;
-static const int QVK_COMBINED_IMAGE_SAMPLERS_PER_POOL = 256;
-static const int QVK_STORAGE_BUFFERS_PER_POOL = 128;
-static const int QVK_STORAGE_IMAGES_PER_POOL = 128;
-
-static const int QVK_MAX_ACTIVE_TIMESTAMP_PAIRS = 16;
-
-// no vk_mem_alloc.h available here, void* is good enough
-typedef void * QVkAlloc;
-typedef void * QVkAllocator;
-
-struct QVkBuffer : public QRhiBuffer
-{
- QVkBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, int size);
- ~QVkBuffer();
- void destroy() override;
- bool create() override;
- QRhiBuffer::NativeBuffer nativeBuffer() override;
- char *beginFullDynamicBufferUpdateForCurrentFrame() override;
- void endFullDynamicBufferUpdateForCurrentFrame() override;
-
- VkBuffer buffers[QVK_FRAMES_IN_FLIGHT];
- QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];
- struct DynamicUpdate {
- int offset;
- QRhiBufferData data;
- };
- QVarLengthArray<DynamicUpdate, 16> pendingDynamicUpdates[QVK_FRAMES_IN_FLIGHT];
- VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
- QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
- struct UsageState {
- VkAccessFlags access = 0;
- VkPipelineStageFlags stage = 0;
- };
- UsageState usageState[QVK_FRAMES_IN_FLIGHT];
- int lastActiveFrameSlot = -1;
- uint generation = 0;
- friend class QRhiVulkan;
-};
-
-Q_DECLARE_TYPEINFO(QVkBuffer::DynamicUpdate, Q_RELOCATABLE_TYPE);
-
-struct QVkTexture;
-
-struct QVkRenderBuffer : public QRhiRenderBuffer
-{
- QVkRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
- int sampleCount, Flags flags,
- QRhiTexture::Format backingFormatHint);
- ~QVkRenderBuffer();
- void destroy() override;
- bool create() override;
- QRhiTexture::Format backingFormat() const override;
-
- VkDeviceMemory memory = VK_NULL_HANDLE;
- VkImage image = VK_NULL_HANDLE;
- VkImageView imageView = VK_NULL_HANDLE;
- VkSampleCountFlagBits samples;
- QVkTexture *backingTexture = nullptr;
- VkFormat vkformat;
- int lastActiveFrameSlot = -1;
- friend class QRhiVulkan;
-};
-
-struct QVkTexture : public QRhiTexture
-{
- QVkTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
- int sampleCount, Flags flags);
- ~QVkTexture();
- void destroy() override;
- bool create() override;
- bool createFrom(NativeTexture src) override;
- NativeTexture nativeTexture() override;
- void setNativeLayout(int layout) override;
-
- bool prepareCreate(QSize *adjustedSize = nullptr);
- bool finishCreate();
- VkImageView imageViewForLevel(int level);
-
- VkImage image = VK_NULL_HANDLE;
- VkImageView imageView = VK_NULL_HANDLE;
- QVkAlloc imageAlloc = nullptr;
- VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
- QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
- VkImageView perLevelImageViews[QRhi::MAX_MIP_LEVELS];
- bool owns = true;
- struct UsageState {
- // no tracking of subresource layouts (some operations can keep
- // subresources in different layouts for some time, but that does not
- // need to be kept track of)
- VkImageLayout layout;
- VkAccessFlags access;
- VkPipelineStageFlags stage;
- };
- UsageState usageState;
- VkFormat vkformat;
- uint mipLevelCount = 0;
- VkSampleCountFlagBits samples;
- int lastActiveFrameSlot = -1;
- uint generation = 0;
- friend class QRhiVulkan;
-};
-
-struct QVkSampler : public QRhiSampler
-{
- QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v, AddressMode w);
- ~QVkSampler();
- void destroy() override;
- bool create() override;
-
- VkSampler sampler = VK_NULL_HANDLE;
- int lastActiveFrameSlot = -1;
- uint generation = 0;
- friend class QRhiVulkan;
-};
-
-struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor
-{
- QVkRenderPassDescriptor(QRhiImplementation *rhi);
- ~QVkRenderPassDescriptor();
- void destroy() override;
- bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
- const QRhiNativeHandles *nativeHandles() override;
-
- VkRenderPass rp = VK_NULL_HANDLE;
- bool ownsRp = false;
- QVarLengthArray<VkAttachmentDescription, 8> attDescs;
- QVarLengthArray<VkAttachmentReference, 8> colorRefs;
- QVarLengthArray<VkAttachmentReference, 8> resolveRefs;
- QVarLengthArray<VkSubpassDependency, 2> subpassDeps;
- bool hasDepthStencil = false;
- VkAttachmentReference dsRef;
- QRhiVulkanRenderPassNativeHandles nativeHandlesStruct;
- int lastActiveFrameSlot = -1;
-};
-
-struct QVkRenderTargetData
-{
- VkFramebuffer fb = VK_NULL_HANDLE;
- QVkRenderPassDescriptor *rp = nullptr;
- QSize pixelSize;
- float dpr = 1;
- int sampleCount = 1;
- int colorAttCount = 0;
- int dsAttCount = 0;
- int resolveAttCount = 0;
- static const int MAX_COLOR_ATTACHMENTS = 8;
-};
-
-struct QVkReferenceRenderTarget : public QRhiRenderTarget
-{
- QVkReferenceRenderTarget(QRhiImplementation *rhi);
- ~QVkReferenceRenderTarget();
- void destroy() override;
-
- QSize pixelSize() const override;
- float devicePixelRatio() const override;
- int sampleCount() const override;
-
- QVkRenderTargetData d;
-};
-
-struct QVkTextureRenderTarget : public QRhiTextureRenderTarget
-{
- QVkTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
- ~QVkTextureRenderTarget();
- void destroy() override;
-
- QSize pixelSize() const override;
- float devicePixelRatio() const override;
- int sampleCount() const override;
-
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
- bool create() override;
-
- QVkRenderTargetData d;
- VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
- VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
- int lastActiveFrameSlot = -1;
- friend class QRhiVulkan;
-};
-
-struct QVkShaderResourceBindings : public QRhiShaderResourceBindings
-{
- QVkShaderResourceBindings(QRhiImplementation *rhi);
- ~QVkShaderResourceBindings();
- void destroy() override;
- bool create() override;
-
- QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
- bool hasSlottedResource = false;
- bool hasDynamicOffset = false;
- int poolIndex = -1;
- VkDescriptorSetLayout layout = VK_NULL_HANDLE;
- VkDescriptorSet descSets[QVK_FRAMES_IN_FLIGHT]; // multiple sets to support dynamic buffers
- int lastActiveFrameSlot = -1;
- uint generation = 0;
-
- // Keep track of the generation number of each referenced QRhi* to be able
- // to detect that the underlying descriptor set became out of date and they
- // need to be written again with the up-to-date VkBuffer etc. objects.
- struct BoundUniformBufferData {
- quint64 id;
- uint generation;
- };
- struct BoundSampledTextureData {
- int count;
- struct {
- quint64 texId;
- uint texGeneration;
- quint64 samplerId;
- uint samplerGeneration;
- } d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
- };
- struct BoundStorageImageData {
- quint64 id;
- uint generation;
- };
- struct BoundStorageBufferData {
- quint64 id;
- uint generation;
- };
- struct BoundResourceData {
- union {
- BoundUniformBufferData ubuf;
- BoundSampledTextureData stex;
- BoundStorageImageData simage;
- BoundStorageBufferData sbuf;
- };
- };
- QVarLengthArray<BoundResourceData, 8> boundResourceData[QVK_FRAMES_IN_FLIGHT];
-
- friend class QRhiVulkan;
-};
-
-Q_DECLARE_TYPEINFO(QVkShaderResourceBindings::BoundResourceData, Q_RELOCATABLE_TYPE);
-
-struct QVkGraphicsPipeline : public QRhiGraphicsPipeline
-{
- QVkGraphicsPipeline(QRhiImplementation *rhi);
- ~QVkGraphicsPipeline();
- void destroy() override;
- bool create() override;
-
- VkPipelineLayout layout = VK_NULL_HANDLE;
- VkPipeline pipeline = VK_NULL_HANDLE;
- int lastActiveFrameSlot = -1;
- uint generation = 0;
- friend class QRhiVulkan;
-};
-
-struct QVkComputePipeline : public QRhiComputePipeline
-{
- QVkComputePipeline(QRhiImplementation *rhi);
- ~QVkComputePipeline();
- void destroy() override;
- bool create() override;
-
- VkPipelineLayout layout = VK_NULL_HANDLE;
- VkPipeline pipeline = VK_NULL_HANDLE;
- int lastActiveFrameSlot = -1;
- uint generation = 0;
- friend class QRhiVulkan;
-};
-
-struct QVkCommandBuffer : public QRhiCommandBuffer
-{
- QVkCommandBuffer(QRhiImplementation *rhi);
- ~QVkCommandBuffer();
- void destroy() override;
-
- const QRhiNativeHandles *nativeHandles();
-
- VkCommandBuffer cb = VK_NULL_HANDLE; // primary
- QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct;
-
- enum PassType {
- NoPass,
- RenderPass,
- ComputePass
- };
-
- void resetState() {
- recordingPass = NoPass;
- passUsesSecondaryCb = false;
- currentTarget = nullptr;
- activeSecondaryCbStack.clear();
- resetCommands();
- resetCachedState();
- }
-
- void resetCachedState() {
- currentGraphicsPipeline = nullptr;
- currentComputePipeline = nullptr;
- currentPipelineGeneration = 0;
- currentGraphicsSrb = nullptr;
- currentComputeSrb = nullptr;
- currentSrbGeneration = 0;
- currentDescSetSlot = -1;
- currentIndexBuffer = VK_NULL_HANDLE;
- currentIndexOffset = 0;
- currentIndexFormat = VK_INDEX_TYPE_UINT16;
- memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
- memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
- inExternal = false;
- }
-
- PassType recordingPass;
- bool passUsesSecondaryCb;
- QRhiRenderTarget *currentTarget;
- QRhiGraphicsPipeline *currentGraphicsPipeline;
- QRhiComputePipeline *currentComputePipeline;
- uint currentPipelineGeneration;
- QRhiShaderResourceBindings *currentGraphicsSrb;
- QRhiShaderResourceBindings *currentComputeSrb;
- uint currentSrbGeneration;
- int currentDescSetSlot;
- VkBuffer currentIndexBuffer;
- quint32 currentIndexOffset;
- VkIndexType currentIndexFormat;
- static const int VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32;
- VkBuffer currentVertexBuffers[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
- quint32 currentVertexOffsets[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
- QVarLengthArray<VkCommandBuffer, 4> activeSecondaryCbStack;
- bool inExternal;
-
- struct {
- QHash<QRhiResource *, QPair<VkAccessFlags, bool> > writtenResources;
- void reset() {
- writtenResources.clear();
- }
- } computePassState;
-
- struct Command {
- enum Cmd {
- CopyBuffer,
- CopyBufferToImage,
- CopyImage,
- CopyImageToBuffer,
- ImageBarrier,
- BufferBarrier,
- BlitImage,
- BeginRenderPass,
- EndRenderPass,
- BindPipeline,
- BindDescriptorSet,
- BindVertexBuffer,
- BindIndexBuffer,
- SetViewport,
- SetScissor,
- SetBlendConstants,
- SetStencilRef,
- Draw,
- DrawIndexed,
- DebugMarkerBegin,
- DebugMarkerEnd,
- DebugMarkerInsert,
- TransitionPassResources,
- Dispatch,
- ExecuteSecondary
- };
- Cmd cmd;
-
- union Args {
- struct {
- VkBuffer src;
- VkBuffer dst;
- VkBufferCopy desc;
- } copyBuffer;
- struct {
- VkBuffer src;
- VkImage dst;
- VkImageLayout dstLayout;
- int count;
- int bufferImageCopyIndex;
- } copyBufferToImage;
- struct {
- VkImage src;
- VkImageLayout srcLayout;
- VkImage dst;
- VkImageLayout dstLayout;
- VkImageCopy desc;
- } copyImage;
- struct {
- VkImage src;
- VkImageLayout srcLayout;
- VkBuffer dst;
- VkBufferImageCopy desc;
- } copyImageToBuffer;
- struct {
- VkPipelineStageFlags srcStageMask;
- VkPipelineStageFlags dstStageMask;
- int count;
- int index;
- } imageBarrier;
- struct {
- VkPipelineStageFlags srcStageMask;
- VkPipelineStageFlags dstStageMask;
- int count;
- int index;
- } bufferBarrier;
- struct {
- VkImage src;
- VkImageLayout srcLayout;
- VkImage dst;
- VkImageLayout dstLayout;
- VkFilter filter;
- VkImageBlit desc;
- } blitImage;
- struct {
- VkRenderPassBeginInfo desc;
- int clearValueIndex;
- bool useSecondaryCb;
- } beginRenderPass;
- struct {
- } endRenderPass;
- struct {
- VkPipelineBindPoint bindPoint;
- VkPipeline pipeline;
- } bindPipeline;
- struct {
- VkPipelineBindPoint bindPoint;
- VkPipelineLayout pipelineLayout;
- VkDescriptorSet descSet;
- int dynamicOffsetCount;
- int dynamicOffsetIndex;
- } bindDescriptorSet;
- struct {
- int startBinding;
- int count;
- int vertexBufferIndex;
- int vertexBufferOffsetIndex;
- } bindVertexBuffer;
- struct {
- VkBuffer buf;
- VkDeviceSize ofs;
- VkIndexType type;
- } bindIndexBuffer;
- struct {
- VkViewport viewport;
- } setViewport;
- struct {
- VkRect2D scissor;
- } setScissor;
- struct {
- float c[4];
- } setBlendConstants;
- struct {
- uint32_t ref;
- } setStencilRef;
- struct {
- uint32_t vertexCount;
- uint32_t instanceCount;
- uint32_t firstVertex;
- uint32_t firstInstance;
- } draw;
- struct {
- uint32_t indexCount;
- uint32_t instanceCount;
- uint32_t firstIndex;
- int32_t vertexOffset;
- uint32_t firstInstance;
- } drawIndexed;
- struct {
- VkDebugMarkerMarkerInfoEXT marker;
- int markerNameIndex;
- } debugMarkerBegin;
- struct {
- } debugMarkerEnd;
- struct {
- VkDebugMarkerMarkerInfoEXT marker;
- int markerNameIndex;
- } debugMarkerInsert;
- struct {
- int trackerIndex;
- } transitionResources;
- struct {
- int x, y, z;
- } dispatch;
- struct {
- VkCommandBuffer cb;
- } executeSecondary;
- } args;
- };
-
- QRhiBackendCommandList<Command> commands;
- QVarLengthArray<QRhiPassResourceTracker, 8> passResTrackers;
- int currentPassResTrackerIndex;
-
- void resetCommands() {
- commands.reset();
- resetPools();
-
- passResTrackers.clear();
- currentPassResTrackerIndex = -1;
- }
-
- void resetPools() {
- pools.clearValue.clear();
- pools.bufferImageCopy.clear();
- pools.dynamicOffset.clear();
- pools.vertexBuffer.clear();
- pools.vertexBufferOffset.clear();
- pools.debugMarkerData.clear();
- pools.imageBarrier.clear();
- pools.bufferBarrier.clear();
- }
-
- struct {
- QVarLengthArray<VkClearValue, 4> clearValue;
- QVarLengthArray<VkBufferImageCopy, 16> bufferImageCopy;
- QVarLengthArray<uint32_t, 4> dynamicOffset;
- QVarLengthArray<VkBuffer, 4> vertexBuffer;
- QVarLengthArray<VkDeviceSize, 4> vertexBufferOffset;
- QVarLengthArray<QByteArray, 4> debugMarkerData;
- QVarLengthArray<VkImageMemoryBarrier, 8> imageBarrier;
- QVarLengthArray<VkBufferMemoryBarrier, 8> bufferBarrier;
- } pools;
-
- friend class QRhiVulkan;
-};
-
-struct QVkSwapChain : public QRhiSwapChain
-{
- QVkSwapChain(QRhiImplementation *rhi);
- ~QVkSwapChain();
- void destroy() override;
-
- QRhiCommandBuffer *currentFrameCommandBuffer() override;
- QRhiRenderTarget *currentFrameRenderTarget() override;
-
- QSize surfacePixelSize() override;
-
- QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
- bool createOrResize() override;
-
- bool ensureSurface();
-
- static const quint32 EXPECTED_MAX_BUFFER_COUNT = 4;
-
- QWindow *window = nullptr;
- QSize pixelSize;
- bool supportsReadback = false;
- VkSwapchainKHR sc = VK_NULL_HANDLE;
- int bufferCount = 0;
- VkSurfaceKHR surface = VK_NULL_HANDLE;
- VkSurfaceKHR lastConnectedSurface = VK_NULL_HANDLE;
- VkFormat colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
- VkColorSpaceKHR colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
- QVkRenderBuffer *ds = nullptr;
- VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
- QVarLengthArray<VkPresentModeKHR, 8> supportedPresentationModes;
- VkDeviceMemory msaaImageMem = VK_NULL_HANDLE;
- QVkReferenceRenderTarget rtWrapper;
- QVkCommandBuffer cbWrapper;
-
- struct ImageResources {
- VkImage image = VK_NULL_HANDLE;
- VkImageView imageView = VK_NULL_HANDLE;
- VkFramebuffer fb = VK_NULL_HANDLE;
- VkImage msaaImage = VK_NULL_HANDLE;
- VkImageView msaaImageView = VK_NULL_HANDLE;
- enum LastUse {
- ScImageUseNone,
- ScImageUseRender,
- ScImageUseTransferSource
- };
- LastUse lastUse = ScImageUseNone;
- };
- QVarLengthArray<ImageResources, EXPECTED_MAX_BUFFER_COUNT> imageRes;
-
- struct FrameResources {
- VkFence imageFence = VK_NULL_HANDLE;
- bool imageFenceWaitable = false;
- VkSemaphore imageSem = VK_NULL_HANDLE;
- VkSemaphore drawSem = VK_NULL_HANDLE;
- bool imageAcquired = false;
- bool imageSemWaitable = false;
- VkFence cmdFence = VK_NULL_HANDLE;
- bool cmdFenceWaitable = false;
- VkCommandBuffer cmdBuf = VK_NULL_HANDLE; // primary
- int timestampQueryIndex = -1;
- } frameRes[QVK_FRAMES_IN_FLIGHT];
-
- quint32 currentImageIndex = 0; // index in imageRes
- quint32 currentFrameSlot = 0; // index in frameRes
- int frameCount = 0;
-
- friend class QRhiVulkan;
-};
-
-class QRhiVulkan : public QRhiImplementation
-{
-public:
- QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *importParams = nullptr);
-
- bool create(QRhi::Flags flags) override;
- void destroy() override;
-
- QRhiGraphicsPipeline *createGraphicsPipeline() override;
- QRhiComputePipeline *createComputePipeline() override;
- QRhiShaderResourceBindings *createShaderResourceBindings() override;
- QRhiBuffer *createBuffer(QRhiBuffer::Type type,
- QRhiBuffer::UsageFlags usage,
- int size) override;
- QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
- const QSize &pixelSize,
- int sampleCount,
- QRhiRenderBuffer::Flags flags,
- QRhiTexture::Format backingFormatHint) override;
- QRhiTexture *createTexture(QRhiTexture::Format format,
- const QSize &pixelSize,
- int depth,
- int sampleCount,
- QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
- QRhiSampler::Filter minFilter,
- QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u,
- QRhiSampler::AddressMode v,
- QRhiSampler::AddressMode w) override;
-
- QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
- QRhiTextureRenderTarget::Flags flags) override;
-
- QRhiSwapChain *createSwapChain() override;
- QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
- QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
- QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
- QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
- QRhi::FrameOpResult finish() override;
-
- void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
-
- void beginPass(QRhiCommandBuffer *cb,
- QRhiRenderTarget *rt,
- const QColor &colorClearValue,
- const QRhiDepthStencilClearValue &depthStencilClearValue,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) override;
- void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
-
- void setGraphicsPipeline(QRhiCommandBuffer *cb,
- QRhiGraphicsPipeline *ps) override;
-
- void setShaderResources(QRhiCommandBuffer *cb,
- QRhiShaderResourceBindings *srb,
- int dynamicOffsetCount,
- const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
-
- void setVertexInput(QRhiCommandBuffer *cb,
- int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
- QRhiBuffer *indexBuf, quint32 indexOffset,
- QRhiCommandBuffer::IndexFormat indexFormat) override;
-
- void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
- void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
- void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
- void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
-
- void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
- quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
-
- void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
- quint32 instanceCount, quint32 firstIndex,
- qint32 vertexOffset, quint32 firstInstance) override;
-
- void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
- void debugMarkEnd(QRhiCommandBuffer *cb) override;
- void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
-
- void beginComputePass(QRhiCommandBuffer *cb,
- QRhiResourceUpdateBatch *resourceUpdates,
- QRhiCommandBuffer::BeginPassFlags flags) override;
- void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
- void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
- void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
-
- const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
- void beginExternal(QRhiCommandBuffer *cb) override;
- void endExternal(QRhiCommandBuffer *cb) override;
-
- QList<int> supportedSampleCounts() const override;
- int ubufAlignment() const override;
- bool isYUpInFramebuffer() const override;
- bool isYUpInNDC() const override;
- bool isClipDepthZeroToOne() const override;
- QMatrix4x4 clipSpaceCorrMatrix() const override;
- bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
- bool isFeatureSupported(QRhi::Feature feature) const override;
- int resourceLimit(QRhi::ResourceLimit limit) const override;
- const QRhiNativeHandles *nativeHandles() override;
- QRhiDriverInfo driverInfo() const override;
- void sendVMemStatsToProfiler() override;
- bool makeThreadLocalNativeContextCurrent() override;
- void releaseCachedResources() override;
- bool isDeviceLost() const override;
-
- QByteArray pipelineCacheData() override;
- void setPipelineCacheData(const QByteArray &data) override;
-
- VkResult createDescriptorPool(VkDescriptorPool *pool);
- bool allocateDescriptorSet(VkDescriptorSetAllocateInfo *allocInfo, VkDescriptorSet *result, int *resultPoolIndex);
- uint32_t chooseTransientImageMemType(VkImage img, uint32_t startIndex);
- bool createTransientImage(VkFormat format, const QSize &pixelSize, VkImageUsageFlags usage,
- VkImageAspectFlags aspectMask, VkSampleCountFlagBits samples,
- VkDeviceMemory *mem, VkImage *images, VkImageView *views, int count);
-
- bool recreateSwapChain(QRhiSwapChain *swapChain);
- void releaseSwapChainResources(QRhiSwapChain *swapChain);
-
- VkFormat optimalDepthStencilFormat();
- VkSampleCountFlagBits effectiveSampleCount(int sampleCount);
- bool createDefaultRenderPass(QVkRenderPassDescriptor *rpD,
- bool hasDepthStencil,
- VkSampleCountFlagBits samples,
- VkFormat colorFormat);
- bool createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
- const QRhiColorAttachment *firstColorAttachment,
- const QRhiColorAttachment *lastColorAttachment,
- bool preserveColor,
- bool preserveDs,
- QRhiRenderBuffer *depthStencilBuffer,
- QRhiTexture *depthTexture);
- bool ensurePipelineCache(const void *initialData = nullptr, size_t initialDataSize = 0);
- VkShaderModule createShader(const QByteArray &spirv);
-
- void prepareNewFrame(QRhiCommandBuffer *cb);
- VkCommandBuffer startSecondaryCommandBuffer(QVkRenderTargetData *rtD = nullptr);
- void endAndEnqueueSecondaryCommandBuffer(VkCommandBuffer cb, QVkCommandBuffer *cbD);
- QRhi::FrameOpResult startPrimaryCommandBuffer(VkCommandBuffer *cb);
- QRhi::FrameOpResult endAndSubmitPrimaryCommandBuffer(VkCommandBuffer cb, VkFence cmdFence,
- VkSemaphore *waitSem, VkSemaphore *signalSem);
- void waitCommandCompletion(int frameSlot);
- VkDeviceSize subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
- using BufferImageCopyList = QVarLengthArray<VkBufferImageCopy, 16>;
- void prepareUploadSubres(QVkTexture *texD, int layer, int level,
- const QRhiTextureSubresourceUploadDescription &subresDesc,
- size_t *curOfs, void *mp,
- BufferImageCopyList *copyInfos);
- void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates);
- void executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot);
- void enqueueTransitionPassResources(QVkCommandBuffer *cbD);
- void recordPrimaryCommandBuffer(QVkCommandBuffer *cbD);
- void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
- QVkBuffer *bufD,
- int slot,
- QRhiPassResourceTracker::BufferAccess access,
- QRhiPassResourceTracker::BufferStage stage);
- void trackedRegisterTexture(QRhiPassResourceTracker *passResTracker,
- QVkTexture *texD,
- QRhiPassResourceTracker::TextureAccess access,
- QRhiPassResourceTracker::TextureStage stage);
- void recordTransitionPassResources(QVkCommandBuffer *cbD, const QRhiPassResourceTracker &tracker);
- void activateTextureRenderTarget(QVkCommandBuffer *cbD, QVkTextureRenderTarget *rtD);
- void executeDeferredReleases(bool forced = false);
- void finishActiveReadbacks(bool forced = false);
-
- void setObjectName(uint64_t object, VkDebugReportObjectTypeEXT type, const QByteArray &name, int slot = -1);
- void trackedBufferBarrier(QVkCommandBuffer *cbD, QVkBuffer *bufD, int slot,
- VkAccessFlags access, VkPipelineStageFlags stage);
- void trackedImageBarrier(QVkCommandBuffer *cbD, QVkTexture *texD,
- VkImageLayout layout, VkAccessFlags access, VkPipelineStageFlags stage);
- void depthStencilExplicitBarrier(QVkCommandBuffer *cbD, QVkRenderBuffer *rbD);
- void subresourceBarrier(QVkCommandBuffer *cbD, VkImage image,
- VkImageLayout oldLayout, VkImageLayout newLayout,
- VkAccessFlags srcAccess, VkAccessFlags dstAccess,
- VkPipelineStageFlags srcStage, VkPipelineStageFlags dstStage,
- int startLayer, int layerCount,
- int startLevel, int levelCount);
- void updateShaderResourceBindings(QRhiShaderResourceBindings *srb, int descSetIdx = -1);
- void ensureCommandPoolForNewFrame();
-
- QVulkanInstance *inst = nullptr;
- QWindow *maybeWindow = nullptr;
- QByteArrayList requestedDeviceExtensions;
- bool importedDevice = false;
- VkPhysicalDevice physDev = VK_NULL_HANDLE;
- VkDevice dev = VK_NULL_HANDLE;
- VkCommandPool cmdPool[QVK_FRAMES_IN_FLIGHT] = {};
- int gfxQueueFamilyIdx = -1;
- int gfxQueueIdx = 0;
- VkQueue gfxQueue = VK_NULL_HANDLE;
- quint32 timestampValidBits = 0;
- bool importedAllocator = false;
- QVkAllocator allocator = nullptr;
- QVulkanFunctions *f = nullptr;
- QVulkanDeviceFunctions *df = nullptr;
- QRhi::Flags rhiFlags;
- VkPhysicalDeviceFeatures physDevFeatures;
- VkPhysicalDeviceProperties physDevProperties;
- VkDeviceSize ubufAlign;
- VkDeviceSize texbufAlign;
- bool deviceLost = false;
- bool releaseCachedResourcesCalledBeforeFrameStart = false;
-
- PFN_vkCmdDebugMarkerBeginEXT vkCmdDebugMarkerBegin = nullptr;
- PFN_vkCmdDebugMarkerEndEXT vkCmdDebugMarkerEnd = nullptr;
- PFN_vkCmdDebugMarkerInsertEXT vkCmdDebugMarkerInsert = nullptr;
- PFN_vkDebugMarkerSetObjectNameEXT vkDebugMarkerSetObjectName = nullptr;
-
- PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr;
- PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
- PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
- PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
- PFN_vkQueuePresentKHR vkQueuePresentKHR;
- PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr;
- PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
- PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
-
- struct {
- bool compute = false;
- bool wideLines = false;
- bool debugMarkers = false;
- bool vertexAttribDivisor = false;
- bool texture3DSliceAs2D = false;
- } caps;
-
- VkPipelineCache pipelineCache = VK_NULL_HANDLE;
- struct DescriptorPoolData {
- DescriptorPoolData() { }
- DescriptorPoolData(VkDescriptorPool pool_)
- : pool(pool_)
- { }
- VkDescriptorPool pool = VK_NULL_HANDLE;
- int refCount = 0;
- int allocedDescSets = 0;
- };
- QVarLengthArray<DescriptorPoolData, 8> descriptorPools;
- QVarLengthArray<VkCommandBuffer, 4> freeSecondaryCbs[QVK_FRAMES_IN_FLIGHT];
-
- VkQueryPool timestampQueryPool = VK_NULL_HANDLE;
- QBitArray timestampQueryPoolMap;
-
- VkFormat optimalDsFormat = VK_FORMAT_UNDEFINED;
- QMatrix4x4 clipCorrectMatrix;
-
- QVkSwapChain *currentSwapChain = nullptr;
- QSet<QVkSwapChain *> swapchains;
- QRhiVulkanNativeHandles nativeHandlesStruct;
- QRhiDriverInfo driverInfoStruct;
-
- struct OffscreenFrame {
- OffscreenFrame(QRhiImplementation *rhi)
- {
- for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
- cbWrapper[i] = new QVkCommandBuffer(rhi);
- }
- ~OffscreenFrame()
- {
- for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
- delete cbWrapper[i];
- }
- bool active = false;
- QVkCommandBuffer *cbWrapper[QVK_FRAMES_IN_FLIGHT];
- VkFence cmdFence = VK_NULL_HANDLE;
- } ofr;
-
- struct TextureReadback {
- int activeFrameSlot = -1;
- QRhiReadbackDescription desc;
- QRhiReadbackResult *result;
- VkBuffer stagingBuf;
- QVkAlloc stagingAlloc;
- quint32 byteSize;
- QSize pixelSize;
- QRhiTexture::Format format;
- };
- QVarLengthArray<TextureReadback, 2> activeTextureReadbacks;
- struct BufferReadback {
- int activeFrameSlot = -1;
- QRhiBufferReadbackResult *result;
- int byteSize;
- VkBuffer stagingBuf;
- QVkAlloc stagingAlloc;
- };
- QVarLengthArray<BufferReadback, 2> activeBufferReadbacks;
-
- struct DeferredReleaseEntry {
- enum Type {
- Pipeline,
- ShaderResourceBindings,
- Buffer,
- RenderBuffer,
- Texture,
- Sampler,
- TextureRenderTarget,
- RenderPass,
- StagingBuffer,
- SecondaryCommandBuffer
- };
- Type type;
- int lastActiveFrameSlot; // -1 if not used otherwise 0..FRAMES_IN_FLIGHT-1
- union {
- struct {
- VkPipeline pipeline;
- VkPipelineLayout layout;
- } pipelineState;
- struct {
- int poolIndex;
- VkDescriptorSetLayout layout;
- } shaderResourceBindings;
- struct {
- VkBuffer buffers[QVK_FRAMES_IN_FLIGHT];
- QVkAlloc allocations[QVK_FRAMES_IN_FLIGHT];
- VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
- QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
- } buffer;
- struct {
- VkDeviceMemory memory;
- VkImage image;
- VkImageView imageView;
- } renderBuffer;
- struct {
- VkImage image;
- VkImageView imageView;
- QVkAlloc allocation;
- VkBuffer stagingBuffers[QVK_FRAMES_IN_FLIGHT];
- QVkAlloc stagingAllocations[QVK_FRAMES_IN_FLIGHT];
- VkImageView extraImageViews[QRhi::MAX_MIP_LEVELS];
- } texture;
- struct {
- VkSampler sampler;
- } sampler;
- struct {
- VkFramebuffer fb;
- VkImageView rtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
- VkImageView resrtv[QVkRenderTargetData::MAX_COLOR_ATTACHMENTS];
- } textureRenderTarget;
- struct {
- VkRenderPass rp;
- } renderPass;
- struct {
- VkBuffer stagingBuffer;
- QVkAlloc stagingAllocation;
- } stagingBuffer;
- struct {
- VkCommandBuffer cb;
- } secondaryCommandBuffer;
- };
- };
- QList<DeferredReleaseEntry> releaseQueue;
-};
-
-Q_DECLARE_TYPEINFO(QRhiVulkan::DescriptorPoolData, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QRhiVulkan::DeferredReleaseEntry, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QRhiVulkan::TextureReadback, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QRhiVulkan::BufferReadback, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qrhivulkanext_p.h b/src/gui/rhi/qrhivulkanext_p.h
deleted file mode 100644
index d98067c803..0000000000
--- a/src/gui/rhi/qrhivulkanext_p.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt RHI module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QRHIVULKANEXT_P_H
-#define QRHIVULKANEXT_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qrhivulkan_p.h"
-
-QT_BEGIN_NAMESPACE
-
-#ifndef VK_EXT_vertex_attribute_divisor
-#define VK_EXT_vertex_attribute_divisor 1
-#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
-#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
-
-typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
- VkStructureType sType;
- void* pNext;
- uint32_t maxVertexAttribDivisor;
-} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT;
-
-typedef struct VkVertexInputBindingDivisorDescriptionEXT {
- uint32_t binding;
- uint32_t divisor;
-} VkVertexInputBindingDivisorDescriptionEXT;
-
-typedef struct VkPipelineVertexInputDivisorStateCreateInfoEXT {
- VkStructureType sType;
- const void* pNext;
- uint32_t vertexBindingDivisorCount;
- const VkVertexInputBindingDivisorDescriptionEXT* pVertexBindingDivisors;
-} VkPipelineVertexInputDivisorStateCreateInfoEXT;
-#endif // VK_EXT_vertex_attribute_divisor
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qshader.cpp b/src/gui/rhi/qshader.cpp
index 74255dcf5c..d5fb53e7e6 100644
--- a/src/gui/rhi/qshader.cpp
+++ b/src/gui/rhi/qshader.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qshader_p_p.h"
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qshader_p.h"
#include <QDataStream>
#include <QBuffer>
@@ -45,8 +9,9 @@ QT_BEGIN_NAMESPACE
/*!
\class QShader
- \internal
+ \ingroup painting-3D
\inmodule QtGui
+ \since 6.6
\brief Contains multiple versions of a shader translated to multiple shading languages,
together with reflection metadata.
@@ -57,6 +22,16 @@ QT_BEGIN_NAMESPACE
as, Vulkan, Metal, Direct3D, and OpenGL, take QShader as their input
whenever a shader needs to be specified.
+ \warning The QRhi family of classes in the Qt Gui module, including QShader
+ and QShaderDescription, offer limited compatibility guarantees. There are
+ no source or binary compatibility guarantees for these classes, meaning the
+ API is only guaranteed to work with the Qt version the application was
+ developed against. Source incompatible changes are however aimed to be kept
+ at a minimum and will only be made in minor releases (6.7, 6.8, and so on).
+ To use these classes in an application, link to
+ \c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c
+ rhi prefix, for example \c{#include <rhi/qshader.h>}.
+
A QShader instance is empty and thus invalid by default. To get a useful
instance, the two typical methods are:
@@ -104,8 +79,9 @@ QT_BEGIN_NAMESPACE
can be returned or passed by value. Detach happens implicitly when calling
a setter.
- For reference, QRhi expects that a QShader suitable for all its
- backends contains at least the following:
+ For reference, a typical, portable QRhi expects that a QShader suitable for
+ all its backends contains at least the following. (this excludes support
+ for core profile OpenGL contexts, add GLSL 150 or newer for that)
\list
@@ -113,11 +89,11 @@ QT_BEGIN_NAMESPACE
\li GLSL/ES 100 source code suitable for OpenGL ES 2.0 or newer
- \li GLSL 120 source code suitable for OpenGL 2.1
+ \li GLSL 120 source code suitable for OpenGL 2.1 or newer
- \li HLSL Shader Model 5.0 source code or the corresponding DXBC bytecode suitable for Direct3D 11
+ \li HLSL Shader Model 5.0 source code or the corresponding DXBC bytecode suitable for Direct3D 11/12
- \li Metal Shading Language 1.2 source code or the corresponding bytecode suitable for Metal
+ \li Metal Shading Language 1.2 source code or the corresponding bytecode suitable for Metal 1.2 or newer
\endlist
@@ -138,8 +114,8 @@ QT_BEGIN_NAMESPACE
/*!
\class QShaderVersion
- \internal
\inmodule QtGui
+ \since 6.6
\brief Specifies the shading language version.
@@ -164,6 +140,9 @@ QT_BEGIN_NAMESPACE
A default constructed QShaderVersion contains a version of 100 and no
flags set.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShader
+ for details.
*/
/*!
@@ -176,13 +155,16 @@ QT_BEGIN_NAMESPACE
/*!
\class QShaderKey
- \internal
\inmodule QtGui
+ \since 6.6
\brief Specifies the shading language, the version with flags, and the variant.
A default constructed QShaderKey has source set to SpirvShader and
sourceVersion set to 100. sourceVariant defaults to StandardShader.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShader
+ for details.
*/
/*!
@@ -196,6 +178,7 @@ QT_BEGIN_NAMESPACE
\value MslShader Metal Shading Language
\value DxilShader Direct3D bytecode (HLSL compiled by \c dxc)
\value MetalLibShader Pre-compiled Metal bytecode
+ \value WgslShader WGSL
*/
/*!
@@ -203,25 +186,74 @@ QT_BEGIN_NAMESPACE
Describes what kind of shader code an entry contains.
\value StandardShader The normal, unmodified version of the shader code.
+
\value BatchableVertexShader Vertex shader rewritten to be suitable for Qt Quick scenegraph batching.
+
+ \value UInt16IndexedVertexAsComputeShader A vertex shader meant to be used
+ in a Metal pipeline with tessellation in combination with indexed draw
+ calls sourcing index data from a uint16 index buffer. To support the Metal
+ tessellation pipeline, the vertex shader is translated to a compute shader
+ that may be dependent on the index buffer usage in the draw calls (e.g. if
+ the shader is using gl_VertexIndex), hence the need for three dedicated
+ variants.
+
+ \value UInt32IndexedVertexAsComputeShader A vertex shader meant to be used
+ in a Metal pipeline with tessellation in combination with indexed draw
+ calls sourcing index data from a uint32 index buffer. To support the Metal
+ tessellation pipeline, the vertex shader is translated to a compute shader
+ that may be dependent on the index buffer usage in the draw calls (e.g. if
+ the shader is using gl_VertexIndex), hence the need for three dedicated
+ variants.
+
+ \value NonIndexedVertexAsComputeShader A vertex shader meant to be used in
+ a Metal pipeline with tessellation in combination with non-indexed draw
+ calls. To support the Metal tessellation pipeline, the vertex shader is
+ translated to a compute shader that may be dependent on the index buffer
+ usage in the draw calls (e.g. if the shader is using gl_VertexIndex), hence
+ the need for three dedicated variants.
+ */
+
+/*!
+ \enum QShader::SerializedFormatVersion
+ Describes the desired output format when serializing the QShader.
+
+ The default value for the \c version argument of serialized() is \c Latest.
+ This is sufficient in the vast majority of cases. Specifying another value
+ is needed only when the intention is to generate serialized data that can
+ be loaded by earlier Qt versions. For example, the \c qsb tool uses these
+ enum values when the \c{--qsbversion} command-line argument is given.
+
+ \note Targeting earlier versions will make certain features disfunctional
+ with the generated asset. This is not an issue when using the asset with
+ the specified, older Qt version, given that that Qt version does not have
+ the newer features in newer Qt versions that rely on additional data
+ generated in the QShader and the serialized data stream, but may become a
+ problem if the generated asset is then used with a newer Qt version.
+
+ \value Latest The current Qt version
+ \value Qt_6_5 Qt 6.5
+ \value Qt_6_4 Qt 6.4
*/
/*!
\class QShaderCode
- \internal
\inmodule QtGui
+ \since 6.6
\brief Contains source or binary code for a shader and additional metadata.
When shader() is empty after retrieving a QShaderCode instance from
QShader, it indicates no shader code was found for the requested key.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShader
+ for details.
*/
/*!
Constructs a new, empty (and thus invalid) QShader instance.
*/
QShader::QShader()
- : d(new QShaderPrivate)
+ : d(nullptr)
{
}
@@ -230,42 +262,87 @@ QShader::QShader()
*/
void QShader::detach()
{
- qAtomicDetach(d);
+ if (d)
+ qAtomicDetach(d);
+ else
+ d = new QShaderPrivate;
}
/*!
- \internal
+ Constructs a copy of \a other.
*/
QShader::QShader(const QShader &other)
: d(other.d)
{
- d->ref.ref();
+ if (d)
+ d->ref.ref();
}
/*!
- \internal
+ Assigns \a other to this object.
*/
QShader &QShader::operator=(const QShader &other)
{
- qAtomicAssign(d, other.d);
+ if (d) {
+ if (other.d) {
+ qAtomicAssign(d, other.d);
+ } else {
+ if (!d->ref.deref())
+ delete d;
+ d = nullptr;
+ }
+ } else if (other.d) {
+ other.d->ref.ref();
+ d = other.d;
+ }
return *this;
}
/*!
+ \fn QShader::QShader(QShader &&other) noexcept
+ \since 6.7
+
+ Move-constructs a new QShader from \a other.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new value.
+*/
+
+/*!
+ \fn QShader &QShader::operator=(QShader &&other)
+ \since 6.7
+
+ Move-assigns \a other to this QShader instance.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new value.
+*/
+
+/*!
Destructor.
*/
QShader::~QShader()
{
- if (!d->ref.deref())
+ if (d && !d->ref.deref())
delete d;
}
/*!
+ \fn void QShader::swap(QShader &other)
+ \since 6.7
+
+ Swaps shader \a other with this shader. This operation is very fast and
+ never fails.
+*/
+
+/*!
\return true if the QShader contains at least one shader version.
*/
bool QShader::isValid() const
{
- return !d->shaders.isEmpty();
+ return d ? !d->shaders.isEmpty() : false;
}
/*!
@@ -273,7 +350,7 @@ bool QShader::isValid() const
*/
QShader::Stage QShader::stage() const
{
- return d->stage;
+ return d ? d->stage : QShader::VertexStage;
}
/*!
@@ -281,7 +358,7 @@ QShader::Stage QShader::stage() const
*/
void QShader::setStage(Stage stage)
{
- if (stage != d->stage) {
+ if (!d || stage != d->stage) {
detach();
d->stage = stage;
}
@@ -292,7 +369,7 @@ void QShader::setStage(Stage stage)
*/
QShaderDescription QShader::description() const
{
- return d->desc;
+ return d ? d->desc : QShaderDescription();
}
/*!
@@ -309,7 +386,7 @@ void QShader::setDescription(const QShaderDescription &desc)
*/
QList<QShaderKey> QShader::availableShaders() const
{
- return d->shaders.keys().toVector();
+ return d ? d->shaders.keys().toVector() : QList<QShaderKey>();
}
/*!
@@ -317,7 +394,7 @@ QList<QShaderKey> QShader::availableShaders() const
*/
QShaderCode QShader::shader(const QShaderKey &key) const
{
- return d->shaders.value(key);
+ return d ? d->shaders.value(key) : QShaderCode();
}
/*!
@@ -325,7 +402,7 @@ QShaderCode QShader::shader(const QShaderKey &key) const
*/
void QShader::setShader(const QShaderKey &key, const QShaderCode &shader)
{
- if (d->shaders.value(key) == shader)
+ if (d && d->shaders.value(key) == shader)
return;
detach();
@@ -338,6 +415,9 @@ void QShader::setShader(const QShaderKey &key, const QShaderCode &shader)
*/
void QShader::removeShader(const QShaderKey &key)
{
+ if (!d)
+ return;
+
auto it = d->shaders.find(key);
if (it == d->shaders.end())
return;
@@ -358,39 +438,78 @@ static void writeShaderKey(QDataStream *ds, const QShaderKey &k)
\return a serialized binary version of all the data held by the
QShader, suitable for writing to files or other I/O devices.
+ By default the latest serialization format is used. Use \a version
+ parameter to serialize for a compatibility Qt version. Only when it is
+ known that the generated data stream must be made compatible with an older
+ Qt version at the expense of making it incompatible with features
+ introduced since that Qt version, should another value (for example,
+ \l{SerializedFormatVersion}{Qt_6_5} for Qt 6.5) be used.
+
\sa fromSerialized()
*/
-QByteArray QShader::serialized() const
+QByteArray QShader::serialized(SerializedFormatVersion version) const
{
+ static QShaderPrivate sd;
+ QShaderPrivate *dd = d ? d : &sd;
+
QBuffer buf;
QDataStream ds(&buf);
ds.setVersion(QDataStream::Qt_5_10);
if (!buf.open(QIODevice::WriteOnly))
return QByteArray();
- ds << QShaderPrivate::QSB_VERSION;
- ds << int(d->stage);
- d->desc.serialize(&ds);
- ds << int(d->shaders.count());
- for (auto it = d->shaders.cbegin(), itEnd = d->shaders.cend(); it != itEnd; ++it) {
+ const int qsbVersion = QShaderPrivate::qtQsbVersion(version);
+ ds << qsbVersion;
+
+ ds << int(dd->stage);
+ dd->desc.serialize(&ds, qsbVersion);
+ ds << int(dd->shaders.size());
+ for (auto it = dd->shaders.cbegin(), itEnd = dd->shaders.cend(); it != itEnd; ++it) {
const QShaderKey &k(it.key());
writeShaderKey(&ds, k);
- const QShaderCode &shader(d->shaders.value(k));
+ const QShaderCode &shader(dd->shaders.value(k));
ds << shader.shader();
ds << shader.entryPoint();
}
- ds << int(d->bindings.count());
- for (auto it = d->bindings.cbegin(), itEnd = d->bindings.cend(); it != itEnd; ++it) {
+ ds << int(dd->bindings.size());
+ for (auto it = dd->bindings.cbegin(), itEnd = dd->bindings.cend(); it != itEnd; ++it) {
const QShaderKey &k(it.key());
writeShaderKey(&ds, k);
const NativeResourceBindingMap &map(it.value());
- ds << int(map.count());
+ ds << int(map.size());
for (auto mapIt = map.cbegin(), mapItEnd = map.cend(); mapIt != mapItEnd; ++mapIt) {
ds << mapIt.key();
ds << mapIt.value().first;
ds << mapIt.value().second;
}
}
+ ds << int(dd->combinedImageMap.size());
+ for (auto it = dd->combinedImageMap.cbegin(), itEnd = dd->combinedImageMap.cend(); it != itEnd; ++it) {
+ const QShaderKey &k(it.key());
+ writeShaderKey(&ds, k);
+ const SeparateToCombinedImageSamplerMappingList &list(it.value());
+ ds << int(list.size());
+ for (auto listIt = list.cbegin(), listItEnd = list.cend(); listIt != listItEnd; ++listIt) {
+ ds << listIt->combinedSamplerName;
+ ds << listIt->textureBinding;
+ ds << listIt->samplerBinding;
+ }
+ }
+ if (qsbVersion > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
+ ds << int(dd->nativeShaderInfoMap.size());
+ for (auto it = dd->nativeShaderInfoMap.cbegin(), itEnd = dd->nativeShaderInfoMap.cend(); it != itEnd; ++it) {
+ const QShaderKey &k(it.key());
+ writeShaderKey(&ds, k);
+ ds << it->flags;
+ ds << int(it->extraBufferBindings.size());
+ for (auto mapIt = it->extraBufferBindings.cbegin(), mapItEnd = it->extraBufferBindings.cend();
+ mapIt != mapItEnd; ++mapIt)
+ {
+ ds << mapIt.key();
+ ds << mapIt.value();
+ }
+ }
+ }
return qCompress(buf.buffer());
}
@@ -413,6 +532,9 @@ static void readShaderKey(QDataStream *ds, QShaderKey *k)
/*!
Creates a new QShader instance from the given \a data.
+ If \a data cannot be deserialized successfully, the result is a default
+ constructed QShader for which isValid() returns \c false.
+
\sa serialized()
*/
QShader QShader::fromSerialized(const QByteArray &data)
@@ -425,12 +547,17 @@ QShader QShader::fromSerialized(const QByteArray &data)
return QShader();
QShader bs;
+ bs.detach(); // to get d created
QShaderPrivate *d = QShaderPrivate::get(&bs);
Q_ASSERT(d->ref.loadRelaxed() == 1); // must be detached
int intVal;
ds >> intVal;
d->qsbVersion = intVal;
if (d->qsbVersion != QShaderPrivate::QSB_VERSION
+ && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS
+ && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO
+ && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO
+ && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_CBOR
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON
@@ -486,19 +613,123 @@ QShader QShader::fromSerialized(const QByteArray &data)
}
}
+ if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS) {
+ ds >> count;
+ for (int i = 0; i < count; ++i) {
+ QShaderKey k;
+ readShaderKey(&ds, &k);
+ SeparateToCombinedImageSamplerMappingList list;
+ int listSize;
+ ds >> listSize;
+ for (int b = 0; b < listSize; ++b) {
+ QByteArray combinedSamplerName;
+ ds >> combinedSamplerName;
+ int textureBinding;
+ ds >> textureBinding;
+ int samplerBinding;
+ ds >> samplerBinding;
+ list.append({ combinedSamplerName, textureBinding, samplerBinding });
+ }
+ d->combinedImageMap.insert(k, list);
+ }
+ }
+
+ if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
+ ds >> count;
+ for (int i = 0; i < count; ++i) {
+ QShaderKey k;
+ readShaderKey(&ds, &k);
+ int flags;
+ ds >> flags;
+ QMap<int, int> extraBufferBindings;
+ int mapSize;
+ ds >> mapSize;
+ for (int b = 0; b < mapSize; ++b) {
+ int k, v;
+ ds >> k;
+ ds >> v;
+ extraBufferBindings.insert(k, v);
+ }
+ d->nativeShaderInfoMap.insert(k, { flags, extraBufferBindings });
+ }
+ }
+
return bs;
}
+/*!
+ \fn QShaderVersion::QShaderVersion() = default
+ */
+
+/*!
+ Constructs a new QShaderVersion with version \a v and flags \a f.
+ */
QShaderVersion::QShaderVersion(int v, Flags f)
: m_version(v), m_flags(f)
{
}
+/*!
+ \fn int QShaderVersion::version() const
+ \return the version.
+ */
+
+/*!
+ \fn void QShaderVersion::setVersion(int v)
+ Sets the shading language version to \a v.
+ */
+
+/*!
+ \fn QShaderVersion::Flags QShaderVersion::flags() const
+ \return the flags.
+ */
+
+/*!
+ \fn void QShaderVersion::setFlags(Flags f)
+ Sets the flags \a f.
+ */
+
+/*!
+ \fn QShaderCode::QShaderCode() = default
+ */
+
+/*!
+ Constructs a new QShaderCode with the specified shader source \a code and
+ \a entry point name.
+ */
QShaderCode::QShaderCode(const QByteArray &code, const QByteArray &entry)
: m_shader(code), m_entryPoint(entry)
{
}
+/*!
+ \fn QByteArray QShaderCode::shader() const
+ \return the shader source or bytecode.
+ */
+
+/*!
+ \fn void QShaderCode::setShader(const QByteArray &code)
+ Sets the shader source or byte \a code.
+ */
+
+/*!
+ \fn QByteArray QShaderCode::entryPoint() const
+ \return the entry point name.
+ */
+
+/*!
+ \fn void QShaderCode::setEntryPoint(const QByteArray &entry)
+ Sets the \a entry point name.
+ */
+
+/*!
+ \fn QShaderKey::QShaderKey() = default
+ */
+
+/*!
+ Constructs a new QShaderKey with shader type \a s, version \a sver, and
+ variant \a svar.
+ */
QShaderKey::QShaderKey(QShader::Source s,
const QShaderVersion &sver,
QShader::Variant svar)
@@ -509,6 +740,36 @@ QShaderKey::QShaderKey(QShader::Source s,
}
/*!
+ \fn QShader::Source QShaderKey::source() const
+ \return the shader type.
+ */
+
+/*!
+ \fn void QShaderKey::setSource(QShader::Source s)
+ Sets the shader type \a s.
+ */
+
+/*!
+ \fn QShaderVersion QShaderKey::sourceVersion() const
+ \return the shading language version.
+ */
+
+/*!
+ \fn void QShaderKey::setSourceVersion(const QShaderVersion &sver)
+ Sets the shading language version \a sver.
+ */
+
+/*!
+ \fn QShader::Variant QShaderKey::sourceVariant() const
+ \return the type of the variant to use.
+ */
+
+/*!
+ \fn void QShaderKey::setSourceVariant(QShader::Variant svar)
+ Sets the type of variant to use to \a svar.
+ */
+
+/*!
Returns \c true if the two QShader objects \a lhs and \a rhs are equal,
meaning they are for the same stage with matching sets of shader source or
binary code.
@@ -517,16 +778,18 @@ QShaderKey::QShaderKey(QShader::Source s,
*/
bool operator==(const QShader &lhs, const QShader &rhs) noexcept
{
+ if (!lhs.d || !rhs.d)
+ return lhs.d == rhs.d;
+
return lhs.d->stage == rhs.d->stage
- && lhs.d->shaders == rhs.d->shaders;
- // do not bother with desc and bindings, if the shader code is the same, the description must match too
+ && lhs.d->shaders == rhs.d->shaders
+ && lhs.d->bindings == rhs.d->bindings;
}
/*!
- \internal
\fn bool operator!=(const QShader &lhs, const QShader &rhs)
- Returns \c false if the values in the two QShader objects \a a and \a b
+ Returns \c false if the values in the two QShader objects \a lhs and \a rhs
are equal; otherwise returns \c true.
\relates QShader
@@ -539,11 +802,14 @@ bool operator==(const QShader &lhs, const QShader &rhs) noexcept
*/
size_t qHash(const QShader &s, size_t seed) noexcept
{
- QtPrivate::QHashCombine hash;
- seed = hash(seed, s.stage());
- seed = qHashRange(s.d->shaders.keyValueBegin(),
- s.d->shaders.keyValueEnd(),
- seed);
+ if (s.d) {
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, s.stage());
+ if (!s.d->shaders.isEmpty()) {
+ seed = hash(seed, s.d->shaders.firstKey());
+ seed = hash(seed, std::as_const(s.d->shaders).first());
+ }
+ }
return seed;
}
@@ -566,11 +832,28 @@ size_t qHash(const QShaderVersion &s, size_t seed) noexcept
#endif
/*!
- \internal
+ \return true if \a lhs is smaller than \a rhs.
+
+ Establishes a sorting order between the two QShaderVersion \a lhs and \a rhs.
+
+ \relates QShaderVersion
+ */
+bool operator<(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
+{
+ if (lhs.version() < rhs.version())
+ return true;
+
+ if (lhs.version() == rhs.version())
+ return int(lhs.flags()) < int(rhs.flags());
+
+ return false;
+}
+
+/*!
\fn bool operator!=(const QShaderVersion &lhs, const QShaderVersion &rhs)
- Returns \c false if the values in the two QShaderVersion objects \a a
- and \a b are equal; otherwise returns \c true.
+ Returns \c false if the values in the two QShaderVersion objects \a lhs
+ and \a rhs are equal; otherwise returns \c true.
\relates QShaderVersion
*/
@@ -587,11 +870,34 @@ bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
}
/*!
- \internal
+ \return true if \a lhs is smaller than \a rhs.
+
+ Establishes a sorting order between the two keys \a lhs and \a rhs.
+
+ \relates QShaderKey
+ */
+bool operator<(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
+{
+ if (int(lhs.source()) < int(rhs.source()))
+ return true;
+
+ if (int(lhs.source()) == int(rhs.source())) {
+ if (lhs.sourceVersion() < rhs.sourceVersion())
+ return true;
+ if (lhs.sourceVersion() == rhs.sourceVersion()) {
+ if (int(lhs.sourceVariant()) < int(rhs.sourceVariant()))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*!
\fn bool operator!=(const QShaderKey &lhs, const QShaderKey &rhs)
- Returns \c false if the values in the two QShaderKey objects \a a
- and \a b are equal; otherwise returns \c true.
+ Returns \c false if the values in the two QShaderKey objects \a lhs
+ and \a rhs are equal; otherwise returns \c true.
\relates QShaderKey
*/
@@ -621,11 +927,10 @@ bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) noexcept
}
/*!
- \internal
\fn bool operator!=(const QShaderCode &lhs, const QShaderCode &rhs)
- Returns \c false if the values in the two QShaderCode objects \a a
- and \a b are equal; otherwise returns \c true.
+ Returns \c false if the values in the two QShaderCode objects \a lhs
+ and \a rhs are equal; otherwise returns \c true.
\relates QShaderCode
*/
@@ -646,11 +951,15 @@ QDebug operator<<(QDebug dbg, const QShader &bs)
const QShaderPrivate *d = bs.d;
QDebugStateSaver saver(dbg);
- dbg.nospace() << "QShader("
- << "stage=" << d->stage
- << " shaders=" << d->shaders.keys()
- << " desc.isValid=" << d->desc.isValid()
- << ')';
+ if (d) {
+ dbg.nospace() << "QShader("
+ << "stage=" << d->stage
+ << " shaders=" << d->shaders.keys()
+ << " desc.isValid=" << d->desc.isValid()
+ << ')';
+ } else {
+ dbg.nospace() << "QShader()";
+ }
return dbg;
}
@@ -675,7 +984,7 @@ QDebug operator<<(QDebug dbg, const QShaderVersion &v)
/*!
\typedef QShader::NativeResourceBindingMap
- Synonym for QHash<int, QPair<int, int>>.
+ Synonym for QMap<int, QPair<int, int>>.
The resource binding model QRhi assumes is based on SPIR-V. This means that
uniform buffers, storage buffers, combined image samplers, and storage
@@ -684,17 +993,20 @@ QDebug operator<<(QDebug dbg, const QShaderVersion &v)
\c binding layout qualifier in the Vulkan-compatible GLSL shader.
Graphics APIs other than Vulkan may use a resource binding model that is
- not fully compatible with this. In addition, the generator of the shader
- code translated from SPIR-V may choose not to take the SPIR-V binding
- qualifiers into account, for various reasons. (this is the case with the
- Metal backend of SPIRV-Cross, for example).
+ not fully compatible with this. The generator of the shader code translated
+ from SPIR-V may choose not to take the SPIR-V binding qualifiers into
+ account, for various reasons. This is the case with the Metal backend of
+ SPIRV-Cross, for example. In addition, even when an automatic, implicit
+ translation is mostly possible (e.g. by using SPIR-V binding points as HLSL
+ resource register indices), assigning resource bindings without being
+ constrained by the SPIR-V binding points can lead to better results.
Therefore, a QShader may expose an additional map that describes what the
- native binding point for a given SPIR-V binding is. The QRhi backends are
- expected to use this map automatically, as appropriate. The value is a
- pair, because combined image samplers may map to two native resources (a
- texture and a sampler) in some shading languages. In that case the second
- value refers to the sampler.
+ native binding point for a given SPIR-V binding is. The QRhi backends, for
+ which this is relevant, are expected to use this map automatically, as
+ appropriate. The value is a pair, because combined image samplers may map
+ to two native resources (a texture and a sampler) in some shading
+ languages. In that case the second value refers to the sampler.
\note The native binding may be -1, in case there is no active binding for
the resource in the shader. (for example, there is a uniform block
@@ -705,16 +1017,20 @@ QDebug operator<<(QDebug dbg, const QShaderVersion &v)
*/
/*!
- \return the native binding map for \a key or null if no extra mapping is
- available, or is not applicable.
+ \return the native binding map for \a key. The map is empty if no mapping
+ is available for \a key (for example, because the map is not applicable for
+ the API and shading language described by \a key).
*/
-const QShader::NativeResourceBindingMap *QShader::nativeResourceBindingMap(const QShaderKey &key) const
+QShader::NativeResourceBindingMap QShader::nativeResourceBindingMap(const QShaderKey &key) const
{
+ if (!d)
+ return {};
+
auto it = d->bindings.constFind(key);
if (it == d->bindings.cend())
- return nullptr;
+ return {};
- return &it.value();
+ return it.value();
}
/*!
@@ -733,6 +1049,9 @@ void QShader::setResourceBindingMap(const QShaderKey &key, const NativeResourceB
*/
void QShader::removeResourceBindingMap(const QShaderKey &key)
{
+ if (!d)
+ return;
+
auto it = d->bindings.find(key);
if (it == d->bindings.end())
return;
@@ -741,4 +1060,162 @@ void QShader::removeResourceBindingMap(const QShaderKey &key)
d->bindings.erase(it);
}
+/*!
+ \typedef QShader::SeparateToCombinedImageSamplerMappingList
+
+ Synonym for QList<QShader::SeparateToCombinedImageSamplerMapping>.
+ */
+
+/*!
+ \struct QShader::SeparateToCombinedImageSamplerMapping
+ \inmodule QtGui
+ \brief Mapping metadata for sampler uniforms.
+
+ Describes a mapping from a traditional combined image sampler uniform to
+ binding points for a separate texture and sampler.
+
+ For example, if \c combinedImageSampler is \c{"_54"}, \c textureBinding is
+ \c 1, and \c samplerBinding is \c 2, this means that the GLSL shader code
+ contains a \c sampler2D (or sampler3D, etc.) uniform with the name of
+ \c{_54} which corresponds to two separate resource bindings (\c 1 and \c 2)
+ in the original shader.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShader
+ for details.
+ */
+
+/*!
+ \variable QShader::SeparateToCombinedImageSamplerMapping::combinedSamplerName
+*/
+
+/*!
+ \variable QShader::SeparateToCombinedImageSamplerMapping::textureBinding
+*/
+
+/*!
+ \variable QShader::SeparateToCombinedImageSamplerMapping::samplerBinding
+*/
+
+/*!
+ \return the combined image sampler mapping list for \a key, or an empty
+ list if there is no data available for \a key, for example because such a
+ mapping is not applicable for the shading language.
+ */
+QShader::SeparateToCombinedImageSamplerMappingList QShader::separateToCombinedImageSamplerMappingList(const QShaderKey &key) const
+{
+ if (!d)
+ return {};
+
+ auto it = d->combinedImageMap.constFind(key);
+ if (it == d->combinedImageMap.cend())
+ return {};
+
+ return it.value();
+}
+
+/*!
+ Stores the given combined image sampler mapping \a list associated with \a key.
+
+ \sa separateToCombinedImageSamplerMappingList()
+ */
+void QShader::setSeparateToCombinedImageSamplerMappingList(const QShaderKey &key,
+ const SeparateToCombinedImageSamplerMappingList &list)
+{
+ detach();
+ d->combinedImageMap[key] = list;
+}
+
+/*!
+ Removes the combined image sampler mapping list for \a key.
+ */
+void QShader::removeSeparateToCombinedImageSamplerMappingList(const QShaderKey &key)
+{
+ if (!d)
+ return;
+
+ auto it = d->combinedImageMap.find(key);
+ if (it == d->combinedImageMap.end())
+ return;
+
+ detach();
+ d->combinedImageMap.erase(it);
+}
+
+/*!
+ \struct QShader::NativeShaderInfo
+ \inmodule QtGui
+ \brief Additional metadata about the native shader code.
+
+ Describes information about the native shader code, if applicable. This
+ becomes relevant with certain shader languages for certain shader stages,
+ in case the translation from SPIR-V involves the introduction of
+ additional, "magic" inputs, outputs, or resources in the generated shader.
+ Such additions may be dependent on the original source code (i.e. the usage
+ of various GLSL language constructs or built-ins), and therefore it needs
+ to be indicated in a dynamic manner if certain features got added to the
+ generated shader code.
+
+ As an example, consider a tessellation control shader with a per-patch (not
+ per-vertex) output variable. This is translated to a Metal compute shader
+ outputting (among others) into an spvPatchOut buffer. But this buffer would
+ not be present at all if per-patch output variables were not used. The fact
+ that the shader code relies on such a buffer present can be indicated by
+ the data in this struct.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShader
+ for details.
+ */
+
+/*!
+ \variable QShader::NativeShaderInfo::flags
+*/
+
+/*!
+ \variable QShader::NativeShaderInfo::extraBufferBindings
+*/
+
+/*!
+ \return the native shader info struct for \a key, or an empty object if
+ there is no data available for \a key, for example because such a mapping
+ is not applicable for the shading language or the shader stage.
+ */
+QShader::NativeShaderInfo QShader::nativeShaderInfo(const QShaderKey &key) const
+{
+ if (!d)
+ return {};
+
+ auto it = d->nativeShaderInfoMap.constFind(key);
+ if (it == d->nativeShaderInfoMap.cend())
+ return {};
+
+ return it.value();
+}
+
+/*!
+ Stores the given native shader \a info associated with \a key.
+
+ \sa nativeShaderInfo()
+ */
+void QShader::setNativeShaderInfo(const QShaderKey &key, const NativeShaderInfo &info)
+{
+ detach();
+ d->nativeShaderInfoMap[key] = info;
+}
+
+/*!
+ Removes the native shader information for \a key.
+ */
+void QShader::removeNativeShaderInfo(const QShaderKey &key)
+{
+ if (!d)
+ return;
+
+ auto it = d->nativeShaderInfoMap.find(key);
+ if (it == d->nativeShaderInfoMap.end())
+ return;
+
+ detach();
+ d->nativeShaderInfoMap.erase(it);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/rhi/qshader.h b/src/gui/rhi/qshader.h
new file mode 100644
index 0000000000..2465081366
--- /dev/null
+++ b/src/gui/rhi/qshader.h
@@ -0,0 +1,241 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSHADER_H
+#define QSHADER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the RHI API, with limited compatibility guarantees.
+// Usage of this API may make your code source and binary incompatible with
+// future versions of Qt.
+//
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qmap.h>
+#include <rhi/qshaderdescription.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QShaderPrivate;
+class QShaderKey;
+
+#ifdef Q_OS_INTEGRITY
+ class QShaderVersion;
+ size_t qHash(const QShaderVersion &, size_t = 0) noexcept;
+#endif
+
+class Q_GUI_EXPORT QShaderVersion
+{
+public:
+ enum Flag {
+ GlslEs = 0x01
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QShaderVersion() = default;
+ QShaderVersion(int v, Flags f = Flags());
+
+ int version() const { return m_version; }
+ void setVersion(int v) { m_version = v; }
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f) { m_flags = f; }
+
+private:
+ int m_version = 100;
+ Flags m_flags;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderVersion::Flags)
+Q_DECLARE_TYPEINFO(QShaderVersion, Q_RELOCATABLE_TYPE);
+
+class QShaderCode;
+Q_GUI_EXPORT size_t qHash(const QShaderCode &, size_t = 0) noexcept;
+
+class Q_GUI_EXPORT QShaderCode
+{
+public:
+ QShaderCode() = default;
+ QShaderCode(const QByteArray &code, const QByteArray &entry = QByteArray());
+
+ QByteArray shader() const { return m_shader; }
+ void setShader(const QByteArray &code) { m_shader = code; }
+
+ QByteArray entryPoint() const { return m_entryPoint; }
+ void setEntryPoint(const QByteArray &entry) { m_entryPoint = entry; }
+
+private:
+ friend Q_GUI_EXPORT size_t qHash(const QShaderCode &, size_t) noexcept;
+
+ QByteArray m_shader;
+ QByteArray m_entryPoint;
+};
+
+Q_DECLARE_TYPEINFO(QShaderCode, Q_RELOCATABLE_TYPE);
+
+class Q_GUI_EXPORT QShader
+{
+public:
+ enum Stage {
+ VertexStage = 0,
+ TessellationControlStage,
+ TessellationEvaluationStage,
+ GeometryStage,
+ FragmentStage,
+ ComputeStage
+ };
+
+ enum Source {
+ SpirvShader = 0,
+ GlslShader,
+ HlslShader,
+ DxbcShader, // fxc
+ MslShader,
+ DxilShader, // dxc
+ MetalLibShader, // xcrun metal + xcrun metallib
+ WgslShader
+ };
+
+ enum Variant {
+ StandardShader = 0,
+ BatchableVertexShader,
+ UInt16IndexedVertexAsComputeShader,
+ UInt32IndexedVertexAsComputeShader,
+ NonIndexedVertexAsComputeShader
+ };
+
+ enum class SerializedFormatVersion {
+ Latest = 0,
+ Qt_6_5,
+ Qt_6_4
+ };
+
+ QShader();
+ QShader(const QShader &other);
+ QShader &operator=(const QShader &other);
+ QShader(QShader &&other) noexcept : d(std::exchange(other.d, nullptr)) {}
+ QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QShader)
+ ~QShader();
+
+ void swap(QShader &other) noexcept { qt_ptr_swap(d, other.d); }
+ void detach();
+
+ bool isValid() const;
+
+ Stage stage() const;
+ void setStage(Stage stage);
+
+ QShaderDescription description() const;
+ void setDescription(const QShaderDescription &desc);
+
+ QList<QShaderKey> availableShaders() const;
+ QShaderCode shader(const QShaderKey &key) const;
+ void setShader(const QShaderKey &key, const QShaderCode &shader);
+ void removeShader(const QShaderKey &key);
+
+ QByteArray serialized(SerializedFormatVersion version = SerializedFormatVersion::Latest) const;
+ static QShader fromSerialized(const QByteArray &data);
+
+ using NativeResourceBindingMap = QMap<int, QPair<int, int> >; // binding -> native_binding[, native_binding]
+ NativeResourceBindingMap nativeResourceBindingMap(const QShaderKey &key) const;
+ void setResourceBindingMap(const QShaderKey &key, const NativeResourceBindingMap &map);
+ void removeResourceBindingMap(const QShaderKey &key);
+
+ struct SeparateToCombinedImageSamplerMapping {
+ QByteArray combinedSamplerName;
+ int textureBinding;
+ int samplerBinding;
+ };
+ using SeparateToCombinedImageSamplerMappingList = QList<SeparateToCombinedImageSamplerMapping>;
+ SeparateToCombinedImageSamplerMappingList separateToCombinedImageSamplerMappingList(const QShaderKey &key) const;
+ void setSeparateToCombinedImageSamplerMappingList(const QShaderKey &key,
+ const SeparateToCombinedImageSamplerMappingList &list);
+ void removeSeparateToCombinedImageSamplerMappingList(const QShaderKey &key);
+
+ struct NativeShaderInfo {
+ int flags = 0;
+ QMap<int, int> extraBufferBindings;
+ };
+ NativeShaderInfo nativeShaderInfo(const QShaderKey &key) const;
+ void setNativeShaderInfo(const QShaderKey &key, const NativeShaderInfo &info);
+ void removeNativeShaderInfo(const QShaderKey &key);
+
+private:
+ QShaderPrivate *d;
+ friend struct QShaderPrivate;
+ friend Q_GUI_EXPORT bool operator==(const QShader &, const QShader &) noexcept;
+ friend Q_GUI_EXPORT size_t qHash(const QShader &, size_t) noexcept;
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QShader &);
+#endif
+};
+
+class Q_GUI_EXPORT QShaderKey
+{
+public:
+ QShaderKey() = default;
+ QShaderKey(QShader::Source s,
+ const QShaderVersion &sver,
+ QShader::Variant svar = QShader::StandardShader);
+
+ QShader::Source source() const { return m_source; }
+ void setSource(QShader::Source s) { m_source = s; }
+
+ QShaderVersion sourceVersion() const { return m_sourceVersion; }
+ void setSourceVersion(const QShaderVersion &sver) { m_sourceVersion = sver; }
+
+ QShader::Variant sourceVariant() const { return m_sourceVariant; }
+ void setSourceVariant(QShader::Variant svar) { m_sourceVariant = svar; }
+
+private:
+ QShader::Source m_source = QShader::SpirvShader;
+ QShaderVersion m_sourceVersion;
+ QShader::Variant m_sourceVariant = QShader::StandardShader;
+};
+
+Q_DECLARE_TYPEINFO(QShaderKey, Q_RELOCATABLE_TYPE);
+
+Q_GUI_EXPORT bool operator==(const QShader &lhs, const QShader &rhs) noexcept;
+Q_GUI_EXPORT size_t qHash(const QShader &s, size_t seed = 0) noexcept;
+
+inline bool operator!=(const QShader &lhs, const QShader &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+Q_GUI_EXPORT bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept;
+Q_GUI_EXPORT bool operator<(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept;
+Q_GUI_EXPORT bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) noexcept;
+Q_GUI_EXPORT bool operator<(const QShaderKey &lhs, const QShaderKey &rhs) noexcept;
+Q_GUI_EXPORT bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) noexcept;
+
+inline bool operator!=(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const QShaderCode &lhs, const QShaderCode &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+Q_GUI_EXPORT size_t qHash(const QShaderKey &k, size_t seed = 0) noexcept;
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShader &);
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QShaderKey &k);
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QShaderVersion &v);
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qshader_p.h b/src/gui/rhi/qshader_p.h
index b320340229..f77bcb1259 100644
--- a/src/gui/rhi/qshader_p.h
+++ b/src/gui/rhi/qshader_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSHADER_P_H
#define QSHADER_P_H
@@ -51,192 +15,77 @@
// We mean it.
//
-#include <QtGui/qtguiglobal.h>
-#include <private/qshaderdescription_p.h>
+#include <rhi/qshader.h>
+#include <QtCore/QAtomicInt>
+#include <QtCore/QMap>
+#include <QtCore/QDebug>
QT_BEGIN_NAMESPACE
-struct QShaderPrivate;
-class QShaderKey;
-
-#ifdef Q_OS_INTEGRITY
- class QShaderVersion;
- size_t qHash(const QShaderVersion &, size_t = 0) noexcept;
-#endif
-
-class Q_GUI_EXPORT QShaderVersion
+struct Q_GUI_EXPORT QShaderPrivate
{
-public:
- enum Flag {
- GlslEs = 0x01
+ static const int QSB_VERSION = 9;
+ static const int QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS = 8;
+ static const int QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO = 7;
+ static const int QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO = 6;
+ static const int QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS = 5;
+ static const int QSB_VERSION_WITHOUT_VAR_ARRAYDIMS = 4;
+ static const int QSB_VERSION_WITH_CBOR = 3;
+ static const int QSB_VERSION_WITH_BINARY_JSON = 2;
+ static const int QSB_VERSION_WITHOUT_BINDINGS = 1;
+
+ enum MslNativeShaderInfoExtraBufferBindings {
+ MslTessVertIndicesBufferBinding = 0,
+ MslTessVertTescOutputBufferBinding,
+ MslTessTescTessLevelBufferBinding,
+ MslTessTescPatchOutputBufferBinding,
+ MslTessTescParamsBufferBinding,
+ MslTessTescInputBufferBinding,
+ MslBufferSizeBufferBinding,
+ MslMultiViewMaskBufferBinding
};
- Q_DECLARE_FLAGS(Flags, Flag)
-
- QShaderVersion() = default;
- QShaderVersion(int v, Flags f = Flags());
-
- int version() const { return m_version; }
- void setVersion(int v) { m_version = v; }
-
- Flags flags() const { return m_flags; }
- void setFlags(Flags f) { m_flags = f; }
-
-private:
- int m_version = 100;
- Flags m_flags;
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderVersion::Flags)
-Q_DECLARE_TYPEINFO(QShaderVersion, Q_RELOCATABLE_TYPE);
-
-class QShaderCode;
-Q_GUI_EXPORT size_t qHash(const QShaderCode &, size_t = 0) noexcept;
-
-class Q_GUI_EXPORT QShaderCode
-{
-public:
- QShaderCode() = default;
- QShaderCode(const QByteArray &code, const QByteArray &entry = QByteArray());
-
- QByteArray shader() const { return m_shader; }
- void setShader(const QByteArray &code) { m_shader = code; }
-
- QByteArray entryPoint() const { return m_entryPoint; }
- void setEntryPoint(const QByteArray &entry) { m_entryPoint = entry; }
-
-private:
- friend Q_GUI_EXPORT size_t qHash(const QShaderCode &, size_t) noexcept;
-
- QByteArray m_shader;
- QByteArray m_entryPoint;
-};
-
-Q_DECLARE_TYPEINFO(QShaderCode, Q_RELOCATABLE_TYPE);
-
-class Q_GUI_EXPORT QShader
-{
-public:
- enum Stage {
- VertexStage = 0,
- TessellationControlStage,
- TessellationEvaluationStage,
- GeometryStage,
- FragmentStage,
- ComputeStage
- };
-
- enum Source {
- SpirvShader = 0,
- GlslShader,
- HlslShader,
- DxbcShader, // fxc
- MslShader,
- DxilShader, // dxc
- MetalLibShader // xcrun metal + xcrun metallib
- };
-
- enum Variant {
- StandardShader = 0,
- BatchableVertexShader
- };
-
- QShader();
- QShader(const QShader &other);
- QShader &operator=(const QShader &other);
- ~QShader();
- void detach();
-
- bool isValid() const;
- Stage stage() const;
- void setStage(Stage stage);
-
- QShaderDescription description() const;
- void setDescription(const QShaderDescription &desc);
-
- QList<QShaderKey> availableShaders() const;
- QShaderCode shader(const QShaderKey &key) const;
- void setShader(const QShaderKey &key, const QShaderCode &shader);
- void removeShader(const QShaderKey &key);
-
- QByteArray serialized() const;
- static QShader fromSerialized(const QByteArray &data);
-
- using NativeResourceBindingMap = QHash<int, QPair<int, int> >; // binding -> native_binding[, native_binding]
- const NativeResourceBindingMap *nativeResourceBindingMap(const QShaderKey &key) const;
- void setResourceBindingMap(const QShaderKey &key, const NativeResourceBindingMap &map);
- void removeResourceBindingMap(const QShaderKey &key);
-
-private:
- QShaderPrivate *d;
- friend struct QShaderPrivate;
- friend Q_GUI_EXPORT bool operator==(const QShader &, const QShader &) noexcept;
- friend Q_GUI_EXPORT size_t qHash(const QShader &, size_t) noexcept;
-#ifndef QT_NO_DEBUG_STREAM
- friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QShader &);
-#endif
-};
-
-class Q_GUI_EXPORT QShaderKey
-{
-public:
- QShaderKey() = default;
- QShaderKey(QShader::Source s,
- const QShaderVersion &sver,
- QShader::Variant svar = QShader::StandardShader);
-
- QShader::Source source() const { return m_source; }
- void setSource(QShader::Source s) { m_source = s; }
-
- QShaderVersion sourceVersion() const { return m_sourceVersion; }
- void setSourceVersion(const QShaderVersion &sver) { m_sourceVersion = sver; }
-
- QShader::Variant sourceVariant() const { return m_sourceVariant; }
- void setSourceVariant(QShader::Variant svar) { m_sourceVariant = svar; }
-
-private:
- QShader::Source m_source = QShader::SpirvShader;
- QShaderVersion m_sourceVersion;
- QShader::Variant m_sourceVariant = QShader::StandardShader;
+ QShaderPrivate()
+ : ref(1)
+ {
+ }
+
+ QShaderPrivate(const QShaderPrivate &other)
+ : ref(1),
+ qsbVersion(other.qsbVersion),
+ stage(other.stage),
+ desc(other.desc),
+ shaders(other.shaders),
+ bindings(other.bindings),
+ combinedImageMap(other.combinedImageMap),
+ nativeShaderInfoMap(other.nativeShaderInfoMap)
+ {
+ }
+
+ static QShaderPrivate *get(QShader *s) { return s->d; }
+ static const QShaderPrivate *get(const QShader *s) { return s->d; }
+ static int qtQsbVersion(QShader::SerializedFormatVersion qtVersion) {
+ switch (qtVersion) {
+ case QShader::SerializedFormatVersion::Qt_6_4:
+ return (QShaderPrivate::QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS + 1);
+ case QShader::SerializedFormatVersion::Qt_6_5:
+ return (QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO + 1);
+ default:
+ return QShaderPrivate::QSB_VERSION;
+ }
+ }
+
+ QAtomicInt ref;
+ int qsbVersion = QSB_VERSION;
+ QShader::Stage stage = QShader::VertexStage;
+ QShaderDescription desc;
+ // QMap not QHash because we need to be able to iterate based on sorted keys
+ QMap<QShaderKey, QShaderCode> shaders;
+ QMap<QShaderKey, QShader::NativeResourceBindingMap> bindings;
+ QMap<QShaderKey, QShader::SeparateToCombinedImageSamplerMappingList> combinedImageMap;
+ QMap<QShaderKey, QShader::NativeShaderInfo> nativeShaderInfoMap;
};
-Q_DECLARE_TYPEINFO(QShaderKey, Q_RELOCATABLE_TYPE);
-
-Q_GUI_EXPORT bool operator==(const QShader &lhs, const QShader &rhs) noexcept;
-Q_GUI_EXPORT size_t qHash(const QShader &s, size_t seed = 0) noexcept;
-
-inline bool operator!=(const QShader &lhs, const QShader &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-Q_GUI_EXPORT bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept;
-Q_GUI_EXPORT bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) noexcept;
-Q_GUI_EXPORT bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) noexcept;
-
-inline bool operator!=(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const QShaderCode &lhs, const QShaderCode &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-Q_GUI_EXPORT size_t qHash(const QShaderKey &k, size_t seed = 0) noexcept;
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QShader &);
-Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QShaderKey &k);
-Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QShaderVersion &v);
-#endif
-
QT_END_NAMESPACE
#endif
diff --git a/src/gui/rhi/qshader_p_p.h b/src/gui/rhi/qshader_p_p.h
deleted file mode 100644
index 2f6afb4a6d..0000000000
--- a/src/gui/rhi/qshader_p_p.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHADER_P_P_H
-#define QSHADER_P_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of a number of Qt sources files. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qshader_p.h"
-#include <QtCore/QAtomicInt>
-#include <QtCore/QHash>
-#include <QtCore/QDebug>
-
-QT_BEGIN_NAMESPACE
-
-struct Q_GUI_EXPORT QShaderPrivate
-{
- static const int QSB_VERSION = 5;
- static const int QSB_VERSION_WITHOUT_VAR_ARRAYDIMS = 4;
- static const int QSB_VERSION_WITH_CBOR = 3;
- static const int QSB_VERSION_WITH_BINARY_JSON = 2;
- static const int QSB_VERSION_WITHOUT_BINDINGS = 1;
-
- QShaderPrivate()
- : ref(1)
- {
- }
-
- QShaderPrivate(const QShaderPrivate *other)
- : ref(1),
- qsbVersion(other->qsbVersion),
- stage(other->stage),
- desc(other->desc),
- shaders(other->shaders),
- bindings(other->bindings)
- {
- }
-
- static QShaderPrivate *get(QShader *s) { return s->d; }
- static const QShaderPrivate *get(const QShader *s) { return s->d; }
-
- QAtomicInt ref;
- int qsbVersion = QSB_VERSION;
- QShader::Stage stage = QShader::VertexStage;
- QShaderDescription desc;
- QHash<QShaderKey, QShaderCode> shaders;
- QHash<QShaderKey, QShader::NativeResourceBindingMap> bindings;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qshaderdescription.cpp b/src/gui/rhi/qshaderdescription.cpp
index 2c79acb1c7..f64daf02ef 100644
--- a/src/gui/rhi/qshaderdescription.cpp
+++ b/src/gui/rhi/qshaderdescription.cpp
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qshaderdescription_p_p.h"
-#include "qshader_p_p.h"
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qshaderdescription_p.h"
+#include "qshader_p.h"
#include <QDebug>
#include <QDataStream>
#include <QJsonObject>
@@ -48,11 +12,22 @@ QT_BEGIN_NAMESPACE
/*!
\class QShaderDescription
- \internal
+ \ingroup painting-3D
\inmodule QtGui
+ \since 6.6
\brief Describes the interface of a shader.
+ \warning The QRhi family of classes in the Qt Gui module, including QShader
+ and QShaderDescription, offer limited compatibility guarantees. There are
+ no source or binary compatibility guarantees for these classes, meaning the
+ API is only guaranteed to work with the Qt version the application was
+ developed against. Source incompatible changes are however aimed to be kept
+ at a minimum and will only be made in minor releases (6.7, 6.8, and so on).
+ To use these classes in an application, link to
+ \c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c
+ rhi prefix, for example \c{#include <rhi/qshaderdescription.h>}.
+
A shader typically has a set of inputs and outputs. A vertex shader for
example has a number of input variables and may use one or more uniform
buffers to access data (e.g. a modelview matrix) provided by the
@@ -87,8 +62,6 @@ QT_BEGIN_NAMESPACE
float opacity;
} ubuf;
- out gl_PerVertex { vec4 gl_Position; };
-
void main()
{
v_color = color;
@@ -222,6 +195,7 @@ QT_BEGIN_NAMESPACE
\value SamplerRect
\value SamplerBuffer
\value SamplerExternalOES
+ \value Sampler For separate samplers.
\value Image1D
\value Image2D
\value Image2DMS
@@ -235,28 +209,179 @@ QT_BEGIN_NAMESPACE
\value ImageRect
\value ImageBuffer
\value Struct
+ \value Half
+ \value Half2
+ \value Half3
+ \value Half4
*/
/*!
- \class QShaderDescription::InOutVariable
- \internal
+ \enum QShaderDescription::ImageFormat
+ Image format.
+
+ \value ImageFormatUnknown
+ \value ImageFormatRgba32f
+ \value ImageFormatRgba16f
+ \value ImageFormatR32f
+ \value ImageFormatRgba8
+ \value ImageFormatRgba8Snorm
+ \value ImageFormatRg32f
+ \value ImageFormatRg16f
+ \value ImageFormatR11fG11fB10f
+ \value ImageFormatR16f
+ \value ImageFormatRgba16
+ \value ImageFormatRgb10A2
+ \value ImageFormatRg16
+ \value ImageFormatRg8
+ \value ImageFormatR16
+ \value ImageFormatR8
+ \value ImageFormatRgba16Snorm
+ \value ImageFormatRg16Snorm
+ \value ImageFormatRg8Snorm
+ \value ImageFormatR16Snorm
+ \value ImageFormatR8Snorm
+ \value ImageFormatRgba32i
+ \value ImageFormatRgba16i
+ \value ImageFormatRgba8i
+ \value ImageFormatR32i
+ \value ImageFormatRg32i
+ \value ImageFormatRg16i
+ \value ImageFormatRg8i
+ \value ImageFormatR16i
+ \value ImageFormatR8i
+ \value ImageFormatRgba32ui
+ \value ImageFormatRgba16ui
+ \value ImageFormatRgba8ui
+ \value ImageFormatR32ui
+ \value ImageFormatRgb10a2ui
+ \value ImageFormatRg32ui
+ \value ImageFormatRg16ui
+ \value ImageFormatRg8ui
+ \value ImageFormatR16ui
+ \value ImageFormatR8ui
+ */
+
+/*!
+ \enum QShaderDescription::ImageFlag
+ Image flags.
+
+ \value ReadOnlyImage
+ \value WriteOnlyImage
+ */
+
+/*!
+ \enum QShaderDescription::QualifierFlag
+ Qualifier flags.
+
+ \value QualifierReadOnly
+ \value QualifierWriteOnly
+ \value QualifierCoherent
+ \value QualifierVolatile
+ \value QualifierRestrict
+ */
+
+/*!
+ \struct QShaderDescription::InOutVariable
\inmodule QtGui
+ \since 6.6
\brief Describes an input or output variable in the shader.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
+ for details.
*/
/*!
- \class QShaderDescription::BlockVariable
- \internal
+ \variable QShaderDescription::InOutVariable::name
+ */
+
+/*!
+ \variable QShaderDescription::InOutVariable::type
+ */
+
+/*!
+ \variable QShaderDescription::InOutVariable::location
+ */
+
+/*!
+ \variable QShaderDescription::InOutVariable::binding
+ */
+
+/*!
+ \variable QShaderDescription::InOutVariable::descriptorSet
+ */
+
+/*!
+ \variable QShaderDescription::InOutVariable::imageFormat
+ */
+
+/*!
+ \variable QShaderDescription::InOutVariable::imageFlags
+ */
+
+/*!
+ \variable QShaderDescription::InOutVariable::arrayDims
+ */
+
+/*!
+ \variable QShaderDescription::InOutVariable::perPatch
+ */
+
+/*!
+ \variable QShaderDescription::InOutVariable::structMembers
+ */
+
+/*!
+ \struct QShaderDescription::BlockVariable
\inmodule QtGui
+ \since 6.6
\brief Describes a member of a uniform or push constant block.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
+ for details.
*/
/*!
- \class QShaderDescription::UniformBlock
- \internal
+ \variable QShaderDescription::BlockVariable::name
+ */
+
+/*!
+ \variable QShaderDescription::BlockVariable::type
+ */
+
+/*!
+ \variable QShaderDescription::BlockVariable::offset
+ */
+
+/*!
+ \variable QShaderDescription::BlockVariable::size
+ */
+
+/*!
+ \variable QShaderDescription::BlockVariable::arrayDims
+ */
+
+/*!
+ \variable QShaderDescription::BlockVariable::arrayStride
+ */
+
+/*!
+ \variable QShaderDescription::BlockVariable::matrixStride
+ */
+
+/*!
+ \variable QShaderDescription::BlockVariable::matrixIsRowMajor
+ */
+
+/*!
+ \variable QShaderDescription::BlockVariable::structMembers
+ */
+
+/*!
+ \struct QShaderDescription::UniformBlock
\inmodule QtGui
+ \since 6.6
\brief Describes a uniform block.
@@ -264,22 +389,157 @@ QT_BEGIN_NAMESPACE
(like GLSL 120 or GLSL/ES 100), uniform blocks are replaced with ordinary
uniforms in a struct. The name of the struct, and so the prefix for the
uniforms generated from the block members, is given by structName.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
+ for details.
*/
/*!
- \class QShaderDescription::PushConstantBlock
- \internal
+ \variable QShaderDescription::UniformBlock::blockName
+ */
+
+/*!
+ \variable QShaderDescription::UniformBlock::structName
+ */
+
+/*!
+ \variable QShaderDescription::UniformBlock::size
+ */
+
+/*!
+ \variable QShaderDescription::UniformBlock::binding
+ */
+
+/*!
+ \variable QShaderDescription::UniformBlock::descriptorSet
+ */
+
+/*!
+ \variable QShaderDescription::UniformBlock::members
+ */
+
+/*!
+ \struct QShaderDescription::PushConstantBlock
\inmodule QtGui
+ \since 6.6
\brief Describes a push constant block.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
+ for details.
*/
/*!
- \class QShaderDescription::StorageBlock
- \internal
+ \variable QShaderDescription::PushConstantBlock::name
+ */
+
+/*!
+ \variable QShaderDescription::PushConstantBlock::size
+ */
+
+/*!
+ \variable QShaderDescription::PushConstantBlock::members
+ */
+
+/*!
+ \struct QShaderDescription::StorageBlock
\inmodule QtGui
+ \since 6.6
\brief Describes a shader storage block.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
+ for details.
+ */
+
+/*!
+ \variable QShaderDescription::StorageBlock::blockName
+ */
+
+/*!
+ \variable QShaderDescription::StorageBlock::instanceName
+ */
+
+/*!
+ \variable QShaderDescription::StorageBlock::knownSize
+ */
+
+/*!
+ \variable QShaderDescription::StorageBlock::binding
+ */
+
+/*!
+ \variable QShaderDescription::StorageBlock::descriptorSet
+ */
+
+/*!
+ \variable QShaderDescription::StorageBlock::members
+ */
+
+/*!
+ \variable QShaderDescription::StorageBlock::runtimeArrayStride
+ */
+
+/*!
+ \variable QShaderDescription::StorageBlock::qualifierFlags
+ */
+
+/*!
+ \struct QShaderDescription::BuiltinVariable
+ \inmodule QtGui
+ \since 6.6
+
+ \brief Describes a built-in variable.
+
+ \note This is a RHI API with limited compatibility guarantees, see \l QShaderDescription
+ for details.
+ */
+
+/*!
+ \variable QShaderDescription::BuiltinVariable::type
+ */
+
+/*!
+ \variable QShaderDescription::BuiltinVariable::varType
+ */
+
+/*!
+ \variable QShaderDescription::BuiltinVariable::arrayDims
+ */
+
+/*!
+ \enum QShaderDescription::BuiltinType
+ Built-in variable type.
+
+ \value PositionBuiltin
+ \value PointSizeBuiltin
+ \value ClipDistanceBuiltin
+ \value CullDistanceBuiltin
+ \value VertexIdBuiltin
+ \value InstanceIdBuiltin
+ \value PrimitiveIdBuiltin
+ \value InvocationIdBuiltin
+ \value LayerBuiltin
+ \value ViewportIndexBuiltin
+ \value TessLevelOuterBuiltin
+ \value TessLevelInnerBuiltin
+ \value TessCoordBuiltin
+ \value PatchVerticesBuiltin
+ \value FragCoordBuiltin
+ \value PointCoordBuiltin
+ \value FrontFacingBuiltin
+ \value SampleIdBuiltin
+ \value SamplePositionBuiltin
+ \value SampleMaskBuiltin
+ \value FragDepthBuiltin
+ \value NumWorkGroupsBuiltin
+ \value WorkgroupSizeBuiltin
+ \value WorkgroupIdBuiltin
+ \value LocalInvocationIdBuiltin
+ \value GlobalInvocationIdBuiltin
+ \value LocalInvocationIndexBuiltin
+ \value VertexIndexBuiltin
+ \value InstanceIndexBuiltin
*/
/*!
@@ -302,7 +562,7 @@ void QShaderDescription::detach()
}
/*!
- \internal
+ Constructs a copy of \a other.
*/
QShaderDescription::QShaderDescription(const QShaderDescription &other)
: d(other.d)
@@ -311,7 +571,7 @@ QShaderDescription::QShaderDescription(const QShaderDescription &other)
}
/*!
- \internal
+ Assigns \a other to this object.
*/
QShaderDescription &QShaderDescription::operator=(const QShaderDescription &other)
{
@@ -336,7 +596,9 @@ bool QShaderDescription::isValid() const
{
return !d->inVars.isEmpty() || !d->outVars.isEmpty()
|| !d->uniformBlocks.isEmpty() || !d->pushConstantBlocks.isEmpty() || !d->storageBlocks.isEmpty()
- || !d->combinedImageSamplers.isEmpty() || !d->storageImages.isEmpty();
+ || !d->combinedImageSamplers.isEmpty() || !d->storageImages.isEmpty()
+ || !d->separateImages.isEmpty() || !d->separateSamplers.isEmpty()
+ || !d->inBuiltins.isEmpty() || !d->outBuiltins.isEmpty();
}
/*!
@@ -352,13 +614,14 @@ QByteArray QShaderDescription::toJson() const
}
/*!
- Serializes this QShaderDescription to \a stream.
+ Serializes this QShaderDescription to \a stream. \a version specifies
+ the qsb version.
\sa deserialize(), toJson()
*/
-void QShaderDescription::serialize(QDataStream *stream) const
+void QShaderDescription::serialize(QDataStream *stream, int version) const
{
- d->writeToStream(stream);
+ d->writeToStream(stream, version);
}
/*!
@@ -436,6 +699,7 @@ QList<QShaderDescription::PushConstantBlock> QShaderDescription::pushConstantBlo
"blockName": "StuffSsbo",
"instanceName": "buf",
"knownSize": 16,
+ "runtimeArrayStride": 16
"members": [
{
"name": "whatever",
@@ -473,7 +737,10 @@ QList<QShaderDescription::PushConstantBlock> QShaderDescription::pushConstantBlo
\note The size of the last member in the storage block is undefined. This shows
up as \c size 0 and an array dimension of \c{[0]}. The storage block's \c knownSize
- excludes the size of the last member since that will only be known at run time.
+ excludes the size of the last member since that will only be known at run time. The
+ stride in bytes between array items for a last member with undefined array size is
+ \c runtimeArrayStride. This value is determined according to the specified buffer
+ memory layout standard (std140, std430) rules.
\note SSBOs are not available with some graphics APIs, such as, OpenGL 2.x or
OpenGL ES older than 3.1.
@@ -510,6 +777,16 @@ QList<QShaderDescription::InOutVariable> QShaderDescription::combinedImageSample
return d->combinedImageSamplers;
}
+QList<QShaderDescription::InOutVariable> QShaderDescription::separateImages() const
+{
+ return d->separateImages;
+}
+
+QList<QShaderDescription::InOutVariable> QShaderDescription::separateSamplers() const
+{
+ return d->separateSamplers;
+}
+
/*!
\return the list of image variables.
@@ -538,7 +815,26 @@ QList<QShaderDescription::InOutVariable> QShaderDescription::storageImages() con
}
/*!
- Returns the local size of a compute shader.
+ \return the list of active builtins used as input. For example, a
+ tessellation evaluation shader reading the value of gl_TessCoord and
+ gl_Position will have TessCoordBuiltin and PositionBuiltin listed here.
+ */
+QVector<QShaderDescription::BuiltinVariable> QShaderDescription::inputBuiltinVariables() const
+{
+ return d->inBuiltins;
+}
+
+/*!
+ \return the list of active built-in variables used as input. For example, a
+ vertex shader will very often have PositionBuiltin as an output built-in.
+ */
+QVector<QShaderDescription::BuiltinVariable> QShaderDescription::outputBuiltinVariables() const
+{
+ return d->outBuiltins;
+}
+
+/*!
+ \return the local size of a compute shader.
For example, for a compute shader with the following declaration the
function returns { 256, 16, 1}.
@@ -552,146 +848,346 @@ std::array<uint, 3> QShaderDescription::computeShaderLocalSize() const
return d->localSize;
}
-static struct TypeTab {
- QString k;
+/*!
+ \return the number of output vertices.
+
+ For example, for a tessellation control shader with the following
+ declaration the function returns 3.
+
+ \badcode
+ layout(vertices = 3) out;
+ \endcode
+ */
+uint QShaderDescription::tessellationOutputVertexCount() const
+{
+ return d->tessOutVertCount;
+}
+
+/*!
+ \enum QShaderDescription::TessellationMode
+
+ \value UnknownTessellationMode
+ \value TrianglesTessellationMode
+ \value QuadTessellationMode
+ \value IsolineTessellationMode
+ */
+
+/*!
+ \return the tessellation execution mode for a tessellation control or
+ evaluation shader.
+
+ When not set, the returned value is UnknownTessellationMode.
+
+ For example, for a tessellation evaluation shader with the following
+ declaration the function returns TrianglesTessellationMode.
+
+ \badcode
+ layout(triangles) in;
+ \endcode
+ */
+QShaderDescription::TessellationMode QShaderDescription::tessellationMode() const
+{
+ return d->tessMode;
+}
+
+/*!
+ \enum QShaderDescription::TessellationWindingOrder
+
+ \value UnknownTessellationWindingOrder
+ \value CwTessellationWindingOrder
+ \value CcwTessellationWindingOrder
+ */
+
+/*!
+ \return the tessellation winding order for a tessellation control or
+ evaluation shader.
+
+ When not set, the returned value is UnknownTessellationWindingOrder.
+
+ For example, for a tessellation evaluation shader with the following
+ declaration the function returns CcwTessellationWindingOrder.
+
+ \badcode
+ layout(triangles, fractional_odd_spacing, ccw) in;
+ \endcode
+ */
+QShaderDescription::TessellationWindingOrder QShaderDescription::tessellationWindingOrder() const
+{
+ return d->tessWind;
+}
+
+/*!
+ \enum QShaderDescription::TessellationPartitioning
+
+ \value UnknownTessellationPartitioning
+ \value EqualTessellationPartitioning
+ \value FractionalEvenTessellationPartitioning
+ \value FractionalOddTessellationPartitioning
+ */
+
+/*!
+ \return the tessellation partitioning mode for a tessellation control or
+ evaluation shader.
+
+ When not set, the returned value is UnknownTessellationPartitioning.
+
+ For example, for a tessellation evaluation shader with the following
+ declaration the function returns FractionalOddTessellationPartitioning.
+
+ \badcode
+ layout(triangles, fractional_odd_spacing, ccw) in;
+ \endcode
+ */
+QShaderDescription::TessellationPartitioning QShaderDescription::tessellationPartitioning() const
+{
+ return d->tessPart;
+}
+
+static const struct TypeTab {
+ const char k[20];
QShaderDescription::VariableType v;
} typeTab[] = {
- { QLatin1String("float"), QShaderDescription::Float },
- { QLatin1String("vec2"), QShaderDescription::Vec2 },
- { QLatin1String("vec3"), QShaderDescription::Vec3 },
- { QLatin1String("vec4"), QShaderDescription::Vec4 },
- { QLatin1String("mat2"), QShaderDescription::Mat2 },
- { QLatin1String("mat3"), QShaderDescription::Mat3 },
- { QLatin1String("mat4"), QShaderDescription::Mat4 },
-
- { QLatin1String("struct"), QShaderDescription::Struct },
-
- { QLatin1String("sampler1D"), QShaderDescription::Sampler1D },
- { QLatin1String("sampler2D"), QShaderDescription::Sampler2D },
- { QLatin1String("sampler2DMS"), QShaderDescription::Sampler2DMS },
- { QLatin1String("sampler3D"), QShaderDescription::Sampler3D },
- { QLatin1String("samplerCube"), QShaderDescription::SamplerCube },
- { QLatin1String("sampler1DArray"), QShaderDescription::Sampler1DArray },
- { QLatin1String("sampler2DArray"), QShaderDescription::Sampler2DArray },
- { QLatin1String("sampler2DMSArray"), QShaderDescription::Sampler2DMSArray },
- { QLatin1String("sampler3DArray"), QShaderDescription::Sampler3DArray },
- { QLatin1String("samplerCubeArray"), QShaderDescription::SamplerCubeArray },
- { QLatin1String("samplerRect"), QShaderDescription::SamplerRect },
- { QLatin1String("samplerBuffer"), QShaderDescription::SamplerBuffer },
- { QLatin1String("samplerExternalOES"), QShaderDescription::SamplerExternalOES },
-
- { QLatin1String("mat2x3"), QShaderDescription::Mat2x3 },
- { QLatin1String("mat2x4"), QShaderDescription::Mat2x4 },
- { QLatin1String("mat3x2"), QShaderDescription::Mat3x2 },
- { QLatin1String("mat3x4"), QShaderDescription::Mat3x4 },
- { QLatin1String("mat4x2"), QShaderDescription::Mat4x2 },
- { QLatin1String("mat4x3"), QShaderDescription::Mat4x3 },
-
- { QLatin1String("int"), QShaderDescription::Int },
- { QLatin1String("ivec2"), QShaderDescription::Int2 },
- { QLatin1String("ivec3"), QShaderDescription::Int3 },
- { QLatin1String("ivec4"), QShaderDescription::Int4 },
-
- { QLatin1String("uint"), QShaderDescription::Uint },
- { QLatin1String("uvec2"), QShaderDescription::Uint2 },
- { QLatin1String("uvec3"), QShaderDescription::Uint3 },
- { QLatin1String("uvec4"), QShaderDescription::Uint4 },
-
- { QLatin1String("bool"), QShaderDescription::Bool },
- { QLatin1String("bvec2"), QShaderDescription::Bool2 },
- { QLatin1String("bvec3"), QShaderDescription::Bool3 },
- { QLatin1String("bvec4"), QShaderDescription::Bool4 },
-
- { QLatin1String("double"), QShaderDescription::Double },
- { QLatin1String("dvec2"), QShaderDescription::Double2 },
- { QLatin1String("dvec3"), QShaderDescription::Double3 },
- { QLatin1String("dvec4"), QShaderDescription::Double4 },
- { QLatin1String("dmat2"), QShaderDescription::DMat2 },
- { QLatin1String("dmat3"), QShaderDescription::DMat3 },
- { QLatin1String("dmat4"), QShaderDescription::DMat4 },
- { QLatin1String("dmat2x3"), QShaderDescription::DMat2x3 },
- { QLatin1String("dmat2x4"), QShaderDescription::DMat2x4 },
- { QLatin1String("dmat3x2"), QShaderDescription::DMat3x2 },
- { QLatin1String("dmat3x4"), QShaderDescription::DMat3x4 },
- { QLatin1String("dmat4x2"), QShaderDescription::DMat4x2 },
- { QLatin1String("dmat4x3"), QShaderDescription::DMat4x3 },
-
- { QLatin1String("image1D"), QShaderDescription::Image1D },
- { QLatin1String("image2D"), QShaderDescription::Image2D },
- { QLatin1String("image2DMS"), QShaderDescription::Image2DMS },
- { QLatin1String("image3D"), QShaderDescription::Image3D },
- { QLatin1String("imageCube"), QShaderDescription::ImageCube },
- { QLatin1String("image1DArray"), QShaderDescription::Image1DArray },
- { QLatin1String("image2DArray"), QShaderDescription::Image2DArray },
- { QLatin1String("image2DMSArray"), QShaderDescription::Image2DMSArray },
- { QLatin1String("image3DArray"), QShaderDescription::Image3DArray },
- { QLatin1String("imageCubeArray"), QShaderDescription::ImageCubeArray },
- { QLatin1String("imageRect"), QShaderDescription::ImageRect },
- { QLatin1String("imageBuffer"), QShaderDescription::ImageBuffer }
-};
-
-static QString typeStr(const QShaderDescription::VariableType &t)
+ { "float", QShaderDescription::Float },
+ { "vec2", QShaderDescription::Vec2 },
+ { "vec3", QShaderDescription::Vec3 },
+ { "vec4", QShaderDescription::Vec4 },
+ { "mat2", QShaderDescription::Mat2 },
+ { "mat3", QShaderDescription::Mat3 },
+ { "mat4", QShaderDescription::Mat4 },
+
+ { "struct", QShaderDescription::Struct },
+
+ { "sampler1D", QShaderDescription::Sampler1D },
+ { "sampler2D", QShaderDescription::Sampler2D },
+ { "sampler2DMS", QShaderDescription::Sampler2DMS },
+ { "sampler3D", QShaderDescription::Sampler3D },
+ { "samplerCube", QShaderDescription::SamplerCube },
+ { "sampler1DArray", QShaderDescription::Sampler1DArray },
+ { "sampler2DArray", QShaderDescription::Sampler2DArray },
+ { "sampler2DMSArray", QShaderDescription::Sampler2DMSArray },
+ { "sampler3DArray", QShaderDescription::Sampler3DArray },
+ { "samplerCubeArray", QShaderDescription::SamplerCubeArray },
+ { "samplerRect", QShaderDescription::SamplerRect },
+ { "samplerBuffer", QShaderDescription::SamplerBuffer },
+ { "samplerExternalOES", QShaderDescription::SamplerExternalOES },
+ { "sampler", QShaderDescription::Sampler },
+
+ { "mat2x3", QShaderDescription::Mat2x3 },
+ { "mat2x4", QShaderDescription::Mat2x4 },
+ { "mat3x2", QShaderDescription::Mat3x2 },
+ { "mat3x4", QShaderDescription::Mat3x4 },
+ { "mat4x2", QShaderDescription::Mat4x2 },
+ { "mat4x3", QShaderDescription::Mat4x3 },
+
+ { "int", QShaderDescription::Int },
+ { "ivec2", QShaderDescription::Int2 },
+ { "ivec3", QShaderDescription::Int3 },
+ { "ivec4", QShaderDescription::Int4 },
+
+ { "uint", QShaderDescription::Uint },
+ { "uvec2", QShaderDescription::Uint2 },
+ { "uvec3", QShaderDescription::Uint3 },
+ { "uvec4", QShaderDescription::Uint4 },
+
+ { "bool", QShaderDescription::Bool },
+ { "bvec2", QShaderDescription::Bool2 },
+ { "bvec3", QShaderDescription::Bool3 },
+ { "bvec4", QShaderDescription::Bool4 },
+
+ { "double", QShaderDescription::Double },
+ { "dvec2", QShaderDescription::Double2 },
+ { "dvec3", QShaderDescription::Double3 },
+ { "dvec4", QShaderDescription::Double4 },
+ { "dmat2", QShaderDescription::DMat2 },
+ { "dmat3", QShaderDescription::DMat3 },
+ { "dmat4", QShaderDescription::DMat4 },
+ { "dmat2x3", QShaderDescription::DMat2x3 },
+ { "dmat2x4", QShaderDescription::DMat2x4 },
+ { "dmat3x2", QShaderDescription::DMat3x2 },
+ { "dmat3x4", QShaderDescription::DMat3x4 },
+ { "dmat4x2", QShaderDescription::DMat4x2 },
+ { "dmat4x3", QShaderDescription::DMat4x3 },
+
+ { "image1D", QShaderDescription::Image1D },
+ { "image2D", QShaderDescription::Image2D },
+ { "image2DMS", QShaderDescription::Image2DMS },
+ { "image3D", QShaderDescription::Image3D },
+ { "imageCube", QShaderDescription::ImageCube },
+ { "image1DArray", QShaderDescription::Image1DArray },
+ { "image2DArray", QShaderDescription::Image2DArray },
+ { "image2DMSArray", QShaderDescription::Image2DMSArray },
+ { "image3DArray", QShaderDescription::Image3DArray },
+ { "imageCubeArray", QShaderDescription::ImageCubeArray },
+ { "imageRect", QShaderDescription::ImageRect },
+ { "imageBuffer", QShaderDescription::ImageBuffer },
+
+ { "half", QShaderDescription::Half },
+ { "half2", QShaderDescription::Half2 },
+ { "half3", QShaderDescription::Half3 },
+ { "half4", QShaderDescription::Half4 } };
+
+static QLatin1StringView typeStr(QShaderDescription::VariableType t)
{
for (size_t i = 0; i < sizeof(typeTab) / sizeof(TypeTab); ++i) {
if (typeTab[i].v == t)
- return typeTab[i].k;
+ return QLatin1StringView(typeTab[i].k);
}
- return QString();
+ return {};
}
-static struct ImageFormatTab {
- QString k;
+static const struct ImageFormatTab {
+ const char k[15];
QShaderDescription::ImageFormat v;
} imageFormatTab[] {
- { QLatin1String("unknown"), QShaderDescription::ImageFormatUnknown },
- { QLatin1String("rgba32f"), QShaderDescription::ImageFormatRgba32f },
- { QLatin1String("rgba16"), QShaderDescription::ImageFormatRgba16f },
- { QLatin1String("r32f"), QShaderDescription::ImageFormatR32f },
- { QLatin1String("rgba8"), QShaderDescription::ImageFormatRgba8 },
- { QLatin1String("rgba8_snorm"), QShaderDescription::ImageFormatRgba8Snorm },
- { QLatin1String("rg32f"), QShaderDescription::ImageFormatRg32f },
- { QLatin1String("rg16f"), QShaderDescription::ImageFormatRg16f },
- { QLatin1String("r11f_g11f_b10f"), QShaderDescription::ImageFormatR11fG11fB10f },
- { QLatin1String("r16f"), QShaderDescription::ImageFormatR16f },
- { QLatin1String("rgba16"), QShaderDescription::ImageFormatRgba16 },
- { QLatin1String("rgb10_a2"), QShaderDescription::ImageFormatRgb10A2 },
- { QLatin1String("rg16"), QShaderDescription::ImageFormatRg16 },
- { QLatin1String("rg8"), QShaderDescription::ImageFormatRg8 },
- { QLatin1String("r16"), QShaderDescription::ImageFormatR16 },
- { QLatin1String("r8"), QShaderDescription::ImageFormatR8 },
- { QLatin1String("rgba16_snorm"), QShaderDescription::ImageFormatRgba16Snorm },
- { QLatin1String("rg16_snorm"), QShaderDescription::ImageFormatRg16Snorm },
- { QLatin1String("rg8_snorm"), QShaderDescription::ImageFormatRg8Snorm },
- { QLatin1String("r16_snorm"), QShaderDescription::ImageFormatR16Snorm },
- { QLatin1String("r8_snorm"), QShaderDescription::ImageFormatR8Snorm },
- { QLatin1String("rgba32i"), QShaderDescription::ImageFormatRgba32i },
- { QLatin1String("rgba16i"), QShaderDescription::ImageFormatRgba16i },
- { QLatin1String("rgba8i"), QShaderDescription::ImageFormatRgba8i },
- { QLatin1String("r32i"), QShaderDescription::ImageFormatR32i },
- { QLatin1String("rg32i"), QShaderDescription::ImageFormatRg32i },
- { QLatin1String("rg16i"), QShaderDescription::ImageFormatRg16i },
- { QLatin1String("rg8i"), QShaderDescription::ImageFormatRg8i },
- { QLatin1String("r16i"), QShaderDescription::ImageFormatR16i },
- { QLatin1String("r8i"), QShaderDescription::ImageFormatR8i },
- { QLatin1String("rgba32ui"), QShaderDescription::ImageFormatRgba32ui },
- { QLatin1String("rgba16ui"), QShaderDescription::ImageFormatRgba16ui },
- { QLatin1String("rgba8ui"), QShaderDescription::ImageFormatRgba8ui },
- { QLatin1String("r32ui"), QShaderDescription::ImageFormatR32ui },
- { QLatin1String("rgb10_a2ui"), QShaderDescription::ImageFormatRgb10a2ui },
- { QLatin1String("rg32ui"), QShaderDescription::ImageFormatRg32ui },
- { QLatin1String("rg16ui"), QShaderDescription::ImageFormatRg16ui },
- { QLatin1String("rg8ui"), QShaderDescription::ImageFormatRg8ui },
- { QLatin1String("r16ui"), QShaderDescription::ImageFormatR16ui },
- { QLatin1String("r8ui"), QShaderDescription::ImageFormatR8ui }
+ { "unknown", QShaderDescription::ImageFormatUnknown },
+ { "rgba32f", QShaderDescription::ImageFormatRgba32f },
+ { "rgba16", QShaderDescription::ImageFormatRgba16f },
+ { "r32f", QShaderDescription::ImageFormatR32f },
+ { "rgba8", QShaderDescription::ImageFormatRgba8 },
+ { "rgba8_snorm", QShaderDescription::ImageFormatRgba8Snorm },
+ { "rg32f", QShaderDescription::ImageFormatRg32f },
+ { "rg16f", QShaderDescription::ImageFormatRg16f },
+ { "r11f_g11f_b10f", QShaderDescription::ImageFormatR11fG11fB10f },
+ { "r16f", QShaderDescription::ImageFormatR16f },
+ { "rgba16", QShaderDescription::ImageFormatRgba16 },
+ { "rgb10_a2", QShaderDescription::ImageFormatRgb10A2 },
+ { "rg16", QShaderDescription::ImageFormatRg16 },
+ { "rg8", QShaderDescription::ImageFormatRg8 },
+ { "r16", QShaderDescription::ImageFormatR16 },
+ { "r8", QShaderDescription::ImageFormatR8 },
+ { "rgba16_snorm", QShaderDescription::ImageFormatRgba16Snorm },
+ { "rg16_snorm", QShaderDescription::ImageFormatRg16Snorm },
+ { "rg8_snorm", QShaderDescription::ImageFormatRg8Snorm },
+ { "r16_snorm", QShaderDescription::ImageFormatR16Snorm },
+ { "r8_snorm", QShaderDescription::ImageFormatR8Snorm },
+ { "rgba32i", QShaderDescription::ImageFormatRgba32i },
+ { "rgba16i", QShaderDescription::ImageFormatRgba16i },
+ { "rgba8i", QShaderDescription::ImageFormatRgba8i },
+ { "r32i", QShaderDescription::ImageFormatR32i },
+ { "rg32i", QShaderDescription::ImageFormatRg32i },
+ { "rg16i", QShaderDescription::ImageFormatRg16i },
+ { "rg8i", QShaderDescription::ImageFormatRg8i },
+ { "r16i", QShaderDescription::ImageFormatR16i },
+ { "r8i", QShaderDescription::ImageFormatR8i },
+ { "rgba32ui", QShaderDescription::ImageFormatRgba32ui },
+ { "rgba16ui", QShaderDescription::ImageFormatRgba16ui },
+ { "rgba8ui", QShaderDescription::ImageFormatRgba8ui },
+ { "r32ui", QShaderDescription::ImageFormatR32ui },
+ { "rgb10_a2ui", QShaderDescription::ImageFormatRgb10a2ui },
+ { "rg32ui", QShaderDescription::ImageFormatRg32ui },
+ { "rg16ui", QShaderDescription::ImageFormatRg16ui },
+ { "rg8ui", QShaderDescription::ImageFormatRg8ui },
+ { "r16ui", QShaderDescription::ImageFormatR16ui },
+ { "r8ui", QShaderDescription::ImageFormatR8ui }
};
-static QString imageFormatStr(const QShaderDescription::ImageFormat &f)
+static QLatin1StringView imageFormatStr(QShaderDescription::ImageFormat f)
{
for (size_t i = 0; i < sizeof(imageFormatTab) / sizeof(ImageFormatTab); ++i) {
if (imageFormatTab[i].v == f)
- return imageFormatTab[i].k;
+ return QLatin1StringView(imageFormatTab[i].k);
}
- return QString();
+ return {};
+}
+
+static const struct BuiltinTypeTab {
+ const char k[21];
+ QShaderDescription::BuiltinType v;
+} builtinTypeTab[] = {
+ { "Position", QShaderDescription::PositionBuiltin },
+ { "PointSize", QShaderDescription::PointSizeBuiltin },
+ { "ClipDistance", QShaderDescription::ClipDistanceBuiltin },
+ { "CullDistance", QShaderDescription::CullDistanceBuiltin },
+ { "VertexId", QShaderDescription::VertexIdBuiltin },
+ { "InstanceId", QShaderDescription::InstanceIdBuiltin },
+ { "PrimitiveId", QShaderDescription::PrimitiveIdBuiltin },
+ { "InvocationId", QShaderDescription::InvocationIdBuiltin },
+ { "Layer", QShaderDescription::LayerBuiltin },
+ { "ViewportIndex", QShaderDescription::ViewportIndexBuiltin },
+ { "TessLevelOuter", QShaderDescription::TessLevelOuterBuiltin },
+ { "TessLevelInner", QShaderDescription::TessLevelInnerBuiltin },
+ { "TessCoord", QShaderDescription::TessCoordBuiltin },
+ { "PatchVertices", QShaderDescription::PatchVerticesBuiltin },
+ { "FragCoord", QShaderDescription::FragCoordBuiltin },
+ { "PointCoord", QShaderDescription::PointCoordBuiltin },
+ { "FrontFacing", QShaderDescription::FrontFacingBuiltin },
+ { "SampleId", QShaderDescription::SampleIdBuiltin },
+ { "SamplePosition", QShaderDescription::SamplePositionBuiltin },
+ { "SampleMask", QShaderDescription::SampleMaskBuiltin },
+ { "FragDepth", QShaderDescription::FragDepthBuiltin },
+ { "NumWorkGroups", QShaderDescription::NumWorkGroupsBuiltin },
+ { "WorkgroupSize", QShaderDescription::WorkgroupSizeBuiltin },
+ { "WorkgroupId", QShaderDescription::WorkgroupIdBuiltin },
+ { "LocalInvocationId", QShaderDescription::LocalInvocationIdBuiltin },
+ { "GlobalInvocationId", QShaderDescription::GlobalInvocationIdBuiltin },
+ { "LocalInvocationIndex", QShaderDescription::LocalInvocationIndexBuiltin },
+ { "VertexIndex", QShaderDescription::VertexIndexBuiltin },
+ { "InstanceIndex", QShaderDescription::InstanceIndexBuiltin }
+};
+
+static QLatin1StringView builtinTypeStr(QShaderDescription::BuiltinType t)
+{
+ for (size_t i = 0; i < sizeof(builtinTypeTab) / sizeof(BuiltinTypeTab); ++i) {
+ if (builtinTypeTab[i].v == t)
+ return QLatin1StringView(builtinTypeTab[i].k);
+ }
+ return {};
+}
+
+static const struct TessellationModeTab {
+ const char k[10];
+ QShaderDescription::TessellationMode v;
+} tessellationModeTab[] {
+ { "unknown", QShaderDescription::UnknownTessellationMode },
+ { "triangles", QShaderDescription::TrianglesTessellationMode },
+ { "quad", QShaderDescription::QuadTessellationMode },
+ { "isoline", QShaderDescription::IsolineTessellationMode }
+};
+
+static QLatin1StringView tessModeStr(QShaderDescription::TessellationMode mode)
+{
+ for (size_t i = 0; i < sizeof(tessellationModeTab) / sizeof(TessellationModeTab); ++i) {
+ if (tessellationModeTab[i].v == mode)
+ return QLatin1StringView(tessellationModeTab[i].k);
+ }
+ return {};
+}
+
+static const struct TessellationWindingOrderTab {
+ const char k[8];
+ QShaderDescription::TessellationWindingOrder v;
+} tessellationWindingOrderTab[] {
+ { "unknown", QShaderDescription::UnknownTessellationWindingOrder },
+ { "cw", QShaderDescription::CwTessellationWindingOrder },
+ { "ccw", QShaderDescription::CcwTessellationWindingOrder }
+};
+
+static QLatin1StringView tessWindStr(QShaderDescription::TessellationWindingOrder w)
+{
+ for (size_t i = 0; i < sizeof(tessellationWindingOrderTab) / sizeof(TessellationWindingOrderTab); ++i) {
+ if (tessellationWindingOrderTab[i].v == w)
+ return QLatin1StringView(tessellationWindingOrderTab[i].k);
+ }
+ return {};
+}
+
+static const struct TessellationPartitioningTab {
+ const char k[24];
+ QShaderDescription::TessellationPartitioning v;
+} tessellationPartitioningTab[] {
+ { "unknown", QShaderDescription::UnknownTessellationPartitioning },
+ { "equal_spacing", QShaderDescription::EqualTessellationPartitioning },
+ { "fractional_even_spacing", QShaderDescription::FractionalEvenTessellationPartitioning },
+ { "fractional_odd_spacing", QShaderDescription::FractionalOddTessellationPartitioning }
+};
+
+static QLatin1StringView tessPartStr(QShaderDescription::TessellationPartitioning p)
+{
+ for (size_t i = 0; i < sizeof(tessellationPartitioningTab) / sizeof(TessellationPartitioningTab); ++i) {
+ if (tessellationPartitioningTab[i].v == p)
+ return QLatin1StringView(tessellationPartitioningTab[i].k);
+ }
+ return {};
}
#ifndef QT_NO_DEBUG_STREAM
@@ -708,7 +1204,11 @@ QDebug operator<<(QDebug dbg, const QShaderDescription &sd)
<< " pcBlocks " << d->pushConstantBlocks
<< " storageBlocks " << d->storageBlocks
<< " combinedSamplers " << d->combinedImageSamplers
- << " images " << d->storageImages
+ << " storageImages " << d->storageImages
+ << " separateImages " << d->separateImages
+ << " separateSamplers " << d->separateSamplers
+ << " inBuiltins " << d->inBuiltins
+ << " outBuiltins " << d->outBuiltins
<< ')';
} else {
dbg.nospace() << "QShaderDescription(null)";
@@ -721,6 +1221,8 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var)
{
QDebugStateSaver saver(dbg);
dbg.nospace() << "InOutVariable(" << typeStr(var.type) << ' ' << var.name;
+ if (var.perPatch)
+ dbg.nospace() << " per-patch";
if (var.location >= 0)
dbg.nospace() << " location=" << var.location;
if (var.binding >= 0)
@@ -733,6 +1235,8 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var)
dbg.nospace() << " imageFlags=" << var.imageFlags;
if (!var.arrayDims.isEmpty())
dbg.nospace() << " array=" << var.arrayDims;
+ if (!var.structMembers.isEmpty())
+ dbg.nospace() << " structMembers=" << var.structMembers;
dbg.nospace() << ')';
return dbg;
}
@@ -740,8 +1244,10 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var)
QDebug operator<<(QDebug dbg, const QShaderDescription::BlockVariable &var)
{
QDebugStateSaver saver(dbg);
- dbg.nospace() << "BlockVariable(" << typeStr(var.type) << ' ' << var.name
- << " offset=" << var.offset << " size=" << var.size;
+ dbg.nospace() << "BlockVariable(" << typeStr(var.type) << ' ' << var.name;
+ if (var.offset != -1)
+ dbg.nospace() << " offset=" << var.offset;
+ dbg.nospace() << " size=" << var.size;
if (!var.arrayDims.isEmpty())
dbg.nospace() << " array=" << var.arrayDims;
if (var.arrayStride)
@@ -786,111 +1292,169 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::StorageBlock &blk)
dbg.nospace() << " binding=" << blk.binding;
if (blk.descriptorSet >= 0)
dbg.nospace() << " set=" << blk.descriptorSet;
+ if (blk.runtimeArrayStride)
+ dbg.nospace() << " runtimeArrayStride=" << blk.runtimeArrayStride;
+ if (blk.qualifierFlags)
+ dbg.nospace() << " qualifierFlags=" << blk.qualifierFlags;
dbg.nospace() << ' ' << blk.members << ')';
return dbg;
}
+
+QDebug operator<<(QDebug dbg, const QShaderDescription::BuiltinVariable &builtin)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "BuiltinVariable(type=" << builtinTypeStr(builtin.type);
+ dbg.nospace() << " varType=" << typeStr(builtin.varType);
+ if (!builtin.arrayDims.isEmpty())
+ dbg.nospace() << " array=" << builtin.arrayDims;
+ dbg.nospace() << ")";
+ return dbg;
+}
#endif
-static const QString nameKey = QLatin1String("name");
-static const QString typeKey = QLatin1String("type");
-static const QString locationKey = QLatin1String("location");
-static const QString bindingKey = QLatin1String("binding");
-static const QString setKey = QLatin1String("set");
-static const QString imageFormatKey = QLatin1String("imageFormat");
-static const QString imageFlagsKey = QLatin1String("imageFlags");
-static const QString offsetKey = QLatin1String("offset");
-static const QString arrayDimsKey = QLatin1String("arrayDims");
-static const QString arrayStrideKey = QLatin1String("arrayStride");
-static const QString matrixStrideKey = QLatin1String("matrixStride");
-static const QString matrixRowMajorKey = QLatin1String("matrixRowMajor");
-static const QString structMembersKey = QLatin1String("structMembers");
-static const QString membersKey = QLatin1String("members");
-static const QString inputsKey = QLatin1String("inputs");
-static const QString outputsKey = QLatin1String("outputs");
-static const QString uniformBlocksKey = QLatin1String("uniformBlocks");
-static const QString blockNameKey = QLatin1String("blockName");
-static const QString structNameKey = QLatin1String("structName");
-static const QString instanceNameKey = QLatin1String("instanceName");
-static const QString sizeKey = QLatin1String("size");
-static const QString knownSizeKey = QLatin1String("knownSize");
-static const QString pushConstantBlocksKey = QLatin1String("pushConstantBlocks");
-static const QString storageBlocksKey = QLatin1String("storageBlocks");
-static const QString combinedImageSamplersKey = QLatin1String("combinedImageSamplers");
-static const QString storageImagesKey = QLatin1String("storageImages");
-static const QString localSizeKey = QLatin1String("localSize");
+#define JSON_KEY(key) static constexpr QLatin1StringView key ## Key() noexcept { return QLatin1StringView( #key ); }
+JSON_KEY(name)
+JSON_KEY(type)
+JSON_KEY(location)
+JSON_KEY(binding)
+JSON_KEY(set)
+JSON_KEY(perPatch)
+JSON_KEY(imageFormat)
+JSON_KEY(imageFlags)
+JSON_KEY(offset)
+JSON_KEY(arrayDims)
+JSON_KEY(arrayStride)
+JSON_KEY(matrixStride)
+JSON_KEY(matrixRowMajor)
+JSON_KEY(structMembers)
+JSON_KEY(members)
+JSON_KEY(inputs)
+JSON_KEY(outputs)
+JSON_KEY(uniformBlocks)
+JSON_KEY(blockName)
+JSON_KEY(structName)
+JSON_KEY(instanceName)
+JSON_KEY(size)
+JSON_KEY(knownSize)
+JSON_KEY(pushConstantBlocks)
+JSON_KEY(storageBlocks)
+JSON_KEY(combinedImageSamplers)
+JSON_KEY(storageImages)
+JSON_KEY(inBuiltins)
+JSON_KEY(outBuiltins)
+JSON_KEY(computeLocalSize)
+JSON_KEY(tessellationOutputVertexCount)
+JSON_KEY(tessellationMode)
+JSON_KEY(tessellationWindingOrder)
+JSON_KEY(tessellationPartitioning)
+JSON_KEY(separateImages)
+JSON_KEY(separateSamplers)
+JSON_KEY(runtimeArrayStride)
+JSON_KEY(qualifierFlags)
+#undef JSON_KEY
static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v)
{
if (v.location >= 0)
- (*obj)[locationKey] = v.location;
+ (*obj)[locationKey()] = v.location;
if (v.binding >= 0)
- (*obj)[bindingKey] = v.binding;
+ (*obj)[bindingKey()] = v.binding;
if (v.descriptorSet >= 0)
- (*obj)[setKey] = v.descriptorSet;
+ (*obj)[setKey()] = v.descriptorSet;
+ if (v.perPatch)
+ (*obj)[perPatchKey()] = v.perPatch;
if (v.imageFormat != QShaderDescription::ImageFormatUnknown)
- (*obj)[imageFormatKey] = imageFormatStr(v.imageFormat);
+ (*obj)[imageFormatKey()] = imageFormatStr(v.imageFormat);
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;
+ (*obj)[arrayDimsKey()] = dimArr;
}
}
-static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v)
+static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v, int version)
{
(*stream) << v.location;
(*stream) << v.binding;
(*stream) << v.descriptorSet;
(*stream) << int(v.imageFormat);
(*stream) << int(v.imageFlags);
- (*stream) << int(v.arrayDims.count());
+ (*stream) << int(v.arrayDims.size());
for (int dim : v.arrayDims)
(*stream) << dim;
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO)
+ (*stream) << quint8(v.perPatch);
}
-static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
+static void serializeBuiltinVar(QDataStream *stream, const QShaderDescription::BuiltinVariable &v, int version)
{
- QJsonObject obj;
- obj[nameKey] = QString::fromUtf8(v.name);
- obj[typeKey] = typeStr(v.type);
- addDeco(&obj, v);
- return obj;
-}
-
-static void serializeInOutVar(QDataStream *stream, const QShaderDescription::InOutVariable &v)
-{
- (*stream) << QString::fromUtf8(v.name);
(*stream) << int(v.type);
- serializeDecorations(stream, v);
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
+ (*stream) << int(v.varType);
+ (*stream) << int(v.arrayDims.size());
+ for (int dim : v.arrayDims)
+ (*stream) << dim;
+ }
}
static QJsonObject blockMemberObject(const QShaderDescription::BlockVariable &v)
{
QJsonObject obj;
- obj[nameKey] = QString::fromUtf8(v.name);
- obj[typeKey] = typeStr(v.type);
- obj[offsetKey] = v.offset;
- obj[sizeKey] = v.size;
+ obj[nameKey()] = QString::fromUtf8(v.name);
+ obj[typeKey()] = typeStr(v.type);
+ if (v.offset != -1)
+ obj[offsetKey()] = v.offset;
+ obj[sizeKey()] = v.size;
if (!v.arrayDims.isEmpty()) {
QJsonArray dimArr;
for (int dim : v.arrayDims)
dimArr.append(dim);
- obj[arrayDimsKey] = dimArr;
+ obj[arrayDimsKey()] = dimArr;
}
if (v.arrayStride)
- obj[arrayStrideKey] = v.arrayStride;
+ obj[arrayStrideKey()] = v.arrayStride;
if (v.matrixStride)
- obj[matrixStrideKey] = v.matrixStride;
+ obj[matrixStrideKey()] = v.matrixStride;
if (v.matrixIsRowMajor)
- obj[matrixRowMajorKey] = true;
+ obj[matrixRowMajorKey()] = true;
+ if (!v.structMembers.isEmpty()) {
+ QJsonArray arr;
+ for (const QShaderDescription::BlockVariable &sv : v.structMembers)
+ arr.append(blockMemberObject(sv));
+ obj[structMembersKey()] = arr;
+ }
+ return obj;
+}
+
+static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
+{
+ QJsonObject obj;
+ obj[nameKey()] = QString::fromUtf8(v.name);
+ obj[typeKey()] = typeStr(v.type);
+ addDeco(&obj, v);
if (!v.structMembers.isEmpty()) {
QJsonArray arr;
for (const QShaderDescription::BlockVariable &sv : v.structMembers)
arr.append(blockMemberObject(sv));
- obj[structMembersKey] = arr;
+ obj[structMembersKey()] = arr;
+ }
+ return obj;
+}
+
+static QJsonObject builtinObject(const QShaderDescription::BuiltinVariable &v)
+{
+ QJsonObject obj;
+
+ obj[nameKey()] = builtinTypeStr(v.type);
+ obj[typeKey()] = typeStr(v.varType);
+ if (!v.arrayDims.isEmpty()) {
+ QJsonArray dimArr;
+ for (int dim : v.arrayDims)
+ dimArr.append(dim);
+ obj[arrayDimsKey()] = dimArr;
}
return obj;
}
@@ -901,174 +1465,272 @@ static void serializeBlockMemberVar(QDataStream *stream, const QShaderDescriptio
(*stream) << int(v.type);
(*stream) << v.offset;
(*stream) << v.size;
- (*stream) << int(v.arrayDims.count());
+ (*stream) << int(v.arrayDims.size());
for (int dim : v.arrayDims)
(*stream) << dim;
(*stream) << v.arrayStride;
(*stream) << v.matrixStride;
(*stream) << v.matrixIsRowMajor;
- (*stream) << int(v.structMembers.count());
+ (*stream) << int(v.structMembers.size());
for (const QShaderDescription::BlockVariable &sv : v.structMembers)
serializeBlockMemberVar(stream, sv);
}
+static void serializeInOutVar(QDataStream *stream, const QShaderDescription::InOutVariable &v,
+ int version)
+{
+ (*stream) << QString::fromUtf8(v.name);
+ (*stream) << int(v.type);
+ serializeDecorations(stream, v, version);
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
+ (*stream) << int(v.structMembers.size());
+ for (const QShaderDescription::BlockVariable &sv : v.structMembers)
+ serializeBlockMemberVar(stream, sv);
+ }
+}
+
QJsonDocument QShaderDescriptionPrivate::makeDoc()
{
QJsonObject root;
QJsonArray jinputs;
- for (const QShaderDescription::InOutVariable &v : qAsConst(inVars))
+ for (const QShaderDescription::InOutVariable &v : std::as_const(inVars))
jinputs.append(inOutObject(v));
if (!jinputs.isEmpty())
- root[inputsKey] = jinputs;
+ root[inputsKey()] = jinputs;
QJsonArray joutputs;
- for (const QShaderDescription::InOutVariable &v : qAsConst(outVars))
+ for (const QShaderDescription::InOutVariable &v : std::as_const(outVars))
joutputs.append(inOutObject(v));
if (!joutputs.isEmpty())
- root[outputsKey] = joutputs;
+ root[outputsKey()] = joutputs;
QJsonArray juniformBlocks;
for (const QShaderDescription::UniformBlock &b : uniformBlocks) {
QJsonObject juniformBlock;
- juniformBlock[blockNameKey] = QString::fromUtf8(b.blockName);
- juniformBlock[structNameKey] = QString::fromUtf8(b.structName);
- juniformBlock[sizeKey] = b.size;
+ juniformBlock[blockNameKey()] = QString::fromUtf8(b.blockName);
+ juniformBlock[structNameKey()] = QString::fromUtf8(b.structName);
+ juniformBlock[sizeKey()] = b.size;
if (b.binding >= 0)
- juniformBlock[bindingKey] = b.binding;
+ juniformBlock[bindingKey()] = b.binding;
if (b.descriptorSet >= 0)
- juniformBlock[setKey] = b.descriptorSet;
+ juniformBlock[setKey()] = b.descriptorSet;
QJsonArray members;
for (const QShaderDescription::BlockVariable &v : b.members)
members.append(blockMemberObject(v));
- juniformBlock[membersKey] = members;
+ juniformBlock[membersKey()] = members;
juniformBlocks.append(juniformBlock);
}
if (!juniformBlocks.isEmpty())
- root[uniformBlocksKey] = juniformBlocks;
+ root[uniformBlocksKey()] = juniformBlocks;
QJsonArray jpushConstantBlocks;
for (const QShaderDescription::PushConstantBlock &b : pushConstantBlocks) {
QJsonObject jpushConstantBlock;
- jpushConstantBlock[nameKey] = QString::fromUtf8(b.name);
- jpushConstantBlock[sizeKey] = b.size;
+ jpushConstantBlock[nameKey()] = QString::fromUtf8(b.name);
+ jpushConstantBlock[sizeKey()] = b.size;
QJsonArray members;
for (const QShaderDescription::BlockVariable &v : b.members)
members.append(blockMemberObject(v));
- jpushConstantBlock[membersKey] = members;
+ jpushConstantBlock[membersKey()] = members;
jpushConstantBlocks.append(jpushConstantBlock);
}
if (!jpushConstantBlocks.isEmpty())
- root[pushConstantBlocksKey] = jpushConstantBlocks;
+ root[pushConstantBlocksKey()] = jpushConstantBlocks;
QJsonArray jstorageBlocks;
for (const QShaderDescription::StorageBlock &b : storageBlocks) {
QJsonObject jstorageBlock;
- jstorageBlock[blockNameKey] = QString::fromUtf8(b.blockName);
- jstorageBlock[instanceNameKey] = QString::fromUtf8(b.instanceName);
- jstorageBlock[knownSizeKey] = b.knownSize;
+ jstorageBlock[blockNameKey()] = QString::fromUtf8(b.blockName);
+ jstorageBlock[instanceNameKey()] = QString::fromUtf8(b.instanceName);
+ jstorageBlock[knownSizeKey()] = b.knownSize;
if (b.binding >= 0)
- jstorageBlock[bindingKey] = b.binding;
+ jstorageBlock[bindingKey()] = b.binding;
if (b.descriptorSet >= 0)
- jstorageBlock[setKey] = b.descriptorSet;
+ jstorageBlock[setKey()] = b.descriptorSet;
+ if (b.runtimeArrayStride)
+ jstorageBlock[runtimeArrayStrideKey()] = b.runtimeArrayStride;
+ if (b.qualifierFlags)
+ jstorageBlock[qualifierFlagsKey()] = int(b.qualifierFlags);
QJsonArray members;
for (const QShaderDescription::BlockVariable &v : b.members)
members.append(blockMemberObject(v));
- jstorageBlock[membersKey] = members;
+ jstorageBlock[membersKey()] = members;
jstorageBlocks.append(jstorageBlock);
}
if (!jstorageBlocks.isEmpty())
- root[storageBlocksKey] = jstorageBlocks;
+ root[storageBlocksKey()] = jstorageBlocks;
QJsonArray jcombinedSamplers;
- for (const QShaderDescription::InOutVariable &v : qAsConst(combinedImageSamplers)) {
+ for (const QShaderDescription::InOutVariable &v : std::as_const(combinedImageSamplers)) {
QJsonObject sampler;
- sampler[nameKey] = QString::fromUtf8(v.name);
- sampler[typeKey] = typeStr(v.type);
+ sampler[nameKey()] = QString::fromUtf8(v.name);
+ sampler[typeKey()] = typeStr(v.type);
addDeco(&sampler, v);
jcombinedSamplers.append(sampler);
}
if (!jcombinedSamplers.isEmpty())
- root[combinedImageSamplersKey] = jcombinedSamplers;
+ root[combinedImageSamplersKey()] = jcombinedSamplers;
QJsonArray jstorageImages;
- for (const QShaderDescription::InOutVariable &v : qAsConst(storageImages)) {
+ for (const QShaderDescription::InOutVariable &v : std::as_const(storageImages)) {
QJsonObject image;
- image[nameKey] = QString::fromUtf8(v.name);
- image[typeKey] = typeStr(v.type);
+ image[nameKey()] = QString::fromUtf8(v.name);
+ image[typeKey()] = typeStr(v.type);
addDeco(&image, v);
jstorageImages.append(image);
}
if (!jstorageImages.isEmpty())
- root[storageImagesKey] = jstorageImages;
+ root[storageImagesKey()] = jstorageImages;
+
+ QJsonArray jinBuiltins;
+ for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins))
+ jinBuiltins.append(builtinObject(v));
+ if (!jinBuiltins.isEmpty())
+ root[inBuiltinsKey()] = jinBuiltins;
+
+ QJsonArray joutBuiltins;
+ for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins))
+ joutBuiltins.append(builtinObject(v));
+ if (!joutBuiltins.isEmpty())
+ root[outBuiltinsKey()] = joutBuiltins;
+
+ if (localSize[0] || localSize[1] || localSize[2]) {
+ QJsonArray jlocalSize;
+ for (size_t i = 0; i < 3; ++i)
+ jlocalSize.append(QJsonValue(int(localSize[i])));
+ root[computeLocalSizeKey()] = jlocalSize;
+ }
+
+ if (tessOutVertCount)
+ root[tessellationOutputVertexCountKey()] = int(tessOutVertCount);
+
+ if (tessMode != QShaderDescription::UnknownTessellationMode)
+ root[tessellationModeKey()] = tessModeStr(tessMode);
+
+ if (tessWind != QShaderDescription::UnknownTessellationWindingOrder)
+ root[tessellationWindingOrderKey()] = tessWindStr(tessWind);
- QJsonArray jlocalSize;
- for (int i = 0; i < 3; ++i)
- jlocalSize.append(QJsonValue(int(localSize[i])));
- root[localSizeKey] = jlocalSize;
+ if (tessPart != QShaderDescription::UnknownTessellationPartitioning)
+ root[tessellationPartitioningKey()] = tessPartStr(tessPart);
+
+ QJsonArray jseparateImages;
+ for (const QShaderDescription::InOutVariable &v : std::as_const(separateImages)) {
+ QJsonObject image;
+ image[nameKey()] = QString::fromUtf8(v.name);
+ image[typeKey()] = typeStr(v.type);
+ addDeco(&image, v);
+ jseparateImages.append(image);
+ }
+ if (!jseparateImages.isEmpty())
+ root[separateImagesKey()] = jseparateImages;
+
+ QJsonArray jseparateSamplers;
+ for (const QShaderDescription::InOutVariable &v : std::as_const(separateSamplers)) {
+ QJsonObject sampler;
+ sampler[nameKey()] = QString::fromUtf8(v.name);
+ sampler[typeKey()] = typeStr(v.type);
+ addDeco(&sampler, v);
+ jseparateSamplers.append(sampler);
+ }
+ if (!jseparateSamplers.isEmpty())
+ root[separateSamplersKey()] = jseparateSamplers;
return QJsonDocument(root);
}
-void QShaderDescriptionPrivate::writeToStream(QDataStream *stream)
+void QShaderDescriptionPrivate::writeToStream(QDataStream *stream, int version)
{
- (*stream) << int(inVars.count());
- for (const QShaderDescription::InOutVariable &v : qAsConst(inVars))
- serializeInOutVar(stream, v);
+ (*stream) << int(inVars.size());
+ for (const QShaderDescription::InOutVariable &v : std::as_const(inVars))
+ serializeInOutVar(stream, v, version);
- (*stream) << int(outVars.count());
- for (const QShaderDescription::InOutVariable &v : qAsConst(outVars))
- serializeInOutVar(stream, v);
+ (*stream) << int(outVars.size());
+ for (const QShaderDescription::InOutVariable &v : std::as_const(outVars))
+ serializeInOutVar(stream, v, version);
- (*stream) << int(uniformBlocks.count());
+ (*stream) << int(uniformBlocks.size());
for (const QShaderDescription::UniformBlock &b : uniformBlocks) {
(*stream) << QString::fromUtf8(b.blockName);
(*stream) << QString::fromUtf8(b.structName);
(*stream) << b.size;
(*stream) << b.binding;
(*stream) << b.descriptorSet;
- (*stream) << int(b.members.count());
+ (*stream) << int(b.members.size());
for (const QShaderDescription::BlockVariable &v : b.members)
serializeBlockMemberVar(stream, v);
}
- (*stream) << int(pushConstantBlocks.count());
+ (*stream) << int(pushConstantBlocks.size());
for (const QShaderDescription::PushConstantBlock &b : pushConstantBlocks) {
(*stream) << QString::fromUtf8(b.name);
(*stream) << b.size;
- (*stream) << int(b.members.count());
+ (*stream) << int(b.members.size());
for (const QShaderDescription::BlockVariable &v : b.members)
serializeBlockMemberVar(stream, v);
}
- (*stream) << int(storageBlocks.count());
+ (*stream) << int(storageBlocks.size());
for (const QShaderDescription::StorageBlock &b : storageBlocks) {
(*stream) << QString::fromUtf8(b.blockName);
(*stream) << QString::fromUtf8(b.instanceName);
(*stream) << b.knownSize;
(*stream) << b.binding;
(*stream) << b.descriptorSet;
- (*stream) << int(b.members.count());
+ (*stream) << int(b.members.size());
for (const QShaderDescription::BlockVariable &v : b.members)
serializeBlockMemberVar(stream, v);
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO) {
+ (*stream) << b.runtimeArrayStride;
+ (*stream) << b.qualifierFlags;
+ }
}
- (*stream) << int(combinedImageSamplers.count());
- for (const QShaderDescription::InOutVariable &v : qAsConst(combinedImageSamplers)) {
+ (*stream) << int(combinedImageSamplers.size());
+ for (const QShaderDescription::InOutVariable &v : std::as_const(combinedImageSamplers)) {
(*stream) << QString::fromUtf8(v.name);
(*stream) << int(v.type);
- serializeDecorations(stream, v);
+ serializeDecorations(stream, v, version);
}
- (*stream) << int(storageImages.count());
- for (const QShaderDescription::InOutVariable &v : qAsConst(storageImages)) {
+ (*stream) << int(storageImages.size());
+ for (const QShaderDescription::InOutVariable &v : std::as_const(storageImages)) {
(*stream) << QString::fromUtf8(v.name);
(*stream) << int(v.type);
- serializeDecorations(stream, v);
+ serializeDecorations(stream, v, version);
}
for (size_t i = 0; i < 3; ++i)
- (*stream) << localSize[i];
+ (*stream) << quint32(localSize[i]);
+
+ (*stream) << int(separateImages.size());
+ for (const QShaderDescription::InOutVariable &v : std::as_const(separateImages)) {
+ (*stream) << QString::fromUtf8(v.name);
+ (*stream) << int(v.type);
+ serializeDecorations(stream, v, version);
+ }
+
+ (*stream) << int(separateSamplers.size());
+ for (const QShaderDescription::InOutVariable &v : std::as_const(separateSamplers)) {
+ (*stream) << QString::fromUtf8(v.name);
+ (*stream) << int(v.type);
+ serializeDecorations(stream, v, version);
+ }
+
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
+ (*stream) << quint32(tessOutVertCount);
+ (*stream) << quint32(tessMode);
+ (*stream) << quint32(tessWind);
+ (*stream) << quint32(tessPart);
+
+ (*stream) << int(inBuiltins.size());
+ for (const QShaderDescription::BuiltinVariable &v : std::as_const(inBuiltins))
+ serializeBuiltinVar(stream, v, version);
+
+ (*stream) << int(outBuiltins.size());
+ for (const QShaderDescription::BuiltinVariable &v : std::as_const(outBuiltins))
+ serializeBuiltinVar(stream, v, version);
+ }
}
static void deserializeDecorations(QDataStream *stream, int version, QShaderDescription::InOutVariable *v)
@@ -1088,18 +1750,29 @@ static void deserializeDecorations(QDataStream *stream, int version, QShaderDesc
for (int i = 0; i < f; ++i)
(*stream) >> v->arrayDims[i];
}
+
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
+ quint8 b;
+ (*stream) >> b;
+ v->perPatch = b;
+ }
}
-static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version)
+static QShaderDescription::BuiltinVariable deserializeBuiltinVar(QDataStream *stream, int version)
{
- QShaderDescription::InOutVariable var;
- QString tmp;
- (*stream) >> tmp;
- var.name = tmp.toUtf8();
+ QShaderDescription::BuiltinVariable var;
int t;
(*stream) >> t;
- var.type = QShaderDescription::VariableType(t);
- deserializeDecorations(stream, version, &var);
+ var.type = QShaderDescription::BuiltinType(t);
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
+ (*stream) >> t;
+ var.varType = QShaderDescription::VariableType(t);
+ int count;
+ (*stream) >> count;
+ var.arrayDims.resize(count);
+ for (int i = 0; i < count; ++i)
+ (*stream) >> var.arrayDims[i];
+ }
return var;
}
@@ -1129,6 +1802,26 @@ static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *
return var;
}
+static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version)
+{
+ QShaderDescription::InOutVariable var;
+ QString tmp;
+ (*stream) >> tmp;
+ var.name = tmp.toUtf8();
+ int t;
+ (*stream) >> t;
+ var.type = QShaderDescription::VariableType(t);
+ deserializeDecorations(stream, version, &var);
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS) {
+ int count;
+ (*stream) >> count;
+ var.structMembers.resize(count);
+ for (int i = 0; i < count; ++i)
+ var.structMembers[i] = deserializeBlockMemberVar(stream, version);
+ }
+ return var;
+}
+
void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version)
{
Q_ASSERT(ref.loadRelaxed() == 1); // must be detached
@@ -1192,6 +1885,11 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version)
storageBlocks[i].members.resize(memberCount);
for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
+
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO) {
+ (*stream) >> storageBlocks[i].runtimeArrayStride;
+ (*stream) >> storageBlocks[i].qualifierFlags;
+ }
}
(*stream) >> count;
@@ -1218,8 +1916,59 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version)
deserializeDecorations(stream, version, &storageImages[i]);
}
- for (size_t i = 0; i < 3; ++i)
- (*stream) >> localSize[i];
+ for (size_t i = 0; i < 3; ++i) {
+ quint32 v;
+ (*stream) >> v;
+ localSize[i] = v;
+ }
+
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS) {
+ (*stream) >> count;
+ separateImages.resize(count);
+ for (int i = 0; i < count; ++i) {
+ QString tmp;
+ (*stream) >> tmp;
+ separateImages[i].name = tmp.toUtf8();
+ int t;
+ (*stream) >> t;
+ separateImages[i].type = QShaderDescription::VariableType(t);
+ deserializeDecorations(stream, version, &separateImages[i]);
+ }
+
+ (*stream) >> count;
+ separateSamplers.resize(count);
+ for (int i = 0; i < count; ++i) {
+ QString tmp;
+ (*stream) >> tmp;
+ separateSamplers[i].name = tmp.toUtf8();
+ int t;
+ (*stream) >> t;
+ separateSamplers[i].type = QShaderDescription::VariableType(t);
+ deserializeDecorations(stream, version, &separateSamplers[i]);
+ }
+ }
+
+ if (version > QShaderPrivate::QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO) {
+ quint32 v;
+ (*stream) >> v;
+ tessOutVertCount = v;
+ (*stream) >> v;
+ tessMode = QShaderDescription::TessellationMode(v);
+ (*stream) >> v;
+ tessWind = QShaderDescription::TessellationWindingOrder(v);
+ (*stream) >> v;
+ tessPart = QShaderDescription::TessellationPartitioning(v);
+
+ (*stream) >> count;
+ inBuiltins.resize(count);
+ for (int i = 0; i < count; ++i)
+ inBuiltins[i] = deserializeBuiltinVar(stream, version);
+
+ (*stream) >> count;
+ outBuiltins.resize(count);
+ for (int i = 0; i < count; ++i)
+ outBuiltins[i] = deserializeBuiltinVar(stream, version);
+ }
}
/*!
@@ -1239,8 +1988,16 @@ bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) no
&& lhs.d->pushConstantBlocks == rhs.d->pushConstantBlocks
&& lhs.d->storageBlocks == rhs.d->storageBlocks
&& lhs.d->combinedImageSamplers == rhs.d->combinedImageSamplers
+ && lhs.d->separateImages == rhs.d->separateImages
+ && lhs.d->separateSamplers == rhs.d->separateSamplers
&& lhs.d->storageImages == rhs.d->storageImages
- && lhs.d->localSize == rhs.d->localSize;
+ && lhs.d->inBuiltins == rhs.d->inBuiltins
+ && lhs.d->outBuiltins == rhs.d->outBuiltins
+ && lhs.d->localSize == rhs.d->localSize
+ && lhs.d->tessOutVertCount == rhs.d->tessOutVertCount
+ && lhs.d->tessMode == rhs.d->tessMode
+ && lhs.d->tessWind == rhs.d->tessWind
+ && lhs.d->tessPart == rhs.d->tessPart;
}
/*!
@@ -1258,7 +2015,9 @@ bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescr
&& lhs.descriptorSet == rhs.descriptorSet
&& lhs.imageFormat == rhs.imageFormat
&& lhs.imageFlags == rhs.imageFlags
- && lhs.arrayDims == rhs.arrayDims;
+ && lhs.arrayDims == rhs.arrayDims
+ && lhs.perPatch == rhs.perPatch
+ && lhs.structMembers == rhs.structMembers;
}
/*!
@@ -1322,7 +2081,22 @@ bool operator==(const QShaderDescription::StorageBlock &lhs, const QShaderDescri
&& lhs.knownSize == rhs.knownSize
&& lhs.binding == rhs.binding
&& lhs.descriptorSet == rhs.descriptorSet
+ && lhs.runtimeArrayStride == rhs.runtimeArrayStride
+ && lhs.qualifierFlags == rhs.qualifierFlags
&& lhs.members == rhs.members;
}
+/*!
+ Returns \c true if the two BuiltinVariable objects \a lhs and \a rhs are
+ equal.
+
+ \relates QShaderDescription::BuiltinVariable
+ */
+bool operator==(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept
+{
+ return lhs.type == rhs.type
+ && lhs.varType == rhs.varType
+ && lhs.arrayDims == rhs.arrayDims;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/rhi/qshaderdescription.h b/src/gui/rhi/qshaderdescription.h
new file mode 100644
index 0000000000..02492a1598
--- /dev/null
+++ b/src/gui/rhi/qshaderdescription.h
@@ -0,0 +1,386 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QSHADERDESCRIPTION_H
+#define QSHADERDESCRIPTION_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the RHI API, with limited compatibility guarantees.
+// Usage of this API may make your code source and binary incompatible with
+// future versions of Qt.
+//
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qlist.h>
+#include <array>
+
+QT_BEGIN_NAMESPACE
+
+struct QShaderDescriptionPrivate;
+class QDataStream;
+
+class Q_GUI_EXPORT QShaderDescription
+{
+public:
+ QShaderDescription();
+ QShaderDescription(const QShaderDescription &other);
+ QShaderDescription &operator=(const QShaderDescription &other);
+ ~QShaderDescription();
+ void detach();
+
+ bool isValid() const;
+
+ void serialize(QDataStream *stream, int version) const;
+ QByteArray toJson() const;
+
+ static QShaderDescription deserialize(QDataStream *stream, int version);
+
+ enum VariableType {
+ Unknown = 0,
+
+ // do not reorder
+ Float,
+ Vec2,
+ Vec3,
+ Vec4,
+ Mat2,
+ Mat2x3,
+ Mat2x4,
+ Mat3,
+ Mat3x2,
+ Mat3x4,
+ Mat4,
+ Mat4x2,
+ Mat4x3,
+
+ Int,
+ Int2,
+ Int3,
+ Int4,
+
+ Uint,
+ Uint2,
+ Uint3,
+ Uint4,
+
+ Bool,
+ Bool2,
+ Bool3,
+ Bool4,
+
+ Double,
+ Double2,
+ Double3,
+ Double4,
+ DMat2,
+ DMat2x3,
+ DMat2x4,
+ DMat3,
+ DMat3x2,
+ DMat3x4,
+ DMat4,
+ DMat4x2,
+ DMat4x3,
+
+ Sampler1D,
+ Sampler2D,
+ Sampler2DMS,
+ Sampler3D,
+ SamplerCube,
+ Sampler1DArray,
+ Sampler2DArray,
+ Sampler2DMSArray,
+ Sampler3DArray,
+ SamplerCubeArray,
+ SamplerRect,
+ SamplerBuffer,
+ SamplerExternalOES,
+ Sampler,
+
+ Image1D,
+ Image2D,
+ Image2DMS,
+ Image3D,
+ ImageCube,
+ Image1DArray,
+ Image2DArray,
+ Image2DMSArray,
+ Image3DArray,
+ ImageCubeArray,
+ ImageRect,
+ ImageBuffer,
+
+ Struct,
+
+ Half,
+ Half2,
+ Half3,
+ Half4
+ };
+
+ enum ImageFormat {
+ // must match SPIR-V's ImageFormat
+ ImageFormatUnknown = 0,
+ ImageFormatRgba32f = 1,
+ ImageFormatRgba16f = 2,
+ ImageFormatR32f = 3,
+ ImageFormatRgba8 = 4,
+ ImageFormatRgba8Snorm = 5,
+ ImageFormatRg32f = 6,
+ ImageFormatRg16f = 7,
+ ImageFormatR11fG11fB10f = 8,
+ ImageFormatR16f = 9,
+ ImageFormatRgba16 = 10,
+ ImageFormatRgb10A2 = 11,
+ ImageFormatRg16 = 12,
+ ImageFormatRg8 = 13,
+ ImageFormatR16 = 14,
+ ImageFormatR8 = 15,
+ ImageFormatRgba16Snorm = 16,
+ ImageFormatRg16Snorm = 17,
+ ImageFormatRg8Snorm = 18,
+ ImageFormatR16Snorm = 19,
+ ImageFormatR8Snorm = 20,
+ ImageFormatRgba32i = 21,
+ ImageFormatRgba16i = 22,
+ ImageFormatRgba8i = 23,
+ ImageFormatR32i = 24,
+ ImageFormatRg32i = 25,
+ ImageFormatRg16i = 26,
+ ImageFormatRg8i = 27,
+ ImageFormatR16i = 28,
+ ImageFormatR8i = 29,
+ ImageFormatRgba32ui = 30,
+ ImageFormatRgba16ui = 31,
+ ImageFormatRgba8ui = 32,
+ ImageFormatR32ui = 33,
+ ImageFormatRgb10a2ui = 34,
+ ImageFormatRg32ui = 35,
+ ImageFormatRg16ui = 36,
+ ImageFormatRg8ui = 37,
+ ImageFormatR16ui = 38,
+ ImageFormatR8ui = 39
+ };
+
+ enum ImageFlag {
+ ReadOnlyImage = 1 << 0,
+ WriteOnlyImage = 1 << 1
+ };
+ Q_DECLARE_FLAGS(ImageFlags, ImageFlag)
+
+ enum QualifierFlag {
+ QualifierReadOnly = 1 << 0,
+ QualifierWriteOnly = 1 << 1,
+ QualifierCoherent = 1 << 2,
+ QualifierVolatile = 1 << 3,
+ QualifierRestrict = 1 << 4,
+ };
+ Q_DECLARE_FLAGS(QualifierFlags, QualifierFlag)
+
+ // Optional data (like decorations) usually default to an otherwise invalid value (-1 or 0). This is intentional.
+
+ struct BlockVariable {
+ QByteArray name;
+ VariableType type = Unknown;
+ int offset = 0;
+ int size = 0;
+ QList<int> arrayDims;
+ int arrayStride = 0;
+ int matrixStride = 0;
+ bool matrixIsRowMajor = false;
+ QList<BlockVariable> structMembers;
+ };
+
+ struct InOutVariable {
+ QByteArray name;
+ VariableType type = Unknown;
+ int location = -1;
+ int binding = -1;
+ int descriptorSet = -1;
+ ImageFormat imageFormat = ImageFormatUnknown;
+ ImageFlags imageFlags;
+ QList<int> arrayDims;
+ bool perPatch = false;
+ QList<BlockVariable> structMembers;
+ };
+
+ struct UniformBlock {
+ QByteArray blockName;
+ QByteArray structName; // instanceName
+ int size = 0;
+ int binding = -1;
+ int descriptorSet = -1;
+ QList<BlockVariable> members;
+ };
+
+ struct PushConstantBlock {
+ QByteArray name;
+ int size = 0;
+ QList<BlockVariable> members;
+ };
+
+ struct StorageBlock {
+ QByteArray blockName;
+ QByteArray instanceName;
+ int knownSize = 0;
+ int binding = -1;
+ int descriptorSet = -1;
+ QList<BlockVariable> members;
+ int runtimeArrayStride = 0;
+ QualifierFlags qualifierFlags;
+ };
+
+ QList<InOutVariable> inputVariables() const;
+ QList<InOutVariable> outputVariables() const;
+ QList<UniformBlock> uniformBlocks() const;
+ QList<PushConstantBlock> pushConstantBlocks() const;
+ QList<StorageBlock> storageBlocks() const;
+ QList<InOutVariable> combinedImageSamplers() const;
+ QList<InOutVariable> separateImages() const;
+ QList<InOutVariable> separateSamplers() const;
+ QList<InOutVariable> storageImages() const;
+
+ enum BuiltinType {
+ // must match SpvBuiltIn
+ PositionBuiltin = 0,
+ PointSizeBuiltin = 1,
+ ClipDistanceBuiltin = 3,
+ CullDistanceBuiltin = 4,
+ VertexIdBuiltin = 5,
+ InstanceIdBuiltin = 6,
+ PrimitiveIdBuiltin = 7,
+ InvocationIdBuiltin = 8,
+ LayerBuiltin = 9,
+ ViewportIndexBuiltin = 10,
+ TessLevelOuterBuiltin = 11,
+ TessLevelInnerBuiltin = 12,
+ TessCoordBuiltin = 13,
+ PatchVerticesBuiltin = 14,
+ FragCoordBuiltin = 15,
+ PointCoordBuiltin = 16,
+ FrontFacingBuiltin = 17,
+ SampleIdBuiltin = 18,
+ SamplePositionBuiltin = 19,
+ SampleMaskBuiltin = 20,
+ FragDepthBuiltin = 22,
+ NumWorkGroupsBuiltin = 24,
+ WorkgroupSizeBuiltin = 25,
+ WorkgroupIdBuiltin = 26,
+ LocalInvocationIdBuiltin = 27,
+ GlobalInvocationIdBuiltin = 28,
+ LocalInvocationIndexBuiltin = 29,
+ VertexIndexBuiltin = 42,
+ InstanceIndexBuiltin = 43
+ };
+
+ struct BuiltinVariable {
+ BuiltinType type;
+ VariableType varType;
+ QList<int> arrayDims;
+ };
+
+ QList<BuiltinVariable> inputBuiltinVariables() const;
+ QList<BuiltinVariable> outputBuiltinVariables() const;
+
+ std::array<uint, 3> computeShaderLocalSize() const;
+
+ uint tessellationOutputVertexCount() const;
+
+ enum TessellationMode {
+ UnknownTessellationMode,
+ TrianglesTessellationMode,
+ QuadTessellationMode,
+ IsolineTessellationMode
+ };
+
+ TessellationMode tessellationMode() const;
+
+ enum TessellationWindingOrder {
+ UnknownTessellationWindingOrder,
+ CwTessellationWindingOrder,
+ CcwTessellationWindingOrder
+ };
+
+ TessellationWindingOrder tessellationWindingOrder() const;
+
+ enum TessellationPartitioning {
+ UnknownTessellationPartitioning,
+ EqualTessellationPartitioning,
+ FractionalEvenTessellationPartitioning,
+ FractionalOddTessellationPartitioning
+ };
+
+ TessellationPartitioning tessellationPartitioning() const;
+
+private:
+ QShaderDescriptionPrivate *d;
+ friend struct QShaderDescriptionPrivate;
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription &);
+#endif
+ friend Q_GUI_EXPORT bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderDescription::ImageFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderDescription::QualifierFlags)
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::InOutVariable &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::BlockVariable &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::UniformBlock &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::PushConstantBlock &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::StorageBlock &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::BuiltinVariable &);
+#endif
+
+Q_GUI_EXPORT bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept;
+Q_GUI_EXPORT bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept;
+Q_GUI_EXPORT bool operator==(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept;
+Q_GUI_EXPORT bool operator==(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept;
+Q_GUI_EXPORT bool operator==(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept;
+Q_GUI_EXPORT bool operator==(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept;
+Q_GUI_EXPORT bool operator==(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept;
+
+inline bool operator!=(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+inline bool operator!=(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept
+{
+ return !(lhs == rhs);
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/rhi/qshaderdescription_p.h b/src/gui/rhi/qshaderdescription_p.h
index edaa964527..df694bbf40 100644
--- a/src/gui/rhi/qshaderdescription_p.h
+++ b/src/gui/rhi/qshaderdescription_p.h
@@ -1,44 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#ifndef QSHADERDESCRIPTION_H
-#define QSHADERDESCRIPTION_H
+#ifndef QSHADERDESCRIPTION_P_H
+#define QSHADERDESCRIPTION_P_H
//
// W A R N I N G
@@ -51,275 +15,67 @@
// We mean it.
//
-#include <QtGui/qtguiglobal.h>
-#include <QtCore/QString>
+#include <rhi/qshaderdescription.h>
#include <QtCore/QList>
-#include <array>
+#include <QtCore/QAtomicInt>
+#include <QtCore/QJsonDocument>
QT_BEGIN_NAMESPACE
-struct QShaderDescriptionPrivate;
-class QDataStream;
-
-class Q_GUI_EXPORT QShaderDescription
+struct Q_GUI_EXPORT QShaderDescriptionPrivate
{
-public:
- QShaderDescription();
- QShaderDescription(const QShaderDescription &other);
- QShaderDescription &operator=(const QShaderDescription &other);
- ~QShaderDescription();
- void detach();
-
- bool isValid() const;
-
- void serialize(QDataStream *stream) const;
- QByteArray toJson() const;
-
- static QShaderDescription deserialize(QDataStream *stream, int version);
-
- enum VariableType {
- Unknown = 0,
-
- // do not reorder
- Float,
- Vec2,
- Vec3,
- Vec4,
- Mat2,
- Mat2x3,
- Mat2x4,
- Mat3,
- Mat3x2,
- Mat3x4,
- Mat4,
- Mat4x2,
- Mat4x3,
-
- Int,
- Int2,
- Int3,
- Int4,
-
- Uint,
- Uint2,
- Uint3,
- Uint4,
-
- Bool,
- Bool2,
- Bool3,
- Bool4,
-
- Double,
- Double2,
- Double3,
- Double4,
- DMat2,
- DMat2x3,
- DMat2x4,
- DMat3,
- DMat3x2,
- DMat3x4,
- DMat4,
- DMat4x2,
- DMat4x3,
-
- Sampler1D,
- Sampler2D,
- Sampler2DMS,
- Sampler3D,
- SamplerCube,
- Sampler1DArray,
- Sampler2DArray,
- Sampler2DMSArray,
- Sampler3DArray,
- SamplerCubeArray,
- SamplerRect,
- SamplerBuffer,
- SamplerExternalOES,
-
- Image1D,
- Image2D,
- Image2DMS,
- Image3D,
- ImageCube,
- Image1DArray,
- Image2DArray,
- Image2DMSArray,
- Image3DArray,
- ImageCubeArray,
- ImageRect,
- ImageBuffer,
-
- Struct
- };
-
- enum ImageFormat {
- // must match SPIR-V's ImageFormat
- ImageFormatUnknown = 0,
- ImageFormatRgba32f = 1,
- ImageFormatRgba16f = 2,
- ImageFormatR32f = 3,
- ImageFormatRgba8 = 4,
- ImageFormatRgba8Snorm = 5,
- ImageFormatRg32f = 6,
- ImageFormatRg16f = 7,
- ImageFormatR11fG11fB10f = 8,
- ImageFormatR16f = 9,
- ImageFormatRgba16 = 10,
- ImageFormatRgb10A2 = 11,
- ImageFormatRg16 = 12,
- ImageFormatRg8 = 13,
- ImageFormatR16 = 14,
- ImageFormatR8 = 15,
- ImageFormatRgba16Snorm = 16,
- ImageFormatRg16Snorm = 17,
- ImageFormatRg8Snorm = 18,
- ImageFormatR16Snorm = 19,
- ImageFormatR8Snorm = 20,
- ImageFormatRgba32i = 21,
- ImageFormatRgba16i = 22,
- ImageFormatRgba8i = 23,
- ImageFormatR32i = 24,
- ImageFormatRg32i = 25,
- ImageFormatRg16i = 26,
- ImageFormatRg8i = 27,
- ImageFormatR16i = 28,
- ImageFormatR8i = 29,
- ImageFormatRgba32ui = 30,
- ImageFormatRgba16ui = 31,
- ImageFormatRgba8ui = 32,
- ImageFormatR32ui = 33,
- ImageFormatRgb10a2ui = 34,
- ImageFormatRg32ui = 35,
- ImageFormatRg16ui = 36,
- ImageFormatRg8ui = 37,
- ImageFormatR16ui = 38,
- ImageFormatR8ui = 39
- };
-
- enum ImageFlag {
- ReadOnlyImage = 1 << 0,
- WriteOnlyImage = 1 << 1
- };
- Q_DECLARE_FLAGS(ImageFlags, ImageFlag)
-
- // Optional data (like decorations) usually default to an otherwise invalid value (-1 or 0). This is intentional.
-
- struct InOutVariable {
- QByteArray name;
- VariableType type = Unknown;
- int location = -1;
- int binding = -1;
- int descriptorSet = -1;
- ImageFormat imageFormat = ImageFormatUnknown;
- ImageFlags imageFlags;
- QList<int> arrayDims;
- };
-
- struct BlockVariable {
- QByteArray name;
- VariableType type = Unknown;
- int offset = 0;
- int size = 0;
- QList<int> arrayDims;
- int arrayStride = 0;
- int matrixStride = 0;
- bool matrixIsRowMajor = false;
- QList<BlockVariable> structMembers;
- };
-
- struct UniformBlock {
- QByteArray blockName;
- QByteArray structName; // instanceName
- int size = 0;
- int binding = -1;
- int descriptorSet = -1;
- QList<BlockVariable> members;
- };
-
- struct PushConstantBlock {
- QByteArray name;
- int size = 0;
- QList<BlockVariable> members;
- };
-
- struct StorageBlock {
- QByteArray blockName;
- QByteArray instanceName;
- int knownSize = 0;
- int binding = -1;
- int descriptorSet = -1;
- QList<BlockVariable> members;
- };
-
- QList<InOutVariable> inputVariables() const;
- QList<InOutVariable> outputVariables() const;
- QList<UniformBlock> uniformBlocks() const;
- QList<PushConstantBlock> pushConstantBlocks() const;
- QList<StorageBlock> storageBlocks() const;
- QList<InOutVariable> combinedImageSamplers() const;
- QList<InOutVariable> storageImages() const;
-
- std::array<uint, 3> computeShaderLocalSize() const;
-
-private:
- QShaderDescriptionPrivate *d;
- friend struct QShaderDescriptionPrivate;
-#ifndef QT_NO_DEBUG_STREAM
- friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription &);
-#endif
- friend Q_GUI_EXPORT bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept;
+ QShaderDescriptionPrivate()
+ : ref(1)
+ {
+ }
+
+ QShaderDescriptionPrivate(const QShaderDescriptionPrivate &other)
+ : ref(1),
+ inVars(other.inVars),
+ outVars(other.outVars),
+ uniformBlocks(other.uniformBlocks),
+ pushConstantBlocks(other.pushConstantBlocks),
+ storageBlocks(other.storageBlocks),
+ combinedImageSamplers(other.combinedImageSamplers),
+ separateImages(other.separateImages),
+ separateSamplers(other.separateSamplers),
+ storageImages(other.storageImages),
+ inBuiltins(other.inBuiltins),
+ outBuiltins(other.outBuiltins),
+ localSize(other.localSize),
+ tessOutVertCount(other.tessOutVertCount),
+ tessMode(other.tessMode),
+ tessWind(other.tessWind),
+ tessPart(other.tessPart)
+ {
+ }
+
+ static QShaderDescriptionPrivate *get(QShaderDescription *desc) { return desc->d; }
+ static const QShaderDescriptionPrivate *get(const QShaderDescription *desc) { return desc->d; }
+
+ QJsonDocument makeDoc();
+ void writeToStream(QDataStream *stream, int version);
+ void loadFromStream(QDataStream *stream, int version);
+
+ QAtomicInt ref;
+ QList<QShaderDescription::InOutVariable> inVars;
+ QList<QShaderDescription::InOutVariable> outVars;
+ QList<QShaderDescription::UniformBlock> uniformBlocks;
+ QList<QShaderDescription::PushConstantBlock> pushConstantBlocks;
+ QList<QShaderDescription::StorageBlock> storageBlocks;
+ QList<QShaderDescription::InOutVariable> combinedImageSamplers;
+ QList<QShaderDescription::InOutVariable> separateImages;
+ QList<QShaderDescription::InOutVariable> separateSamplers;
+ QList<QShaderDescription::InOutVariable> storageImages;
+ QList<QShaderDescription::BuiltinVariable> inBuiltins;
+ QList<QShaderDescription::BuiltinVariable> outBuiltins;
+ std::array<uint, 3> localSize = {};
+ uint tessOutVertCount = 0;
+ QShaderDescription::TessellationMode tessMode = QShaderDescription::UnknownTessellationMode;
+ QShaderDescription::TessellationWindingOrder tessWind = QShaderDescription::UnknownTessellationWindingOrder;
+ QShaderDescription::TessellationPartitioning tessPart = QShaderDescription::UnknownTessellationPartitioning;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderDescription::ImageFlags)
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription &);
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::InOutVariable &);
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::BlockVariable &);
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::UniformBlock &);
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::PushConstantBlock &);
-Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::StorageBlock &);
-#endif
-
-Q_GUI_EXPORT bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept;
-Q_GUI_EXPORT bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept;
-Q_GUI_EXPORT bool operator==(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept;
-Q_GUI_EXPORT bool operator==(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept;
-Q_GUI_EXPORT bool operator==(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept;
-Q_GUI_EXPORT bool operator==(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept;
-
-inline bool operator!=(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
QT_END_NAMESPACE
#endif
diff --git a/src/gui/rhi/qshaderdescription_p_p.h b/src/gui/rhi/qshaderdescription_p_p.h
deleted file mode 100644
index e0bed856b7..0000000000
--- a/src/gui/rhi/qshaderdescription_p_p.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt Gui module
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHADERDESCRIPTION_P_H
-#define QSHADERDESCRIPTION_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of a number of Qt sources files. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qshaderdescription_p.h"
-#include <QtCore/QList>
-#include <QtCore/QAtomicInt>
-#include <QtCore/QJsonDocument>
-
-QT_BEGIN_NAMESPACE
-
-struct Q_GUI_EXPORT QShaderDescriptionPrivate
-{
- QShaderDescriptionPrivate()
- : ref(1)
- {
- localSize[0] = localSize[1] = localSize[2] = 0;
- }
-
- QShaderDescriptionPrivate(const QShaderDescriptionPrivate *other)
- : ref(1),
- inVars(other->inVars),
- outVars(other->outVars),
- uniformBlocks(other->uniformBlocks),
- pushConstantBlocks(other->pushConstantBlocks),
- storageBlocks(other->storageBlocks),
- combinedImageSamplers(other->combinedImageSamplers),
- storageImages(other->storageImages),
- localSize(other->localSize)
- {
- }
-
- static QShaderDescriptionPrivate *get(QShaderDescription *desc) { return desc->d; }
- static const QShaderDescriptionPrivate *get(const QShaderDescription *desc) { return desc->d; }
-
- QJsonDocument makeDoc();
- void writeToStream(QDataStream *stream);
- void loadFromStream(QDataStream *stream, int version);
-
- QAtomicInt ref;
- QList<QShaderDescription::InOutVariable> inVars;
- QList<QShaderDescription::InOutVariable> outVars;
- QList<QShaderDescription::UniformBlock> uniformBlocks;
- QList<QShaderDescription::PushConstantBlock> pushConstantBlocks;
- QList<QShaderDescription::StorageBlock> storageBlocks;
- QList<QShaderDescription::InOutVariable> combinedImageSamplers;
- QList<QShaderDescription::InOutVariable> storageImages;
- std::array<uint, 3> localSize;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/gui/rhi/qt_attribution.json b/src/gui/rhi/qt_attribution.json
new file mode 100644
index 0000000000..c356f5f087
--- /dev/null
+++ b/src/gui/rhi/qt_attribution.json
@@ -0,0 +1,16 @@
+[
+ {
+ "Id": "rhi-miniengine-d3d12-mipmap",
+ "Name": "Mipmap generator for D3D12",
+ "QDocModule": "qtgui",
+ "Description": "Compute shader for mipmap generation from MiniEngine in DirectX-Graphics-Samples",
+ "QtUsage": "Compute shader for mipmap generation with Direct 3D 12",
+
+ "Homepage": "https://github.com/microsoft/DirectX-Graphics-Samples",
+ "Version": "0aa79bad78992da0b6a8279ddb9002c1753cb849",
+ "License": "MIT License",
+ "LicenseId": "MIT",
+ "LicenseFile": "MiniEngine_LICENSE.txt",
+ "Copyright": "Copyright (c) 2015 Microsoft"
+ }
+]
diff --git a/src/gui/rhi/tdr.hlsl b/src/gui/rhi/tdr.hlsl
deleted file mode 100644
index f79de91c4a..0000000000
--- a/src/gui/rhi/tdr.hlsl
+++ /dev/null
@@ -1,9 +0,0 @@
-RWBuffer<uint> uav;
-cbuffer ConstantBuffer { uint zero; }
-
-[numthreads(256, 1, 1)]
-void killDeviceByTimingOut(uint3 id: SV_DispatchThreadID)
-{
- while (zero == 0)
- uav[id.x] = zero;
-}
diff --git a/src/gui/rhi/test.hlsl b/src/gui/rhi/test.hlsl
new file mode 100644
index 0000000000..2417762f83
--- /dev/null
+++ b/src/gui/rhi/test.hlsl
@@ -0,0 +1,24 @@
+struct Input
+{
+ float4 position : TEXCOORD0;
+ float3 color : TEXCOORD1;
+};
+
+struct Output
+{
+ float4 position : SV_Position;
+ float3 color : TEXCOORD0;
+};
+
+cbuffer buf : register(b0)
+{
+ row_major float4x4 ubuf_mvp;
+};
+
+Output main(Input input)
+{
+ Output output;
+ output.position = mul(input.position, ubuf_mvp);
+ output.color = input.color;
+ return output;
+}
diff --git a/src/gui/rhi/vs_test_p.h b/src/gui/rhi/vs_test_p.h
new file mode 100644
index 0000000000..5feaef7d38
--- /dev/null
+++ b/src/gui/rhi/vs_test_p.h
@@ -0,0 +1,237 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef VS_TEST_P_H
+#define VS_TEST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+
+#ifdef Q_OS_WIN
+
+#include <qt_windows.h>
+
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer buf
+// {
+//
+// row_major float4x4 ubuf_mvp; // Offset: 0 Size: 64
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// buf cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// TEXCOORD 0 xyzw 0 NONE float xyzw
+// TEXCOORD 1 xyz 1 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 xyz 1 NONE float xyz
+//
+vs_5_0
+dcl_globalFlags refactoringAllowed
+dcl_constantbuffer CB0[4], immediateIndexed
+dcl_input v0.xyzw
+dcl_input v1.xyz
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xyz
+dcl_temps 1
+mul r0.xyzw, v0.yyyy, cb0[1].xyzw
+mad r0.xyzw, v0.xxxx, cb0[0].xyzw, r0.xyzw
+mad r0.xyzw, v0.zzzz, cb0[2].xyzw, r0.xyzw
+mad o0.xyzw, v0.wwww, cb0[3].xyzw, r0.xyzw
+mov o1.xyz, v1.xyzx
+ret
+// Approximately 6 instruction slots used
+#endif
+
+inline constexpr BYTE g_testVertexShader[] =
+{
+ 68, 88, 66, 67, 75, 198,
+ 18, 149, 172, 244, 247, 123,
+ 98, 31, 128, 185, 22, 199,
+ 182, 233, 1, 0, 0, 0,
+ 140, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 60, 1, 0, 0, 136, 1,
+ 0, 0, 224, 1, 0, 0,
+ 240, 2, 0, 0, 82, 68,
+ 69, 70, 0, 1, 0, 0,
+ 1, 0, 0, 0, 96, 0,
+ 0, 0, 1, 0, 0, 0,
+ 60, 0, 0, 0, 0, 5,
+ 254, 255, 0, 1, 0, 0,
+ 216, 0, 0, 0, 82, 68,
+ 49, 49, 60, 0, 0, 0,
+ 24, 0, 0, 0, 32, 0,
+ 0, 0, 40, 0, 0, 0,
+ 36, 0, 0, 0, 12, 0,
+ 0, 0, 0, 0, 0, 0,
+ 92, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0,
+ 0, 0, 98, 117, 102, 0,
+ 92, 0, 0, 0, 1, 0,
+ 0, 0, 120, 0, 0, 0,
+ 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 160, 0, 0, 0, 0, 0,
+ 0, 0, 64, 0, 0, 0,
+ 2, 0, 0, 0, 180, 0,
+ 0, 0, 0, 0, 0, 0,
+ 255, 255, 255, 255, 0, 0,
+ 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 117, 98,
+ 117, 102, 95, 109, 118, 112,
+ 0, 102, 108, 111, 97, 116,
+ 52, 120, 52, 0, 171, 171,
+ 2, 0, 3, 0, 4, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 169, 0, 0, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 49,
+ 48, 46, 49, 0, 73, 83,
+ 71, 78, 68, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 15,
+ 0, 0, 56, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 7, 7,
+ 0, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78,
+ 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 7, 8, 0, 0,
+ 83, 86, 95, 80, 111, 115,
+ 105, 116, 105, 111, 110, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 171, 171,
+ 83, 72, 69, 88, 8, 1,
+ 0, 0, 80, 0, 1, 0,
+ 66, 0, 0, 0, 106, 8,
+ 0, 1, 89, 0, 0, 4,
+ 70, 142, 32, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0,
+ 95, 0, 0, 3, 242, 16,
+ 16, 0, 0, 0, 0, 0,
+ 95, 0, 0, 3, 114, 16,
+ 16, 0, 1, 0, 0, 0,
+ 103, 0, 0, 4, 242, 32,
+ 16, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 114, 32, 16, 0,
+ 1, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0,
+ 56, 0, 0, 8, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 86, 21, 16, 0, 0, 0,
+ 0, 0, 70, 142, 32, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 50, 0, 0, 10,
+ 242, 0, 16, 0, 0, 0,
+ 0, 0, 6, 16, 16, 0,
+ 0, 0, 0, 0, 70, 142,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0,
+ 50, 0, 0, 10, 242, 0,
+ 16, 0, 0, 0, 0, 0,
+ 166, 26, 16, 0, 0, 0,
+ 0, 0, 70, 142, 32, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 50, 0,
+ 0, 10, 242, 32, 16, 0,
+ 0, 0, 0, 0, 246, 31,
+ 16, 0, 0, 0, 0, 0,
+ 70, 142, 32, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 70, 14, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 114, 32, 16, 0, 1, 0,
+ 0, 0, 70, 18, 16, 0,
+ 1, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84,
+ 148, 0, 0, 0, 6, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
+
+#endif // Q_OS_WIN
+
+#endif // VS_TEST_P_H
diff --git a/src/gui/text/coretext/qcoretextfontdatabase.mm b/src/gui/text/coretext/qcoretextfontdatabase.mm
index ee145a03d5..19f3a2b335 100644
--- a/src/gui/text/coretext/qcoretextfontdatabase.mm
+++ b/src/gui/text/coretext/qcoretextfontdatabase.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
@@ -49,6 +13,7 @@
#endif
#include <QtCore/qelapsedtimer.h>
+#include <QtCore/private/qcore_mac_p.h>
#include "qcoretextfontdatabase_p.h"
#include "qfontengine_coretext_p.h"
@@ -60,12 +25,19 @@
#include <QtGui/private/qfontengine_ft_p.h>
#endif
+#include <QtGui/qpa/qwindowsysteminterface.h>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+QT_IMPL_METATYPE_EXTERN_TAGGED(QCFType<CGFontRef>, QCFType_CGFontRef)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QCFType<CFURLRef>, QCFType_CFURLRef)
+
// this could become a list of all languages used for each writing
// system, instead of using the single most common language.
-static const char *languageForWritingSystem[] = {
- 0, // Any
+static const char languageForWritingSystem[][8] = {
+ "", // Any
"en", // Latin
"el", // Greek
"ru", // Cyrillic
@@ -95,24 +67,35 @@ static const char *languageForWritingSystem[] = {
"ja", // Japanese
"ko", // Korean
"vi", // Vietnamese
- 0, // Symbol
+ "", // Symbol
"sga", // Ogham
"non", // Runic
"man" // N'Ko
};
-enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) };
+enum { LanguageCount = sizeof languageForWritingSystem / sizeof *languageForWritingSystem };
QCoreTextFontDatabase::QCoreTextFontDatabase()
: m_hasPopulatedAliases(false)
{
+#if defined(Q_OS_MACOS)
+ m_fontSetObserver = QMacNotificationObserver(nil, NSFontSetChangedNotification, [] {
+ qCDebug(lcQpaFonts) << "Fonts have changed";
+ QPlatformFontDatabase::repopulateFontDatabase();
+ });
+#endif
}
QCoreTextFontDatabase::~QCoreTextFontDatabase()
{
- for (CTFontDescriptorRef ref : qAsConst(m_systemFontDescriptors))
- CFRelease(ref);
+ qDeleteAll(m_themeFonts);
}
+CTFontDescriptorRef descriptorForFamily(const QString &familyName)
+{
+ return CTFontDescriptorCreateWithAttributes(CFDictionaryRef(@{
+ (id)kCTFontFamilyNameAttribute: familyName.toNSString()
+ }));
+}
void QCoreTextFontDatabase::populateFontDatabase()
{
qCDebug(lcQpaFonts) << "Populating font database...";
@@ -124,16 +107,121 @@ void QCoreTextFontDatabase::populateFontDatabase()
for (NSString *familyName in familyNames.as<const NSArray *>())
QPlatformFontDatabase::registerFontFamily(QString::fromNSString(familyName));
+ // Some fonts has special handling since macOS Catalina: It is available
+ // on the platform, so that it may be used by applications directly, but does not
+ // get enumerated. Since there are no alternatives, we hardcode it.
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSCatalina
+ && !qEnvironmentVariableIsSet("QT_NO_HARDCODED_FALLBACK_FONTS")) {
+ m_hardcodedFallbackFonts[QChar::Script_Adlam] = QStringLiteral("Noto Sans Adlam");
+ m_hardcodedFallbackFonts[QChar::Script_Ahom] = QStringLiteral("Noto Serif Ahom");
+ m_hardcodedFallbackFonts[QChar::Script_Avestan] = QStringLiteral("Noto Sans Avestan");
+ m_hardcodedFallbackFonts[QChar::Script_Balinese] = QStringLiteral("Noto Serif Balinese");
+ m_hardcodedFallbackFonts[QChar::Script_Bamum] = QStringLiteral("Noto Sans Bamum");
+ m_hardcodedFallbackFonts[QChar::Script_BassaVah] = QStringLiteral("Noto Sans Bassa Vah");
+ m_hardcodedFallbackFonts[QChar::Script_Batak] = QStringLiteral("Noto Sans Batak");
+ m_hardcodedFallbackFonts[QChar::Script_Bhaiksuki] = QStringLiteral("Noto Sans Bhaiksuki");
+ m_hardcodedFallbackFonts[QChar::Script_Brahmi] = QStringLiteral("Noto Sans Brahmi");
+ m_hardcodedFallbackFonts[QChar::Script_Buginese] = QStringLiteral("Noto Sans Buginese");
+ m_hardcodedFallbackFonts[QChar::Script_Buhid] = QStringLiteral("Noto Sans Buhid");
+ m_hardcodedFallbackFonts[QChar::Script_Carian] = QStringLiteral("Noto Sans Carian");
+ m_hardcodedFallbackFonts[QChar::Script_CaucasianAlbanian] = QStringLiteral("Noto Sans Caucasian Albanian");
+ m_hardcodedFallbackFonts[QChar::Script_Chakma] = QStringLiteral("Noto Sans Chakma");
+ m_hardcodedFallbackFonts[QChar::Script_Cham] = QStringLiteral("Noto Sans Cham");
+ m_hardcodedFallbackFonts[QChar::Script_Coptic] = QStringLiteral("Noto Sans Coptic");
+ m_hardcodedFallbackFonts[QChar::Script_Cuneiform] = QStringLiteral("Noto Sans Cuneiform");
+ m_hardcodedFallbackFonts[QChar::Script_Cypriot] = QStringLiteral("Noto Sans Cypriot");
+ m_hardcodedFallbackFonts[QChar::Script_Duployan] = QStringLiteral("Noto Sans Duployan");
+ m_hardcodedFallbackFonts[QChar::Script_EgyptianHieroglyphs] = QStringLiteral("Noto Sans Egyptian Hieroglyphs");
+ m_hardcodedFallbackFonts[QChar::Script_Elbasan] = QStringLiteral("Noto Sans Elbasan");
+ m_hardcodedFallbackFonts[QChar::Script_Glagolitic] = QStringLiteral("Noto Sans Glagolitic");
+ m_hardcodedFallbackFonts[QChar::Script_Gothic] = QStringLiteral("Noto Sans Gothic");
+ m_hardcodedFallbackFonts[QChar::Script_HanifiRohingya] = QStringLiteral("Noto Sans Hanifi Rohingya");
+ m_hardcodedFallbackFonts[QChar::Script_Hanunoo] = QStringLiteral("Noto Sans Hanunoo");
+ m_hardcodedFallbackFonts[QChar::Script_Hatran] = QStringLiteral("Noto Sans Hatran");
+ m_hardcodedFallbackFonts[QChar::Script_ImperialAramaic] = QStringLiteral("Noto Sans Imperial Aramaic");
+ m_hardcodedFallbackFonts[QChar::Script_InscriptionalPahlavi] = QStringLiteral("Noto Sans Inscriptional Pahlavi");
+ m_hardcodedFallbackFonts[QChar::Script_InscriptionalParthian] = QStringLiteral("Noto Sans Inscriptional Parthian");
+ m_hardcodedFallbackFonts[QChar::Script_Javanese] = QStringLiteral("Noto Sans Javanese");
+ m_hardcodedFallbackFonts[QChar::Script_Kaithi] = QStringLiteral("Noto Sans Kaithi");
+ m_hardcodedFallbackFonts[QChar::Script_KayahLi] = QStringLiteral("Noto Sans Kayah Li");
+ m_hardcodedFallbackFonts[QChar::Script_Kharoshthi] = QStringLiteral("Noto Sans Kharoshthi");
+ m_hardcodedFallbackFonts[QChar::Script_Khojki] = QStringLiteral("Noto Sans Khojki");
+ m_hardcodedFallbackFonts[QChar::Script_Khudawadi] = QStringLiteral("Noto Sans Khudawadi");
+ m_hardcodedFallbackFonts[QChar::Script_Lepcha] = QStringLiteral("Noto Sans Lepcha");
+ m_hardcodedFallbackFonts[QChar::Script_Limbu] = QStringLiteral("Noto Sans Limbu");
+ m_hardcodedFallbackFonts[QChar::Script_LinearA] = QStringLiteral("Noto Sans Linear A");
+ m_hardcodedFallbackFonts[QChar::Script_LinearB] = QStringLiteral("Noto Sans Linear B");
+ m_hardcodedFallbackFonts[QChar::Script_Lisu] = QStringLiteral("Noto Sans Lisu");
+ m_hardcodedFallbackFonts[QChar::Script_Lycian] = QStringLiteral("Noto Sans Lycian");
+ m_hardcodedFallbackFonts[QChar::Script_Lydian] = QStringLiteral("Noto Sans Lydian");
+ m_hardcodedFallbackFonts[QChar::Script_Mahajani] = QStringLiteral("Noto Sans Mahajani");
+ m_hardcodedFallbackFonts[QChar::Script_Mandaic] = QStringLiteral("Noto Sans Mandaic");
+ m_hardcodedFallbackFonts[QChar::Script_Manichaean] = QStringLiteral("Noto Sans Manichaean");
+ m_hardcodedFallbackFonts[QChar::Script_Marchen] = QStringLiteral("Noto Sans Marchen");
+ m_hardcodedFallbackFonts[QChar::Script_MendeKikakui] = QStringLiteral("Noto Sans Mende Kikakui");
+ m_hardcodedFallbackFonts[QChar::Script_MeroiticCursive] = QStringLiteral("Noto Sans Meroitic");
+ m_hardcodedFallbackFonts[QChar::Script_MeroiticHieroglyphs] = QStringLiteral("Noto Sans Meroitic");
+ m_hardcodedFallbackFonts[QChar::Script_Miao] = QStringLiteral("Noto Sans Miao");
+ m_hardcodedFallbackFonts[QChar::Script_Modi] = QStringLiteral("Noto Sans Modi");
+ m_hardcodedFallbackFonts[QChar::Script_Mongolian] = QStringLiteral("Noto Sans Mongolian");
+ m_hardcodedFallbackFonts[QChar::Script_Mro] = QStringLiteral("Noto Sans Mro");
+ m_hardcodedFallbackFonts[QChar::Script_MeeteiMayek] = QStringLiteral("Noto Sans Meetei Mayek");
+ m_hardcodedFallbackFonts[QChar::Script_Multani] = QStringLiteral("Noto Sans Multani");
+ m_hardcodedFallbackFonts[QChar::Script_Nabataean] = QStringLiteral("Noto Sans Nabataean");
+ m_hardcodedFallbackFonts[QChar::Script_Newa] = QStringLiteral("Noto Sans Newa");
+ m_hardcodedFallbackFonts[QChar::Script_NewTaiLue] = QStringLiteral("Noto Sans New Tai Lue");
+ m_hardcodedFallbackFonts[QChar::Script_Nko] = QStringLiteral("Noto Sans Nko");
+ m_hardcodedFallbackFonts[QChar::Script_OlChiki] = QStringLiteral("Noto Sans Ol Chiki");
+ m_hardcodedFallbackFonts[QChar::Script_OldHungarian] = QStringLiteral("Noto Sans Old Hungarian");
+ m_hardcodedFallbackFonts[QChar::Script_OldItalic] = QStringLiteral("Noto Sans Old Italic");
+ m_hardcodedFallbackFonts[QChar::Script_OldNorthArabian] = QStringLiteral("Noto Sans Old North Arabian");
+ m_hardcodedFallbackFonts[QChar::Script_OldPermic] = QStringLiteral("Noto Sans Old Permic");
+ m_hardcodedFallbackFonts[QChar::Script_OldPersian] = QStringLiteral("Noto Sans Old Persian");
+ m_hardcodedFallbackFonts[QChar::Script_OldSouthArabian] = QStringLiteral("Noto Sans Old South Arabian");
+ m_hardcodedFallbackFonts[QChar::Script_OldTurkic] = QStringLiteral("Noto Sans Old Turkic");
+ m_hardcodedFallbackFonts[QChar::Script_Osage] = QStringLiteral("Noto Sans Osage");
+ m_hardcodedFallbackFonts[QChar::Script_Osmanya] = QStringLiteral("Noto Sans Osmanya");
+ m_hardcodedFallbackFonts[QChar::Script_PahawhHmong] = QStringLiteral("Noto Sans Pahawh Hmong");
+ m_hardcodedFallbackFonts[QChar::Script_Palmyrene] = QStringLiteral("Noto Sans Palmyrene");
+ m_hardcodedFallbackFonts[QChar::Script_PauCinHau] = QStringLiteral("Noto Sans Pau Cin Hau");
+ m_hardcodedFallbackFonts[QChar::Script_PhagsPa] = QStringLiteral("Noto Sans PhagsPa");
+ m_hardcodedFallbackFonts[QChar::Script_Phoenician] = QStringLiteral("Noto Sans Phoenician");
+ m_hardcodedFallbackFonts[QChar::Script_PsalterPahlavi] = QStringLiteral("Noto Sans Psalter Pahlavi");
+ m_hardcodedFallbackFonts[QChar::Script_Rejang] = QStringLiteral("Noto Sans Rejang");
+ m_hardcodedFallbackFonts[QChar::Script_Samaritan] = QStringLiteral("Noto Sans Samaritan");
+ m_hardcodedFallbackFonts[QChar::Script_Saurashtra] = QStringLiteral("Noto Sans Saurashtra");
+ m_hardcodedFallbackFonts[QChar::Script_Sharada] = QStringLiteral("Noto Sans Sharada");
+ m_hardcodedFallbackFonts[QChar::Script_Siddham] = QStringLiteral("Noto Sans Siddham");
+ m_hardcodedFallbackFonts[QChar::Script_SoraSompeng] = QStringLiteral("Noto Sans Sora Sompeng");
+ m_hardcodedFallbackFonts[QChar::Script_Sundanese] = QStringLiteral("Noto Sans Sundanese");
+ m_hardcodedFallbackFonts[QChar::Script_SylotiNagri] = QStringLiteral("Noto Sans Syloti Nagri");
+ m_hardcodedFallbackFonts[QChar::Script_Tagalog] = QStringLiteral("Noto Sans Tagalog");
+ m_hardcodedFallbackFonts[QChar::Script_Tagbanwa] = QStringLiteral("Noto Sans Tagbanwa");
+ m_hardcodedFallbackFonts[QChar::Script_Takri] = QStringLiteral("Noto Sans Takri");
+ m_hardcodedFallbackFonts[QChar::Script_TaiLe] = QStringLiteral("Noto Sans Tai Le");
+ m_hardcodedFallbackFonts[QChar::Script_TaiTham] = QStringLiteral("Noto Sans Tai Tham");
+ m_hardcodedFallbackFonts[QChar::Script_TaiViet] = QStringLiteral("Noto Sans Tai Viet");
+ m_hardcodedFallbackFonts[QChar::Script_Thaana] = QStringLiteral("Noto Sans Thaana");
+ m_hardcodedFallbackFonts[QChar::Script_Tifinagh] = QStringLiteral("Noto Sans Tifinagh");
+ m_hardcodedFallbackFonts[QChar::Script_Tirhuta] = QStringLiteral("Noto Sans Tirhuta");
+ m_hardcodedFallbackFonts[QChar::Script_Ugaritic] = QStringLiteral("Noto Sans Ugaritic");
+ m_hardcodedFallbackFonts[QChar::Script_Vai] = QStringLiteral("Noto Sans Vai");
+ m_hardcodedFallbackFonts[QChar::Script_WarangCiti] = QStringLiteral("Noto Sans Warang Citi");
+ m_hardcodedFallbackFonts[QChar::Script_Wancho] = QStringLiteral("Noto Sans Wancho");
+ m_hardcodedFallbackFonts[QChar::Script_Yi] = QStringLiteral("Noto Sans Yi");
+ }
+
qCDebug(lcQpaFonts) << "Populating available families took" << elapsed.restart() << "ms";
- // Force creating the theme fonts to get the descriptors in m_systemFontDescriptors
- if (m_themeFonts.isEmpty())
- (void)themeFonts();
+ populateThemeFonts();
- qCDebug(lcQpaFonts) << "Resolving theme fonts took" << elapsed.restart() << "ms";
+ for (auto familyName : m_systemFontDescriptors.keys()) {
+ for (auto fontDescriptor : m_systemFontDescriptors.value(familyName))
+ populateFromDescriptor(fontDescriptor, familyName);
+ }
- for (CTFontDescriptorRef fontDesc : m_systemFontDescriptors)
- populateFromDescriptor(fontDesc);
+ // The font database now has a reference to the original descriptors
+ m_systemFontDescriptors.clear();
qCDebug(lcQpaFonts) << "Populating system descriptors took" << elapsed.restart() << "ms";
@@ -143,6 +231,12 @@ void QCoreTextFontDatabase::populateFontDatabase()
bool QCoreTextFontDatabase::populateFamilyAliases(const QString &missingFamily)
{
#if defined(Q_OS_MACOS)
+ if (isFamilyPopulated(missingFamily)) {
+ // We got here because one of the other properties of the font mismatched,
+ // for example the style, so there's no point in populating font aliases.
+ return false;
+ }
+
if (m_hasPopulatedAliases)
return false;
@@ -190,14 +284,20 @@ bool QCoreTextFontDatabase::populateFamilyAliases(const QString &missingFamily)
#endif
}
+CTFontDescriptorRef descriptorForFamily(const char *familyName)
+{
+ return descriptorForFamily(QString::fromLatin1(familyName));
+}
+
void QCoreTextFontDatabase::populateFamily(const QString &familyName)
{
- QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, QCFString(familyName));
- QCFType<CTFontDescriptorRef> nameOnlyDescriptor = CTFontDescriptorCreateWithAttributes(attributes);
+ qCDebug(lcQpaFonts) << "Populating family" << familyName;
- // A single family might match several different fonts with different styles eg.
- QCFType<CFArrayRef> matchingFonts = (CFArrayRef) CTFontDescriptorCreateMatchingFontDescriptors(nameOnlyDescriptor, 0);
+ // A single family might match several different fonts with different styles.
+ // We need to add them all so that the font database has the full picture,
+ // as once a family has been populated we will not populate it again.
+ QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(familyName);
+ QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor, nullptr);
if (!matchingFonts) {
qCWarning(lcQpaFonts) << "QCoreTextFontDatabase: Found no matching fonts for family" << familyName;
return;
@@ -210,7 +310,12 @@ void QCoreTextFontDatabase::populateFamily(const QString &familyName)
void QCoreTextFontDatabase::invalidate()
{
+ qCDebug(lcQpaFonts) << "Invalidating font database";
m_hasPopulatedAliases = false;
+
+ qDeleteAll(m_themeFonts);
+ m_themeFonts.clear();
+ QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>();
}
struct FontDescription {
@@ -256,7 +361,7 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
fd->fixedPitch = false;
if (QCFType<CTFontRef> tempFont = CTFontCreateWithFontDescriptor(font, 0.0, 0)) {
- uint tag = MAKE_TAG('O', 'S', '/', '2');
+ uint tag = QFont::Tag("OS/2").value();
CTFontRef tempFontRef = tempFont;
void *userData = reinterpret_cast<void *>(&tempFontRef);
uint length = 128;
@@ -313,7 +418,7 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
if (QCFType<CFArrayRef> languages = (CFArrayRef) CTFontDescriptorCopyAttribute(font, kCTFontLanguagesAttribute)) {
CFIndex length = CFArrayGetCount(languages);
for (int i = 1; i < LanguageCount; ++i) {
- if (!languageForWritingSystem[i])
+ if (!*languageForWritingSystem[i])
continue;
QCFString lang = CFStringCreateWithCString(NULL, languageForWritingSystem[i], kCFStringEncodingASCII);
if (CFArrayContainsValue(languages, CFRangeMake(0, length), lang))
@@ -384,6 +489,31 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>::fontEngine
qreal scaledPointSize = fontDef.pixelSize;
CGAffineTransform matrix = qt_transform_from_fontdef(fontDef);
+
+ if (!fontDef.variableAxisValues.isEmpty()) {
+ QCFType<CFMutableDictionaryRef> variations = CFDictionaryCreateMutable(nullptr,
+ fontDef.variableAxisValues.size(),
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ for (auto it = fontDef.variableAxisValues.constBegin();
+ it != fontDef.variableAxisValues.constEnd();
+ ++it) {
+ const quint32 tag = it.key().value();
+ const float value = it.value();
+ QCFType<CFNumberRef> tagRef = CFNumberCreate(nullptr, kCFNumberIntType, &tag);
+ QCFType<CFNumberRef> valueRef = CFNumberCreate(nullptr, kCFNumberFloatType, &value);
+
+ CFDictionarySetValue(variations, tagRef, valueRef);
+ }
+ QCFType<CFDictionaryRef> attributes = CFDictionaryCreate(nullptr,
+ (const void **) &kCTFontVariationAttribute,
+ (const void **) &variations,
+ 1,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, attributes);
+ }
+
if (QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, scaledPointSize, &matrix))
return new QCoreTextFontEngine(font, fontDef);
@@ -399,11 +529,19 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory<QFontEngineFT>::fontEngine(const
if (NSValue *fontDataValue = descriptorAttribute<NSValue>(descriptor, (CFStringRef)kQtFontDataAttribute)) {
QByteArray *fontData = static_cast<QByteArray *>(fontDataValue.pointerValue);
return QFontEngineFT::create(*fontData, fontDef.pixelSize,
- static_cast<QFont::HintingPreference>(fontDef.hintingPreference));
+ static_cast<QFont::HintingPreference>(fontDef.hintingPreference), fontDef.variableAxisValues);
} else if (NSURL *url = descriptorAttribute<NSURL>(descriptor, kCTFontURLAttribute)) {
- Q_ASSERT(url.fileURL);
QFontEngine::FaceId faceId;
- faceId.filename = QString::fromNSString(url.path).toUtf8();
+
+ Q_ASSERT(url.fileURL);
+ QString faceFileName{QString::fromNSString(url.path)};
+ faceId.filename = faceFileName.toUtf8();
+
+ QString styleName = QCFString(CTFontDescriptorCopyAttribute(descriptor, kCTFontStyleNameAttribute));
+ faceId.index = QFreetypeFace::getFaceIndexByStyleName(faceFileName, styleName);
+
+ faceId.variableAxes = fontDef.variableAxisValues;
+
return QFontEngineFT::create(fontDef, faceId);
}
// We end up here with a descriptor does not contain Qt font data or kCTFontURLAttribute.
@@ -416,7 +554,7 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory<QFontEngineFT>::fontEngine(const
template <class T>
QFontEngine *QCoreTextFontDatabaseEngineFactory<T>::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
{
- return T::create(fontData, pixelSize, hintingPreference);
+ return T::create(fontData, pixelSize, hintingPreference, {});
}
// Explicitly instantiate so that we don't need the plugin to involve FreeType
@@ -425,18 +563,6 @@ template class QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>;
template class QCoreTextFontDatabaseEngineFactory<QFontEngineFT>;
#endif
-CTFontDescriptorRef descriptorForFamily(const QString &familyName)
-{
- return CTFontDescriptorCreateWithAttributes(CFDictionaryRef(@{
- (id)kCTFontFamilyNameAttribute: familyName.toNSString()
- }));
-}
-
-CTFontDescriptorRef descriptorForFamily(const char *familyName)
-{
- return descriptorForFamily(QString::fromLatin1(familyName));
-}
-
CFArrayRef fallbacksForDescriptor(CTFontDescriptorRef descriptor)
{
QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, 0.0, nullptr);
@@ -446,7 +572,7 @@ CFArrayRef fallbacksForDescriptor(CTFontDescriptorRef descriptor)
}
CFArrayRef cascadeList = CFArrayRef(CTFontCopyDefaultCascadeListForLanguages(font,
- (CFArrayRef)[NSUserDefaults.standardUserDefaults stringArrayForKey:@"AppleLanguages"]));
+ (CFArrayRef)NSLocale.preferredLanguages));
if (!cascadeList) {
qCWarning(lcQpaFonts) << "Failed to create fallback cascade list for" << descriptor;
@@ -508,7 +634,7 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
Q_UNUSED(style);
qCDebug(lcQpaFonts).nospace() << "Resolving fallbacks families for"
- << (!family.isEmpty() ? qPrintable(QLatin1String(" family '%1' with").arg(family)) : "")
+ << (!family.isEmpty() ? qPrintable(" family '%1' with"_L1.arg(family)) : "")
<< " style hint " << styleHint;
QMacAutoReleasePool pool;
@@ -557,7 +683,7 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
// of the required glyphs, or representing them by question marks.
// Move these to the end, so that the proper fonts are preferred.
for (const char *family : { ".Apple Symbols Fallback", ".Noto Sans Universal" }) {
- int index = fallbackList.indexOf(QLatin1String(family));
+ int index = fallbackList.indexOf(QLatin1StringView(family));
if (index >= 0)
fallbackList.move(index, fallbackList.size() - 1);
}
@@ -574,6 +700,31 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo
// add Apple Symbols to cover those too.
if (!fallbackList.contains(QStringLiteral("Apple Symbols")))
fallbackList.append(QStringLiteral("Apple Symbols"));
+ // Some Noto* fonts are not automatically enumerated by system, despite being the main
+ // fonts for their writing system.
+ QString hardcodedFont = m_hardcodedFallbackFonts.value(script);
+ if (!hardcodedFont.isEmpty() && !fallbackList.contains(hardcodedFont)) {
+ if (!isFamilyPopulated(hardcodedFont)) {
+ if (!m_privateFamilies.contains(hardcodedFont)) {
+ QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(hardcodedFont);
+ QCFType<CFArrayRef> matchingFonts = CTFontDescriptorCreateMatchingFontDescriptors(familyDescriptor, nullptr);
+ if (matchingFonts) {
+ const int numFonts = CFArrayGetCount(matchingFonts);
+ for (int i = 0; i < numFonts; ++i)
+ const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingFonts, i)),
+ hardcodedFont);
+
+ fallbackList.append(hardcodedFont);
+ }
+
+ // Register as private family even if the font is not found, in order to avoid
+ // redoing the check later. In later calls, the font will then just be ignored.
+ m_privateFamilies.insert(hardcodedFont);
+ }
+ } else {
+ fallbackList.append(hardcodedFont);
+ }
+ }
#endif
extern QStringList qt_sort_families_by_writing_system(QChar::Script, const QStringList &);
@@ -590,13 +741,20 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
if (!fontData.isEmpty()) {
QCFType<CFDataRef> fontDataReference = fontData.toRawCFData();
- if (QCFType<CTFontDescriptorRef> descriptor = CTFontManagerCreateFontDescriptorFromData(fontDataReference)) {
- // There's no way to get the data back out of a font descriptor created with
- // CTFontManagerCreateFontDescriptorFromData, so we attach the data manually.
- NSDictionary *attributes = @{ kQtFontDataAttribute : [NSValue valueWithPointer:new QByteArray(fontData)] };
- descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, (CFDictionaryRef)attributes);
+ if (QCFType<CFArrayRef> descriptors = CTFontManagerCreateFontDescriptorsFromData(fontDataReference)) {
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
- CFArrayAppendValue(array, descriptor);
+ const int count = CFArrayGetCount(descriptors);
+
+ for (int i = 0; i < count; ++i) {
+ CTFontDescriptorRef descriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(descriptors, i));
+
+ // There's no way to get the data back out of a font descriptor created with
+ // CTFontManagerCreateFontDescriptorFromData, so we attach the data manually.
+ NSDictionary *attributes = @{ kQtFontDataAttribute : [NSValue valueWithPointer:new QByteArray(fontData)] };
+ descriptor = CTFontDescriptorCreateCopyWithAttributes(descriptor, (CFDictionaryRef)attributes);
+ CFArrayAppendValue(array, descriptor);
+ }
+
fonts = array;
}
} else {
@@ -624,7 +782,7 @@ QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData
bool QCoreTextFontDatabase::isPrivateFontFamily(const QString &family) const
{
- if (family.startsWith(QLatin1Char('.')) || family == QLatin1String("LastResort"))
+ if (family.startsWith(u'.') || family == "LastResort"_L1 || m_privateFamilies.contains(family))
return true;
return QPlatformFontDatabase::isPrivateFontFamily(family);
@@ -738,47 +896,106 @@ static CTFontDescriptorRef fontDescriptorFromTheme(QPlatformTheme::Font f)
UIFontDescriptor *desc = [UIFontDescriptor preferredFontDescriptorWithTextStyle:textStyle];
return static_cast<CTFontDescriptorRef>(CFBridgingRetain(desc));
}
-#endif // Q_OS_IOS, Q_OS_TVOS, Q_OS_WATCHOS
+#endif // QT_PLATFORM_UIKIT
// macOS default case and iOS fallback case
return descriptorForFontType(fontTypeFromTheme(f));
}
-const QHash<QPlatformTheme::Font, QFont *> &QCoreTextFontDatabase::themeFonts() const
+void QCoreTextFontDatabase::populateThemeFonts()
{
- if (m_themeFonts.isEmpty()) {
- for (long f = QPlatformTheme::SystemFont; f < QPlatformTheme::NFonts; f++) {
- QPlatformTheme::Font ft = static_cast<QPlatformTheme::Font>(f);
- m_themeFonts.insert(ft, themeFont(ft));
+ QMacAutoReleasePool pool;
+
+ if (!m_themeFonts.isEmpty())
+ return;
+
+ QElapsedTimer elapsed;
+ if (lcQpaFonts().isDebugEnabled())
+ elapsed.start();
+
+ qCDebug(lcQpaFonts) << "Populating theme fonts...";
+
+ for (long f = QPlatformTheme::SystemFont; f < QPlatformTheme::NFonts; f++) {
+ QPlatformTheme::Font themeFont = static_cast<QPlatformTheme::Font>(f);
+ QCFType<CTFontDescriptorRef> fontDescriptor = fontDescriptorFromTheme(themeFont);
+ FontDescription fd;
+ getFontDescription(fontDescriptor, &fd);
+
+ // We might get here from QFontDatabase::systemFont() or QPlatformTheme::font(),
+ // before the font database has initialized itself and populated all available
+ // families. As a result, we can't populate the descriptor at this time, as that
+ // would result in the font database having > 0 families, which would result in
+ // skipping the initialization and population of all other font families. Instead
+ // we store the descriptors for later and populate them during populateFontDatabase().
+
+ bool haveRegisteredFamily = m_systemFontDescriptors.contains(fd.familyName);
+ qCDebug(lcQpaFonts) << "Got" << (haveRegisteredFamily ? "already registered" : "unseen")
+ << "family" << fd.familyName << "for" << themeFont;
+
+ if (!haveRegisteredFamily) {
+ // We need to register all weights and variants of the theme font,
+ // as the user might tweak the returned QFont before use.
+ QList<QCFType<CTFontDescriptorRef>> themeFontVariants;
+
+ auto addFontVariants = [&](CTFontDescriptorRef descriptor) {
+ QCFType<CFArrayRef> matchingDescriptors = CTFontDescriptorCreateMatchingFontDescriptors(descriptor, nullptr);
+ const int matchingDescriptorsCount = matchingDescriptors ? CFArrayGetCount(matchingDescriptors) : 0;
+ qCDebug(lcQpaFonts) << "Enumerating font variants based on" << id(descriptor)
+ << "resulted in" << matchingDescriptorsCount << "matching descriptors"
+ << matchingDescriptors.as<NSArray*>();
+
+ for (int i = 0; i < matchingDescriptorsCount; ++i) {
+ auto matchingDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(matchingDescriptors, i));
+ themeFontVariants.append(QCFType<CTFontDescriptorRef>::constructFromGet(matchingDescriptor));
+ }
+ };
+
+ // Try populating the font variants based on its UI design trait, if available
+ if (@available(macos 10.15, ios 13.0, *)) {
+ auto fontTraits = QCFType<CFDictionaryRef>(CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontTraitsAttribute));
+ static const NSString *kUIFontDesignTrait = @"NSCTFontUIFontDesignTrait";
+ if (id uiFontDesignTrait = fontTraits.as<NSDictionary*>()[kUIFontDesignTrait]) {
+ QCFType<CTFontDescriptorRef> designTraitDescriptor = CTFontDescriptorCreateWithAttributes(
+ CFDictionaryRef(@{ (id)kCTFontTraitsAttribute: @{ kUIFontDesignTrait: uiFontDesignTrait }
+ }));
+ addFontVariants(designTraitDescriptor);
+ }
+ }
+
+ if (themeFontVariants.isEmpty()) {
+ // Fall back to populating variants based on the family name alone
+ QCFType<CTFontDescriptorRef> familyDescriptor = descriptorForFamily(fd.familyName);
+ addFontVariants(familyDescriptor);
+ }
+
+ if (themeFontVariants.isEmpty()) {
+ qCDebug(lcQpaFonts) << "No theme font variants found, falling back to single variant descriptor";
+ themeFontVariants.append(fontDescriptor);
+ }
+
+ m_systemFontDescriptors.insert(fd.familyName, themeFontVariants);
}
+
+ QFont *font = new QFont(fd.familyName, fd.pointSize, fd.weight, fd.style == QFont::StyleItalic);
+ m_themeFonts.insert(themeFont, font);
}
- return m_themeFonts;
+ qCDebug(lcQpaFonts) << "Populating theme fonts took" << elapsed.restart() << "ms";
}
QFont *QCoreTextFontDatabase::themeFont(QPlatformTheme::Font f) const
{
- CTFontDescriptorRef fontDesc = fontDescriptorFromTheme(f);
- FontDescription fd;
- getFontDescription(fontDesc, &fd);
-
- if (!m_systemFontDescriptors.contains(fontDesc))
- m_systemFontDescriptors.insert(fontDesc);
- else
- CFRelease(fontDesc);
+ // The code paths via QFontDatabase::systemFont() or QPlatformTheme::font()
+ // do not ensure that the font database has been populated, so we need to
+ // manually populate the theme fonts lazily here just in case.
+ const_cast<QCoreTextFontDatabase*>(this)->populateThemeFonts();
- QFont *font = new QFont(fd.familyName, fd.pointSize, fd.weight, fd.style == QFont::StyleItalic);
- return font;
+ return m_themeFonts.value(f, nullptr);
}
QFont QCoreTextFontDatabase::defaultFont() const
{
- if (defaultFontName.isEmpty()) {
- QCFType<CTFontDescriptorRef> systemFont = descriptorForFontType(kCTFontUIFontSystem);
- defaultFontName = QCFString(CTFontDescriptorCopyAttribute(systemFont, kCTFontFamilyNameAttribute));
- }
-
- return QFont(defaultFontName);
+ return QFont(*themeFont(QPlatformTheme::SystemFont));
}
bool QCoreTextFontDatabase::fontsAlwaysScalable() const
@@ -797,5 +1014,10 @@ QList<int> QCoreTextFontDatabase::standardSizes() const
return ret;
}
+bool QCoreTextFontDatabase::supportsVariableApplicationFonts() const
+{
+ return true;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/text/coretext/qcoretextfontdatabase_p.h b/src/gui/text/coretext/qcoretextfontdatabase_p.h
index 971ac3cfde..eeea9ad640 100644
--- a/src/gui/text/coretext/qcoretextfontdatabase_p.h
+++ b/src/gui/text/coretext/qcoretextfontdatabase_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCORETEXTFONTDATABASE_H
#define QCORETEXTFONTDATABASE_H
@@ -60,8 +24,8 @@
Q_FORWARD_DECLARE_CF_TYPE(CTFontDescriptor);
Q_FORWARD_DECLARE_CF_TYPE(CTFont);
-Q_DECLARE_METATYPE(QCFType<CGFontRef>);
-Q_DECLARE_METATYPE(QCFType<CFURLRef>);
+QT_DECL_METATYPE_EXTERN_TAGGED(QCFType<CGFontRef>, QCFType_CGFontRef, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN_TAGGED(QCFType<CFURLRef>, QCFType_CFURLRef, Q_GUI_EXPORT)
QT_BEGIN_NAMESPACE
@@ -82,22 +46,26 @@ public:
QFont defaultFont() const override;
bool fontsAlwaysScalable() const override;
QList<int> standardSizes() const override;
+ bool supportsVariableApplicationFonts() const override;
- // For iOS and OS X platform themes
+ // For iOS and macOS platform themes
QFont *themeFont(QPlatformTheme::Font) const;
- const QHash<QPlatformTheme::Font, QFont *> &themeFonts() const;
-
-protected:
- mutable QSet<CTFontDescriptorRef> m_systemFontDescriptors;
private:
+ void populateThemeFonts();
void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString(), QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr);
static CFArrayRef fallbacksForFamily(const QString &family);
- mutable QString defaultFontName;
+ QHash<QPlatformTheme::Font, QFont *> m_themeFonts;
+ QHash<QString, QList<QCFType<CTFontDescriptorRef>>> m_systemFontDescriptors;
+ QHash<QChar::Script, QString> m_hardcodedFallbackFonts;
+ mutable QSet<QString> m_privateFamilies;
- mutable QHash<QPlatformTheme::Font, QFont *> m_themeFonts;
bool m_hasPopulatedAliases;
+
+#if defined(Q_OS_MACOS)
+ QMacNotificationObserver m_fontSetObserver;
+#endif
};
// Split out into separate template class so that the compiler doesn't have
diff --git a/src/gui/text/coretext/qfontengine_coretext.mm b/src/gui/text/coretext/qfontengine_coretext.mm
index d1b13f73e9..b6fef2fecb 100644
--- a/src/gui/text/coretext/qfontengine_coretext.mm
+++ b/src/gui/text/coretext/qfontengine_coretext.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfontengine_coretext_p.h"
@@ -48,6 +12,8 @@
#include <QtGui/qpainterpath.h>
#include <private/qcoregraphics_p.h>
#include <private/qimage_p.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformtheme.h>
#include <cmath>
@@ -161,9 +127,13 @@ public:
QByteArray m_fontData;
};
-QCoreTextFontEngine *QCoreTextFontEngine::create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
+QCoreTextFontEngine *QCoreTextFontEngine::create(const QByteArray &fontData,
+ qreal pixelSize,
+ QFont::HintingPreference hintingPreference,
+ const QMap<QFont::Tag, float> &variableAxisValues)
{
Q_UNUSED(hintingPreference);
+ Q_UNUSED(variableAxisValues);
QCFType<CFDataRef> fontDataReference = fontData.toRawCFData();
QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithCFData(fontDataReference);
@@ -222,6 +192,7 @@ void QCoreTextFontEngine::init()
face_id.index = 0;
QCFString name = CTFontCopyName(ctfont, kCTFontUniqueNameKey);
face_id.filename = QString::fromCFString(name).toUtf8();
+ face_id.variableAxes = fontDef.variableAxisValues;
QCFString family = CTFontCopyFamilyName(ctfont);
fontDef.families = QStringList(family);
@@ -266,7 +237,7 @@ void QCoreTextFontEngine::init()
synthesisFlags |= SynthesizedItalic;
avgCharWidth = 0;
- QByteArray os2Table = getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
+ QByteArray os2Table = getSfntTable(QFont::Tag("OS/2").value());
unsigned emSize = CTFontGetUnitsPerEm(ctfont);
if (os2Table.size() >= 10) {
fsType = qFromBigEndian<quint16>(os2Table.constData() + 8);
@@ -337,14 +308,6 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *
return true;
}
-glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs)
-{
- QFixed w;
- for (int i = 0; i < glyphs.numGlyphs; ++i)
- w += glyphs.effectiveAdvance(i);
- return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs), ascent()+descent(), w, 0);
-}
-
glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
{
glyph_metrics_t ret;
@@ -371,7 +334,7 @@ void QCoreTextFontEngine::initializeHeightMetrics() const
m_descent = QFixed::fromReal(CTFontGetDescent(ctfont));
m_leading = QFixed::fromReal(CTFontGetLeading(ctfont));
- QFontEngine::initializeHeightMetrics();
+ m_heightMetricsQueried = true;
}
QFixed QCoreTextFontEngine::capHeight() const
@@ -406,6 +369,7 @@ bool QCoreTextFontEngine::hasColorGlyphs() const
return glyphFormat == QFontEngine::Format_ARGB;
}
+Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight)
{
QVarLengthArray<QFixedPoint> positions;
@@ -422,7 +386,8 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt
CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight);
- CGAffineTransformConcat(cgMatrix, oldTextMatrix);
+ // FIXME: Should we include the old matrix here? If so we need to assign it.
+ Q_UNUSED(CGAffineTransformConcat(cgMatrix, oldTextMatrix));
if (synthesisFlags & QFontEngine::SynthesizedItalic)
cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0));
@@ -449,7 +414,15 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt
CTFontDrawGlyphs(ctfont, cgGlyphs.data(), cgPositions.data(), glyphs.size(), ctx);
if (synthesisFlags & QFontEngine::SynthesizedBold) {
- CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(),
+ QTransform matrix(cgMatrix.a, cgMatrix.b, cgMatrix.c, cgMatrix.d, cgMatrix.tx, cgMatrix.ty);
+
+ qreal boldOffset = 0.5 * lineThickness().toReal();
+ qreal scale;
+ qt_scaleForTransform(matrix, &scale);
+ boldOffset *= scale;
+
+ CGContextSetTextPosition(ctx,
+ positions[0].x.toReal() + boldOffset,
positions[0].y.toReal());
CTFontDrawGlyphs(ctfont, cgGlyphs.data(), cgPositions.data(), glyphs.size(), ctx);
}
@@ -539,7 +512,11 @@ glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, const QF
return QFontEngine::alphaMapBoundingBox(glyph, subPixelPosition, matrix, format);
glyph_metrics_t br = boundingBox(glyph);
- qcoretextfontengine_scaleMetrics(br, matrix);
+
+ QTransform xform = matrix;
+ if (fontDef.stretch != 100 && fontDef.stretch != QFont::AnyStretch)
+ xform.scale(fontDef.stretch / 100.0, 1.0);
+ qcoretextfontengine_scaleMetrics(br, xform);
// Normalize width and height
if (br.width < 0)
@@ -746,10 +723,12 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, const QFixedPoint &subP
// draw with white or black fill, and then invert the glyph image in the latter case,
// producing an alpha map. This covers the most common use-cases, but longer term we
// should propagate the fill color all the way from the paint engine, and include it
- //in the key for the glyph cache.
+ // in the key for the glyph cache.
- if (!qt_mac_applicationIsInDarkMode())
- return kCGColorBlack;
+ if (auto *platformTheme = QGuiApplicationPrivate::platformTheme()) {
+ if (platformTheme->colorScheme() != Qt::ColorScheme::Dark)
+ return kCGColorBlack;
+ }
}
return kCGColorWhite;
}();
@@ -792,7 +771,13 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, const QFixedPoint &subP
CTFontDrawGlyphs(ctfont, &cgGlyph, &CGPointZero, 1, ctx);
if (synthesisFlags & QFontEngine::SynthesizedBold) {
- CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y);
+ qreal boldOffset = 0.5 * lineThickness().toReal();
+
+ qreal scale;
+ qt_scaleForTransform(matrix, &scale);
+ boldOffset *= scale;
+
+ CGContextSetTextPosition(ctx, pos_x + boldOffset, pos_y);
CTFontDrawGlyphs(ctfont, &cgGlyph, &CGPointZero, 1, ctx);
}
} else {
@@ -884,8 +869,9 @@ void QCoreTextFontEngine::loadAdvancesForGlyphs(QVarLengthArray<CGGlyph> &cgGlyp
QVarLengthArray<CGSize> advances(numGlyphs);
CTFontGetAdvancesForGlyphs(ctfont, kCTFontOrientationHorizontal, cgGlyphs.data(), advances.data(), numGlyphs);
+ qreal stretch = fontDef.stretch != QFont::AnyStretch ? fontDef.stretch / 100.0 : 1.0;
for (int i = 0; i < numGlyphs; ++i)
- glyphs->advances[i] = QFixed::fromReal(advances[i].width);
+ glyphs->advances[i] = QFixed::fromReal(advances[i].width * stretch);
}
QFontEngine::FaceId QCoreTextFontEngine::faceId() const
diff --git a/src/gui/text/coretext/qfontengine_coretext_p.h b/src/gui/text/coretext/qfontengine_coretext_p.h
index 361153b37a..af87f5f6f3 100644
--- a/src/gui/text/coretext/qfontengine_coretext_p.h
+++ b/src/gui/text/coretext/qfontengine_coretext_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTENGINE_CORETEXT_P_H
#define QFONTENGINE_CORETEXT_P_H
@@ -77,7 +41,6 @@ public:
bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
void recalcAdvances(QGlyphLayout *, ShaperFlags) const override;
- glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
glyph_metrics_t boundingBox(glyph_t glyph) override;
QFixed capHeight() const override;
@@ -128,7 +91,7 @@ public:
static bool ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length);
static QFont::Weight qtWeightFromCFWeight(float value);
- static QCoreTextFontEngine *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
+ static QCoreTextFontEngine *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference, const QMap<QFont::Tag, float> &variableAxisValue);
protected:
QCoreTextFontEngine(const QFontDef &def);
diff --git a/src/gui/text/freetype/qfontengine_ft.cpp b/src/gui/text/freetype/qfontengine_ft.cpp
index 12ba46b7ed..72d2c72fe3 100644
--- a/src/gui/text/freetype/qfontengine_ft.cpp
+++ b/src/gui/text/freetype/qfontengine_ft.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdir.h"
#include "qmetatype.h"
@@ -48,6 +12,7 @@
#include <qscreen.h>
#include <qpa/qplatformscreen.h>
#include <QtCore/QUuid>
+#include <QtCore/QLoggingCategory>
#include <QtGui/QPainterPath>
#ifndef QT_NO_FREETYPE
@@ -59,6 +24,8 @@
#include <qmath.h>
#include <qendian.h>
+#include <memory>
+
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
@@ -68,6 +35,7 @@
#include FT_GLYPH_H
#include FT_MODULE_H
#include FT_LCD_FILTER_H
+#include FT_MULTIPLE_MASTERS_H
#if defined(FT_CONFIG_OPTIONS_H)
#include FT_CONFIG_OPTIONS_H
@@ -87,6 +55,10 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcFontMatch)
+
+using namespace Qt::StringLiterals;
+
#define FLOOR(x) ((x) & -64)
#define CEIL(x) (((x)+63) & -64)
#define TRUNC(x) ((x) >> 6)
@@ -126,19 +98,43 @@ public:
{ }
~QtFreetypeData();
+ struct FaceStyle {
+ QString faceFileName;
+ QString styleName;
+
+ FaceStyle(QString faceFileName, QString styleName)
+ : faceFileName(std::move(faceFileName)),
+ styleName(std::move(styleName))
+ {}
+ };
+
FT_Library library;
QHash<QFontEngine::FaceId, QFreetypeFace *> faces;
+ QHash<FaceStyle, int> faceIndices;
};
QtFreetypeData::~QtFreetypeData()
{
- for (QHash<QFontEngine::FaceId, QFreetypeFace *>::ConstIterator iter = faces.cbegin(); iter != faces.cend(); ++iter)
+ for (auto iter = faces.cbegin(); iter != faces.cend(); ++iter) {
iter.value()->cleanup();
+ if (!iter.value()->ref.deref())
+ delete iter.value();
+ }
faces.clear();
FT_Done_FreeType(library);
library = nullptr;
}
+inline bool operator==(const QtFreetypeData::FaceStyle &style1, const QtFreetypeData::FaceStyle &style2)
+{
+ return style1.faceFileName == style2.faceFileName && style1.styleName == style2.styleName;
+}
+
+inline size_t qHash(const QtFreetypeData::FaceStyle &style, size_t seed)
+{
+ return qHashMulti(seed, style.faceFileName, style.styleName);
+}
+
Q_GLOBAL_STATIC(QThreadStorage<QtFreetypeData *>, theFreetypeData)
QtFreetypeData *qt_getFreetypeData()
@@ -194,10 +190,15 @@ int QFreetypeFace::getPointInOutline(glyph_t glyph, int flags, quint32 point, QF
return Err_Ok;
}
+bool QFreetypeFace::isScalable() const
+{
+ return FT_IS_SCALABLE(face);
+}
+
bool QFreetypeFace::isScalableBitmap() const
{
#ifdef FT_HAS_COLOR
- return !FT_IS_SCALABLE(face) && FT_HAS_COLOR(face);
+ return !isScalable() && FT_HAS_COLOR(face);
#else
return false;
#endif
@@ -220,18 +221,37 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
QtFreetypeData *freetypeData = qt_getFreetypeData();
- QFreetypeFace *freetype = freetypeData->faces.value(face_id, nullptr);
- if (freetype) {
- freetype->ref.ref();
- } else {
- QScopedPointer<QFreetypeFace> newFreetype(new QFreetypeFace);
+ QFreetypeFace *freetype = nullptr;
+ auto it = freetypeData->faces.find(face_id);
+ if (it != freetypeData->faces.end()) {
+ freetype = *it;
+
+ Q_ASSERT(freetype->ref.loadRelaxed() > 0);
+ if (freetype->ref.loadRelaxed() == 1) {
+ // If there is only one reference left to the face, it means it is only referenced by
+ // the cache itself, and thus it is in cleanup state (but the final outside reference
+ // was removed on a different thread so it could not be deleted right away). We then
+ // complete the cleanup and pretend we didn't find it, so that it can be re-created with
+ // the present state.
+ freetype->cleanup();
+ freetypeData->faces.erase(it);
+ delete freetype;
+ freetype = nullptr;
+ } else {
+ freetype->ref.ref();
+ }
+ }
+
+ if (!freetype) {
+ const auto deleter = [](QFreetypeFace *f) { delete f; };
+ std::unique_ptr<QFreetypeFace, decltype(deleter)> newFreetype(new QFreetypeFace, deleter);
FT_Face face;
if (!face_id.filename.isEmpty()) {
QString fileName = QFile::decodeName(face_id.filename);
- if (face_id.filename.startsWith(":qmemoryfonts/")) {
+ if (const char *prefix = ":qmemoryfonts/"; face_id.filename.startsWith(prefix)) {
// from qfontdatabase.cpp
QByteArray idx = face_id.filename;
- idx.remove(0, 14); // remove ':qmemoryfonts/'
+ idx.remove(0, strlen(prefix)); // remove ':qmemoryfonts/'
bool ok = false;
newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
if (!ok)
@@ -253,7 +273,23 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
} else if (FT_New_Face(freetypeData->library, face_id.filename, face_id.index, &face)) {
return nullptr;
}
+
+#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 20900
+ if (face_id.instanceIndex >= 0) {
+ qCDebug(lcFontMatch)
+ << "Selecting named instance" << (face_id.instanceIndex)
+ << "in" << face_id.filename;
+ FT_Set_Named_Instance(face, face_id.instanceIndex + 1);
+ }
+#endif
newFreetype->face = face;
+ newFreetype->mm_var = nullptr;
+ if (FT_IS_NAMED_INSTANCE(newFreetype->face)) {
+ FT_Error ftresult;
+ ftresult = FT_Get_MM_Var(face, &newFreetype->mm_var);
+ if (ftresult != FT_Err_Ok)
+ newFreetype->mm_var = nullptr;
+ }
newFreetype->ref.storeRelaxed(1);
newFreetype->xsize = 0;
@@ -292,14 +328,34 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
FT_Set_Char_Size(face, newFreetype->face->available_sizes[0].x_ppem, newFreetype->face->available_sizes[0].y_ppem, 0, 0);
FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map);
+
+ if (!face_id.variableAxes.isEmpty()) {
+ FT_MM_Var *var = nullptr;
+ FT_Get_MM_Var(newFreetype->face, &var);
+ if (var != nullptr) {
+ QVarLengthArray<FT_Fixed, 16> coords(var->num_axis);
+ FT_Get_Var_Design_Coordinates(face, var->num_axis, coords.data());
+ for (FT_UInt i = 0; i < var->num_axis; ++i) {
+ if (const auto tag = QFont::Tag::fromValue(var->axis[i].tag)) {
+ const auto it = face_id.variableAxes.constFind(*tag);
+ if (it != face_id.variableAxes.constEnd())
+ coords[i] = FT_Fixed(*it * 65536);
+ }
+ }
+ FT_Set_Var_Design_Coordinates(face, var->num_axis, coords.data());
+ FT_Done_MM_Var(qt_getFreetype(), var);
+ }
+ }
+
QT_TRY {
- freetypeData->faces.insert(face_id, newFreetype.data());
+ freetypeData->faces.insert(face_id, newFreetype.get());
} QT_CATCH(...) {
- newFreetype.take()->release(face_id);
+ newFreetype.release()->release(face_id);
// we could return null in principle instead of throwing
QT_RETHROW;
}
- freetype = newFreetype.take();
+ freetype = newFreetype.release();
+ freetype->ref.ref();
}
return freetype;
}
@@ -307,32 +363,93 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
void QFreetypeFace::cleanup()
{
hbFace.reset();
+ if (mm_var && face && face->glyph)
+ FT_Done_MM_Var(face->glyph->library, mm_var);
+ mm_var = nullptr;
FT_Done_Face(face);
face = nullptr;
}
void QFreetypeFace::release(const QFontEngine::FaceId &face_id)
{
- if (!ref.deref()) {
- if (face) {
- QtFreetypeData *freetypeData = qt_getFreetypeData();
+ Q_UNUSED(face_id);
+ bool deleteThis = !ref.deref();
+
+ // If the only reference left over is the cache's reference, we remove it from the cache,
+ // granted that we are on the correct thread. If not, we leave it there to be cleaned out
+ // later. While we are at it, we also purge all left over faces which are only referenced
+ // from the cache.
+ if (face && ref.loadRelaxed() == 1) {
+ QtFreetypeData *freetypeData = qt_getFreetypeData();
+ for (auto it = freetypeData->faces.constBegin(); it != freetypeData->faces.constEnd(); ) {
+ if (it.value()->ref.loadRelaxed() == 1) {
+ it.value()->cleanup();
+ if (it.value() == this)
+ deleteThis = true; // This face, delete at end of function for safety
+ else
+ delete it.value();
+ it = freetypeData->faces.erase(it);
+ } else {
+ ++it;
+ }
+ }
- cleanup();
+ if (freetypeData->faces.isEmpty()) {
+ FT_Done_FreeType(freetypeData->library);
+ freetypeData->library = nullptr;
+ }
+ }
- auto it = freetypeData->faces.constFind(face_id);
- if (it != freetypeData->faces.constEnd())
- freetypeData->faces.erase(it);
+ if (deleteThis)
+ delete this;
+}
- if (freetypeData->faces.isEmpty()) {
- FT_Done_FreeType(freetypeData->library);
- freetypeData->library = nullptr;
- }
+static int computeFaceIndex(const QString &faceFileName, const QString &styleName)
+{
+ FT_Library library = qt_getFreetype();
+
+ int faceIndex = 0;
+ int numFaces = 0;
+
+ do {
+ FT_Face face;
+
+ FT_Error error = FT_New_Face(library, faceFileName.toUtf8().constData(), faceIndex, &face);
+ if (error != FT_Err_Ok) {
+ qDebug() << "FT_New_Face failed for face index" << faceIndex << ':' << Qt::hex << error;
+ break;
}
- delete this;
- }
+ const bool found = QLatin1StringView(face->style_name) == styleName;
+ numFaces = face->num_faces;
+
+ FT_Done_Face(face);
+
+ if (found)
+ return faceIndex;
+ } while (++faceIndex < numFaces);
+
+ // Fall back to the first font face in the file
+ return 0;
}
+int QFreetypeFace::getFaceIndexByStyleName(const QString &faceFileName, const QString &styleName)
+{
+ QtFreetypeData *freetypeData = qt_getFreetypeData();
+
+ // Try to get from cache
+ QtFreetypeData::FaceStyle faceStyle(faceFileName, styleName);
+ int faceIndex = freetypeData->faceIndices.value(faceStyle, -1);
+
+ if (faceIndex >= 0)
+ return faceIndex;
+
+ faceIndex = computeFaceIndex(faceFileName, styleName);
+
+ freetypeData->faceIndices.insert(faceStyle, faceIndex);
+
+ return faceIndex;
+}
void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing, QFixed *scalableBitmapScaleFactor)
{
@@ -594,7 +711,7 @@ static QFontEngine::SubpixelAntialiasingType subpixelAntialiasingTypeHint()
QFontEngineFT *QFontEngineFT::create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData)
{
- QScopedPointer<QFontEngineFT> engine(new QFontEngineFT(fontDef));
+ auto engine = std::make_unique<QFontEngineFT>(fontDef);
QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_Mono;
const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
@@ -616,7 +733,7 @@ QFontEngineFT *QFontEngineFT::create(const QFontDef &fontDef, FaceId faceId, con
}
engine->setQtDefaultHintStyle(static_cast<QFont::HintingPreference>(fontDef.hintingPreference));
- return engine.take();
+ return engine.release();
}
namespace {
@@ -638,27 +755,32 @@ namespace {
fontDef.weight = QFont::Bold;
}
- bool initFromData(const QByteArray &fontData)
+ bool initFromData(const QByteArray &fontData, const QMap<QFont::Tag, float> &variableAxisValues)
{
FaceId faceId;
faceId.filename = "";
faceId.index = 0;
faceId.uuid = QUuid::createUuid().toByteArray();
+ faceId.variableAxes = variableAxisValues;
return init(faceId, true, Format_None, fontData);
}
};
}
-QFontEngineFT *QFontEngineFT::create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
+QFontEngineFT *QFontEngineFT::create(const QByteArray &fontData,
+ qreal pixelSize,
+ QFont::HintingPreference hintingPreference,
+ const QMap<QFont::Tag, float> &variableAxisValues)
{
QFontDef fontDef;
fontDef.pixelSize = pixelSize;
fontDef.stretch = QFont::Unstretched;
fontDef.hintingPreference = hintingPreference;
+ fontDef.variableAxisValues = variableAxisValues;
QFontEngineFTRawData *fe = new QFontEngineFTRawData(fontDef);
- if (!fe->initFromData(fontData)) {
+ if (!fe->initFromData(fontData, variableAxisValues)) {
delete fe;
return nullptr;
}
@@ -711,6 +833,37 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
static void dont_delete(void*) {}
+static FT_UShort calculateActualWeight(QFreetypeFace *freetypeFace, FT_Face face, QFontEngine::FaceId faceId)
+{
+ FT_MM_Var *var = freetypeFace->mm_var;
+ if (var != nullptr && faceId.instanceIndex >= 0 && FT_UInt(faceId.instanceIndex) < var->num_namedstyles) {
+ for (FT_UInt axis = 0; axis < var->num_axis; ++axis) {
+ if (var->axis[axis].tag == QFont::Tag("wght").value()) {
+ return var->namedstyle[faceId.instanceIndex].coords[axis] >> 16;
+ }
+ }
+ }
+ if (const TT_OS2 *os2 = reinterpret_cast<const TT_OS2 *>(FT_Get_Sfnt_Table(face, ft_sfnt_os2))) {
+ return os2->usWeightClass;
+ }
+
+ return 700;
+}
+
+static bool calculateActualItalic(QFreetypeFace *freetypeFace, FT_Face face, QFontEngine::FaceId faceId)
+{
+ FT_MM_Var *var = freetypeFace->mm_var;
+ if (var != nullptr && faceId.instanceIndex >= 0 && FT_UInt(faceId.instanceIndex) < var->num_namedstyles) {
+ for (FT_UInt axis = 0; axis < var->num_axis; ++axis) {
+ if (var->axis[axis].tag == QFont::Tag("ital").value()) {
+ return (var->namedstyle[faceId.instanceIndex].coords[axis] >> 16) == 1;
+ }
+ }
+ }
+
+ return (face->style_flags & FT_STYLE_FLAG_ITALIC);
+}
+
bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
QFreetypeFace *freetypeFace)
{
@@ -734,7 +887,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
PS_FontInfoRec psrec;
// don't assume that type1 fonts are symbol fonts by default
if (FT_Get_PS_Font_Info(freetype->face, &psrec) == FT_Err_Ok) {
- symbol = !fontDef.families.isEmpty() && bool(fontDef.families.first().contains(QLatin1String("symbol"), Qt::CaseInsensitive));
+ symbol = !fontDef.families.isEmpty() && bool(fontDef.families.constFirst().contains("symbol"_L1, Qt::CaseInsensitive));
}
freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing, &scalableBitmapScaleFactor);
@@ -742,34 +895,36 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
FT_Face face = lockFace();
if (FT_IS_SCALABLE(face)) {
- bool fake_oblique = (fontDef.style != QFont::StyleNormal) && !(face->style_flags & FT_STYLE_FLAG_ITALIC) && !qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_ITALIC");
+ bool isItalic = calculateActualItalic(freetype, face, faceId);
+ bool fake_oblique = (fontDef.style != QFont::StyleNormal) && !isItalic && !qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_ITALIC");
if (fake_oblique)
obliquen = true;
FT_Set_Transform(face, &matrix, nullptr);
freetype->matrix = matrix;
// fake bold
if ((fontDef.weight >= QFont::Bold) && !(face->style_flags & FT_STYLE_FLAG_BOLD) && !FT_IS_FIXED_WIDTH(face) && !qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_BOLD")) {
- if (const TT_OS2 *os2 = reinterpret_cast<const TT_OS2 *>(FT_Get_Sfnt_Table(face, ft_sfnt_os2))) {
- if (os2->usWeightClass < 700 && fontDef.pixelSize < 64)
- embolden = true;
+ FT_UShort actualWeight = calculateActualWeight(freetype, face, faceId);
+ if (actualWeight < 700 &&
+ (fontDef.pixelSize < 64 || qEnvironmentVariableIsSet("QT_NO_SYNTHESIZED_BOLD_LIMIT"))) {
+ embolden = true;
}
}
// underline metrics
line_thickness = QFixed::fromFixed(FT_MulFix(face->underline_thickness, face->size->metrics.y_scale));
- underline_position = QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale));
+ QFixed center_position = QFixed::fromFixed(-FT_MulFix(face->underline_position, face->size->metrics.y_scale));
+ underline_position = center_position - line_thickness / 2;
} else {
// ad hoc algorithm
int score = fontDef.weight * fontDef.pixelSize;
- line_thickness = score / 700;
+ line_thickness = score / 7000;
// looks better with thicker line for small pointsizes
if (line_thickness < 2 && score >= 1050)
line_thickness = 2;
underline_position = ((line_thickness * 2) + 3) / 6;
- if (isScalableBitmap()) {
+ cacheEnabled = false;
+ if (isScalableBitmap())
glyphFormat = defaultFormat = GlyphFormat::Format_ARGB;
- cacheEnabled = false;
- }
}
if (line_thickness < 1)
line_thickness = 1;
@@ -780,7 +935,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
TrueType fonts with embedded bitmaps may have a bitmap font specific
ascent/descent in the EBLC table. There is no direct public API
to extract those values. The only way we've found is to trick freetype
- into thinking that it's not a scalable font in FT_SelectSize so that
+ into thinking that it's not a scalable font in FT_Select_Size so that
the metrics are retrieved from the bitmap strikes.
*/
if (FT_IS_SCALABLE(face)) {
@@ -794,7 +949,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
metrics.ascender = face->size->metrics.ascender;
metrics.descender = face->size->metrics.descender;
if (metrics.descender > 0
- && QString::fromUtf8(face->family_name) == QLatin1String("Courier New")) {
+ && QString::fromUtf8(face->family_name) == "Courier New"_L1) {
metrics.descender *= -1;
}
metrics.height = metrics.ascender - metrics.descender + leading;
@@ -1072,7 +1227,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
}
int glyph_buffer_size = 0;
- QScopedArrayPointer<uchar> glyph_buffer;
+ std::unique_ptr<uchar[]> glyph_buffer;
FT_Render_Mode renderMode = (default_hint_style == HintLight) ? FT_RENDER_MODE_LIGHT : FT_RENDER_MODE_NORMAL;
switch (format) {
case Format_Mono:
@@ -1117,7 +1272,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
uchar *src = slot->bitmap.buffer;
- uchar *dst = glyph_buffer.data();
+ uchar *dst = glyph_buffer.get();
int h = slot->bitmap.rows;
// Some fonts return bitmaps even when we requested something else:
if (format == Format_Mono) {
@@ -1146,7 +1301,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
} else if (slot->bitmap.pixel_mode == 7 /*FT_PIXEL_MODE_BGRA*/) {
Q_ASSERT(format == Format_ARGB);
uchar *src = slot->bitmap.buffer;
- uchar *dst = glyph_buffer.data();
+ uchar *dst = glyph_buffer.get();
int h = slot->bitmap.rows;
while (h--) {
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
@@ -1166,7 +1321,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
} else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
Q_ASSERT(format == Format_A8);
uchar *src = slot->bitmap.buffer;
- uchar *dst = glyph_buffer.data();
+ uchar *dst = glyph_buffer.get();
int h = slot->bitmap.rows;
int bytes = info.width;
while (h--) {
@@ -1176,10 +1331,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
}
} else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) {
Q_ASSERT(format == Format_A32);
- convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB);
+ convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer.get(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB);
} else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) {
Q_ASSERT(format == Format_A32);
- convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB);
+ convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer.get(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB);
} else {
qWarning("QFontEngine: Glyph rendered in unknown pixel_mode=%d", slot->bitmap.pixel_mode);
return nullptr;
@@ -1198,7 +1353,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
g->advance = info.xOff;
g->format = format;
delete [] g->data;
- g->data = glyph_buffer.take();
+ g->data = glyph_buffer.release();
if (set)
set->setGlyph(glyph, subPixelPosition, g);
@@ -1215,7 +1370,7 @@ QFontEngine::Properties QFontEngineFT::properties() const
{
Properties p = freetype->properties();
if (p.postscriptName.isEmpty()) {
- p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(fontDef.families.first().toUtf8());
+ p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(fontDef.families.constFirst().toUtf8());
}
return freetype->properties();
@@ -1442,7 +1597,7 @@ void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_me
bool QFontEngineFT::supportsTransformation(const QTransform &transform) const
{
- return transform.type() <= QTransform::TxRotate;
+ return transform.type() <= QTransform::TxRotate && (freetype->isScalable() || freetype->isScalableBitmap());
}
void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
@@ -1705,9 +1860,8 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
QFixed y = overall.yoff + glyphs.offsets[i].y - g->y;
overall.x = qMin(overall.x, x);
overall.y = qMin(overall.y, y);
- xmax = qMax(xmax, x + g->width);
- ymax = qMax(ymax, y + g->height);
- overall.xoff += g->advance;
+ xmax = qMax(xmax, x.ceil() + g->width);
+ ymax = qMax(ymax, y.ceil() + g->height);
if (!cacheEnabled && g != &emptyGlyph)
delete g;
} else {
@@ -1722,8 +1876,8 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
overall.y = qMin(overall.y, y);
xmax = qMax(xmax, x + TRUNC(right - left));
ymax = qMax(ymax, y + TRUNC(top - bottom));
- overall.xoff += int(TRUNC(ROUND(face->glyph->advance.x)));
}
+ overall.xoff += glyphs.effectiveAdvance(i);
}
overall.height = qMax(overall.height, ymax - overall.y);
overall.width = xmax - overall.x;
@@ -1787,7 +1941,15 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph,
const QTransform &matrix,
QFontEngine::GlyphFormat format)
{
- Glyph *g = loadGlyphFor(glyph, subPixelPosition, format, matrix, true);
+ // When rendering glyphs into a cache via the alphaMap* functions, we disable
+ // outline drawing. To ensure the bounding box matches the rendered glyph, we
+ // need to do the same here.
+
+ const bool needsImageTransform = !FT_IS_SCALABLE(freetype->face)
+ && matrix.type() > QTransform::TxTranslate;
+ if (needsImageTransform && format == QFontEngine::Format_Mono)
+ format = QFontEngine::Format_A8;
+ Glyph *g = loadGlyphFor(glyph, subPixelPosition, format, matrix, true, true);
glyph_metrics_t overall;
if (g) {
@@ -1813,7 +1975,7 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph,
unlockFace();
}
- if (isScalableBitmap())
+ if (isScalableBitmap() || needsImageTransform)
overall = scaledBitmapMetrics(overall, matrix);
return overall;
}
@@ -1913,12 +2075,17 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g,
const QFixedPoint &subPixelPosition,
const QTransform &t)
{
- const GlyphFormat neededFormat = antialias ? Format_A8 : Format_Mono;
+ const bool needsImageTransform = !FT_IS_SCALABLE(freetype->face)
+ && t.type() > QTransform::TxTranslate;
+ const GlyphFormat neededFormat = antialias || needsImageTransform ? Format_A8 : Format_Mono;
Glyph *glyph = loadGlyphFor(g, subPixelPosition, neededFormat, t, false, true);
QImage img = alphaMapFromGlyphData(glyph, neededFormat);
- img = img.copy();
+ if (needsImageTransform)
+ img = img.transformed(t, Qt::SmoothTransformation);
+ else
+ img = img.copy();
if (!cacheEnabled && glyph != &emptyGlyph)
delete glyph;
diff --git a/src/gui/text/freetype/qfontengine_ft_p.h b/src/gui/text/freetype/qfontengine_ft_p.h
index 03059c7d13..c8e5e20d37 100644
--- a/src/gui/text/freetype/qfontengine_ft_p.h
+++ b/src/gui/text/freetype/qfontengine_ft_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTENGINE_FT_P_H
#define QFONTENGINE_FT_P_H
//
@@ -55,6 +19,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
+#include FT_MULTIPLE_MASTERS_H
#ifndef Q_OS_WIN
@@ -85,6 +50,8 @@ public:
const QByteArray &fontData = QByteArray());
void release(const QFontEngine::FaceId &face_id);
+ static int getFaceIndexByStyleName(const QString &faceFileName, const QString &styleName);
+
// locks the struct for usage. Any read/write operations require locking.
void lock()
{
@@ -96,6 +63,7 @@ public:
}
FT_Face face;
+ FT_MM_Var *mm_var;
int xsize; // 26.6
int ysize; // 26.6
FT_Matrix matrix;
@@ -109,6 +77,7 @@ public:
int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints);
+ bool isScalable() const;
bool isScalableBitmap() const;
static void addGlyphToPath(FT_Face face, FT_GlyphSlot g, const QFixedPoint &point, QPainterPath *path, FT_Fixed x_scale, FT_Fixed y_scale);
@@ -117,7 +86,6 @@ public:
private:
friend class QFontEngineFT;
friend class QtFreetypeData;
- friend struct QScopedPointerDeleter<QFreetypeFace>;
QFreetypeFace() = default;
~QFreetypeFace() {}
void cleanup();
@@ -301,7 +269,7 @@ private:
HintStyle defaultHintStyle() const { return default_hint_style; }
static QFontEngineFT *create(const QFontDef &fontDef, FaceId faceId, const QByteArray &fontData = QByteArray());
- static QFontEngineFT *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
+ static QFontEngineFT *create(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference, const QMap<QFont::Tag, float> &variableAxisValue);
protected:
@@ -360,8 +328,6 @@ private:
QFixed scalableBitmapScaleFactor;
};
-Q_DECLARE_TYPEINFO(QFontEngineFT::QGlyphSet, Q_RELOCATABLE_TYPE);
-
inline size_t qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g, size_t seed = 0)
{
diff --git a/src/gui/text/freetype/qfreetypefontdatabase.cpp b/src/gui/text/freetype/qfreetypefontdatabase.cpp
index ac7520c495..018e590ac2 100644
--- a/src/gui/text/freetype/qfreetypefontdatabase.cpp
+++ b/src/gui/text/freetype/qfreetypefontdatabase.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfreetypefontdatabase_p.h"
@@ -46,6 +10,8 @@
#include <QtCore/QLibraryInfo>
#include <QtCore/QDir>
#include <QtCore/QtEndian>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QUuid>
#undef QT_NO_FREETYPE
#include "qfontengine_ft_p.h"
@@ -54,8 +20,16 @@
#include FT_TRUETYPE_TABLES_H
#include FT_ERRORS_H
+#include FT_MULTIPLE_MASTERS_H
+#include FT_SFNT_NAMES_H
+#include FT_TRUETYPE_IDS_H
+
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcFontDb)
+
+using namespace Qt::StringLiterals;
+
void QFreeTypeFontDatabase::populateFontDatabase()
{
QString fontpath = fontDir();
@@ -68,14 +42,14 @@ void QFreeTypeFontDatabase::populateFontDatabase()
return;
}
- QStringList nameFilters;
- nameFilters << QLatin1String("*.ttf")
- << QLatin1String("*.ttc")
- << QLatin1String("*.pfa")
- << QLatin1String("*.pfb")
- << QLatin1String("*.otf");
+ static const QString nameFilters[] = {
+ u"*.ttf"_s,
+ u"*.pfa"_s,
+ u"*.pfb"_s,
+ u"*.otf"_s,
+ };
- const auto fis = dir.entryInfoList(nameFilters, QDir::Files);
+ const auto fis = dir.entryInfoList(QStringList::fromReadOnlyData(nameFilters), QDir::Files);
for (const QFileInfo &fi : fis) {
const QByteArray file = QFile::encodeName(fi.absoluteFilePath());
QFreeTypeFontDatabase::addTTFile(QByteArray(), file);
@@ -88,14 +62,24 @@ QFontEngine *QFreeTypeFontDatabase::fontEngine(const QFontDef &fontDef, void *us
QFontEngine::FaceId faceId;
faceId.filename = QFile::encodeName(fontfile->fileName);
faceId.index = fontfile->indexValue;
+ faceId.instanceIndex = fontfile->instanceIndex;
+ faceId.variableAxes = fontDef.variableAxisValues;
+
+ // Make sure the FaceId compares uniquely in cases where a
+ // file name is not provided.
+ if (faceId.filename.isEmpty()) {
+ QUuid::Id128Bytes id{};
+ memcpy(&id, &usrPtr, sizeof(usrPtr));
+ faceId.uuid = QUuid(id).toByteArray();
+ }
- return QFontEngineFT::create(fontDef, faceId);
+ return QFontEngineFT::create(fontDef, faceId, fontfile->data);
}
QFontEngine *QFreeTypeFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize,
QFont::HintingPreference hintingPreference)
{
- return QFontEngineFT::create(fontData, pixelSize, hintingPreference);
+ return QFontEngineFT::create(fontData, pixelSize, hintingPreference, {});
}
QStringList QFreeTypeFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont)
@@ -111,6 +95,114 @@ void QFreeTypeFontDatabase::releaseHandle(void *handle)
extern FT_Library qt_getFreetype();
+void QFreeTypeFontDatabase::addNamedInstancesForFace(void *face_,
+ int faceIndex,
+ const QString &family,
+ const QString &styleName,
+ QFont::Weight weight,
+ QFont::Stretch stretch,
+ QFont::Style style,
+ bool fixedPitch,
+ const QSupportedWritingSystems &writingSystems,
+ const QByteArray &fileName,
+ const QByteArray &fontData)
+{
+ FT_Face face = reinterpret_cast<FT_Face>(face_);
+
+ // Note: The following does not actually depend on API from 2.9, but the
+ // FT_Set_Named_Instance() was added in 2.9, so to avoid populating the database with
+ // named instances that cannot be selected, we disable the feature on older Freetype
+ // versions.
+#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 20900
+ FT_MM_Var *var = nullptr;
+ FT_Get_MM_Var(face, &var);
+ if (var != nullptr) {
+ std::unique_ptr<FT_MM_Var, void(*)(FT_MM_Var*)> varGuard(var, [](FT_MM_Var *res) {
+ FT_Done_MM_Var(qt_getFreetype(), res);
+ });
+
+ for (FT_UInt i = 0; i < var->num_namedstyles; ++i) {
+ FT_UInt id = var->namedstyle[i].strid;
+
+ QFont::Weight instanceWeight = weight;
+ QFont::Stretch instanceStretch = stretch;
+ QFont::Style instanceStyle = style;
+ for (FT_UInt axis = 0; axis < var->num_axis; ++axis) {
+ if (var->axis[axis].tag == QFont::Tag("wght").value()) {
+ instanceWeight = QFont::Weight(var->namedstyle[i].coords[axis] >> 16);
+ } else if (var->axis[axis].tag == QFont::Tag("wdth").value()) {
+ instanceStretch = QFont::Stretch(var->namedstyle[i].coords[axis] >> 16);
+ } else if (var->axis[axis].tag == QFont::Tag("ital").value()) {
+ FT_UInt ital = var->namedstyle[i].coords[axis] >> 16;
+ if (ital == 1)
+ instanceStyle = QFont::StyleItalic;
+ else
+ instanceStyle = QFont::StyleNormal;
+ }
+ }
+
+ FT_UInt count = FT_Get_Sfnt_Name_Count(face);
+ for (FT_UInt j = 0; j < count; ++j) {
+ FT_SfntName name;
+ if (FT_Get_Sfnt_Name(face, j, &name))
+ continue;
+
+ if (name.name_id != id)
+ continue;
+
+ // Only support Unicode for now
+ if (name.encoding_id != TT_MS_ID_UNICODE_CS)
+ continue;
+
+ // Sfnt names stored as UTF-16BE
+ QString instanceName;
+ for (FT_UInt k = 0; k < name.string_len; k += 2)
+ instanceName += QChar((name.string[k] << 8) + name.string[k + 1]);
+ if (instanceName != styleName) {
+ FontFile *variantFontFile = new FontFile{
+ QFile::decodeName(fileName),
+ faceIndex,
+ int(i),
+ fontData
+ };
+
+ qCDebug(lcFontDb) << "Registering named instance" << i
+ << ":" << instanceName
+ << "for font family" << family
+ << "with weight" << instanceWeight
+ << ", style" << instanceStyle
+ << ", stretch" << instanceStretch;
+
+ registerFont(family,
+ instanceName,
+ QString(),
+ instanceWeight,
+ instanceStyle,
+ instanceStretch,
+ true,
+ true,
+ 0,
+ fixedPitch,
+ writingSystems,
+ variantFontFile);
+ }
+ }
+ }
+ }
+#else
+ Q_UNUSED(face);
+ Q_UNUSED(family);
+ Q_UNUSED(styleName);
+ Q_UNUSED(weight);
+ Q_UNUSED(stretch);
+ Q_UNUSED(style);
+ Q_UNUSED(fixedPitch);
+ Q_UNUSED(writingSystems);
+ Q_UNUSED(fontData);
+#endif
+
+}
+
QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file, QFontDatabasePrivate::ApplicationFont *applicationFont)
{
FT_Library library = qt_getFreetype();
@@ -153,6 +245,7 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
}
}
+ QFont::Stretch stretch = QFont::Unstretched;
TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
if (os2) {
quint32 unicodeRange[4] = {
@@ -191,14 +284,46 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
else if (w <= 10)
weight = QFont::Black;
}
+
+ switch (os2->usWidthClass) {
+ case 1:
+ stretch = QFont::UltraCondensed;
+ break;
+ case 2:
+ stretch = QFont::ExtraCondensed;
+ break;
+ case 3:
+ stretch = QFont::Condensed;
+ break;
+ case 4:
+ stretch = QFont::SemiCondensed;
+ break;
+ case 5:
+ stretch = QFont::Unstretched;
+ break;
+ case 6:
+ stretch = QFont::SemiExpanded;
+ break;
+ case 7:
+ stretch = QFont::Expanded;
+ break;
+ case 8:
+ stretch = QFont::ExtraExpanded;
+ break;
+ case 9:
+ stretch = QFont::UltraExpanded;
+ break;
+ }
}
QString family = QString::fromLatin1(face->family_name);
- FontFile *fontFile = new FontFile;
- fontFile->fileName = QFile::decodeName(file);
- fontFile->indexValue = index;
+ FontFile *fontFile = new FontFile{
+ QFile::decodeName(file),
+ index,
+ -1,
+ fontData
+ };
- QFont::Stretch stretch = QFont::Unstretched;
QString styleName = QString::fromLatin1(face->style_name);
if (applicationFont != nullptr) {
@@ -213,6 +338,9 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
}
registerFont(family, styleName, QString(), weight, style, stretch, true, true, 0, fixedPitch, writingSystems, fontFile);
+
+ addNamedInstancesForFace(face, index, family, styleName, weight, stretch, style, fixedPitch, writingSystems, file, fontData);
+
families.append(family);
FT_Done_Face(face);
@@ -221,4 +349,13 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
return families;
}
+bool QFreeTypeFontDatabase::supportsVariableApplicationFonts() const
+{
+#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 20900
+ return true;
+#else
+ return false;
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/text/freetype/qfreetypefontdatabase_p.h b/src/gui/text/freetype/qfreetypefontdatabase_p.h
index 2cc725bd06..5fcec585d2 100644
--- a/src/gui/text/freetype/qfreetypefontdatabase_p.h
+++ b/src/gui/text/freetype/qfreetypefontdatabase_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFREETYPEFONTDATABASE_H
#define QFREETYPEFONTDATABASE_H
@@ -54,6 +18,7 @@
#include <qpa/qplatformfontdatabase.h>
#include <QtCore/QByteArray>
#include <QtCore/QString>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -61,6 +26,12 @@ struct FontFile
{
QString fileName;
int indexValue;
+ int instanceIndex = -1;
+
+ // Note: The data may be implicitly shared throughout the
+ // font database and platform font database, so be careful
+ // to never detach when accessing this member!
+ const QByteArray data;
};
class Q_GUI_EXPORT QFreeTypeFontDatabase : public QPlatformFontDatabase
@@ -71,6 +42,14 @@ public:
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr) override;
void releaseHandle(void *handle) override;
+ bool supportsVariableApplicationFonts() const override;
+
+ static void addNamedInstancesForFace(void *face, int faceIndex,
+ const QString &family, const QString &styleName,
+ QFont::Weight weight, QFont::Stretch stretch,
+ QFont::Style style, bool fixedPitch,
+ const QSupportedWritingSystems &writingSystems,
+ const QByteArray &fileName, const QByteArray &fontData);
static QStringList addTTFile(const QByteArray &fontData, const QByteArray &file, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr);
};
diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp
index 90726100e2..3e5144b157 100644
--- a/src/gui/text/qabstracttextdocumentlayout.cpp
+++ b/src/gui/text/qabstracttextdocumentlayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qabstracttextdocumentlayout.h>
#include <qtextformat.h>
@@ -137,7 +101,7 @@ QTextObjectInterface::~QTextObjectInterface()
\warning Copy and Paste operations ignore custom text objects.
- \sa {Text Object Example}, QTextCharFormat, QTextLayout
+ \sa QTextCharFormat, QTextLayout
*/
/*!
@@ -435,7 +399,8 @@ void QAbstractTextDocumentLayout::registerHandler(int objectType, QObject *compo
if (!iface)
return; // ### print error message on terminal?
- connect(component, SIGNAL(destroyed(QObject*)), this, SLOT(_q_handlerDestroyed(QObject*)));
+ QObjectPrivate::connect(component, &QObject::destroyed, d,
+ &QAbstractTextDocumentLayoutPrivate::_q_handlerDestroyed);
QTextObjectHandler h;
h.iface = iface;
@@ -456,7 +421,8 @@ void QAbstractTextDocumentLayout::unregisterHandler(int objectType, QObject *com
const auto it = d->handlers.constFind(objectType);
if (it != d->handlers.cend() && (!component || component == it->component)) {
if (component)
- disconnect(component, SIGNAL(destroyed(QObject*)), this, SLOT(_q_handlerDestroyed(QObject*)));
+ QObjectPrivate::disconnect(component, &QObject::destroyed, d,
+ &QAbstractTextDocumentLayoutPrivate::_q_handlerDestroyed);
d->handlers.erase(it);
}
}
@@ -636,7 +602,7 @@ QTextFormat QAbstractTextDocumentLayout::formatAt(const QPointF &pos) const
if (blockBr.contains(pos)) {
QTextLayout *layout = block.layout();
int relativeCursorPos = cursorPos - block.position();
- const int preeditLength = layout ? layout->preeditAreaText().length() : 0;
+ const int preeditLength = layout ? layout->preeditAreaText().size() : 0;
if (preeditLength > 0 && relativeCursorPos > layout->preeditAreaPosition())
cursorPos -= qMin(cursorPos - layout->preeditAreaPosition(), preeditLength);
break;
diff --git a/src/gui/text/qabstracttextdocumentlayout.h b/src/gui/text/qabstracttextdocumentlayout.h
index 4dd3e16160..dfafb1098f 100644
--- a/src/gui/text/qabstracttextdocumentlayout.h
+++ b/src/gui/text/qabstracttextdocumentlayout.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTTEXTDOCUMENTLAYOUT_H
#define QABSTRACTTEXTDOCUMENTLAYOUT_H
@@ -129,7 +93,6 @@ private:
friend class QTextEngine;
friend class QTextLayout;
friend class QTextLine;
- Q_PRIVATE_SLOT(d_func(), void _q_handlerDestroyed(QObject *obj))
Q_PRIVATE_SLOT(d_func(), int _q_dynamicPageCountSlot())
Q_PRIVATE_SLOT(d_func(), QSizeF _q_dynamicDocumentSizeSlot())
};
@@ -144,7 +107,7 @@ public:
virtual void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format) = 0;
};
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
Q_DECLARE_INTERFACE(QTextObjectInterface, "org.qt-project.Qt.QTextObjectInterface")
#endif
diff --git a/src/gui/text/qabstracttextdocumentlayout_p.h b/src/gui/text/qabstracttextdocumentlayout_p.h
index 88035eb66d..6bd42d78d8 100644
--- a/src/gui/text/qabstracttextdocumentlayout_p.h
+++ b/src/gui/text/qabstracttextdocumentlayout_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTTEXTDOCUMENTLAYOUT_P_H
#define QABSTRACTTEXTDOCUMENTLAYOUT_P_H
@@ -54,7 +18,10 @@
#include <QtGui/private/qtguiglobal_p.h>
#include "private/qobject_p.h"
#include "qtextdocument_p.h"
+#include "qabstracttextdocumentlayout.h"
+
#include "QtCore/qhash.h"
+#include <QtCore/qpointer.h>
QT_BEGIN_NAMESPACE
@@ -82,6 +49,16 @@ public:
docPrivate = QTextDocumentPrivate::get(doc);
}
+ static QAbstractTextDocumentLayoutPrivate *get(QAbstractTextDocumentLayout *layout)
+ {
+ return layout->d_func();
+ }
+
+ bool hasHandlers() const
+ {
+ return !handlers.isEmpty();
+ }
+
inline int _q_dynamicPageCountSlot() const
{ return q_func()->pageCount(); }
inline QSizeF _q_dynamicDocumentSizeSlot() const
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 574436d6f6..e5815ffce2 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -1,44 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcssparser_p.h"
+#include <QtCore/qmap.h>
#include <qdebug.h>
#include <qicon.h>
#include <qcolor.h>
@@ -54,6 +19,12 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+QT_IMPL_METATYPE_EXTERN_TAGGED(QCss::BackgroundData, QCss__BackgroundData)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QCss::LengthData, QCss__LengthData)
+QT_IMPL_METATYPE_EXTERN_TAGGED(QCss::BorderData, QCss__BorderData)
+
#include "qcssscanner.cpp"
using namespace QCss;
@@ -68,14 +39,18 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "-qt-background-role", QtBackgroundRole },
{ "-qt-block-indent", QtBlockIndent },
{ "-qt-fg-texture-cachekey", QtForegroundTextureCacheKey },
+ { "-qt-foreground", QtForeground },
{ "-qt-line-height-type", QtLineHeightType },
{ "-qt-list-indent", QtListIndent },
{ "-qt-list-number-prefix", QtListNumberPrefix },
{ "-qt-list-number-suffix", QtListNumberSuffix },
{ "-qt-paragraph-type", QtParagraphType },
+ { "-qt-stroke-color", QtStrokeColor },
+ { "-qt-stroke-width", QtStrokeWidth },
{ "-qt-style-features", QtStyleFeatures },
{ "-qt-table-type", QtTableType },
{ "-qt-user-state", QtUserState },
+ { "accent-color", QtAccent },
{ "alternate-background-color", QtAlternateBackground },
{ "background", Background },
{ "background-attachment", BackgroundAttachment },
@@ -157,6 +132,7 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "padding-top", PaddingTop },
{ "page-break-after", PageBreakAfter },
{ "page-break-before", PageBreakBefore },
+ { "placeholder-text-color", QtPlaceHolderTextColor },
{ "position", Position },
{ "right", Right },
{ "selection-background-color", QtSelectionBackground },
@@ -262,7 +238,7 @@ static const short indexOfId[NumKnownValues] = { 0, 41, 48, 42, 49, 50, 55, 35,
QString Value::toString() const
{
if (type == KnownIdentifier) {
- return QLatin1String(values[indexOfId[variant.toInt()]].name);
+ return QLatin1StringView(values[indexOfId[variant.toInt()]].name);
} else {
return variant.toString();
}
@@ -355,12 +331,12 @@ static const QCssKnownValue styleFeatures[NumKnownStyleFeatures - 1] = {
static bool operator<(const QString &name, const QCssKnownValue &prop)
{
- return QString::compare(name, QLatin1String(prop.name), Qt::CaseInsensitive) < 0;
+ return QString::compare(name, QLatin1StringView(prop.name), Qt::CaseInsensitive) < 0;
}
static bool operator<(const QCssKnownValue &prop, const QString &name)
{
- return QString::compare(QLatin1String(prop.name), name, Qt::CaseInsensitive) < 0;
+ return QString::compare(QLatin1StringView(prop.name), name, Qt::CaseInsensitive) < 0;
}
static quint64 findKnownValue(const QString &name, const QCssKnownValue *start, int numValues)
@@ -437,7 +413,7 @@ int ValueExtractor::lengthValue(const Declaration &decl)
{
if (decl.d->parsed.isValid())
return lengthValueFromData(qvariant_cast<LengthData>(decl.d->parsed), f);
- if (decl.d->values.count() < 1)
+ if (decl.d->values.size() < 1)
return 0;
LengthData data = lengthValue(decl.d->values.at(0));
decl.d->parsed = QVariant::fromValue<LengthData>(data);
@@ -456,7 +432,7 @@ void ValueExtractor::lengthValues(const Declaration &decl, int *m)
LengthData datas[4];
int i;
- for (i = 0; i < qMin(decl.d->values.count(), 4); i++)
+ for (i = 0; i < qMin(decl.d->values.size(), 4); i++)
datas[i] = lengthValue(decl.d->values[i]);
if (i == 0) {
@@ -484,7 +460,7 @@ bool ValueExtractor::extractGeometry(int *w, int *h, int *minw, int *minh, int *
{
extractFont();
bool hit = false;
- for (int i = 0; i < declarations.count(); i++) {
+ for (int i = 0; i < declarations.size(); i++) {
const Declaration &decl = declarations.at(i);
switch (decl.d->propertyId) {
case Width: *w = lengthValue(decl); break;
@@ -506,7 +482,7 @@ bool ValueExtractor::extractPosition(int *left, int *top, int *right, int *botto
{
extractFont();
bool hit = false;
- for (int i = 0; i < declarations.count(); i++) {
+ for (int i = 0; i < declarations.size(); i++) {
const Declaration &decl = declarations.at(i);
switch (decl.d->propertyId) {
case Left: *left = lengthValue(decl); break;
@@ -529,7 +505,7 @@ bool ValueExtractor::extractBox(int *margins, int *paddings, int *spacing)
{
extractFont();
bool hit = false;
- for (int i = 0; i < declarations.count(); i++) {
+ for (int i = 0; i < declarations.size(); i++) {
const Declaration &decl = declarations.at(i);
switch (decl.d->propertyId) {
case PaddingLeft: paddings[LeftEdge] = lengthValue(decl); break;
@@ -556,7 +532,7 @@ bool ValueExtractor::extractBox(int *margins, int *paddings, int *spacing)
int ValueExtractor::extractStyleFeatures()
{
int features = StyleFeature_None;
- for (int i = 0; i < declarations.count(); i++) {
+ for (int i = 0; i < declarations.size(); i++) {
const Declaration &decl = declarations.at(i);
if (decl.d->propertyId == QtStyleFeatures)
features = decl.styleFeaturesValue();
@@ -573,9 +549,9 @@ QSize ValueExtractor::sizeValue(const Declaration &decl)
}
LengthData x[2] = { {0, LengthData::None }, {0, LengthData::None} };
- if (decl.d->values.count() > 0)
+ if (decl.d->values.size() > 0)
x[0] = lengthValue(decl.d->values.at(0));
- if (decl.d->values.count() > 1)
+ if (decl.d->values.size() > 1)
x[1] = lengthValue(decl.d->values.at(1));
else
x[1] = x[0];
@@ -597,7 +573,7 @@ bool ValueExtractor::extractBorder(int *borders, QBrush *colors, BorderStyle *st
{
extractFont();
bool hit = false;
- for (int i = 0; i < declarations.count(); i++) {
+ for (int i = 0; i < declarations.size(); i++) {
const Declaration &decl = declarations.at(i);
switch (decl.d->propertyId) {
case BorderLeftWidth: borders[LeftEdge] = lengthValue(decl); break;
@@ -656,7 +632,7 @@ bool ValueExtractor::extractOutline(int *borders, QBrush *colors, BorderStyle *s
{
extractFont();
bool hit = false;
- for (int i = 0; i < declarations.count(); i++) {
+ for (int i = 0; i < declarations.size(); i++) {
const Declaration &decl = declarations.at(i);
switch (decl.d->propertyId) {
case OutlineWidth: lengthValues(decl, borders); break;
@@ -725,11 +701,11 @@ static ColorData parseColorValue(QCss::Value v)
return ColorData();
QStringList lst = v.variant.toStringList();
- if (lst.count() != 2)
+ if (lst.size() != 2)
return ColorData();
const QString &identifier = lst.at(0);
- if ((identifier.compare(QLatin1String("palette"), Qt::CaseInsensitive)) == 0) {
+ if ((identifier.compare("palette"_L1, Qt::CaseInsensitive)) == 0) {
int role = findKnownValue(lst.at(1).trimmed(), values, NumKnownValues);
if (role >= Value_FirstColorRole && role <= Value_LastColorRole)
return (QPalette::ColorRole)(role-Value_FirstColorRole);
@@ -737,14 +713,14 @@ static ColorData parseColorValue(QCss::Value v)
return ColorData();
}
- const bool rgb = identifier.startsWith(QLatin1String("rgb"));
- const bool hsv = !rgb && identifier.startsWith(QLatin1String("hsv"));
- const bool hsl = !rgb && !hsv && identifier.startsWith(QLatin1String("hsl"));
+ const bool rgb = identifier.startsWith("rgb"_L1);
+ const bool hsv = !rgb && identifier.startsWith("hsv"_L1);
+ const bool hsl = !rgb && !hsv && identifier.startsWith("hsl"_L1);
if (!rgb && !hsv && !hsl)
return ColorData();
- const bool hasAlpha = identifier.size() == 4 && identifier.at(3) == QLatin1Char('a');
+ const bool hasAlpha = identifier.size() == 4 && identifier.at(3) == u'a';
if (identifier.size() > 3 && !hasAlpha)
return ColorData();
@@ -755,7 +731,7 @@ static ColorData parseColorValue(QCss::Value v)
QList<QCss::Value> colorDigits;
if (!p.parseExpr(&colorDigits))
return ColorData();
- const int tokenCount = colorDigits.count();
+ const int tokenCount = colorDigits.size();
for (int i = 0; i < qMin(tokenCount, 7); i += 2) {
if (colorDigits.at(i).type == Value::Percentage) {
@@ -772,11 +748,11 @@ static ColorData parseColorValue(QCss::Value v)
return ColorData();
if (hasAlpha && tokenCount != 7) {
- qWarning("QCssParser::parseColorValue: Specified color with alpha value but no alpha given: '%s'", qPrintable(lst.join(QLatin1Char(' '))));
+ qWarning("QCssParser::parseColorValue: Specified color with alpha value but no alpha given: '%s'", qPrintable(lst.join(u' ')));
return ColorData();
}
if (!hasAlpha && tokenCount != 5) {
- qWarning("QCssParser::parseColorValue: Specified color without alpha value but alpha given: '%s'", qPrintable(lst.join(QLatin1Char(' '))));
+ qWarning("QCssParser::parseColorValue: Specified color without alpha value but alpha given: '%s'", qPrintable(lst.join(u' ')));
return ColorData();
}
@@ -822,11 +798,11 @@ static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal)
return BrushData();
QStringList lst = v.variant.toStringList();
- if (lst.count() != 2)
+ if (lst.size() != 2)
return BrushData();
QStringList gradFuncs;
- gradFuncs << QLatin1String("qlineargradient") << QLatin1String("qradialgradient") << QLatin1String("qconicalgradient") << QLatin1String("qgradient");
+ gradFuncs << "qlineargradient"_L1 << "qradialgradient"_L1 << "qconicalgradient"_L1 << "qgradient"_L1;
int gradType = -1;
if ((gradType = gradFuncs.indexOf(lst.at(0).toLower())) == -1)
@@ -837,7 +813,11 @@ static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal)
int spread = -1;
QStringList spreads;
- spreads << QLatin1String("pad") << QLatin1String("reflect") << QLatin1String("repeat");
+ spreads << "pad"_L1 << "reflect"_L1 << "repeat"_L1;
+
+ int coordinateMode = -1;
+ QStringList coordinateModes;
+ coordinateModes << "logical"_L1 << "stretchtodevice"_L1 << "objectbounding"_L1 << "object"_L1;
bool dependsOnThePalette = false;
Parser parser(lst.at(1));
@@ -850,7 +830,7 @@ static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal)
if (!parser.test(COLON))
return BrushData();
parser.skipSpace();
- if (attr.compare(QLatin1String("stop"), Qt::CaseInsensitive) == 0) {
+ if (attr.compare("stop"_L1, Qt::CaseInsensitive) == 0) {
QCss::Value stop, color;
parser.next();
if (!parser.parseTerm(&stop)) return BrushData();
@@ -865,20 +845,21 @@ static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal)
parser.next();
QCss::Value value;
(void)parser.parseTerm(&value);
- if (attr.compare(QLatin1String("spread"), Qt::CaseInsensitive) == 0) {
+ if (attr.compare("spread"_L1, Qt::CaseInsensitive) == 0)
spread = spreads.indexOf(value.variant.toString());
- } else {
+ else if (attr.compare("coordinatemode"_L1, Qt::CaseInsensitive) == 0)
+ coordinateMode = coordinateModes.indexOf(value.variant.toString());
+ else
vars[attr] = value.variant.toReal();
- }
}
parser.skipSpace();
(void)parser.test(COMMA);
}
if (gradType == 0) {
- QLinearGradient lg(vars.value(QLatin1String("x1")), vars.value(QLatin1String("y1")),
- vars.value(QLatin1String("x2")), vars.value(QLatin1String("y2")));
- lg.setCoordinateMode(QGradient::ObjectBoundingMode);
+ QLinearGradient lg(vars.value("x1"_L1), vars.value("y1"_L1),
+ vars.value("x2"_L1), vars.value("y2"_L1));
+ lg.setCoordinateMode(coordinateMode < 0 ? QGradient::ObjectBoundingMode : QGradient::CoordinateMode(coordinateMode));
lg.setStops(stops);
if (spread != -1)
lg.setSpread(QGradient::Spread(spread));
@@ -889,10 +870,10 @@ static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal)
}
if (gradType == 1) {
- QRadialGradient rg(vars.value(QLatin1String("cx")), vars.value(QLatin1String("cy")),
- vars.value(QLatin1String("radius")), vars.value(QLatin1String("fx")),
- vars.value(QLatin1String("fy")));
- rg.setCoordinateMode(QGradient::ObjectBoundingMode);
+ QRadialGradient rg(vars.value("cx"_L1), vars.value("cy"_L1),
+ vars.value("radius"_L1), vars.value("fx"_L1),
+ vars.value("fy"_L1));
+ rg.setCoordinateMode(coordinateMode < 0 ? QGradient::ObjectBoundingMode : QGradient::CoordinateMode(coordinateMode));
rg.setStops(stops);
if (spread != -1)
rg.setSpread(QGradient::Spread(spread));
@@ -903,9 +884,8 @@ static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal)
}
if (gradType == 2) {
- QConicalGradient cg(vars.value(QLatin1String("cx")), vars.value(QLatin1String("cy")),
- vars.value(QLatin1String("angle")));
- cg.setCoordinateMode(QGradient::ObjectBoundingMode);
+ QConicalGradient cg(vars.value("cx"_L1), vars.value("cy"_L1), vars.value("angle"_L1));
+ cg.setCoordinateMode(coordinateMode < 0 ? QGradient::ObjectBoundingMode : QGradient::CoordinateMode(coordinateMode));
cg.setStops(stops);
if (spread != -1)
cg.setSpread(QGradient::Spread(spread));
@@ -989,7 +969,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord
if (decl.d->values.at(i).type == Value::Length || decl.d->values.at(i).type == Value::Number) {
data.width = lengthValue(decl.d->values.at(i));
*width = lengthValueFromData(data.width, f);
- if (++i >= decl.d->values.count()) {
+ if (++i >= decl.d->values.size()) {
decl.d->parsed = QVariant::fromValue<BorderData>(data);
return;
}
@@ -998,7 +978,7 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord
data.style = parseStyleValue(decl.d->values.at(i));
if (data.style != BorderStyle_Unknown) {
*style = data.style;
- if (++i >= decl.d->values.count()) {
+ if (++i >= decl.d->values.size()) {
decl.d->parsed = QVariant::fromValue<BorderData>(data);
return;
}
@@ -1007,9 +987,11 @@ void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::Bord
}
data.color = parseBrushValue(decl.d->values.at(i), pal);
- *color = brushFromData(data.color, pal);
- if (data.color.type != BrushData::DependsOnThePalette)
- decl.d->parsed = QVariant::fromValue<BorderData>(data);
+ if (data.color.type != BrushData::Invalid) {
+ *color = brushFromData(data.color, pal);
+ if (data.color.type != BrushData::DependsOnThePalette)
+ decl.d->parsed = QVariant::fromValue<BorderData>(data);
+ }
}
static void parseShorthandBackgroundProperty(const QList<QCss::Value> &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal)
@@ -1019,7 +1001,7 @@ static void parseShorthandBackgroundProperty(const QList<QCss::Value> &values, B
*repeat = Repeat_XY;
*alignment = Qt::AlignTop | Qt::AlignLeft;
- for (int i = 0; i < values.count(); ++i) {
+ for (int i = 0; i < values.size(); ++i) {
const QCss::Value &v = values.at(i);
if (v.type == Value::Uri) {
*image = v.variant.toString();
@@ -1041,7 +1023,7 @@ static void parseShorthandBackgroundProperty(const QList<QCss::Value> &values, B
if (v.type == Value::KnownIdentifier) {
const int start = i;
int count = 1;
- if (i < values.count() - 1
+ if (i < values.size() - 1
&& values.at(i + 1).type == Value::KnownIdentifier) {
++i;
++count;
@@ -1063,7 +1045,7 @@ bool ValueExtractor::extractBackground(QBrush *brush, QString *image, Repeat *re
Origin *clip)
{
bool hit = false;
- for (int i = 0; i < declarations.count(); ++i) {
+ for (int i = 0; i < declarations.size(); ++i) {
const Declaration &decl = declarations.at(i);
if (decl.d->values.isEmpty())
continue;
@@ -1140,14 +1122,14 @@ static bool setFontSizeFromValue(QCss::Value value, QFont *font, int *fontSizeAd
bool valid = false;
QString s = value.variant.toString();
- if (s.endsWith(QLatin1String("pt"), Qt::CaseInsensitive)) {
+ if (s.endsWith("pt"_L1, Qt::CaseInsensitive)) {
s.chop(2);
value.variant = s;
if (value.variant.convert(QMetaType::fromType<qreal>())) {
font->setPointSizeF(qBound(qreal(0), value.variant.toReal(), qreal(1 << 24) - 1));
valid = true;
}
- } else if (s.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) {
+ } else if (s.endsWith("px"_L1, Qt::CaseInsensitive)) {
s.chop(2);
value.variant = s;
if (value.variant.convert(QMetaType::fromType<int>())) {
@@ -1211,7 +1193,7 @@ static bool setFontFamilyFromValues(const QList<QCss::Value> &values, QFont *fon
QString family;
QStringList families;
bool shouldAddSpace = false;
- for (int i = start; i < values.count(); ++i) {
+ for (int i = start; i < values.size(); ++i) {
const QCss::Value &v = values.at(i);
if (v.type == Value::TermOperatorComma) {
families << family;
@@ -1223,7 +1205,7 @@ static bool setFontFamilyFromValues(const QList<QCss::Value> &values, QFont *fon
if (str.isEmpty())
break;
if (shouldAddSpace)
- family += QLatin1Char(' ');
+ family += u' ';
family += str;
shouldAddSpace = true;
}
@@ -1237,7 +1219,7 @@ static bool setFontFamilyFromValues(const QList<QCss::Value> &values, QFont *fon
static void setTextDecorationFromValues(const QList<QCss::Value> &values, QFont *font)
{
- for (int i = 0; i < values.count(); ++i) {
+ for (int i = 0; i < values.size(); ++i) {
if (values.at(i).type != Value::KnownIdentifier)
continue;
switch (values.at(i).variant.toInt()) {
@@ -1259,12 +1241,12 @@ static void setLetterSpacingFromValue(const QCss::Value &value, QFont *font)
QString s = value.variant.toString();
qreal val;
bool ok = false;
- if (s.endsWith(QLatin1String("em"), Qt::CaseInsensitive)) {
+ if (s.endsWith("em"_L1, Qt::CaseInsensitive)) {
s.chop(2);
val = s.toDouble(&ok);
if (ok)
font->setLetterSpacing(QFont::PercentageSpacing, (val + 1.0) * 100);
- } else if (s.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) {
+ } else if (s.endsWith("px"_L1, Qt::CaseInsensitive)) {
s.chop(2);
val = s.toDouble(&ok);
if (ok)
@@ -1275,7 +1257,7 @@ static void setLetterSpacingFromValue(const QCss::Value &value, QFont *font)
static void setWordSpacingFromValue(const QCss::Value &value, QFont *font)
{
QString s = value.variant.toString();
- if (s.endsWith(QLatin1String("px"), Qt::CaseInsensitive)) {
+ if (s.endsWith("px"_L1, Qt::CaseInsensitive)) {
s.chop(2);
qreal val;
bool ok = false;
@@ -1292,7 +1274,7 @@ static void parseShorthandFontProperty(const QList<QCss::Value> &values, QFont *
*fontSizeAdjustment = -255;
int i = 0;
- while (i < values.count()) {
+ while (i < values.size()) {
if (setFontStyleFromValue(values.at(i), font)
|| setFontWeightFromValue(values.at(i), font))
++i;
@@ -1300,12 +1282,12 @@ static void parseShorthandFontProperty(const QList<QCss::Value> &values, QFont *
break;
}
- if (i < values.count()) {
+ if (i < values.size()) {
setFontSizeFromValue(values.at(i), font, fontSizeAdjustment);
++i;
}
- if (i < values.count()) {
+ if (i < values.size()) {
setFontFamilyFromValues(values, font, i);
}
}
@@ -1342,7 +1324,7 @@ bool ValueExtractor::extractFont(QFont *font, int *fontSizeAdjustment)
}
bool hit = false;
- for (int i = 0; i < declarations.count(); ++i) {
+ for (int i = 0; i < declarations.size(); ++i) {
const Declaration &decl = declarations.at(i);
if (decl.d->values.isEmpty())
continue;
@@ -1370,16 +1352,23 @@ bool ValueExtractor::extractFont(QFont *font, int *fontSizeAdjustment)
return hit;
}
-bool ValueExtractor::extractPalette(QBrush *fg, QBrush *sfg, QBrush *sbg, QBrush *abg)
+bool ValueExtractor::extractPalette(QBrush *foreground,
+ QBrush *selectedForeground,
+ QBrush *selectedBackground,
+ QBrush *alternateBackground,
+ QBrush *placeHolderTextForeground,
+ QBrush *accent)
{
bool hit = false;
- for (int i = 0; i < declarations.count(); ++i) {
+ for (int i = 0; i < declarations.size(); ++i) {
const Declaration &decl = declarations.at(i);
switch (decl.d->propertyId) {
- case Color: *fg = decl.brushValue(pal); break;
- case QtSelectionForeground: *sfg = decl.brushValue(pal); break;
- case QtSelectionBackground: *sbg = decl.brushValue(pal); break;
- case QtAlternateBackground: *abg = decl.brushValue(pal); break;
+ case Color: *foreground = decl.brushValue(pal); break;
+ case QtSelectionForeground: *selectedForeground = decl.brushValue(pal); break;
+ case QtSelectionBackground: *selectedBackground = decl.brushValue(pal); break;
+ case QtAlternateBackground: *alternateBackground = decl.brushValue(pal); break;
+ case QtPlaceHolderTextColor: *placeHolderTextForeground = decl.brushValue(pal); break;
+ case QtAccent: *accent = decl.brushValue(pal); break;
default: continue;
}
hit = true;
@@ -1398,12 +1387,12 @@ void ValueExtractor::extractFont()
bool ValueExtractor::extractImage(QIcon *icon, Qt::Alignment *a, QSize *size)
{
bool hit = false;
- for (int i = 0; i < declarations.count(); ++i) {
+ for (int i = 0; i < declarations.size(); ++i) {
const Declaration &decl = declarations.at(i);
switch (decl.d->propertyId) {
case QtImage:
*icon = decl.iconValue();
- if (decl.d->values.count() > 0 && decl.d->values.at(0).type == Value::Uri) {
+ if (decl.d->values.size() > 0 && decl.d->values.at(0).type == Value::Uri) {
// try to pull just the size from the image...
QImageReader imageReader(decl.d->values.at(0).variant.toString());
if ((*size = imageReader.size()).isNull()) {
@@ -1456,14 +1445,23 @@ bool ValueExtractor::extractIcon(QIcon *icon, QSize *size)
// Declaration
QColor Declaration::colorValue(const QPalette &pal) const
{
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return QColor();
if (d->parsed.isValid()) {
- if (d->parsed.userType() == QMetaType::QColor)
+ switch (d->parsed.typeId()) {
+ case qMetaTypeId<QColor>():
return qvariant_cast<QColor>(d->parsed);
- if (d->parsed.userType() == QMetaType::Int)
+ case qMetaTypeId<int>():
return pal.color((QPalette::ColorRole)(d->parsed.toInt()));
+ case qMetaTypeId<QList<QVariant>>():
+ if (d->parsed.toList().size() == 1) {
+ auto parsedList = d->parsed.toList();
+ const auto &value = parsedList.at(0);
+ return qvariant_cast<QColor>(value);
+ }
+ break;
+ }
}
ColorData color = parseColorValue(d->values.at(0));
@@ -1478,7 +1476,7 @@ QColor Declaration::colorValue(const QPalette &pal) const
QBrush Declaration::brushValue(const QPalette &pal) const
{
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return QBrush();
if (d->parsed.isValid()) {
@@ -1507,8 +1505,9 @@ void Declaration::brushValues(QBrush *c, const QPalette &pal) const
int i = 0;
if (d->parsed.isValid()) {
needParse = 0;
+ Q_ASSERT(d->parsed.metaType() == QMetaType::fromType<QList<QVariant>>());
QList<QVariant> v = d->parsed.toList();
- for (i = 0; i < qMin(v.count(), 4); i++) {
+ for (i = 0; i < qMin(v.size(), 4); i++) {
if (v.at(i).userType() == QMetaType::QBrush) {
c[i] = qvariant_cast<QBrush>(v.at(i));
} else if (v.at(i).userType() == QMetaType::Int) {
@@ -1520,7 +1519,7 @@ void Declaration::brushValues(QBrush *c, const QPalette &pal) const
}
if (needParse != 0) {
QList<QVariant> v;
- for (i = 0; i < qMin(d->values.count(), 4); i++) {
+ for (i = 0; i < qMin(d->values.size(), 4); i++) {
if (!(needParse & (1<<i)))
continue;
BrushData data = parseBrushValue(d->values.at(i), pal);
@@ -1547,7 +1546,7 @@ void Declaration::brushValues(QBrush *c, const QPalette &pal) const
bool Declaration::realValue(qreal *real, const char *unit) const
{
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return false;
const Value &v = d->values.at(0);
if (unit && v.type != Value::Length)
@@ -1555,7 +1554,7 @@ bool Declaration::realValue(qreal *real, const char *unit) const
const QString str = v.variant.toString();
QStringView s(str);
if (unit) {
- const QLatin1String unitStr(unit);
+ const QLatin1StringView unitStr(unit);
if (!s.endsWith(unitStr, Qt::CaseInsensitive))
return false;
s.chop(unitStr.size());
@@ -1574,7 +1573,7 @@ static bool intValueHelper(const QCss::Value &v, int *i, const char *unit)
const QString str = v.variant.toString();
QStringView s(str);
if (unit) {
- const QLatin1String unitStr(unit);
+ const QLatin1StringView unitStr(unit);
if (!s.endsWith(unitStr, Qt::CaseInsensitive))
return false;
s.chop(unitStr.size());
@@ -1588,7 +1587,7 @@ static bool intValueHelper(const QCss::Value &v, int *i, const char *unit)
bool Declaration::intValue(int *i, const char *unit) const
{
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return false;
return intValueHelper(d->values.at(0), i, unit);
}
@@ -1599,7 +1598,7 @@ QSize Declaration::sizeValue() const
return qvariant_cast<QSize>(d->parsed);
int x[2] = { 0, 0 };
- const int count = d->values.count();
+ const int count = d->values.size();
for (int i = 0; i < count; ++i) {
if (i > 1) {
qWarning("QCssParser::sizeValue: Too many values provided");
@@ -1626,7 +1625,7 @@ QSize Declaration::sizeValue() const
QRect Declaration::rectValue() const
{
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return QRect();
if (d->parsed.isValid())
@@ -1636,10 +1635,10 @@ QRect Declaration::rectValue() const
if (v.type != Value::Function)
return QRect();
const QStringList func = v.variant.toStringList();
- if (func.count() != 2 || func.at(0).compare(QLatin1String("rect")) != 0)
+ if (func.size() != 2 || func.at(0).compare("rect"_L1) != 0)
return QRect();
- const auto args = QStringView{func[1]}.split(QLatin1Char(' '), Qt::SkipEmptyParts);
- if (args.count() != 4)
+ const auto args = QStringView{func[1]}.split(u' ', Qt::SkipEmptyParts);
+ if (args.size() != 4)
return QRect();
QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt());
d->parsed = QVariant::fromValue<QRect>(rect);
@@ -1651,7 +1650,7 @@ void Declaration::colorValues(QColor *c, const QPalette &pal) const
int i;
if (d->parsed.isValid()) {
QList<QVariant> v = d->parsed.toList();
- for (i = 0; i < qMin(d->values.count(), 4); i++) {
+ for (i = 0; i < qMin(d->values.size(), 4); i++) {
if (v.at(i).userType() == QMetaType::QColor) {
c[i] = qvariant_cast<QColor>(v.at(i));
} else {
@@ -1660,7 +1659,7 @@ void Declaration::colorValues(QColor *c, const QPalette &pal) const
}
} else {
QList<QVariant> v;
- for (i = 0; i < qMin(d->values.count(), 4); i++) {
+ for (i = 0; i < qMin(d->values.size(), 4); i++) {
ColorData color = parseColorValue(d->values.at(i));
if (color.type == ColorData::Role) {
v += QVariant::fromValue<int>(color.role);
@@ -1681,7 +1680,7 @@ void Declaration::colorValues(QColor *c, const QPalette &pal) const
BorderStyle Declaration::styleValue() const
{
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return BorderStyle_None;
return parseStyleValue(d->values.at(0));
}
@@ -1689,7 +1688,7 @@ BorderStyle Declaration::styleValue() const
void Declaration::styleValues(BorderStyle *s) const
{
int i;
- for (i = 0; i < qMin(d->values.count(), 4); i++)
+ for (i = 0; i < qMin(d->values.size(), 4); i++)
s[i] = parseStyleValue(d->values.at(i));
if (i == 0) s[0] = s[1] = s[2] = s[3] = BorderStyle_None;
else if (i == 1) s[3] = s[2] = s[1] = s[0];
@@ -1701,7 +1700,7 @@ Repeat Declaration::repeatValue() const
{
if (d->parsed.isValid())
return static_cast<Repeat>(d->parsed.toInt());
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return Repeat_Unknown;
int v = findKnownValue(d->values.at(0).variant.toString(),
repeats, NumKnownRepeats);
@@ -1713,7 +1712,7 @@ Origin Declaration::originValue() const
{
if (d->parsed.isValid())
return static_cast<Origin>(d->parsed.toInt());
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return Origin_Unknown;
int v = findKnownValue(d->values.at(0).variant.toString(),
origins, NumKnownOrigins);
@@ -1725,7 +1724,7 @@ PositionMode Declaration::positionValue() const
{
if (d->parsed.isValid())
return static_cast<PositionMode>(d->parsed.toInt());
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return PositionMode_Unknown;
int v = findKnownValue(d->values.at(0).variant.toString(),
positions, NumKnownPositionModes);
@@ -1737,7 +1736,7 @@ Attachment Declaration::attachmentValue() const
{
if (d->parsed.isValid())
return static_cast<Attachment>(d->parsed.toInt());
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return Attachment_Unknown;
int v = findKnownValue(d->values.at(0).variant.toString(),
attachments, NumKnownAttachments);
@@ -1751,7 +1750,7 @@ int Declaration::styleFeaturesValue() const
if (d->parsed.isValid())
return d->parsed.toInt();
int features = StyleFeature_None;
- for (int i = 0; i < d->values.count(); i++) {
+ for (int i = 0; i < d->values.size(); i++) {
features |= static_cast<int>(findKnownValue(d->values.value(i).variant.toString(),
styleFeatures, NumKnownStyleFeatures));
}
@@ -1770,10 +1769,10 @@ Qt::Alignment Declaration::alignmentValue() const
{
if (d->parsed.isValid())
return Qt::Alignment(d->parsed.toInt());
- if (d->values.isEmpty() || d->values.count() > 2)
+ if (d->values.isEmpty() || d->values.size() > 2)
return Qt::AlignLeft | Qt::AlignTop;
- Qt::Alignment v = parseAlignment(d->values.constData(), d->values.count());
+ Qt::Alignment v = parseAlignment(d->values.constData(), d->values.size());
d->parsed = int(v);
return v;
}
@@ -1787,12 +1786,12 @@ void Declaration::borderImageValue(QString *image, int *cuts,
cuts[i] = -1;
*h = *v = TileMode_Stretch;
- if (d->values.count() < 2)
+ if (d->values.size() < 2)
return;
if (d->values.at(1).type == Value::Number) { // cuts!
int i;
- for (i = 0; i < qMin(d->values.count()-1, 4); i++) {
+ for (i = 0; i < qMin(d->values.size()-1, 4); i++) {
const Value& v = d->values.at(i+1);
if (v.type != Value::Number)
break;
@@ -1808,9 +1807,9 @@ void Declaration::borderImageValue(QString *image, int *cuts,
*v = static_cast<TileMode>(findKnownValue(d->values.last().variant.toString(),
tileModes, NumKnownTileModes));
}
- if (d->values[d->values.count() - 2].type == Value::Identifier) {
+ if (d->values[d->values.size() - 2].type == Value::Identifier) {
*h = static_cast<TileMode>
- (findKnownValue(d->values[d->values.count()-2].variant.toString(),
+ (findKnownValue(d->values[d->values.size()-2].variant.toString(),
tileModes, NumKnownTileModes));
} else
*h = *v;
@@ -1818,10 +1817,10 @@ void Declaration::borderImageValue(QString *image, int *cuts,
bool Declaration::borderCollapseValue() const
{
- if (d->values.count() != 1)
+ if (d->values.size() != 1)
return false;
else
- return d->values.at(0).toString() == QLatin1String("collapse");
+ return d->values.at(0).toString() == "collapse"_L1;
}
QIcon Declaration::iconValue() const
@@ -1830,7 +1829,7 @@ QIcon Declaration::iconValue() const
return qvariant_cast<QIcon>(d->parsed);
QIcon icon;
- for (int i = 0; i < d->values.count();) {
+ for (int i = 0; i < d->values.size();) {
const Value &value = d->values.at(i++);
if (value.type != Value::Uri)
break;
@@ -1838,7 +1837,7 @@ QIcon Declaration::iconValue() const
QIcon::Mode mode = QIcon::Normal;
QIcon::State state = QIcon::Off;
for (int j = 0; j < 2; j++) {
- if (i != d->values.count() && d->values.at(i).type == Value::KnownIdentifier) {
+ if (i != d->values.size() && d->values.at(i).type == Value::KnownIdentifier) {
switch (d->values.at(i).variant.toInt()) {
case Value_Disabled: mode = QIcon::Disabled; break;
case Value_Active: mode = QIcon::Active; break;
@@ -1860,7 +1859,7 @@ QIcon Declaration::iconValue() const
else
icon.addPixmap(uri, mode, state);
- if (i == d->values.count())
+ if (i == d->values.size())
break;
if (d->values.at(i).type == Value::TermOperatorComma)
@@ -1876,13 +1875,13 @@ QIcon Declaration::iconValue() const
int Selector::specificity() const
{
int val = 0;
- for (int i = 0; i < basicSelectors.count(); ++i) {
+ for (int i = 0; i < basicSelectors.size(); ++i) {
const BasicSelector &sel = basicSelectors.at(i);
if (!sel.elementName.isEmpty())
val += 1;
- val += (sel.pseudos.count() + sel.attributeSelectors.count()) * 0x10;
- val += sel.ids.count() * 0x100;
+ val += (sel.pseudos.size() + sel.attributeSelectors.size()) * 0x10;
+ val += sel.ids.size() * 0x100;
}
return val;
}
@@ -1901,7 +1900,7 @@ quint64 Selector::pseudoClass(quint64 *negated) const
if (bs.pseudos.isEmpty())
return PseudoClass_Unspecified;
quint64 pc = PseudoClass_Unknown;
- for (int i = !pseudoElement().isEmpty(); i < bs.pseudos.count(); i++) {
+ for (int i = !pseudoElement().isEmpty(); i < bs.pseudos.size(); i++) {
const Pseudo &pseudo = bs.pseudos.at(i);
if (pseudo.type == PseudoClass_Unknown)
return PseudoClass_Unknown;
@@ -1918,23 +1917,23 @@ quint64 Selector::pseudoClass(quint64 *negated) const
void StyleSheet::buildIndexes(Qt::CaseSensitivity nameCaseSensitivity)
{
QList<StyleRule> universals;
- for (int i = 0; i < styleRules.count(); ++i) {
+ for (int i = 0; i < styleRules.size(); ++i) {
const StyleRule &rule = styleRules.at(i);
QList<Selector> universalsSelectors;
- for (int j = 0; j < rule.selectors.count(); ++j) {
+ for (int j = 0; j < rule.selectors.size(); ++j) {
const Selector& selector = rule.selectors.at(j);
if (selector.basicSelectors.isEmpty())
continue;
if (selector.basicSelectors.at(0).relationToNext == BasicSelector::NoRelation) {
- if (selector.basicSelectors.count() != 1)
+ if (selector.basicSelectors.size() != 1)
continue;
- } else if (selector.basicSelectors.count() <= 1) {
+ } else if (selector.basicSelectors.size() <= 1) {
continue;
}
- const BasicSelector &sel = selector.basicSelectors.at(selector.basicSelectors.count() - 1);
+ const BasicSelector &sel = selector.basicSelectors.at(selector.basicSelectors.size() - 1);
if (!sel.ids.isEmpty()) {
StyleRule nr;
@@ -1979,7 +1978,7 @@ bool StyleSelector::nodeNameEquals(NodePtr node, const QString& nodeName) const
QStringList StyleSelector::nodeIds(NodePtr node) const
{
- return QStringList(attribute(node, QLatin1String("id")));
+ return QStringList(attributeValue(node, QCss::AttributeSelector{"id"_L1, {}, AttributeSelector::NoMatch}));
}
bool StyleSelector::selectorMatches(const Selector &selector, NodePtr node)
@@ -1988,14 +1987,14 @@ bool StyleSelector::selectorMatches(const Selector &selector, NodePtr node)
return false;
if (selector.basicSelectors.at(0).relationToNext == BasicSelector::NoRelation) {
- if (selector.basicSelectors.count() != 1)
+ if (selector.basicSelectors.size() != 1)
return false;
return basicSelectorMatches(selector.basicSelectors.at(0), node);
}
- if (selector.basicSelectors.count() <= 1)
+ if (selector.basicSelectors.size() <= 1)
return false;
- int i = selector.basicSelectors.count() - 1;
+ int i = selector.basicSelectors.size() - 1;
node = duplicateNode(node);
bool match = true;
@@ -2003,7 +2002,7 @@ bool StyleSelector::selectorMatches(const Selector &selector, NodePtr node)
do {
match = basicSelectorMatches(sel, node);
if (!match) {
- if (i == selector.basicSelectors.count() - 1) // first element must always match!
+ if (i == selector.basicSelectors.size() - 1) // first element must always match!
break;
if (sel.relationToNext != BasicSelector::MatchNextSelectorIfAncestor &&
sel.relationToNext != BasicSelector::MatchNextSelectorIfIndirectAdjecent)
@@ -2048,10 +2047,10 @@ bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node)
if (!hasAttributes(node))
return false;
- for (int i = 0; i < sel.attributeSelectors.count(); ++i) {
+ for (int i = 0; i < sel.attributeSelectors.size(); ++i) {
const QCss::AttributeSelector &a = sel.attributeSelectors.at(i);
- const QString attrValue = attribute(node, a.name);
+ const QString attrValue = attributeValue(node, a);
if (attrValue.isNull())
return false;
@@ -2076,7 +2075,7 @@ bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node)
break;
}
case QCss::AttributeSelector::MatchDashMatch: {
- const QString dashPrefix = a.value + QLatin1Char('-');
+ const QString dashPrefix = a.value + u'-';
if (attrValue != a.value && !attrValue.startsWith(dashPrefix))
return false;
break;
@@ -2111,14 +2110,14 @@ bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node)
void StyleSelector::matchRule(NodePtr node, const StyleRule &rule, StyleSheetOrigin origin,
int depth, QMultiMap<uint, StyleRule> *weightedRules)
{
- for (int j = 0; j < rule.selectors.count(); ++j) {
+ for (int j = 0; j < rule.selectors.size(); ++j) {
const Selector& selector = rule.selectors.at(j);
if (selectorMatches(selector, node)) {
uint weight = rule.order
+ selector.specificity() *0x100
+ (uint(origin) + depth)*0x100000;
StyleRule newRule = rule;
- if (rule.selectors.count() > 1) {
+ if (rule.selectors.size() > 1) {
newRule.selectors.resize(1);
newRule.selectors[0] = selector;
}
@@ -2139,15 +2138,15 @@ QList<StyleRule> StyleSelector::styleRulesForNode(NodePtr node)
QMultiMap<uint, StyleRule> weightedRules; // (spec, rule) that will be sorted below
//prune using indexed stylesheet
- for (int sheetIdx = 0; sheetIdx < styleSheets.count(); ++sheetIdx) {
+ for (int sheetIdx = 0; sheetIdx < styleSheets.size(); ++sheetIdx) {
const StyleSheet &styleSheet = styleSheets.at(sheetIdx);
- for (int i = 0; i < styleSheet.styleRules.count(); ++i) {
+ for (int i = 0; i < styleSheet.styleRules.size(); ++i) {
matchRule(node, styleSheet.styleRules.at(i), styleSheet.origin, styleSheet.depth, &weightedRules);
}
if (!styleSheet.idIndex.isEmpty()) {
QStringList ids = nodeIds(node);
- for (int i = 0; i < ids.count(); i++) {
+ for (int i = 0; i < ids.size(); i++) {
const QString &key = ids.at(i);
QMultiHash<QString, StyleRule>::const_iterator it = styleSheet.idIndex.constFind(key);
while (it != styleSheet.idIndex.constEnd() && it.key() == key) {
@@ -2158,7 +2157,7 @@ QList<StyleRule> StyleSelector::styleRulesForNode(NodePtr node)
}
if (!styleSheet.nameIndex.isEmpty()) {
QStringList names = nodeNames(node);
- for (int i = 0; i < names.count(); i++) {
+ for (int i = 0; i < names.size(); i++) {
QString name = names.at(i);
if (nameCaseSensitivity == Qt::CaseInsensitive)
name = std::move(name).toLower();
@@ -2170,9 +2169,9 @@ QList<StyleRule> StyleSelector::styleRulesForNode(NodePtr node)
}
}
if (!medium.isEmpty()) {
- for (int i = 0; i < styleSheet.mediaRules.count(); ++i) {
+ for (int i = 0; i < styleSheet.mediaRules.size(); ++i) {
if (styleSheet.mediaRules.at(i).media.contains(medium, Qt::CaseInsensitive)) {
- for (int j = 0; j < styleSheet.mediaRules.at(i).styleRules.count(); ++j) {
+ for (int j = 0; j < styleSheet.mediaRules.at(i).styleRules.size(); ++j) {
matchRule(node, styleSheet.mediaRules.at(i).styleRules.at(j), styleSheet.origin,
styleSheet.depth, &weightedRules);
}
@@ -2181,7 +2180,7 @@ QList<StyleRule> StyleSelector::styleRulesForNode(NodePtr node)
}
}
- rules.reserve(weightedRules.count());
+ rules.reserve(weightedRules.size());
QMultiMap<uint, StyleRule>::const_iterator it = weightedRules.constBegin();
for ( ; it != weightedRules.constEnd() ; ++it)
rules += *it;
@@ -2195,11 +2194,11 @@ QList<Declaration> StyleSelector::declarationsForNode(NodePtr node, const char *
{
QList<Declaration> decls;
QList<StyleRule> rules = styleRulesForNode(node);
- for (int i = 0; i < rules.count(); i++) {
+ for (int i = 0; i < rules.size(); i++) {
const Selector& selector = rules.at(i).selectors.at(0);
const QString pseudoElement = selector.pseudoElement();
- if (extraPseudo && pseudoElement == QLatin1String(extraPseudo)) {
+ if (extraPseudo && pseudoElement == QLatin1StringView(extraPseudo)) {
decls += rules.at(i).declarations;
continue;
}
@@ -2230,7 +2229,7 @@ QString Scanner::preprocess(const QString &input, bool *hasEscapeSequences)
int i = 0;
while (i < output.size()) {
- if (output.at(i) == QLatin1Char('\\')) {
+ if (output.at(i) == u'\\') {
++i;
// test for unicode hex escape
@@ -2267,8 +2266,7 @@ QString Scanner::preprocess(const QString &input, bool *hasEscapeSequences)
int QCssScanner_Generated::handleCommentStart()
{
while (pos < input.size() - 1) {
- if (input.at(pos) == QLatin1Char('*')
- && input.at(pos + 1) == QLatin1Char('/')) {
+ if (input.at(pos) == u'*' && input.at(pos + 1) == u'/') {
pos += 2;
break;
}
@@ -2298,7 +2296,7 @@ QString Symbol::lexem() const
if (len > 0)
result.reserve(len);
for (int i = 0; i < len; ++i) {
- if (text.at(start + i) == QLatin1Char('\\') && i < len - 1)
+ if (text.at(start + i) == u'\\' && i < len - 1)
++i;
result += text.at(start + i);
}
@@ -2323,7 +2321,7 @@ void Parser::init(const QString &css, bool isFile)
if (isFile) {
QFile file(css);
if (file.open(QFile::ReadOnly)) {
- sourcePath = QFileInfo(styleSheet).absolutePath() + QLatin1Char('/');
+ sourcePath = QFileInfo(styleSheet).absolutePath() + u'/';
QTextStream stream(&file);
styleSheet = stream.readAll();
} else {
@@ -2344,7 +2342,7 @@ void Parser::init(const QString &css, bool isFile)
bool Parser::parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity)
{
- if (testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("charset"))) {
+ if (testTokenAndEndsWith(ATKEYWORD_SYM, "charset"_L1)) {
while (test(S) || test(CDO) || test(CDC)) {}
if (!next(STRING)) return false;
if (!next(SEMICOLON)) return false;
@@ -2391,8 +2389,7 @@ Symbol Parser::errorSymbol()
static inline void removeOptionalQuotes(QString *str)
{
- if (!str->startsWith(QLatin1Char('\''))
- && !str->startsWith(QLatin1Char('\"')))
+ if (!str->startsWith(u'\'') && !str->startsWith(u'\"'))
return;
str->remove(0, 1);
str->chop(1);
@@ -2609,7 +2606,7 @@ bool Parser::parseSimpleSelector(BasicSelector *basicSel)
} else if (testClass()) {
onceMore = true;
AttributeSelector a;
- a.name = QLatin1String("class");
+ a.name = "class"_L1;
a.valueMatchCriterium = AttributeSelector::MatchIncludes;
if (!parseClass(&a.value)) return false;
basicSel->attributeSelectors.append(a);
@@ -2720,7 +2717,7 @@ bool Parser::testPrio()
index = rewind;
return false;
}
- if (lexem().compare(QLatin1String("important"), Qt::CaseInsensitive) != 0) {
+ if (lexem().compare("important"_L1, Qt::CaseInsensitive) != 0) {
index = rewind;
return false;
}
@@ -2823,7 +2820,7 @@ bool Parser::parseTerm(Value *value)
} else if (testFunction()) {
QString name, args;
if (!parseFunction(&name, &args)) return false;
- if (name == QLatin1String("url")) {
+ if (name == "url"_L1) {
value->type = Value::Uri;
removeOptionalQuotes(&args);
if (QFileInfo(args).isRelative() && !sourcePath.isEmpty()) {
@@ -2865,7 +2862,7 @@ bool Parser::parseFunction(QString *name, QString *args)
bool Parser::parseHexColor(QColor *col)
{
- col->setNamedColor(lexem());
+ *col = QColor::fromString(lexem());
if (!col->isValid()) {
qWarning("QCssParser::parseHexColor: Unknown color name '%s'",lexem().toLatin1().constData());
return false;
@@ -2884,7 +2881,7 @@ bool Parser::testAndParseUri(QString *uri)
index = rewind;
return false;
}
- if (name.compare(QLatin1String("url"), Qt::CaseInsensitive) != 0) {
+ if (name.compare("url"_L1, Qt::CaseInsensitive) != 0) {
index = rewind;
return false;
}
@@ -2911,7 +2908,7 @@ bool Parser::next(QCss::TokenType t)
bool Parser::test(QCss::TokenType t)
{
- if (index >= symbols.count())
+ if (index >= symbols.size())
return false;
if (symbols.at(index).token == t) {
++index;
@@ -2978,7 +2975,7 @@ bool Parser::until(QCss::TokenType target, QCss::TokenType target2)
return false;
}
-bool Parser::testTokenAndEndsWith(QCss::TokenType t, QLatin1String str)
+bool Parser::testTokenAndEndsWith(QCss::TokenType t, QLatin1StringView str)
{
if (!test(t)) return false;
if (!lexem().endsWith(str, Qt::CaseInsensitive)) {
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index 56af5c8bb2..c1cfb1ac9b 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QCSSPARSER_P_H
#define QCSSPARSER_P_H
@@ -55,7 +19,6 @@
#include <QtCore/QStringList>
#include <QtCore/QList>
#include <QtCore/QVariant>
-#include <QtCore/QPair>
#include <QtCore/QSize>
#include <QtCore/QMultiHash>
#include <QtGui/QFont>
@@ -202,6 +165,11 @@ enum Property {
LetterSpacing,
WordSpacing,
TextDecorationColor,
+ QtPlaceHolderTextColor,
+ QtAccent,
+ QtStrokeWidth,
+ QtStrokeColor,
+ QtForeground,
NumProperties
};
@@ -557,11 +525,10 @@ struct AttributeSelector
MatchEndsWith,
MatchContains
};
- inline AttributeSelector() : valueMatchCriterium(NoMatch) {}
QString name;
QString value;
- ValueMatchType valueMatchCriterium;
+ ValueMatchType valueMatchCriterium = NoMatch;
};
QT_CSS_DECLARE_TYPEINFO(AttributeSelector, Q_RELOCATABLE_TYPE)
@@ -666,7 +633,7 @@ public:
QList<Declaration> declarationsForNode(NodePtr node, const char *extraPseudo = nullptr);
virtual bool nodeNameEquals(NodePtr node, const QString& nodeName) const;
- virtual QString attribute(NodePtr node, const QString &name) const = 0;
+ virtual QString attributeValue(NodePtr node, const QCss::AttributeSelector &aSelector) const = 0;
virtual bool hasAttributes(NodePtr node) const = 0;
virtual QStringList nodeIds(NodePtr node) const;
virtual QStringList nodeNames(NodePtr node) const = 0;
@@ -800,9 +767,9 @@ public:
inline bool testMedium() { return test(IDENT); }
inline bool parseNextMedium(QStringList *media) { if (!testMedium()) return recordError(); return parseMedium(media); }
inline bool testPseudoPage() { return test(COLON); }
- inline bool testImport() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("import")); }
- inline bool testMedia() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("media")); }
- inline bool testPage() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("page")); }
+ inline bool testImport() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1StringView("import")); }
+ inline bool testMedia() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1StringView("media")); }
+ inline bool testPage() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1StringView("page")); }
inline bool testCombinator() { return test(PLUS) || test(GREATER) || test(TILDE) || test(S); }
inline bool testProperty() { return test(IDENT); }
bool testTerm();
@@ -822,7 +789,7 @@ public:
inline void skipSpace() { while (test(S)) {}; }
- inline bool hasNext() const { return index < symbols.count(); }
+ inline bool hasNext() const { return index < symbols.size(); }
inline TokenType next() { return symbols.at(index++).token; }
bool next(TokenType t);
bool test(TokenType t);
@@ -833,10 +800,10 @@ public:
QString lexemUntil(TokenType t);
bool until(TokenType target, TokenType target2 = NONE);
inline TokenType lookup() const {
- return (index - 1) < symbols.count() ? symbols.at(index - 1).token : NONE;
+ return (index - 1) < symbols.size() ? symbols.at(index - 1).token : NONE;
}
- bool testTokenAndEndsWith(TokenType t, QLatin1String str);
+ bool testTokenAndEndsWith(TokenType t, QLatin1StringView str);
inline bool recordError() { errorIndex = index; return false; }
@@ -860,7 +827,9 @@ struct Q_GUI_EXPORT ValueExtractor
bool extractBox(int *margins, int *paddings, int *spacing = nullptr);
bool extractBorder(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii);
bool extractOutline(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii, int *offsets);
- bool extractPalette(QBrush *fg, QBrush *sfg, QBrush *sbg, QBrush *abg);
+ bool extractPalette(QBrush *foreground, QBrush *selectedForeground, QBrush *selectedBackground,
+ QBrush *alternateBackground, QBrush *placeHolderTextForeground,
+ QBrush *accent);
int extractStyleFeatures();
bool extractImage(QIcon *icon, Qt::Alignment *a, QSize *size);
bool extractIcon(QIcon *icon, QSize *size);
@@ -886,9 +855,9 @@ private:
QT_END_NAMESPACE
-Q_DECLARE_METATYPE( QCss::BackgroundData )
-Q_DECLARE_METATYPE( QCss::LengthData )
-Q_DECLARE_METATYPE( QCss::BorderData )
+QT_DECL_METATYPE_EXTERN_TAGGED(QCss::BackgroundData, QCss__BackgroundData, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN_TAGGED(QCss::LengthData, QCss__LengthData, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN_TAGGED(QCss::BorderData, QCss__BorderData, Q_GUI_EXPORT)
#undef QT_CSS_DECLARE_TYPEINFO
diff --git a/src/gui/text/qcssscanner.cpp b/src/gui/text/qcssscanner.cpp
index d48cbb71d7..7bfa797782 100644
--- a/src/gui/text/qcssscanner.cpp
+++ b/src/gui/text/qcssscanner.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// auto generated by qtbase/util/lexgen/. DO NOT EDIT.
class QCssScanner_Generated
@@ -44,7 +8,7 @@ public:
QCssScanner_Generated(const QString &inp);
inline QChar next() {
- return (pos < input.length()) ? input.at(pos++) : QChar();
+ return (pos < input.size()) ? input.at(pos++) : QChar();
}
int handleCommentStart();
int lex();
diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp
index a3fdfd63d1..fe230188c6 100644
--- a/src/gui/text/qdistancefield.cpp
+++ b/src/gui/text/qdistancefield.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdistancefield_p.h"
#include <qmath.h>
@@ -45,6 +9,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcDistanceField, "qt.distanceField");
namespace
@@ -564,14 +530,14 @@ static void makeDistanceField(QDistanceFieldData *data, const QPainterPath &path
|| (to.y() < offs << 8) || (to.y() >= (imgHeight - offs) << 8));
}
- isConvex.resize(normals.count());
- for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++) {
+ isConvex.resize(normals.size());
+ for (int next = 0, prev = normals.size() - 1; next < normals.size(); prev = next++) {
isConvex[prev] = normals.at(prev).x() * normals.at(next).y()
- normals.at(prev).y() * normals.at(next).x() < 0;
}
// Draw quads.
- for (int next = 0, prev = normals.count() - 1; next < normals.count(); prev = next++) {
+ for (int next = 0, prev = normals.size() - 1; next < normals.size(); prev = next++) {
QPoint n = normals.at(next);
QPoint intPrev = vertices.at(prev);
QPoint extPrev = vertices.at(prev);
@@ -796,7 +762,7 @@ bool qt_fontHasNarrowOutlines(const QRawFont &f)
if (!font.isValid())
return false;
- QList<quint32> glyphIndices = font.glyphIndexesForString(QLatin1String("O"));
+ QList<quint32> glyphIndices = font.glyphIndexesForString("O"_L1);
if (glyphIndices.isEmpty() || glyphIndices[0] == 0)
return false;
@@ -1092,7 +1058,7 @@ QImage QDistanceField::toImage(QImage::Format format) const
}
if (image.format() != format)
- image = image.convertToFormat(format);
+ image = std::move(image).convertToFormat(format);
}
return image;
diff --git a/src/gui/text/qdistancefield_p.h b/src/gui/text/qdistancefield_p.h
index 823bfaf1c6..dbc7a0abb5 100644
--- a/src/gui/text/qdistancefield_p.h
+++ b/src/gui/text/qdistancefield_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDISTANCEFIELD_H
#define QDISTANCEFIELD_H
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index b6d7160cd4..7fd590c355 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfont.h"
#include "qdebug.h"
@@ -67,6 +31,8 @@
#include <QtCore/QMutexLocker>
#include <QtCore/QMutex>
+#include <array>
+
// #define QFONTCACHE_DEBUG
#ifdef QFONTCACHE_DEBUG
# define FC_DEBUG qDebug
@@ -124,6 +90,9 @@ bool QFontDef::exactMatch(const QFontDef &other) const
return false;
}
+ if (variableAxisValues != other.variableAxisValues)
+ return false;
+
return (styleHint == other.styleHint
&& styleStrategy == other.styleStrategy
&& weight == other.weight
@@ -136,14 +105,14 @@ bool QFontDef::exactMatch(const QFontDef &other) const
);
}
-extern bool qt_is_gui_used;
+extern bool qt_is_tty_app;
Q_GUI_EXPORT int qt_defaultDpiX()
{
if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi))
return 96;
- if (!qt_is_gui_used)
+ if (qt_is_tty_app)
return 75;
if (const QScreen *screen = QGuiApplication::primaryScreen())
@@ -158,7 +127,7 @@ Q_GUI_EXPORT int qt_defaultDpiY()
if (QCoreApplication::instance()->testAttribute(Qt::AA_Use96Dpi))
return 96;
- if (!qt_is_gui_used)
+ if (qt_is_tty_app)
return 75;
if (const QScreen *screen = QGuiApplication::primaryScreen())
@@ -176,7 +145,7 @@ Q_GUI_EXPORT int qt_defaultDpi()
/* Helper function to convert between legacy Qt and OpenType font weights. */
static int convertWeights(int weight, bool inverted)
{
- static const QVarLengthArray<QPair<int, int>, 9> legacyToOpenTypeMap = {
+ static constexpr std::array<int, 2> legacyToOpenTypeMap[] = {
{ 0, QFont::Thin }, { 12, QFont::ExtraLight }, { 25, QFont::Light },
{ 50, QFont::Normal }, { 57, QFont::Medium }, { 63, QFont::DemiBold },
{ 75, QFont::Bold }, { 81, QFont::ExtraBold }, { 87, QFont::Black },
@@ -187,8 +156,8 @@ static int convertWeights(int weight, bool inverted)
// Go through and find the closest mapped value
for (auto mapping : legacyToOpenTypeMap) {
- const int weightOld = inverted ? mapping.second : mapping.first;
- const int weightNew = inverted ? mapping.first : mapping.second;
+ const int weightOld = mapping[ inverted];
+ const int weightNew = mapping[!inverted];
const int dist = qAbs(weightOld - weight);
if (dist < closestDist) {
result = weightNew;
@@ -208,14 +177,14 @@ static QStringList splitIntoFamilies(const QString &family)
QStringList familyList;
if (family.isEmpty())
return familyList;
- const auto list = QStringView{family}.split(QLatin1Char(','));
+ const auto list = QStringView{family}.split(u',');
const int numFamilies = list.size();
familyList.reserve(numFamilies);
for (int i = 0; i < numFamilies; ++i) {
auto str = list.at(i).trimmed();
- if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
- || (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\'')))) {
- str = str.mid(1, str.length() - 2);
+ if ((str.startsWith(u'"') && str.endsWith(u'"'))
+ || (str.startsWith(u'\'') && str.endsWith(u'\''))) {
+ str = str.mid(1, str.size() - 2);
}
familyList << str.toString();
}
@@ -247,7 +216,7 @@ QFontPrivate::QFontPrivate(const QFontPrivate &other)
strikeOut(other.strikeOut), kerning(other.kerning),
capital(other.capital), letterSpacingIsAbsolute(other.letterSpacingIsAbsolute),
letterSpacing(other.letterSpacing), wordSpacing(other.wordSpacing),
- scFont(other.scFont)
+ features(other.features), scFont(other.scFont)
{
if (scFont && scFont != this)
scFont->ref.ref();
@@ -377,9 +346,38 @@ void QFontPrivate::resolve(uint mask, const QFontPrivate *other)
wordSpacing = other->wordSpacing;
if (! (mask & QFont::CapitalizationResolved))
capital = other->capital;
+
+ if (!(mask & QFont::FeaturesResolved))
+ features = other->features;
+
+ if (!(mask & QFont::VariableAxesResolved))
+ request.variableAxisValues = other->request.variableAxisValues;
}
+bool QFontPrivate::hasVariableAxis(QFont::Tag tag, float value) const
+{
+ return request.variableAxisValues.contains(tag) && request.variableAxisValues.value(tag) == value;
+}
+void QFontPrivate::setVariableAxis(QFont::Tag tag, float value)
+{
+ request.variableAxisValues.insert(tag, value);
+}
+
+void QFontPrivate::unsetVariableAxis(QFont::Tag tag)
+{
+ request.variableAxisValues.remove(tag);
+}
+
+void QFontPrivate::setFeature(QFont::Tag tag, quint32 value)
+{
+ features.insert(tag, value);
+}
+
+void QFontPrivate::unsetFeature(QFont::Tag tag)
+{
+ features.remove(tag);
+}
QFontEngineData::QFontEngineData()
@@ -449,7 +447,7 @@ QFontEngineData::~QFontEngineData()
The attributes set in the constructor can also be set later, e.g.
setFamily(), setPointSize(), setPointSizeF(), setWeight() and
setItalic(). The remaining attributes must be set after
- contstruction, e.g. setBold(), setUnderline(), setOverline(),
+ construction, e.g. setBold(), setUnderline(), setOverline(),
setStrikeOut() and setFixedPitch(). QFontInfo objects should be
created \e after the font's attributes have been set. A QFontInfo
object will not change, even if you change the font's
@@ -494,8 +492,6 @@ QFontEngineData::~QFontEngineData()
The font matching algorithm works as follows:
\list 1
\li The specified font families (set by setFamilies()) are searched for.
- \li If not found, then if set the specified font family exists and can be used to represent
- the writing system in use, it will be selected.
\li If not, a replacement font that supports the writing system is
selected. The font matching algorithm will try to find the
best match for all the properties set in the QFont. How this is
@@ -562,10 +558,10 @@ QFontEngineData::~QFontEngineData()
For more general information on fonts, see the
\l{comp.fonts FAQ}{comp.fonts FAQ}.
- Information on encodings can be found from
- \l{Roman Czyborra's} page.
+ Information on encodings can be found from the
+ \l{UTR17} page.
- \sa QFontMetrics, QFontInfo, QFontDatabase, {Character Map Example}
+ \sa QFontMetrics, QFontInfo, QFontDatabase
*/
/*!
@@ -692,7 +688,6 @@ QFont::QFont()
}
/*!
- \deprecated
Constructs a font object with the specified \a family, \a
pointSize, \a weight and \a italic settings.
@@ -821,7 +816,7 @@ QFont &QFont::operator=(const QFont &font)
*/
QString QFont::family() const
{
- return d->request.families.isEmpty() ? QString() : d->request.families.first();
+ return d->request.families.isEmpty() ? QString() : d->request.families.constFirst();
}
/*!
@@ -835,22 +830,11 @@ QString QFont::family() const
available a family will be set using the \l{QFont}{font matching}
algorithm.
- This will split the family string on a comma and call setFamilies() with the
- resulting list. To preserve a font that uses a comma in it's name then use
- setFamilies() directly. From Qt 6.2 this behavior will no longer happen and
- \a family will be passed as a single family.
-
\sa family(), setStyleHint(), setFamilies(), families(), QFontInfo
*/
void QFont::setFamily(const QString &family)
{
-#ifdef QT_DEBUG
- if (family.contains(QLatin1Char(','))) {
- qWarning("From Qt 6.2, QFont::setFamily() will no long split the family string on the comma"
- " and will keep it as a single family");
- }
-#endif
- setFamilies(splitIntoFamilies(family));
+ setFamilies(QStringList(family));
}
/*!
@@ -939,13 +923,7 @@ int QFont::pointSize() const
\li PreferVerticalHinting
\li PreferFullHinting
\row
- \li Windows Vista (w/o Platform Update) and earlier
- \li Full hinting
- \li Full hinting
- \li Full hinting
- \li Full hinting
- \row
- \li Windows 7 and Windows Vista (w/Platform Update) and DirectWrite enabled in Qt
+ \li Windows and DirectWrite enabled in Qt
\li Full hinting
\li Vertical hinting
\li Vertical hinting
@@ -964,12 +942,6 @@ int QFont::pointSize() const
\li No hinting
\endtable
- \note Please be aware that altering the hinting preference on Windows is available through
- the DirectWrite font engine. This is available on Windows Vista after installing the platform
- update, and on Windows 7. In order to use this extension, configure Qt using -directwrite.
- The target application will then depend on the availability of DirectWrite on the target
- system.
-
*/
/*!
@@ -1065,7 +1037,8 @@ qreal QFont::pointSizeF() const
}
/*!
- Sets the font size to \a pixelSize pixels.
+ Sets the font size to \a pixelSize pixels, with a maxiumum size
+ of an unsigned 16-bit integer.
Using this function makes the font device dependent. Use
setPointSize() or setPointSizeF() to set the size of the font
@@ -1183,7 +1156,7 @@ QFont::Weight QFont::weight() const
#if QT_DEPRECATED_SINCE(6, 0)
/*!
- \deprecated Use setWeight() instead.
+ \deprecated [6.0] Use setWeight() instead.
Sets the weight of the font to \a legacyWeight using the legacy font
weight scale of Qt 5 and previous versions.
@@ -1195,7 +1168,7 @@ QFont::Weight QFont::weight() const
\note If styleName() is set, this value may be ignored for font selection.
- \sa setWeight(), weight(), legacyWeight(), QFontInfo
+ \sa setWeight(), weight(), QFontInfo
*/
void QFont::setLegacyWeight(int legacyWeight)
{
@@ -1203,7 +1176,7 @@ void QFont::setLegacyWeight(int legacyWeight)
}
/*!
- \deprecated Use weight() instead.
+ \deprecated [6.0] Use weight() instead.
Returns the weight of the font converted to the non-standard font
weight scale used in Qt 5 and earlier versions.
@@ -1561,7 +1534,7 @@ void QFont::setStyleStrategy(StyleStrategy s)
Predefined stretch values that follow the CSS naming convention. The higher
the value, the more stretched the text is.
- \value AnyStretch 0 Accept any stretch matched using the other QFont properties (added in Qt 5.8)
+ \value [since 5.8] AnyStretch 0 Accept any stretch matched using the other QFont properties
\value UltraCondensed 50
\value ExtraCondensed 62
\value Condensed 75
@@ -1799,6 +1772,7 @@ bool QFont::operator==(const QFont &f) const
&& f.d->letterSpacingIsAbsolute == d->letterSpacingIsAbsolute
&& f.d->letterSpacing == d->letterSpacing
&& f.d->wordSpacing == d->wordSpacing
+ && f.d->features == d->features
));
}
@@ -1836,7 +1810,37 @@ bool QFont::operator<(const QFont &f) const
int f1attrs = (f.d->underline << 3) + (f.d->overline << 2) + (f.d->strikeOut<<1) + f.d->kerning;
int f2attrs = (d->underline << 3) + (d->overline << 2) + (d->strikeOut<<1) + d->kerning;
- return f1attrs < f2attrs;
+ if (f1attrs != f2attrs) return f1attrs < f2attrs;
+
+ if (d->features.size() != f.d->features.size())
+ return f.d->features.size() < d->features.size();
+
+ {
+ auto it = d->features.constBegin();
+ auto jt = f.d->features.constBegin();
+ for (; it != d->features.constEnd(); ++it, ++jt) {
+ if (it.key() != jt.key())
+ return jt.key() < it.key();
+ if (it.value() != jt.value())
+ return jt.value() < it.value();
+ }
+ }
+
+ if (r1.variableAxisValues.size() != r2.variableAxisValues.size())
+ return r1.variableAxisValues.size() < r2.variableAxisValues.size();
+
+ {
+ auto it = r1.variableAxisValues.constBegin();
+ auto jt = r2.variableAxisValues.constBegin();
+ for (; it != r1.variableAxisValues.constEnd(); ++it, ++jt) {
+ if (it.key() != jt.key())
+ return jt.key() < it.key();
+ if (it.value() != jt.value())
+ return jt.value() < it.value();
+ }
+ }
+
+ return false;
}
@@ -2130,7 +2134,7 @@ QString QFont::key() const
*/
QString QFont::toString() const
{
- const QChar comma(QLatin1Char(','));
+ const QChar comma(u',');
QString fontDescription = family() + comma +
QString::number( pointSizeF()) + comma +
QString::number( pixelSize()) + comma +
@@ -2178,8 +2182,8 @@ size_t qHash(const QFont &font, size_t seed) noexcept
bool QFont::fromString(const QString &descrip)
{
const auto sr = QStringView(descrip).trimmed();
- const auto l = sr.split(QLatin1Char(','));
- const int count = l.count();
+ const auto l = sr.split(u',');
+ const int count = l.size();
if (!count || (count > 2 && count < 9) || count == 9 || count > 17 ||
l.first().isEmpty()) {
qWarning("QFont::fromString: Invalid description '%s'",
@@ -2257,6 +2261,404 @@ void QFont::cacheStatistics()
{
}
+/*!
+ \class QFont::Tag
+ \brief The QFont::Tag type provides access to advanced font features.
+ \since 6.7
+ \inmodule QtGui
+
+ QFont provides access to advanced features when shaping text. A feature is defined
+ by a tag, which can be represented as a four-character string, or as a 32bit integer
+ value. This type represents such a tag in a type-safe way. It can be constructed from
+ a four-character, 8bit string literal, or from a corresponding 32bit integer value.
+ Using a shorter or longer string literal will result in a compile-time error.
+
+ \code
+ QFont font;
+ // Correct
+ font.setFeature("frac");
+
+ // Wrong - won't compile
+ font.setFeature("fraction");
+
+ // Wrong - will produce runtime warning and fail
+ font.setFeature(u"fraction"_s);
+ \endcode
+
+ The named constructors allow to create a tag from an 32bit integer or string value,
+ and will return a \c std::nullopt when the input is invalid.
+
+ \sa QFont::setFeature(), QFont::featureTags()
+*/
+
+/*!
+ \fn QFont::Tag::Tag()
+
+ Default constructor, producing an invalid tag.
+*/
+
+/*!
+ \fn template <size_t N> QFont::Tag::Tag(const char (&str)[N]) noexcept
+
+ Constructs a tag from a string literal, \a str. The literal must be exactly four
+ characters long.
+
+ \code
+ font.setFeature("frac", 1);
+ \endcode
+
+ \sa fromString(), fromValue()
+*/
+
+/*!
+ \fn bool QFont::Tag::comparesEqual(const QFont::Tag &lhs, const QFont::Tag &rhs) noexcept
+ \fn Qt::strong_ordering QFont::Tag::compareThreeWay(const QFont::Tag &lhs, const QFont::Tag &rhs) noexcept
+
+ Compare \a lhs with \a rhs for equality and ordering.
+*/
+
+/*!
+ \fn size_t QFont::Tag::qHash(QFont::Tag key, size_t seed) noexcept
+
+ Returns the hash value for \a key, using \a seed to seed the calculation.
+*/
+
+/*!
+ \fn quint32 QFont::Tag::value() const noexcept
+
+ Returns the numerical value of this tag.
+
+ \sa isValid(), fromValue()
+*/
+
+/*!
+ \fn bool QFont::Tag::isValid() const noexcept
+
+ Returns whether the tag is valid. A tag is valid if its value is not zero.
+
+ \sa value(), fromValue(), fromString()
+*/
+
+/*!
+ \fn QByteArray QFont::Tag::toString() const noexcept
+
+ Returns the string representation of this tag as a byte array.
+
+ \sa fromString()
+*/
+
+/*!
+ \fn std::optional<QFont::Tag> QFont::Tag::fromValue(quint32 value) noexcept
+
+ Returns a tag constructed from \a value, or \c std::nullopt if the tag produced
+ would be invalid.
+
+ \sa isValid()
+*/
+
+/*!
+ Returns a tag constructed from the string in \a view. The string must be exactly
+ four characters long.
+
+ Returns \c std::nullopt if the input is not four characters long, or if the tag
+ produced would be invalid.
+
+ \sa isValid(), fromValue()
+*/
+std::optional<QFont::Tag> QFont::Tag::fromString(QAnyStringView view) noexcept
+{
+ if (view.size() != 4) {
+ qWarning("The tag name must be exactly 4 characters long!");
+ return std::nullopt;
+ }
+ const QFont::Tag maybeTag = view.visit([](auto view) {
+ using CharType = decltype(view.at(0));
+ if constexpr (std::is_same_v<CharType, char>) {
+ const char bytes[5] = { view.at(0), view.at(1), view.at(2), view.at(3), 0 };
+ return Tag(bytes);
+ } else {
+ const char bytes[5] = { view.at(0).toLatin1(), view.at(1).toLatin1(),
+ view.at(2).toLatin1(), view.at(3).toLatin1(), 0 };
+ return Tag(bytes);
+ }
+ });
+ return maybeTag.isValid() ? std::optional<Tag>(maybeTag) : std::nullopt;
+}
+
+/*!
+ \fn QDataStream &operator<<(QDataStream &, QFont::Tag)
+ \fn QDataStream &operator>>(QDataStream &, QFont::Tag &)
+ \relates QFont::Tag
+
+ Data stream operators for QFont::Tag.
+*/
+
+/*!
+ \since 6.7
+
+ Applies a \a value to the variable axis corresponding to \a tag.
+
+ Variable fonts provide a way to store multiple variations (with different weights, widths
+ or styles) in the same font file. The variations are given as floating point values for
+ a pre-defined set of parameters, called "variable axes". Specific instances are typically
+ given names by the font designer, and, in Qt, these can be selected using setStyleName()
+ just like traditional sub-families.
+
+ In some cases, it is also useful to provide arbitrary values for the different axes. For
+ instance, if a font has a Regular and Bold sub-family, you may want a weight in-between these.
+ You could then manually request this by supplying a custom value for the "wght" axis in the
+ font.
+
+ \code
+ QFont font;
+ font.setVariableAxis("wght", (QFont::Normal + QFont::Bold) / 2.0f);
+ \endcode
+
+ If the "wght" axis is supported by the font and the given value is within its defined range,
+ a font corresponding to the weight 550.0 will be provided.
+
+ There are a few standard axes than many fonts provide, such as "wght" (weight), "wdth" (width),
+ "ital" (italic) and "opsz" (optical size). They each have indivdual ranges defined in the font
+ itself. For instance, "wght" may span from 100 to 900 (QFont::Thin to QFont::Black) whereas
+ "ital" can span from 0 to 1 (from not italic to fully italic).
+
+ A font may also choose to define custom axes; the only limitation is that the name has to
+ meet the requirements for a QFont::Tag (sequence of four latin-1 characters.)
+
+ By default, no variable axes are set.
+
+ \note In order to use variable axes on Windows, the application has to run with either the
+ FreeType or DirectWrite font databases. See the documentation for
+ QGuiApplication::QGuiApplication() for more information on how to select these technologies.
+
+ \sa unsetVariableAxis
+ */
+void QFont::setVariableAxis(Tag tag, float value)
+{
+ if (tag.isValid()) {
+ if (resolve_mask & QFont::VariableAxesResolved && d->hasVariableAxis(tag, value))
+ return;
+
+ detach();
+
+ d->setVariableAxis(tag, value);
+ resolve_mask |= QFont::VariableAxesResolved;
+ }
+}
+
+/*!
+ \since 6.7
+
+ Unsets a previously set variable axis value given by \a tag.
+
+ \note If no value has previously been given for this tag, the QFont will still consider its
+ variable axes as set when resolving against other QFont values.
+
+ \sa setVariableAxis
+*/
+void QFont::unsetVariableAxis(Tag tag)
+{
+ if (tag.isValid()) {
+ detach();
+
+ d->unsetVariableAxis(tag);
+ resolve_mask |= QFont::VariableAxesResolved;
+ }
+}
+
+/*!
+ \since 6.7
+
+ Returns a list of tags for all variable axes currently set on this QFont.
+
+ See \l{QFont::}{setVariableAxis()} for more details on variable axes.
+
+ \sa QFont::Tag, setVariableAxis(), unsetVariableAxis(), isVariableAxisSet(), clearVariableAxes()
+*/
+QList<QFont::Tag> QFont::variableAxisTags() const
+{
+ return d->request.variableAxisValues.keys();
+}
+
+/*!
+ \since 6.7
+
+ Returns the value set for a specific variable axis \a tag. If the tag has not been set, 0.0 will
+ be returned instead.
+
+ See \l{QFont::}{setVariableAxis()} for more details on variable axes.
+
+ \sa QFont::Tag, setVariableAxis(), unsetVariableAxis(), isVariableAxisSet(), clearVariableAxes()
+*/
+float QFont::variableAxisValue(Tag tag) const
+{
+ return d->request.variableAxisValues.value(tag);
+}
+
+/*!
+ \since 6.7
+
+ Returns true if a value for the variable axis given by \a tag has been set on the QFont,
+ otherwise returns false.
+
+ See \l{QFont::}{setVariableAxis()} for more details on font variable axes.
+
+ \sa QFont::Tag, setVariableAxis(), unsetVariableAxis(), variableAxisValue(), clearVariableAxes()
+*/
+bool QFont::isVariableAxisSet(Tag tag) const
+{
+ return d->request.variableAxisValues.contains(tag);
+}
+
+/*!
+ \since 6.7
+
+ Clears any previously set variable axis values on the QFont.
+
+ See \l{QFont::}{setVariableAxis()} for more details on variable axes.
+
+ \sa QFont::Tag, setVariableAxis(), unsetVariableAxis(), isVariableAxisSet(), variableAxisValue()
+*/
+void QFont::clearVariableAxes()
+{
+ if (d->request.variableAxisValues.isEmpty())
+ return;
+
+ detach();
+ d->request.variableAxisValues.clear();
+}
+
+
+/*!
+ \since 6.7
+ \overload
+
+ Applies an integer value to the typographical feature specified by \a tag when shaping the
+ text. This provides advanced access to the font shaping process, and can be used to support
+ font features that are otherwise not covered in the API.
+
+ The feature is specified by a \l{QFont::Tag}{tag}, which is typically encoded from the
+ four-character feature name in the font feature map.
+
+ This integer \a value passed along with the tag in most cases represents a boolean value: A zero
+ value means the feature is disabled, and a non-zero value means it is enabled. For certain
+ font features, however, it may have other interpretations. For example, when applied to the
+ \c salt feature, the value is an index that specifies the stylistic alternative to use.
+
+ For example, the \c frac font feature will convert diagonal fractions separated with a slash
+ (such as \c 1/2) with a different representation. Typically this will involve baking the full
+ fraction into a single character width (such as \c ½).
+
+ If a font supports the \c frac feature, then it can be enabled in the shaper by setting
+ \c{features["frac"] = 1} in the font feature map.
+
+ \note By default, Qt will enable and disable certain font features based on other font
+ properties. In particular, the \c kern feature will be enabled/disabled depending on the
+ \l kerning() property of the QFont. In addition, all ligature features
+ (\c liga, \c clig, \c dlig, \c hlig) will be disabled if a \l letterSpacing() is applied,
+ but only for writing systems where the use of ligature is cosmetic. For writing systems where
+ ligatures are required, the features will remain in their default state. The values set using
+ setFeature() and related functions will override the default behavior. If, for instance,
+ the feature "kern" is set to 1, then kerning will always be enabled, regardless of whether the
+ kerning property is set to false. Similarly, if it is set to 0, then it will always be disabled.
+ To reset a font feature to its default behavior, you can unset it using unsetFeature().
+
+ \sa QFont::Tag, clearFeatures(), setFeature(), unsetFeature(), featureTags()
+*/
+void QFont::setFeature(Tag tag, quint32 value)
+{
+ if (tag.isValid()) {
+ d->detachButKeepEngineData(this);
+ d->setFeature(tag, value);
+ resolve_mask |= QFont::FeaturesResolved;
+ }
+}
+
+/*!
+ \since 6.7
+ \overload
+
+ Unsets the \a tag from the map of explicitly enabled/disabled features.
+
+ \note Even if the feature has not previously been added, this will mark the font features map
+ as modified in this QFont, so that it will take precedence when resolving against other fonts.
+
+ Unsetting an existing feature on the QFont reverts behavior to the default.
+
+ See \l setFeature() for more details on font features.
+
+ \sa QFont::Tag, clearFeatures(), setFeature(), featureTags(), featureValue()
+*/
+void QFont::unsetFeature(Tag tag)
+{
+ if (tag.isValid()) {
+ d->detachButKeepEngineData(this);
+ d->unsetFeature(tag);
+ resolve_mask |= QFont::FeaturesResolved;
+ }
+}
+
+/*!
+ \since 6.7
+
+ Returns a list of tags for all font features currently set on this QFont.
+
+ See \l{QFont::}{setFeature()} for more details on font features.
+
+ \sa QFont::Tag, setFeature(), unsetFeature(), isFeatureSet(), clearFeatures()
+*/
+QList<QFont::Tag> QFont::featureTags() const
+{
+ return d->features.keys();
+}
+
+/*!
+ \since 6.7
+
+ Returns the value set for a specific feature \a tag. If the tag has not been set, 0 will be
+ returned instead.
+
+ See \l{QFont::}{setFeature()} for more details on font features.
+
+ \sa QFont::Tag, setFeature(), unsetFeature(), featureTags(), isFeatureSet()
+*/
+quint32 QFont::featureValue(Tag tag) const
+{
+ return d->features.value(tag);
+}
+
+/*!
+ \since 6.7
+
+ Returns true if a value for the feature given by \a tag has been set on the QFont, otherwise
+ returns false.
+
+ See \l{QFont::}{setFeature()} for more details on font features.
+
+ \sa QFont::Tag, setFeature(), unsetFeature(), featureTags(), featureValue()
+*/
+bool QFont::isFeatureSet(Tag tag) const
+{
+ return d->features.contains(tag);
+}
+
+/*!
+ \since 6.7
+
+ Clears any previously set features on the QFont.
+
+ See \l{QFont::}{setFeature()} for more details on font features.
+
+ \sa QFont::Tag, setFeature(), unsetFeature(), featureTags(), featureValue()
+*/
+void QFont::clearFeatures()
+{
+ if (d->features.isEmpty())
+ return;
+
+ d->detachButKeepEngineData(this);
+ d->features.clear();
+}
extern QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style,
QFont::StyleHint styleHint, QChar::Script script);
@@ -2336,9 +2738,9 @@ void QFont::setFamilies(const QStringList &families)
QDataStream &operator<<(QDataStream &s, const QFont &font)
{
if (s.version() == 1) {
- s << font.d->request.families.first().toLatin1();
+ s << font.d->request.families.constFirst().toLatin1();
} else {
- s << font.d->request.families.first();
+ s << font.d->request.families.constFirst();
if (s.version() >= QDataStream::Qt_5_4)
s << font.d->request.styleName;
}
@@ -2388,8 +2790,16 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << (quint8)font.d->request.hintingPreference;
if (s.version() >= QDataStream::Qt_5_6)
s << (quint8)font.d->capital;
- if (s.version() >= QDataStream::Qt_5_13)
- s << font.d->request.families;
+ if (s.version() >= QDataStream::Qt_5_13) {
+ if (s.version() < QDataStream::Qt_6_0)
+ s << font.d->request.families.mid(1);
+ else
+ s << font.d->request.families;
+ }
+ if (s.version() >= QDataStream::Qt_6_6)
+ s << font.d->features;
+ if (s.version() >= QDataStream::Qt_6_7)
+ s << font.d->request.variableAxisValues;
return s;
}
@@ -2499,11 +2909,40 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
if (s.version() >= QDataStream::Qt_5_13) {
QStringList value;
s >> value;
- font.d->request.families = value;
+ if (s.version() < QDataStream::Qt_6_0)
+ font.d->request.families.append(value);
+ else
+ font.d->request.families = value;
+ }
+ if (s.version() >= QDataStream::Qt_6_6) {
+ font.d->features.clear();
+ s >> font.d->features;
}
+ if (s.version() >= QDataStream::Qt_6_7) {
+ font.d->request.variableAxisValues.clear();
+ s >> font.d->request.variableAxisValues;
+ }
+
return s;
}
+QDataStream &operator<<(QDataStream &stream, QFont::Tag tag)
+{
+ stream << tag.value();
+ return stream;
+}
+
+QDataStream &operator>>(QDataStream &stream, QFont::Tag &tag)
+{
+ quint32 value;
+ stream >> value;
+ if (const auto maybeTag = QFont::Tag::fromValue(value))
+ tag = *maybeTag;
+ else
+ stream.setStatus(QDataStream::ReadCorruptData);
+ return stream;
+}
+
#endif // QT_NO_DATASTREAM
@@ -2554,6 +2993,35 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
info object is \e not updated.
\endlist
+ \section1 Checking for the existence of a font
+
+ Sometimes it can be useful to check if a font exists before attempting
+ to use it. The most thorough way of doing so is by using \l {exactMatch()}:
+
+ \code
+ const QFont segoeFont(QLatin1String("Segoe UI"));
+ if (QFontInfo(segoeFont).exactMatch()) {
+ // Use the font...
+ }
+ \endcode
+
+ However, this deep search of families can be expensive on some platforms.
+ \c QFontDatabase::families().contains() is a faster, but less thorough
+ alternative:
+
+ \code
+ const QLatin1String segoeUiFamilyName("Segoe UI");
+ if (QFontDatabase::families().contains(segoeUiFamilyName)) {
+ const QFont segoeFont(segoeUiFamilyName);
+ // Use the font...
+ }
+ \endcode
+
+ It's less thorough because it's not a complete search: some font family
+ aliases may be missing from the list. However, this approach results in
+ faster application startup times, and so should always be preferred if
+ possible.
+
\sa QFont, QFontMetrics, QFontDatabase
*/
@@ -2570,6 +3038,8 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
Use QPainter::fontInfo() to get the font info when painting.
This will give correct results also when painting on paint device
that is not screen-compatible.
+
+ \sa {Checking for the existence of a font}
*/
QFontInfo::QFontInfo(const QFont &font)
: d(font.d)
@@ -2611,13 +3081,13 @@ QFontInfo &QFontInfo::operator=(const QFontInfo &fi)
/*!
Returns the family name of the matched window system font.
- \sa QFont::family()
+ \sa QFont::family(), {Checking for the existence of a font}
*/
QString QFontInfo::family() const
{
QFontEngine *engine = d->engineForScript(QChar::Script_Common);
Q_ASSERT(engine != nullptr);
- return engine->fontDef.families.isEmpty() ? QString() : engine->fontDef.families.first();
+ return engine->fontDef.families.isEmpty() ? QString() : engine->fontDef.families.constFirst();
}
/*!
@@ -2793,7 +3263,7 @@ bool QFontInfo::fixedPitch() const
Q_ASSERT(engine != nullptr);
#ifdef Q_OS_MAC
if (!engine->fontDef.fixedPitchComputed) {
- QChar ch[2] = { QLatin1Char('i'), QLatin1Char('m') };
+ QChar ch[2] = { u'i', u'm' };
QGlyphLayoutArray<2> g;
int l = 2;
if (!engine->stringToCMap(ch, 2, &g, &l, {}))
@@ -2840,13 +3310,15 @@ bool QFontInfo::exactMatch() const
// QFontCache
// **********************************************************************
+using namespace std::chrono_literals;
+
#ifdef QFONTCACHE_DEBUG
// fast timeouts for debugging
-static const int fast_timeout = 1000; // 1s
-static const int slow_timeout = 5000; // 5s
+static constexpr auto fast_timeout = 1s;
+static constexpr auto slow_timeout = 5s;
#else
-static const int fast_timeout = 10000; // 10s
-static const int slow_timeout = 300000; // 5m
+static constexpr auto fast_timeout = 10s;
+static constexpr auto slow_timeout = 5min;
#endif // QFONTCACHE_DEBUG
#ifndef QFONTCACHE_MIN_COST
@@ -2875,11 +3347,14 @@ void QFontCache::cleanup()
cache->setLocalData(nullptr);
}
-static QBasicAtomicInt font_cache_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+Q_CONSTINIT static QBasicAtomicInt font_cache_id = Q_BASIC_ATOMIC_INITIALIZER(0);
QFontCache::QFontCache()
: QObject(), total_cost(0), max_cost(min_cost),
- current_timestamp(0), fast(false), timer_id(-1),
+ current_timestamp(0), fast(false),
+ autoClean(QGuiApplication::instance()
+ && (QGuiApplication::instance()->thread() == QThread::currentThread())),
+ timer_id(-1),
m_id(font_cache_id.fetchAndAddRelaxed(1) + 1)
{
}
@@ -3049,10 +3524,14 @@ void QFontCache::increaseCost(uint cost)
if (total_cost > max_cost) {
max_cost = total_cost;
+ if (!autoClean)
+ return;
+
if (timer_id == -1 || ! fast) {
- FC_DEBUG(" TIMER: starting fast timer (%d ms)", fast_timeout);
+ FC_DEBUG(" TIMER: starting fast timer (%d s)", static_cast<int>(fast_timeout.count()));
- if (timer_id != -1) killTimer(timer_id);
+ if (timer_id != -1)
+ killTimer(timer_id);
timer_id = startTimer(fast_timeout);
fast = true;
}
@@ -3143,22 +3622,26 @@ void QFontCache::decreaseCache()
FC_DEBUG(" after sweep, in use %u kb, total %u kb, max %u kb, new max %u kb",
in_use_cost, total_cost, max_cost, new_max_cost);
- if (new_max_cost == max_cost) {
- if (fast) {
- FC_DEBUG(" cannot shrink cache, slowing timer");
+ if (autoClean) {
+ if (new_max_cost == max_cost) {
+ if (fast) {
+ FC_DEBUG(" cannot shrink cache, slowing timer");
- killTimer(timer_id);
- timer_id = startTimer(slow_timeout);
- fast = false;
- }
+ if (timer_id != -1) {
+ killTimer(timer_id);
+ timer_id = startTimer(slow_timeout);
+ fast = false;
+ }
- return;
- } else if (! fast) {
- FC_DEBUG(" dropping into passing gear");
+ return;
+ } else if (! fast) {
+ FC_DEBUG(" dropping into passing gear");
- killTimer(timer_id);
- timer_id = startTimer(fast_timeout);
- fast = true;
+ if (timer_id != -1)
+ killTimer(timer_id);
+ timer_id = startTimer(fast_timeout);
+ fast = true; }
+ }
}
max_cost = new_max_cost;
@@ -3336,6 +3819,15 @@ QDebug operator<<(QDebug stream, const QFont &font)
return stream;
}
+
+QDebug operator<<(QDebug debug, QFont::Tag tag)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote() << tag.toString();
+ return debug;
+}
#endif
QT_END_NAMESPACE
+
+#include "moc_qfont.cpp"
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index 87fc08dda9..ace07780b5 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -1,49 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONT_H
#define QFONT_H
+#include <QtCore/qcompare.h>
+#include <QtCore/qendian.h>
+#include <QtCore/qshareddata.h>
#include <QtGui/qtguiglobal.h>
#include <QtGui/qwindowdefs.h>
#include <QtCore/qstring.h>
-#include <QtCore/qsharedpointer.h>
QT_BEGIN_NAMESPACE
@@ -162,19 +128,22 @@ public:
HintingPreferenceResolved = 0x8000,
StyleNameResolved = 0x10000,
FamiliesResolved = 0x20000,
- AllPropertiesResolved = 0x3ffff
+ FeaturesResolved = 0x40000,
+ VariableAxesResolved = 0x80000,
+ AllPropertiesResolved = 0xfffff
};
Q_ENUM(ResolveProperties)
QFont();
+
QFont(const QString &family, int pointSize = -1, int weight = -1, bool italic = false);
explicit QFont(const QStringList &families, int pointSize = -1, int weight = -1, bool italic = false);
QFont(const QFont &font, const QPaintDevice *pd);
QFont(const QFont &font);
~QFont();
- void swap(QFont &other)
- { qSwap(d, other.d); qSwap(resolve_mask, other.resolve_mask); }
+ void swap(QFont &other) noexcept
+ { d.swap(other.d); std::swap(resolve_mask, other.resolve_mask); }
QString family() const;
void setFamily(const QString &);
@@ -241,6 +210,75 @@ public:
void setHintingPreference(HintingPreference hintingPreference);
HintingPreference hintingPreference() const;
+ struct Tag
+ {
+ constexpr Tag() = default;
+
+ template <size_t N>
+ constexpr Q_IMPLICIT Tag(const char (&str)[N]) noexcept
+ : m_value((quint32(str[0]) << 24) | (quint32(str[1]) << 16)
+ | (quint32(str[2]) << 8) | quint32(str[3]))
+ {
+ static_assert(N == 5, "The tag name must be exactly 4 characters long!");
+ }
+
+ constexpr bool isValid() const noexcept { return m_value != 0; }
+ constexpr quint32 value() const noexcept { return m_value; }
+
+ QByteArray toString() const
+ {
+ const char data[] = {
+ char((m_value & 0xff000000) >> 24),
+ char((m_value & 0x00ff0000) >> 16),
+ char((m_value & 0x0000ff00) >> 8),
+ char((m_value & 0x000000ff)) };
+ return QByteArray(data, sizeof(data));
+ }
+
+ static constexpr std::optional<Tag> fromValue(quint32 value) noexcept
+ {
+ Tag maybeTag;
+ maybeTag.m_value = value;
+ return maybeTag.isValid() ? std::optional<Tag>(maybeTag) : std::nullopt;
+ }
+ Q_GUI_EXPORT static std::optional<Tag> fromString(QAnyStringView view) noexcept;
+
+#ifndef QT_NO_DATASTREAM
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, Tag);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, Tag &);
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug debug, Tag tag);
+#endif
+
+ friend constexpr size_t qHash(Tag key, size_t seed = 0) noexcept
+ { return qHash(key.value(), seed); }
+
+ private:
+ friend constexpr bool comparesEqual(const Tag &lhs, const Tag &rhs) noexcept
+ { return lhs.m_value == rhs.m_value; }
+ friend constexpr Qt::strong_ordering compareThreeWay(const Tag &lhs, const Tag &rhs) noexcept
+ { return Qt::compareThreeWay(lhs.m_value, rhs.m_value); }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QFont::Tag)
+
+ quint32 m_value = 0;
+ };
+
+ void setFeature(Tag tag, quint32 value);
+ void unsetFeature(Tag tag);
+ quint32 featureValue(Tag tag) const;
+ bool isFeatureSet(Tag tag) const;
+ QList<Tag> featureTags() const;
+ void clearFeatures();
+
+ void setVariableAxis(Tag tag, float value);
+ void unsetVariableAxis(Tag tag);
+ bool isVariableAxisSet(Tag tag) const;
+ float variableAxisValue(Tag tag) const;
+ void clearVariableAxes();
+ QList<Tag> variableAxisTags() const;
+
// dupicated from QFontInfo
bool exactMatch() const;
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index f285111c4a..b674e71103 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONT_P_H
#define QFONT_P_H
@@ -91,6 +55,7 @@ struct QFontDef
QString styleName;
QStringList fallBackFamilies;
+ QMap<QFont::Tag, float> variableAxisValues;
qreal pointSize;
qreal pixelSize;
@@ -121,6 +86,7 @@ struct QFontDef
&& families == other.families
&& styleName == other.styleName
&& hintingPreference == other.hintingPreference
+ && variableAxisValues == other.variableAxisValues
;
}
inline bool operator<(const QFontDef &other) const
@@ -139,6 +105,22 @@ struct QFontDef
if (ignorePitch != other.ignorePitch) return ignorePitch < other.ignorePitch;
if (fixedPitch != other.fixedPitch) return fixedPitch < other.fixedPitch;
+ if (variableAxisValues != other.variableAxisValues) {
+ if (variableAxisValues.size() != other.variableAxisValues.size())
+ return variableAxisValues.size() < other.variableAxisValues.size();
+
+ {
+ auto it = variableAxisValues.constBegin();
+ auto jt = other.variableAxisValues.constBegin();
+ for (; it != variableAxisValues.constEnd(); ++it, ++jt) {
+ if (it.key() != jt.key())
+ return jt.key() < it.key();
+ if (it.value() != jt.value())
+ return jt.value() < it.value();
+ }
+ }
+ }
+
return false;
}
};
@@ -156,7 +138,9 @@ inline size_t qHash(const QFontDef &fd, size_t seed = 0) noexcept
fd.fixedPitch,
fd.families,
fd.styleName,
- fd.hintingPreference);
+ fd.hintingPreference,
+ fd.variableAxisValues.keys(),
+ fd.variableAxisValues.values());
}
class QFontEngineData
@@ -200,6 +184,7 @@ public:
QFixed letterSpacing;
QFixed wordSpacing;
+ QHash<QFont::Tag, quint32> features;
mutable QFontPrivate *scFont;
QFont smallCapsFont() const { return QFont(smallCapsFontPrivate()); }
@@ -214,6 +199,13 @@ public:
static void detachButKeepEngineData(QFont *font);
+ void setFeature(QFont::Tag tag, quint32 value);
+ void unsetFeature(QFont::Tag tag);
+
+ void setVariableAxis(QFont::Tag tag, float value);
+ void unsetVariableAxis(QFont::Tag tag);
+ bool hasVariableAxis(QFont::Tag tag, float value) const;
+
private:
QFontPrivate &operator=(const QFontPrivate &) { return *this; }
};
@@ -295,6 +287,7 @@ private:
uint total_cost, max_cost;
uint current_timestamp;
bool fast;
+ const bool autoClean;
int timer_id;
const int m_id;
};
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 3eb59e0f04..d3a13d801b 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfontdatabase.h"
#include "qfontdatabase_p.h"
@@ -62,8 +26,14 @@
#include <qtgui_tracepoints_p.h>
+#ifdef Q_OS_WIN
+#include <QtGui/private/qwindowsfontdatabasebase_p.h>
+#endif
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcFontDb, "qt.text.font.db")
Q_LOGGING_CATEGORY(lcFontMatch, "qt.text.font.match")
@@ -78,6 +48,11 @@ Q_AUTOTEST_EXPORT void qt_setQtEnableTestFont(bool value)
}
#endif
+Q_TRACE_POINT(qtgui, QFontDatabase_loadEngine, const QString &families, int pointSize);
+Q_TRACE_POINT(qtgui, QFontDatabasePrivate_addAppFont, const QString &fileName);
+Q_TRACE_POINT(qtgui, QFontDatabase_addApplicationFont, const QString &fileName);
+Q_TRACE_POINT(qtgui, QFontDatabase_load, const QString &family, int pointSize);
+
static int getFontWeight(const QString &weightString)
{
QString s = weightString.toLower();
@@ -90,41 +65,40 @@ static int getFontWeight(const QString &weightString)
//
// A simple string test is the cheapest, so let's do that first.
// Test in decreasing order of commonness
- if (s == QLatin1String("normal") || s == QLatin1String("regular"))
+ if (s == "normal"_L1 || s == "regular"_L1)
return QFont::Normal;
- if (s == QLatin1String("bold"))
+ if (s == "bold"_L1)
return QFont::Bold;
- if (s == QLatin1String("semibold") || s == QLatin1String("semi bold")
- || s == QLatin1String("demibold") || s == QLatin1String("demi bold"))
+ if (s == "semibold"_L1 || s == "semi bold"_L1 || s == "demibold"_L1 || s == "demi bold"_L1)
return QFont::DemiBold;
- if (s == QLatin1String("medium"))
+ if (s == "medium"_L1)
return QFont::Medium;
- if (s == QLatin1String("black"))
+ if (s == "black"_L1)
return QFont::Black;
- if (s == QLatin1String("light"))
+ if (s == "light"_L1)
return QFont::Light;
- if (s == QLatin1String("thin"))
+ if (s == "thin"_L1)
return QFont::Thin;
const QStringView s2 = QStringView{s}.mid(2);
- if (s.startsWith(QLatin1String("ex")) || s.startsWith(QLatin1String("ul"))) {
- if (s2 == QLatin1String("tralight") || s == QLatin1String("tra light"))
+ if (s.startsWith("ex"_L1) || s.startsWith("ul"_L1)) {
+ if (s2 == "tralight"_L1 || s == "tra light"_L1)
return QFont::ExtraLight;
- if (s2 == QLatin1String("trabold") || s2 == QLatin1String("tra bold"))
+ if (s2 == "trabold"_L1 || s2 == "tra bold"_L1)
return QFont::ExtraBold;
}
// Next up, let's see if contains() matches: slightly more expensive, but
// still fast enough.
- if (s.contains(QLatin1String("bold"))) {
- if (s.contains(QLatin1String("demi")))
+ if (s.contains("bold"_L1)) {
+ if (s.contains("demi"_L1))
return QFont::DemiBold;
return QFont::Bold;
}
- if (s.contains(QLatin1String("thin")))
+ if (s.contains("thin"_L1))
return QFont::Thin;
- if (s.contains(QLatin1String("light")))
+ if (s.contains("light"_L1))
return QFont::Light;
- if (s.contains(QLatin1String("black")))
+ if (s.contains("black"_L1))
return QFont::Black;
// Now, we perform string translations & comparisons with those.
@@ -181,9 +155,9 @@ QtFontStyle::Key::Key(const QString &styleString)
if (!styleString.isEmpty()) {
// First the straightforward no-translation checks, these are fast.
- if (styleString.contains(QLatin1String("Italic")))
+ if (styleString.contains("Italic"_L1))
style = QFont::StyleItalic;
- else if (styleString.contains(QLatin1String("Oblique")))
+ else if (styleString.contains("Oblique"_L1))
style = QFont::StyleOblique;
// Then the translation checks. These aren't as fast.
@@ -285,31 +259,46 @@ bool QtFontFamily::matchesFamilyName(const QString &familyName) const
return equalsCaseInsensitive(name, familyName) || aliases.contains(familyName, Qt::CaseInsensitive);
}
-void QtFontFamily::ensurePopulated()
+bool QtFontFamily::ensurePopulated()
{
if (populated)
- return;
+ return true;
QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamily(name);
- Q_ASSERT_X(populated, Q_FUNC_INFO, qPrintable(name));
+ return populated;
+}
+
+void QFontDatabasePrivate::clearFamilies()
+{
+ while (count--)
+ delete families[count];
+ ::free(families);
+ families = nullptr;
+ count = 0;
+
+ for (auto &font : applicationFonts)
+ font.properties.clear(); // Unpopulate
+
+ populated = false;
+ // don't clear the memory fonts!
}
void QFontDatabasePrivate::invalidate()
{
+ qCDebug(lcFontDb) << "Invalidating font database";
+
QFontCache::instance()->clear();
fallbacksCache.clear();
- free();
+ clearFamilies();
QGuiApplicationPrivate::platformIntegration()->fontDatabase()->invalidate();
- emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged();
+ emit qGuiApp->fontDatabaseChanged();
}
-QtFontFamily *QFontDatabasePrivate::family(const QString &family, FamilyRequestFlags flags)
+QtFontFamily *QFontDatabasePrivate::family(const QString &f, FamilyRequestFlags flags)
{
QtFontFamily *fam = nullptr;
- const QString f = family.trimmed();
-
int low = 0;
int high = count;
int pos = count / 2;
@@ -347,8 +336,10 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &family, FamilyRequestF
fam = families[pos];
}
- if (fam && (flags & EnsurePopulated))
- fam->ensurePopulated();
+ if (fam && (flags & EnsurePopulated)) {
+ if (!fam->ensurePopulated())
+ return nullptr;
+ }
return fam;
}
@@ -438,11 +429,11 @@ Q_GUI_EXPORT QFontDatabase::WritingSystem qt_writing_system_for_script(int scrip
*/
static void parseFontName(const QString &name, QString &foundry, QString &family)
{
- int i = name.indexOf(QLatin1Char('['));
- int li = name.lastIndexOf(QLatin1Char(']'));
+ int i = name.indexOf(u'[');
+ int li = name.lastIndexOf(u']');
if (i >= 0 && li >= 0 && i < li) {
foundry = name.mid(i + 1, li - i - 1);
- if (i > 0 && name[i - 1] == QLatin1Char(' '))
+ if (i > 0 && name[i - 1] == u' ')
i--;
family = name.left(i);
} else {
@@ -453,7 +444,7 @@ static void parseFontName(const QString &name, QString &foundry, QString &family
// capitalize the family/foundry names
bool space = true;
QChar *s = family.data();
- int len = family.length();
+ int len = family.size();
while(len--) {
if (space) *s = s->toUpper();
space = s->isSpace();
@@ -462,7 +453,7 @@ static void parseFontName(const QString &name, QString &foundry, QString &family
space = true;
s = foundry.data();
- len = foundry.length();
+ len = foundry.size();
while(len--) {
if (space) *s = s->toUpper();
space = s->isSpace();
@@ -485,7 +476,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe
QString family;
family = desc.family->name;
if (! desc.foundry->name.isEmpty() && desc.family->count > 1)
- family += QLatin1String(" [") + desc.foundry->name + QLatin1Char(']');
+ family += " ["_L1 + desc.foundry->name + u']';
fontDef->families = QStringList(family);
if (desc.style->smoothScalable
@@ -521,17 +512,14 @@ static QStringList familyList(const QFontDef &req)
return family_list;
}
-Q_GLOBAL_STATIC(QFontDatabasePrivate, privateDb)
Q_GLOBAL_STATIC(QRecursiveMutex, fontDatabaseMutex)
// used in qguiapplication.cpp
void qt_cleanupFontDatabase()
{
- QFontDatabasePrivate *db = privateDb();
- if (db) {
- db->fallbacksCache.clear();
- db->free();
- }
+ auto *db = QFontDatabasePrivate::instance();
+ db->fallbacksCache.clear();
+ db->clearFamilies();
}
// used in qfont.cpp
@@ -542,7 +530,8 @@ QRecursiveMutex *qt_fontdatabase_mutex()
QFontDatabasePrivate *QFontDatabasePrivate::instance()
{
- return privateDb();
+ static QFontDatabasePrivate instance;
+ return &instance;
}
void qt_registerFont(const QString &familyName, const QString &stylename,
@@ -551,7 +540,7 @@ void qt_registerFont(const QString &familyName, const QString &stylename,
bool scalable, int pixelSize, bool fixedPitch,
const QSupportedWritingSystems &writingSystems, void *handle)
{
- QFontDatabasePrivate *d = privateDb();
+ auto *d = QFontDatabasePrivate::instance();
qCDebug(lcFontDb) << "Adding font: familyName" << familyName << "stylename" << stylename << "weight" << weight
<< "style" << style << "pixelSize" << pixelSize << "antialiased" << antialiased << "fixed" << fixedPitch;
QtFontStyle::Key styleKey;
@@ -582,8 +571,10 @@ void qt_registerFont(const QString &familyName, const QString &stylename,
void qt_registerFontFamily(const QString &familyName)
{
+ qCDebug(lcFontDb) << "Registering family" << familyName;
+
// Create uninitialized/unpopulated family
- privateDb()->family(familyName, QFontDatabasePrivate::EnsureCreated);
+ QFontDatabasePrivate::instance()->family(familyName, QFontDatabasePrivate::EnsureCreated);
}
void qt_registerAliasToFontFamily(const QString &familyName, const QString &alias)
@@ -591,7 +582,9 @@ void qt_registerAliasToFontFamily(const QString &familyName, const QString &alia
if (alias.isEmpty())
return;
- QFontDatabasePrivate *d = privateDb();
+ qCDebug(lcFontDb) << "Registering alias" << alias << "to family" << familyName;
+
+ auto *d = QFontDatabasePrivate::instance();
QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::RequestFamily);
if (!f)
return;
@@ -605,7 +598,7 @@ void qt_registerAliasToFontFamily(const QString &familyName, const QString &alia
QString qt_resolveFontFamilyAlias(const QString &alias)
{
if (!alias.isEmpty()) {
- const QFontDatabasePrivate *d = privateDb();
+ const auto *d = QFontDatabasePrivate::instance();
for (int i = 0; i < d->count; ++i)
if (d->families[i]->matchesFamilyName(alias))
return d->families[i]->name;
@@ -615,7 +608,7 @@ QString qt_resolveFontFamilyAlias(const QString &alias)
bool qt_isFontFamilyPopulated(const QString &familyName)
{
- QFontDatabasePrivate *d = privateDb();
+ auto *d = QFontDatabasePrivate::instance();
QtFontFamily *f = d->family(familyName, QFontDatabasePrivate::RequestFamily);
return f != nullptr && f->populated;
}
@@ -639,7 +632,7 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
if (writingSystem >= QFontDatabase::WritingSystemsCount)
writingSystem = QFontDatabase::Any;
- QFontDatabasePrivate *db = privateDb();
+ auto *db = QFontDatabasePrivate::instance();
for (int i = 0; i < db->count; ++i) {
QtFontFamily *f = db->families[i];
@@ -654,7 +647,7 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
for (int k = 0; k < foundry->count; ++k) {
QString name = foundry->name.isEmpty()
? f->name
- : f->name + QLatin1String(" [") + foundry->name + QLatin1Char(']');
+ : f->name + " ["_L1 + foundry->name + u']';
if (style == foundry->styles[k]->key.style)
preferredFallbacks.append(name);
else
@@ -666,13 +659,10 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo
return preferredFallbacks + otherFallbacks;
}
-static void initializeDb();
-
static QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script)
{
- QFontDatabasePrivate *db = privateDb();
- if (!db->count)
- initializeDb();
+ QMutexLocker locker(fontDatabaseMutex());
+ auto *db = QFontDatabasePrivate::ensureFontDatabase();
const QtFontFallbacksCacheKey cacheKey = { family, style, styleHint, script };
@@ -680,7 +670,8 @@ static QStringList fallbacksForFamily(const QString &family, QFont::Style style,
return *fallbacks;
// make sure that the db has all fallback families
- QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
+ QStringList userFallbacks = db->applicationFallbackFontFamilies.value(script == QChar::Script_Common ? QChar::Script_Latin : script);
+ QStringList retList = userFallbacks + QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
QStringList::iterator i;
for (i = retList.begin(); i != retList.end(); ++i) {
@@ -708,31 +699,7 @@ QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFo
return fallbacksForFamily(family, style, styleHint, script);
}
-static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt);
-
-static void initializeDb()
-{
- QFontDatabasePrivate *db = privateDb();
-
- // init by asking for the platformfontdb for the first time or after invalidation
- if (!db->count) {
- QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase();
- for (int i = 0; i < db->applicationFonts.count(); i++) {
- if (!db->applicationFonts.at(i).properties.isEmpty())
- registerFont(&db->applicationFonts[i]);
- }
- }
-}
-
-static inline void load(const QString & = QString(), int = -1)
-{
- // Only initialize the database if it has been cleared or not initialized yet
- if (!privateDb()->count)
- initializeDb();
-}
-
-static
-QFontEngine *loadSingleEngine(int script,
+QFontEngine *QFontDatabasePrivate::loadSingleEngine(int script,
const QFontDef &request,
QtFontFamily *family, QtFontFoundry *foundry,
QtFontStyle *style, QtFontSize *size)
@@ -767,7 +734,7 @@ QFontEngine *loadSingleEngine(int script,
// Also check for OpenType tables when using complex scripts
if (Q_UNLIKELY(!engine->supportsScript(QChar::Script(script)))) {
qWarning(" OpenType support missing for \"%s\", script %d",
- qPrintable(def.families.first()), script);
+ qPrintable(def.families.constFirst()), script);
return nullptr;
}
@@ -783,7 +750,7 @@ QFontEngine *loadSingleEngine(int script,
if (style->key.stretch != 0 && request.stretch != 0
&& (request.styleName.isEmpty() || request.styleName != style->styleName)) {
def.stretch = (request.stretch * 100 + style->key.stretch / 2) / style->key.stretch;
- } else {
+ } else if (request.stretch == QFont::AnyStretch) {
def.stretch = 100;
}
@@ -792,7 +759,7 @@ QFontEngine *loadSingleEngine(int script,
// Also check for OpenType tables when using complex scripts
if (!engine->supportsScript(QChar::Script(script))) {
qWarning(" OpenType support missing for \"%s\", script %d",
- +qPrintable(def.families.first()), script);
+ +qPrintable(def.families.constFirst()), script);
if (engine->ref.loadRelaxed() == 0)
delete engine;
return nullptr;
@@ -812,15 +779,14 @@ QFontEngine *loadSingleEngine(int script,
return engine;
}
-static
-QFontEngine *loadEngine(int script, const QFontDef &request,
+QFontEngine *QFontDatabasePrivate::loadEngine(int script, const QFontDef &request,
QtFontFamily *family, QtFontFoundry *foundry,
QtFontStyle *style, QtFontSize *size)
{
QFontEngine *engine = loadSingleEngine(script, request, family, foundry, style, size);
if (engine && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) {
- Q_TRACE(QFontDatabase_loadEngine, request.families, request.pointSize);
+ Q_TRACE(QFontDatabase_loadEngine, request.families.join(QLatin1Char(';')), request.pointSize);
QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script));
@@ -859,11 +825,6 @@ QtFontStyle::~QtFontStyle()
free(pixelSizes);
}
-static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
-{
- QGuiApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data, fnt->fileName, fnt);
-}
-
static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &styleKey,
const QString &styleName = QString())
{
@@ -904,11 +865,10 @@ static QtFontStyle *bestStyle(QtFontFoundry *foundry, const QtFontStyle::Key &st
}
-static
-unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
+unsigned int QFontDatabasePrivate::bestFoundry(int script, unsigned int score, int styleStrategy,
const QtFontFamily *family, const QString &foundry_name,
QtFontStyle::Key styleKey, int pixelSize, char pitch,
- QtFontDesc *desc, const QString &styleName = QString())
+ QtFontDesc *desc, const QString &styleName)
{
Q_UNUSED(script);
Q_UNUSED(pitch);
@@ -1051,9 +1011,9 @@ static bool matchFamilyName(const QString &familyName, QtFontFamily *f)
Tries to find the best match for a given request and family/foundry
*/
-static int match(int script, const QFontDef &request,
- const QString &family_name, const QString &foundry_name,
- QtFontDesc *desc, const QList<int> &blacklistedFamilies)
+int QFontDatabasePrivate::match(int script, const QFontDef &request, const QString &family_name,
+ const QString &foundry_name, QtFontDesc *desc, const QList<int> &blacklistedFamilies,
+ unsigned int *resultingScore)
{
int result = -1;
@@ -1065,16 +1025,18 @@ static int match(int script, const QFontDef &request,
char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p';
- qCDebug(lcFontMatch, "QFontDatabase::match\n"
+ qCDebug(lcFontMatch, "QFontDatabasePrivate::match\n"
" request:\n"
" family: %s [%s], script: %d\n"
+ " styleName: %s\n"
" weight: %d, style: %d\n"
" stretch: %d\n"
" pixelSize: %g\n"
" pitch: %c",
family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(),
- foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(),
- script, request.weight, request.style, request.stretch, request.pixelSize, pitch);
+ foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(), script,
+ request.styleName.isEmpty() ? "-- any --" : request.styleName.toLatin1().constData(),
+ request.weight, request.style, request.stretch, request.pixelSize, pitch);
desc->family = nullptr;
desc->foundry = nullptr;
@@ -1083,13 +1045,14 @@ static int match(int script, const QFontDef &request,
unsigned int score = ~0u;
- load(family_name, script);
+ QMutexLocker locker(fontDatabaseMutex());
+ QFontDatabasePrivate::ensureFontDatabase();
auto writingSystem = qt_writing_system_for_script(script);
if (writingSystem >= QFontDatabase::WritingSystemsCount)
writingSystem = QFontDatabase::Any;
- QFontDatabasePrivate *db = privateDb();
+ auto *db = QFontDatabasePrivate::instance();
for (int x = 0; x < db->count; ++x) {
if (blacklistedFamilies.contains(x))
continue;
@@ -1098,7 +1061,8 @@ static int match(int script, const QFontDef &request,
if (!matchFamilyName(family_name, test.family))
continue;
- test.family->ensurePopulated();
+ if (!test.family->ensurePopulated())
+ continue;
// Check if family is supported in the script we want
if (writingSystem != QFontDatabase::Any && !familySupportsWritingSystem(test.family, writingSystem))
@@ -1126,6 +1090,10 @@ static int match(int script, const QFontDef &request,
if (newscore < 10) // xlfd instead of FT... just accept it
break;
}
+
+ if (resultingScore != nullptr)
+ *resultingScore = score;
+
return result;
}
@@ -1153,9 +1121,9 @@ static QString styleStringHelper(int weight, QFont::Style style)
}
if (style == QFont::StyleItalic)
- result += QLatin1Char(' ') + QCoreApplication::translate("QFontDatabase", "Italic");
+ result += u' ' + QCoreApplication::translate("QFontDatabase", "Italic");
else if (style == QFont::StyleOblique)
- result += QLatin1Char(' ') + QCoreApplication::translate("QFontDatabase", "Oblique");
+ result += u' ' + QCoreApplication::translate("QFontDatabase", "Oblique");
if (result.isEmpty())
result = QCoreApplication::translate("QFontDatabase", "Normal", "The Normal or Regular font weight");
@@ -1234,12 +1202,12 @@ QString QFontDatabase::styleString(const QFontInfo &fontInfo)
each combination of family and style, displaying this information
in a tree view.
- \sa QFont, QFontInfo, QFontMetrics, {Character Map Example}
+ \sa QFont, QFontInfo, QFontMetrics
*/
/*!
\fn QFontDatabase::QFontDatabase()
- \deprecated Call the class methods as static functions instead.
+ \deprecated [6.0] Call the class methods as static functions instead.
Creates a font database object.
*/
@@ -1298,6 +1266,56 @@ QString QFontDatabase::styleString(const QFontInfo &fontInfo)
*/
/*!
+ \class QFontDatabasePrivate
+ \internal
+
+ Singleton implementation of the public QFontDatabase APIs,
+ accessed through QFontDatabasePrivate::instance().
+
+ The database is organized in multiple levels:
+
+ - QFontDatabasePrivate::families
+ - QtFontFamily::foundries
+ - QtFontFoundry::styles
+ - QtFontStyle::sizes
+ - QtFontSize::pixelSize
+
+ The font database is the single source of truth when doing
+ font matching, so the database must be sufficiently filled
+ before attempting a match.
+
+ The database is populated (filled) from two sources:
+
+ 1. The system (platform's) view of the available fonts
+
+ Initiated via QFontDatabasePrivate::populateFontDatabase().
+
+ a. Can be registered lazily by family only, by calling
+ QPlatformFontDatabase::registerFontFamily(), and later
+ populated via QPlatformFontDatabase::populateFamily().
+
+ b. Or fully registered with all styles, by calling
+ QPlatformFontDatabase::registerFont().
+
+ 2. The fonts registered by the application via Qt APIs
+
+ Initiated via QFontDatabase::addApplicationFont() and
+ QFontDatabase::addApplicationFontFromData().
+
+ Application fonts are always fully registered when added.
+
+ Fonts can be added at any time, so the database may grow even
+ after QFontDatabasePrivate::populateFontDatabase() has been
+ completed.
+
+ The database does not support granular removal of fonts,
+ so if the system fonts change, or an application font is
+ removed, the font database will be cleared and then filled
+ from scratch, via QFontDatabasePrivate:invalidate() and
+ QFontDatabasePrivate::ensureFontDatabase().
+*/
+
+/*!
\internal
Initializes the font database if necessary and returns its
@@ -1305,12 +1323,29 @@ QString QFontDatabase::styleString(const QFontInfo &fontInfo)
*/
QFontDatabasePrivate *QFontDatabasePrivate::ensureFontDatabase()
{
- QFontDatabasePrivate *d = privateDb();
- if (d->count == 0) {
+ auto *d = QFontDatabasePrivate::instance();
+ if (!d->populated) {
+ // The font database may have been partially populated, but to ensure
+ // we can answer queries for any platform- or user-provided family we
+ // need to fully populate it now.
+ qCDebug(lcFontDb) << "Populating font database";
+
if (Q_UNLIKELY(qGuiApp == nullptr || QGuiApplicationPrivate::platformIntegration() == nullptr))
qFatal("QFontDatabase: Must construct a QGuiApplication before accessing QFontDatabase");
- initializeDb();
+ auto *platformFontDatabase = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
+ platformFontDatabase->populateFontDatabase();
+
+ for (int i = 0; i < d->applicationFonts.size(); i++) {
+ auto *font = &d->applicationFonts[i];
+ if (!font->isNull() && !font->isPopulated())
+ platformFontDatabase->addApplicationFont(font->data, font->fileName, font);
+ }
+
+ // Note: Both application fonts and platform fonts may be added
+ // after this initial population, so the only thing we are tracking
+ // is whether we've done our part in ensuring a filled font database.
+ d->populated = true;
}
return d;
}
@@ -1327,14 +1362,13 @@ QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems()
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)();
-
quint64 writingSystemsFound = 0;
static_assert(WritingSystemsCount < 64);
for (int i = 0; i < d->count; ++i) {
QtFontFamily *family = d->families[i];
- family->ensurePopulated();
+ if (!family->ensurePopulated())
+ continue;
if (family->count == 0)
continue;
@@ -1371,8 +1405,6 @@ QList<QFontDatabase::WritingSystem> QFontDatabase::writingSystems(const QString
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)();
-
QList<WritingSystem> list;
QtFontFamily *f = d->family(familyName);
if (!f || f->count == 0)
@@ -1402,15 +1434,14 @@ QStringList QFontDatabase::families(WritingSystem writingSystem)
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)();
-
QStringList flist;
for (int i = 0; i < d->count; i++) {
QtFontFamily *f = d->families[i];
if (f->populated && f->count == 0)
continue;
if (writingSystem != Any) {
- f->ensurePopulated();
+ if (!f->ensurePopulated())
+ continue;
if (f->writingSystems[writingSystem] != QtFontFamily::Supported)
continue;
}
@@ -1421,9 +1452,9 @@ QStringList QFontDatabase::families(WritingSystem writingSystem)
QString str = f->name;
QString foundry = f->foundries[j]->name;
if (!foundry.isEmpty()) {
- str += QLatin1String(" [");
+ str += " ["_L1;
str += foundry;
- str += QLatin1Char(']');
+ str += u']';
}
flist.append(str);
}
@@ -1447,8 +1478,6 @@ QStringList QFontDatabase::styles(const QString &family)
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)(familyName);
-
QStringList l;
QtFontFamily *f = d->family(familyName);
if (!f)
@@ -1492,8 +1521,6 @@ bool QFontDatabase::isFixedPitch(const QString &family,
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)(familyName);
-
QtFontFamily *f = d->family(familyName);
return (f && f->fixedPitch);
}
@@ -1518,8 +1545,6 @@ bool QFontDatabase::isBitmapScalable(const QString &family,
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)(familyName);
-
QtFontFamily *f = d->family(familyName);
if (!f) return bitmapScalable;
@@ -1559,26 +1584,24 @@ bool QFontDatabase::isSmoothlyScalable(const QString &family, const QString &sty
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)(familyName);
-
QtFontFamily *f = d->family(familyName);
if (!f) {
for (int i = 0; i < d->count; i++) {
if (d->families[i]->matchesFamilyName(familyName)) {
f = d->families[i];
- f->ensurePopulated();
- break;
+ if (f->ensurePopulated())
+ break;
}
}
}
if (!f) return smoothScalable;
- QtFontStyle::Key styleKey(style);
+ const QtFontStyle::Key styleKey(style);
for (int j = 0; j < f->count; j++) {
QtFontFoundry *foundry = f->foundries[j];
if (foundryName.isEmpty() || foundry->name.compare(foundryName, Qt::CaseInsensitive) == 0) {
for (int k = 0; k < foundry->count; k++) {
- QtFontStyle *fontStyle = foundry->styles[k];
+ const QtFontStyle *fontStyle = foundry->styles[k];
smoothScalable =
fontStyle->smoothScalable
&& ((style.isEmpty()
@@ -1631,8 +1654,6 @@ QList<int> QFontDatabase::pointSizes(const QString &family,
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)(familyName);
-
QList<int> sizes;
QtFontFamily *fam = d->family(familyName);
@@ -1685,8 +1706,6 @@ QFont QFontDatabase::font(const QString &family, const QString &style,
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)(familyName);
-
QtFontFoundry allStyles(foundryName);
QtFontFamily *f = d->family(familyName);
if (!f) return QGuiApplication::font();
@@ -1734,8 +1753,6 @@ QList<int> QFontDatabase::smoothSizes(const QString &family,
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)(familyName);
-
QList<int> sizes;
QtFontFamily *fam = d->family(familyName);
@@ -1800,8 +1817,6 @@ bool QFontDatabase::italic(const QString &family, const QString &style)
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)(familyName);
-
QtFontFoundry allStyles(foundryName);
QtFontFamily *f = d->family(familyName);
if (!f) return false;
@@ -1835,8 +1850,6 @@ bool QFontDatabase::bold(const QString &family,
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)(familyName);
-
QtFontFoundry allStyles(foundryName);
QtFontFamily *f = d->family(familyName);
if (!f) return false;
@@ -1872,8 +1885,6 @@ int QFontDatabase::weight(const QString &family,
QMutexLocker locker(fontDatabaseMutex());
QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
- QT_PREPEND_NAMESPACE(load)(familyName);
-
QtFontFoundry allStyles(foundryName);
QtFontFamily *f = d->family(familyName);
if (!f) return -1;
@@ -1899,7 +1910,19 @@ bool QFontDatabase::hasFamily(const QString &family)
QString parsedFamily, foundry;
parseFontName(family, foundry, parsedFamily);
const QString familyAlias = QFontDatabasePrivate::resolveFontFamilyAlias(parsedFamily);
- return families().contains(familyAlias, Qt::CaseInsensitive);
+
+ QMutexLocker locker(fontDatabaseMutex());
+ QFontDatabasePrivate *d = QFontDatabasePrivate::ensureFontDatabase();
+
+ for (int i = 0; i < d->count; i++) {
+ QtFontFamily *f = d->families[i];
+ if (f->populated && f->count == 0)
+ continue;
+ if (familyAlias.compare(f->name, Qt::CaseInsensitive) == 0)
+ return true;
+ }
+
+ return false;
}
@@ -2038,90 +2061,87 @@ QString QFontDatabase::writingSystemName(WritingSystem writingSystem)
return QCoreApplication::translate("QFontDatabase", name);
}
-static QStringView writing_system_sample(QFontDatabase::WritingSystem writingSystem)
-{
- switch (writingSystem) {
- case QFontDatabase::Any:
- case QFontDatabase::Symbol:
- // show only ascii characters
- return u"AaBbzZ";
- case QFontDatabase::Latin:
- // This is cheating... we only show latin-1 characters so that we don't
- // end up loading lots of fonts - at least on X11...
- return u"Aa\x00C3\x00E1Zz";
- case QFontDatabase::Greek:
- return u"\x0393\x03B1\x03A9\x03C9";
- case QFontDatabase::Cyrillic:
- return u"\x0414\x0434\x0436\x044f";
- case QFontDatabase::Armenian:
- return u"\x053f\x054f\x056f\x057f";
- case QFontDatabase::Hebrew:
- return u"\x05D0\x05D1\x05D2\x05D3";
- case QFontDatabase::Arabic:
- return u"\x0623\x0628\x062C\x062F\x064A\x0629\x0020\x0639\x0631\x0628\x064A\x0629";
- case QFontDatabase::Syriac:
- return u"\x0715\x0725\x0716\x0726";
- case QFontDatabase::Thaana:
- return u"\x0784\x0794\x078c\x078d";
- case QFontDatabase::Devanagari:
- return u"\x0905\x0915\x0925\x0935";
- case QFontDatabase::Bengali:
- return u"\x0986\x0996\x09a6\x09b6";
- case QFontDatabase::Gurmukhi:
- return u"\x0a05\x0a15\x0a25\x0a35";
- case QFontDatabase::Gujarati:
- return u"\x0a85\x0a95\x0aa5\x0ab5";
- case QFontDatabase::Oriya:
- return u"\x0b06\x0b16\x0b2b\x0b36";
- case QFontDatabase::Tamil:
- return u"\x0b89\x0b99\x0ba9\x0bb9";
- case QFontDatabase::Telugu:
- return u"\x0c05\x0c15\x0c25\x0c35";
- case QFontDatabase::Kannada:
- return u"\x0c85\x0c95\x0ca5\x0cb5";
- case QFontDatabase::Malayalam:
- return u"\x0d05\x0d15\x0d25\x0d35";
- case QFontDatabase::Sinhala:
- return u"\x0d90\x0da0\x0db0\x0dc0";
- case QFontDatabase::Thai:
- return u"\x0e02\x0e12\x0e22\x0e32";
- case QFontDatabase::Lao:
- return u"\x0e8d\x0e9d\x0ead\x0ebd";
- case QFontDatabase::Tibetan:
- return u"\x0f00\x0f01\x0f02\x0f03";
- case QFontDatabase::Myanmar:
- return u"\x1000\x1001\x1002\x1003";
- case QFontDatabase::Georgian:
- return u"\x10a0\x10b0\x10c0\x10d0";
- case QFontDatabase::Khmer:
- return u"\x1780\x1790\x17b0\x17c0";
- case QFontDatabase::SimplifiedChinese:
- return u"\x4e2d\x6587\x8303\x4f8b";
- case QFontDatabase::TraditionalChinese:
- return u"\x4e2d\x6587\x7bc4\x4f8b";
- case QFontDatabase::Japanese:
- return u"\x30b5\x30f3\x30d7\x30eb\x3067\x3059";
- case QFontDatabase::Korean:
- return u"\xac00\xac11\xac1a\xac2f";
- case QFontDatabase::Vietnamese:
- return u"\x1ED7\x1ED9\x1ED1\x1ED3";
- case QFontDatabase::Ogham:
- return u"\x1681\x1682\x1683\x1684";
- case QFontDatabase::Runic:
- return u"\x16a0\x16a1\x16a2\x16a3";
- case QFontDatabase::Nko:
- return u"\x7ca\x7cb\x7cc\x7cd";
- default:
- return nullptr;
- }
-}
-
/*!
Returns a string with sample characters from \a writingSystem.
*/
QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
{
- return writing_system_sample(writingSystem).toString();
+ return [&]() -> QStringView {
+ switch (writingSystem) {
+ case QFontDatabase::Any:
+ case QFontDatabase::Symbol:
+ // show only ascii characters
+ return u"AaBbzZ";
+ case QFontDatabase::Latin:
+ // This is cheating... we only show latin-1 characters so that we don't
+ // end up loading lots of fonts - at least on X11...
+ return u"Aa\x00C3\x00E1Zz";
+ case QFontDatabase::Greek:
+ return u"\x0393\x03B1\x03A9\x03C9";
+ case QFontDatabase::Cyrillic:
+ return u"\x0414\x0434\x0436\x044f";
+ case QFontDatabase::Armenian:
+ return u"\x053f\x054f\x056f\x057f";
+ case QFontDatabase::Hebrew:
+ return u"\x05D0\x05D1\x05D2\x05D3";
+ case QFontDatabase::Arabic:
+ return u"\x0623\x0628\x062C\x062F\x064A\x0629\x0020\x0639\x0631\x0628\x064A\x0629";
+ case QFontDatabase::Syriac:
+ return u"\x0715\x0725\x0716\x0726";
+ case QFontDatabase::Thaana:
+ return u"\x0784\x0794\x078c\x078d";
+ case QFontDatabase::Devanagari:
+ return u"\x0905\x0915\x0925\x0935";
+ case QFontDatabase::Bengali:
+ return u"\x0986\x0996\x09a6\x09b6";
+ case QFontDatabase::Gurmukhi:
+ return u"\x0a05\x0a15\x0a25\x0a35";
+ case QFontDatabase::Gujarati:
+ return u"\x0a85\x0a95\x0aa5\x0ab5";
+ case QFontDatabase::Oriya:
+ return u"\x0b06\x0b16\x0b2b\x0b36";
+ case QFontDatabase::Tamil:
+ return u"\x0b89\x0b99\x0ba9\x0bb9";
+ case QFontDatabase::Telugu:
+ return u"\x0c05\x0c15\x0c25\x0c35";
+ case QFontDatabase::Kannada:
+ return u"\x0c85\x0c95\x0ca5\x0cb5";
+ case QFontDatabase::Malayalam:
+ return u"\x0d05\x0d15\x0d25\x0d35";
+ case QFontDatabase::Sinhala:
+ return u"\x0d90\x0da0\x0db0\x0dc0";
+ case QFontDatabase::Thai:
+ return u"\x0e02\x0e12\x0e22\x0e32";
+ case QFontDatabase::Lao:
+ return u"\x0e8d\x0e9d\x0ead\x0ebd";
+ case QFontDatabase::Tibetan:
+ return u"\x0f00\x0f01\x0f02\x0f03";
+ case QFontDatabase::Myanmar:
+ return u"\x1000\x1001\x1002\x1003";
+ case QFontDatabase::Georgian:
+ return u"\x10a0\x10b0\x10c0\x10d0";
+ case QFontDatabase::Khmer:
+ return u"\x1780\x1790\x17b0\x17c0";
+ case QFontDatabase::SimplifiedChinese:
+ return u"\x4e2d\x6587\x8303\x4f8b";
+ case QFontDatabase::TraditionalChinese:
+ return u"\x4e2d\x6587\x7bc4\x4f8b";
+ case QFontDatabase::Japanese:
+ return u"\x30b5\x30f3\x30d7\x30eb\x3067\x3059";
+ case QFontDatabase::Korean:
+ return u"\xac00\xac11\xac1a\xac2f";
+ case QFontDatabase::Vietnamese:
+ return u"\x1ED7\x1ED9\x1ED1\x1ED3";
+ case QFontDatabase::Ogham:
+ return u"\x1681\x1682\x1683\x1684";
+ case QFontDatabase::Runic:
+ return u"\x16a0\x16a1\x16a2\x16a3";
+ case QFontDatabase::Nko:
+ return u"\x7ca\x7cb\x7cc\x7cd";
+ default:
+ return nullptr;
+ }
+ }().toString();
}
void QFontDatabasePrivate::parseFontName(const QString &name, QString &foundry, QString &family)
@@ -2129,14 +2149,11 @@ void QFontDatabasePrivate::parseFontName(const QString &name, QString &foundry,
QT_PREPEND_NAMESPACE(parseFontName)(name, foundry, family);
}
-void QFontDatabasePrivate::createDatabase()
-{ initializeDb(); }
-
// used from qfontengine_ft.cpp
Q_GUI_EXPORT QByteArray qt_fontdata_from_index(int index)
{
QMutexLocker locker(fontDatabaseMutex());
- return privateDb()->applicationFonts.value(index).data;
+ return QFontDatabasePrivate::instance()->applicationFonts.value(index).data;
}
int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &fileName)
@@ -2148,35 +2165,36 @@ int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &
Q_TRACE(QFontDatabasePrivate_addAppFont, fileName);
int i;
- for (i = 0; i < applicationFonts.count(); ++i)
- if (applicationFonts.at(i).properties.isEmpty())
+ for (i = 0; i < applicationFonts.size(); ++i)
+ if (applicationFonts.at(i).isNull())
break;
- if (i >= applicationFonts.count()) {
+ if (i >= applicationFonts.size()) {
applicationFonts.append(ApplicationFont());
- i = applicationFonts.count() - 1;
+ i = applicationFonts.size() - 1;
}
if (font.fileName.isEmpty() && !fontData.isEmpty())
- font.fileName = QLatin1String(":qmemoryfonts/") + QString::number(i);
+ font.fileName = ":qmemoryfonts/"_L1 + QString::number(i);
- bool wasEmpty = privateDb()->count == 0;
- registerFont(&font);
+ auto *platformFontDatabase = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
+ platformFontDatabase->addApplicationFont(font.data, font.fileName, &font);
if (font.properties.isEmpty())
return -1;
applicationFonts[i] = font;
- // If the cache has not yet been populated, we need to reload the application font later
- if (wasEmpty)
- invalidate();
- else
- emit qApp->fontDatabaseChanged();
+ // The font cache may have cached lookups for the font that was now
+ // loaded, so it has to be flushed.
+ QFontCache::instance()->clear();
+
+ emit qApp->fontDatabaseChanged();
+
return i;
}
bool QFontDatabasePrivate::isApplicationFont(const QString &fileName)
{
- for (int i = 0; i < applicationFonts.count(); ++i)
+ for (int i = 0; i < applicationFonts.size(); ++i)
if (applicationFonts.at(i).fileName == fileName)
return true;
return false;
@@ -2190,13 +2208,12 @@ bool QFontDatabasePrivate::isApplicationFont(const QString &fileName)
with removeApplicationFont() or to retrieve the list of family names contained
in the font.
+//! [add-application-font-doc]
The function returns -1 if the font could not be loaded.
Currently only TrueType fonts, TrueType font collections, and OpenType fonts are
supported.
-
- \note Adding application fonts on Unix/X11 platforms without fontconfig is
- currently not supported.
+//! [add-application-font-doc]
\sa addApplicationFontFromData(), applicationFontFamilies(), removeApplicationFont()
*/
@@ -2213,7 +2230,7 @@ int QFontDatabase::addApplicationFont(const QString &fileName)
data = f.readAll();
}
QMutexLocker locker(fontDatabaseMutex());
- return privateDb()->addAppFont(data, fileName);
+ return QFontDatabasePrivate::instance()->addAppFont(data, fileName);
}
/*!
@@ -2224,19 +2241,14 @@ int QFontDatabase::addApplicationFont(const QString &fileName)
with removeApplicationFont() or to retrieve the list of family names contained
in the font.
- The function returns -1 if the font could not be loaded.
-
- Currently only TrueType fonts and TrueType font collections are supported.
-
- \b{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is
- currently not supported.
+ \include qfontdatabase.cpp add-application-font-doc
\sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont()
*/
int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData)
{
QMutexLocker locker(fontDatabaseMutex());
- return privateDb()->addAppFont(fontData, QString() /* fileName */);
+ return QFontDatabasePrivate::instance()->addAppFont(fontData, QString() /* fileName */);
}
/*!
@@ -2250,11 +2262,12 @@ int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData)
QStringList QFontDatabase::applicationFontFamilies(int id)
{
QMutexLocker locker(fontDatabaseMutex());
+ auto *d = QFontDatabasePrivate::instance();
QStringList ret;
- ret.reserve(privateDb()->applicationFonts.value(id).properties.size());
+ ret.reserve(d->applicationFonts.value(id).properties.size());
- for (const auto &properties : privateDb()->applicationFonts.value(id).properties)
+ for (const auto &properties : d->applicationFonts.value(id).properties)
ret.append(properties.familyName);
return ret;
@@ -2312,8 +2325,8 @@ bool QFontDatabase::removeApplicationFont(int handle)
{
QMutexLocker locker(fontDatabaseMutex());
- QFontDatabasePrivate *db = privateDb();
- if (handle < 0 || handle >= db->applicationFonts.count())
+ auto *db = QFontDatabasePrivate::instance();
+ if (handle < 0 || handle >= db->applicationFonts.size())
return false;
db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont();
@@ -2338,7 +2351,7 @@ bool QFontDatabase::removeAllApplicationFonts()
{
QMutexLocker locker(fontDatabaseMutex());
- QFontDatabasePrivate *db = privateDb();
+ auto *db = QFontDatabasePrivate::instance();
if (!db || db->applicationFonts.isEmpty())
return false;
@@ -2348,20 +2361,148 @@ bool QFontDatabase::removeAllApplicationFonts()
}
/*!
- \internal
+ \since 6.8
+
+ Adds \a familyName as an application-defined fallback font for \a script.
+
+ When Qt encounters characters that are not supported by the selected font, it will search
+ through a list of fallback fonts to find a match for them. This ensures that combining multiple
+ scripts in a single string is possible, even if the main font does not support them.
+
+ The list of fallback fonts is selected based on the script of the string as well as other
+ conditions, such as system language.
+
+ While the system fallback list is usually sufficient, there are cases where it is useful
+ to override the default behavior. One such case is for using application fonts as fallback to
+ ensure cross-platform consistency.
+
+ In another case the application may be written in a script with regional differences and want
+ to run it untranslated in multiple regions. In this case, it might be useful to override the
+ local region's fallback with one that matches the language of the application.
+
+ By passing \a familyName to addApplicationFallbackFontFamily(), this will become the preferred
+ family when matching missing characters from \a script. The \a script must be a valid script
+ (\c QChar::Script_Latin or higher). When adding multiple fonts for the same script, they will
+ be prioritized in reverse order, so that the last family added will be checked first and so
+ on.
+
+ \sa setApplicationFallbackFontFamilies(), removeApplicationFallbackFontFamily(), applicationFallbackFontFamilies()
+*/
+void QFontDatabase::addApplicationFallbackFontFamily(QChar::Script script, const QString &familyName)
+{
+ QMutexLocker locker(fontDatabaseMutex());
+
+ if (script < QChar::Script_Latin) {
+ qCWarning(lcFontDb) << "Invalid script passed to addApplicationFallbackFontFamily:" << script;
+ return;
+ }
+
+ auto *db = QFontDatabasePrivate::instance();
+ auto it = db->applicationFallbackFontFamilies.find(script);
+ if (it == db->applicationFallbackFontFamilies.end())
+ it = db->applicationFallbackFontFamilies.insert(script, QStringList{});
+
+ it->prepend(familyName);
+ db->fallbacksCache.clear();
+}
+
+/*!
+ \since 6.8
+
+ Removes \a familyName from the list of application-defined fallback fonts for \a script,
+ provided that it has previously been added with \l{addApplicationFallbackFontFamily()}.
+
+ Returns true if the family name was in the list and false if it was not.
+
+ \sa addApplicationFallbackFontFamily(), setApplicationFallbackFontFamilies(), applicationFallbackFontFamilies()
+*/
+bool QFontDatabase::removeApplicationFallbackFontFamily(QChar::Script script, const QString &familyName)
+{
+ QMutexLocker locker(fontDatabaseMutex());
+
+ auto *db = QFontDatabasePrivate::instance();
+ auto it = db->applicationFallbackFontFamilies.find(script);
+ if (it != db->applicationFallbackFontFamilies.end()) {
+ if (it->removeAll(familyName) > 0) {
+ if (it->isEmpty())
+ it = db->applicationFallbackFontFamilies.erase(it);
+ QFontCache::instance()->clear();
+ db->fallbacksCache.clear();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*!
+ \since 6.8
+
+ Sets the list of application-defined fallback fonts for \a script to \a familyNames.
+
+ When Qt encounters a character in \a script which is not supported by the current font, it will
+ check the families in \a familyNames, in order from first to last, until it finds a match. See
+ \l{addApplicationFallbackFontFamily()} for more details.
+
+ This function overwrites the current list of application-defined fallback fonts for \a script.
+
+ \sa addApplicationFallbackFontFamily(), removeApplicationFallbackFontFamily(), applicationFallbackFontFamilies()
*/
-QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &request, int script)
+void QFontDatabase::setApplicationFallbackFontFamilies(QChar::Script script, const QStringList &familyNames)
{
QMutexLocker locker(fontDatabaseMutex());
- if (!privateDb()->count)
- initializeDb();
+ if (script < QChar::Script_Latin) {
+ qCWarning(lcFontDb) << "Invalid script passed to setApplicationFallbackFontFamilies:" << script;
+ return;
+ }
+
+ auto *db = QFontDatabasePrivate::instance();
+ db->applicationFallbackFontFamilies[script] = familyNames;
+
+ QFontCache::instance()->clear();
+ db->fallbacksCache.clear();
+}
+
+/*!
+ \since 6.8
+
+ Returns the list of application-defined fallback font families previously added for \a script
+ by the \l{addApplicationFallbackFontFamily()} function.
+
+ \sa setApplicationFallbackFontFamilies(), addApplicationFallbackFontFamily(), removeApplicationFallbackFontFamily()
+*/
+QStringList QFontDatabase::applicationFallbackFontFamilies(QChar::Script script)
+{
+ QMutexLocker locker(fontDatabaseMutex());
+
+ auto *db = QFontDatabasePrivate::instance();
+ return db->applicationFallbackFontFamilies.value(script);
+}
+
+/*!
+ \internal
+*/
+QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &req,
+ int script,
+ bool preferScriptOverFamily)
+{
+ QMutexLocker locker(fontDatabaseMutex());
+ ensureFontDatabase();
QFontEngine *engine;
+#ifdef Q_OS_WIN
+ const QFontDef request = static_cast<QWindowsFontDatabaseBase *>(
+ QGuiApplicationPrivate::platformIntegration()->fontDatabase())
+ ->sanitizeRequest(req);
+#else
+ const QFontDef &request = req;
+#endif
+
#if defined(QT_BUILD_INTERNAL)
// For testing purpose only, emulates an exact-matching monospace font
- if (qt_enable_test_font && request.families.first() == QLatin1String("__Qt__Box__Engine__")) {
+ if (qt_enable_test_font && request.families.first() == "__Qt__Box__Engine__"_L1) {
engine = new QTestFontEngine(request.pixelSize);
engine->fontDef = request;
return engine;
@@ -2392,11 +2533,20 @@ QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &request, int script)
parseFontName(requestFamily, foundry_name, family_name);
QtFontDesc desc;
QList<int> blackListed;
- int index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed);
- if (index < 0 && QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamilyAliases(family_name)) {
- // We populated familiy aliases (e.g. localized families), so try again
+ unsigned int score = UINT_MAX;
+ int index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed, &score);
+ if (score > 0 && QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFamilyAliases(family_name)) {
+ // We populated family aliases (e.g. localized families), so try again
index = match(multi ? QChar::Script_Common : script, request, family_name, foundry_name, &desc, blackListed);
}
+
+ // If we do not find a match and NoFontMerging is set, use the requested font even if it does
+ // not support the script.
+ //
+ // (we do this at the end to prefer foundries that support the script if they exist)
+ if (index < 0 && !multi && !preferScriptOverFamily)
+ index = match(QChar::Script_Common, request, family_name, foundry_name, &desc, blackListed);
+
if (index >= 0) {
QFontDef fontDef = request;
// Don't pass empty family names to the platform font database, since it will then invoke its own matching
@@ -2436,7 +2586,7 @@ QFontEngine *QFontDatabasePrivate::findFont(const QFontDef &request, int script)
if (!engine) {
QtFontDesc desc;
do {
- index = match(multi ? QChar::Script_Common : script, def, def.families.first(), QLatin1String(""), &desc, blackListed);
+ index = match(multi ? QChar::Script_Common : script, def, def.families.constFirst(), ""_L1, &desc, blackListed);
if (index >= 0) {
QFontDef loadDef = def;
if (loadDef.families.isEmpty())
@@ -2498,7 +2648,7 @@ void QFontDatabasePrivate::load(const QFontPrivate *d, int script)
QFontEngine *fe = nullptr;
- Q_TRACE(QFontDatabase_load, req.families, req.pointSize);
+ Q_TRACE(QFontDatabase_load, req.families.join(QLatin1Char(';')), req.pointSize);
req.fallBackFamilies = fallBackFamilies;
if (!req.fallBackFamilies.isEmpty())
@@ -2512,9 +2662,12 @@ void QFontDatabasePrivate::load(const QFontPrivate *d, int script)
family_list << req.families.at(0);
// add the default family
- QString defaultFamily = QGuiApplication::font().families().first();
- if (! family_list.contains(defaultFamily))
- family_list << defaultFamily;
+ const auto families = QGuiApplication::font().families();
+ if (!families.isEmpty()) {
+ QString defaultFamily = families.first();
+ if (! family_list.contains(defaultFamily))
+ family_list << defaultFamily;
+ }
}
@@ -2568,7 +2721,7 @@ Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script
return families;
}
- QFontDatabasePrivate *db = privateDb();
+ auto *db = QFontDatabasePrivate::instance();
QMultiMap<uint, QString> supported;
for (int i = 0; i < families.size(); ++i) {
const QString &family = families.at(i);
@@ -2577,8 +2730,8 @@ Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script
for (int x = 0; x < db->count; ++x) {
if (Q_UNLIKELY(matchFamilyName(family, db->families[x]))) {
testFamily = db->families[x];
- testFamily->ensurePopulated();
- break;
+ if (testFamily->ensurePopulated())
+ break;
}
}
@@ -2596,3 +2749,5 @@ Q_GUI_EXPORT QStringList qt_sort_families_by_writing_system(QChar::Script script
QT_END_NAMESPACE
+#include "moc_qfontdatabase.cpp"
+
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index 79ace4e35b..91a534265e 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTDATABASE_H
#define QFONTDATABASE_H
@@ -109,7 +73,7 @@ public:
static QList<int> standardSizes();
-#if QT_DEPRECATED_SINCE(6, 0)
+#if QT_DEPRECATED_SINCE(6, 0) && !defined(QT_BUILD_GUI_LIB)
QT_DEPRECATED_VERSION_X_6_0("Call the static functions instead") explicit QFontDatabase() = default;
#else
QFontDatabase() = delete;
@@ -148,6 +112,11 @@ public:
static bool removeApplicationFont(int id);
static bool removeAllApplicationFonts();
+ static void addApplicationFallbackFontFamily(QChar::Script script, const QString &familyName);
+ static bool removeApplicationFallbackFontFamily(QChar::Script script, const QString &familyName);
+ static void setApplicationFallbackFontFamilies(QChar::Script, const QStringList &familyNames);
+ static QStringList applicationFallbackFontFamilies(QChar::Script script);
+
static QFont systemFont(SystemFont type);
};
diff --git a/src/gui/text/qfontdatabase_p.h b/src/gui/text/qfontdatabase_p.h
index f7998153a1..38e1b4ad20 100644
--- a/src/gui/text/qfontdatabase_p.h
+++ b/src/gui/text/qfontdatabase_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTDATABASE_P_H
#define QFONTDATABASE_P_H
@@ -54,9 +18,12 @@
#include <QtCore/qcache.h>
#include <QtGui/qfontdatabase.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
+struct QtFontDesc;
+
struct QtFontFallbacksCacheKey
{
QString family;
@@ -207,7 +174,7 @@ struct Q_GUI_EXPORT QtFontFamily
bool matchesFamilyName(const QString &familyName) const;
QtFontFoundry *foundry(const QString &f, bool = false);
- void ensurePopulated();
+ bool ensurePopulated();
};
class Q_GUI_EXPORT QFontDatabasePrivate
@@ -220,9 +187,11 @@ public:
{ }
~QFontDatabasePrivate() {
- free();
+ clearFamilies();
}
+ void clearFamilies();
+
enum FamilyRequestFlags {
RequestFamily = 0,
EnsureCreated,
@@ -230,23 +199,25 @@ public:
};
QtFontFamily *family(const QString &f, FamilyRequestFlags flags = EnsurePopulated);
- void free() {
- while (count--)
- delete families[count];
- ::free(families);
- families = nullptr;
- count = 0;
- // don't clear the memory fonts!
- }
int count;
QtFontFamily **families;
+ bool populated = false;
+
+ QHash<QChar::Script, QStringList> applicationFallbackFontFamilies;
QCache<QtFontFallbacksCacheKey, QStringList> fallbacksCache;
struct ApplicationFont {
QString fileName;
+
+ // Note: The data may be implicitly shared throughout the
+ // font database and platform font database, so be careful
+ // to never detach when accessing this member!
QByteArray data;
+ bool isNull() const { return fileName.isEmpty(); }
+ bool isPopulated() const { return !properties.isEmpty(); }
+
struct Properties {
QString familyName;
QString styleName;
@@ -263,14 +234,34 @@ public:
static QFontDatabasePrivate *instance();
- static void createDatabase();
static void parseFontName(const QString &name, QString &foundry, QString &family);
static QString resolveFontFamilyAlias(const QString &family);
- static QFontEngine *findFont(const QFontDef &request, int script /* QChar::Script */);
+ static QFontEngine *findFont(const QFontDef &request,
+ int script /* QChar::Script */,
+ bool preferScriptOverFamily = false);
static void load(const QFontPrivate *d, int script /* QChar::Script */);
static QFontDatabasePrivate *ensureFontDatabase();
void invalidate();
+
+private:
+ static int match(int script, const QFontDef &request, const QString &family_name,
+ const QString &foundry_name, QtFontDesc *desc, const QList<int> &blacklistedFamilies,
+ unsigned int *resultingScore = nullptr);
+
+ static unsigned int bestFoundry(int script, unsigned int score, int styleStrategy,
+ const QtFontFamily *family, const QString &foundry_name,
+ QtFontStyle::Key styleKey, int pixelSize, char pitch,
+ QtFontDesc *desc, const QString &styleName = QString());
+
+ static QFontEngine *loadSingleEngine(int script, const QFontDef &request,
+ QtFontFamily *family, QtFontFoundry *foundry,
+ QtFontStyle *style, QtFontSize *size);
+
+ static QFontEngine *loadEngine(int script, const QFontDef &request,
+ QtFontFamily *family, QtFontFoundry *foundry,
+ QtFontStyle *style, QtFontSize *size);
+
};
Q_DECLARE_TYPEINFO(QFontDatabasePrivate::ApplicationFont, Q_RELOCATABLE_TYPE);
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 2dbed7383f..dff400c18b 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qdebug.h>
#include <private/qfontengine_p.h>
@@ -90,17 +54,6 @@ static inline bool qSafeFromBigEndian(const uchar *source, const uchar *end, T *
return true;
}
-// Harfbuzz helper functions
-
-#if QT_CONFIG(harfbuzz)
-Q_GLOBAL_STATIC_WITH_ARGS(bool, useHarfbuzzNG,(qgetenv("QT_HARFBUZZ") != "old"))
-
-bool qt_useHarfbuzzNG()
-{
- return *useHarfbuzzNG();
-}
-#endif
-
int QFontEngine::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints)
{
Q_UNUSED(glyph);
@@ -180,7 +133,7 @@ QFontEngine::~QFontEngine()
QFixed QFontEngine::lineThickness() const
{
// ad hoc algorithm
- int score = fontDef.weight * fontDef.pixelSize;
+ int score = fontDef.weight * fontDef.pixelSize / 10;
int lw = score / 700;
// looks better with thicker line for small pointsizes
@@ -199,20 +152,20 @@ void *QFontEngine::harfbuzzFont() const
{
Q_ASSERT(type() != QFontEngine::Multi);
#if QT_CONFIG(harfbuzz)
- if (qt_useHarfbuzzNG())
- return hb_qt_font_get_for_engine(const_cast<QFontEngine *>(this));
-#endif
+ return hb_qt_font_get_for_engine(const_cast<QFontEngine *>(this));
+#else
return nullptr;
+#endif
}
void *QFontEngine::harfbuzzFace() const
{
Q_ASSERT(type() != QFontEngine::Multi);
#if QT_CONFIG(harfbuzz)
- if (qt_useHarfbuzzNG())
- return hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this));
-#endif
+ return hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this));
+#else
return nullptr;
+#endif
}
bool QFontEngine::supportsScript(QChar::Script script) const
@@ -227,23 +180,23 @@ bool QFontEngine::supportsScript(QChar::Script script) const
return true;
#if QT_CONFIG(harfbuzz)
- if (qt_useHarfbuzzNG()) {
- // in AAT fonts, 'gsub' table is effectively replaced by 'mort'/'morx' table
- uint lenMort = 0, lenMorx = 0;
- if (getSfntTableData(MAKE_TAG('m','o','r','t'), nullptr, &lenMort) || getSfntTableData(MAKE_TAG('m','o','r','x'), nullptr, &lenMorx))
- return true;
+ // in AAT fonts, 'gsub' table is effectively replaced by 'mort'/'morx' table
+ uint lenMort = 0, lenMorx = 0;
+ if (getSfntTableData(QFont::Tag("mort").value(), nullptr, &lenMort)
+ || getSfntTableData(QFont::Tag("morx").value(), nullptr, &lenMorx)) {
+ return true;
+ }
- if (hb_face_t *face = hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this))) {
- unsigned int script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
- hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
+ if (hb_face_t *face = hb_qt_face_get_for_engine(const_cast<QFontEngine *>(this))) {
+ unsigned int script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
+ hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
- hb_ot_tags_from_script_and_language(hb_qt_script_to_script(script), HB_LANGUAGE_INVALID,
- &script_count, script_tags,
- nullptr, nullptr);
+ hb_ot_tags_from_script_and_language(hb_qt_script_to_script(script), HB_LANGUAGE_INVALID,
+ &script_count, script_tags,
+ nullptr, nullptr);
- if (hb_ot_layout_table_select_script(face, HB_OT_TAG_GSUB, script_count, script_tags, nullptr, nullptr))
- return true;
- }
+ if (hb_ot_layout_table_select_script(face, HB_OT_TAG_GSUB, script_count, script_tags, nullptr, nullptr))
+ return true;
}
#endif
return false;
@@ -430,11 +383,16 @@ void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rig
bool QFontEngine::processHheaTable() const
{
- QByteArray hhea = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a'));
+ QByteArray hhea = getSfntTable(QFont::Tag("hhea").value());
if (hhea.size() >= 10) {
- qint16 ascent = qFromBigEndian<qint16>(hhea.constData() + 4);
- qint16 descent = qFromBigEndian<qint16>(hhea.constData() + 6);
- qint16 leading = qFromBigEndian<qint16>(hhea.constData() + 8);
+ auto ptr = hhea.constData();
+ qint16 ascent = qFromBigEndian<qint16>(ptr + 4);
+ qint16 descent = qFromBigEndian<qint16>(ptr + 6);
+ qint16 leading = qFromBigEndian<qint16>(ptr + 8);
+
+ // Some fonts may have invalid HHEA data. We detect this and bail out.
+ if (ascent == 0 && descent == 0)
+ return false;
QFixed unitsPerEm = emSquareSize();
m_ascent = QFixed::fromReal(ascent * fontDef.pixelSize) / unitsPerEm;
@@ -450,13 +408,22 @@ bool QFontEngine::processHheaTable() const
void QFontEngine::initializeHeightMetrics() const
{
- bool hasEmbeddedBitmaps = !getSfntTable(MAKE_TAG('E', 'B', 'L', 'C')).isEmpty() || !getSfntTable(MAKE_TAG('C', 'B', 'L', 'C')).isEmpty();
+ bool hasEmbeddedBitmaps =
+ !getSfntTable(QFont::Tag("EBLC").value()).isEmpty()
+ || !getSfntTable(QFont::Tag("CBLC").value()).isEmpty()
+ || !getSfntTable(QFont::Tag("bdat").value()).isEmpty();
if (!hasEmbeddedBitmaps) {
// Get HHEA table values if available
processHheaTable();
// Allow OS/2 metrics to override if present
processOS2Table();
+
+ if (!supportsSubPixelPositions()) {
+ m_ascent = m_ascent.round();
+ m_descent = m_descent.round();
+ m_leading = m_leading.round();
+ }
}
m_heightMetricsQueried = true;
@@ -464,24 +431,32 @@ void QFontEngine::initializeHeightMetrics() const
bool QFontEngine::processOS2Table() const
{
- QByteArray os2 = getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
+ QByteArray os2 = getSfntTable(QFont::Tag("OS/2").value());
if (os2.size() >= 78) {
- quint16 fsSelection = qFromBigEndian<quint16>(os2.constData() + 62);
- qint16 typoAscent = qFromBigEndian<qint16>(os2.constData() + 68);
- qint16 typoDescent = qFromBigEndian<qint16>(os2.constData() + 70);
- qint16 typoLineGap = qFromBigEndian<qint16>(os2.constData() + 72);
- quint16 winAscent = qFromBigEndian<quint16>(os2.constData() + 74);
- quint16 winDescent = qFromBigEndian<quint16>(os2.constData() + 76);
+ auto ptr = os2.constData();
+ quint16 fsSelection = qFromBigEndian<quint16>(ptr + 62);
+ qint16 typoAscent = qFromBigEndian<qint16>(ptr + 68);
+ qint16 typoDescent = qFromBigEndian<qint16>(ptr + 70);
+ qint16 typoLineGap = qFromBigEndian<qint16>(ptr + 72);
+ quint16 winAscent = qFromBigEndian<quint16>(ptr + 74);
+ quint16 winDescent = qFromBigEndian<quint16>(ptr + 76);
enum { USE_TYPO_METRICS = 0x80 };
QFixed unitsPerEm = emSquareSize();
if (fsSelection & USE_TYPO_METRICS) {
+ // Some fonts may have invalid OS/2 data. We detect this and bail out.
+ if (typoAscent == 0 && typoDescent == 0)
+ return false;
m_ascent = QFixed::fromReal(typoAscent * fontDef.pixelSize) / unitsPerEm;
m_descent = -QFixed::fromReal(typoDescent * fontDef.pixelSize) / unitsPerEm;
m_leading = QFixed::fromReal(typoLineGap * fontDef.pixelSize) / unitsPerEm;
} else {
+ // Some fonts may have invalid OS/2 data. We detect this and bail out.
+ if (winAscent == 0 && winDescent == 0)
+ return false;
m_ascent = QFixed::fromReal(winAscent * fontDef.pixelSize) / unitsPerEm;
m_descent = QFixed::fromReal(winDescent * fontDef.pixelSize) / unitsPerEm;
+ m_leading = QFixed{};
}
return true;
@@ -532,7 +507,7 @@ qreal QFontEngine::minRightBearing() const
if (m_minRightBearing == kBearingNotInitialized) {
// Try the 'hhea' font table first, which covers the entire font
- QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a'));
+ QByteArray hheaTable = getSfntTable(QFont::Tag("hhea").value());
if (hheaTable.size() >= int(kMinRightSideBearingOffset + sizeof(qint16))) {
const uchar *tableData = reinterpret_cast<const uchar *>(hheaTable.constData());
Q_ASSERT(q16Dot16ToFloat(qFromBigEndian<quint32>(tableData)) == 1.0);
@@ -596,6 +571,16 @@ qreal QFontEngine::minRightBearing() const
return m_minRightBearing;
}
+glyph_metrics_t QFontEngine::boundingBox(const QGlyphLayout &glyphs)
+{
+ QFixed w;
+ for (int i = 0; i < glyphs.numGlyphs; ++i)
+ w += glyphs.effectiveAdvance(i);
+ const QFixed leftBearing = firstLeftBearing(glyphs);
+ const QFixed rightBearing = lastRightBearing(glyphs);
+ return glyph_metrics_t(leftBearing, -(ascent()), w - leftBearing - rightBearing, ascent() + descent(), w, 0);
+}
+
glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs)
{
glyph_metrics_t overall;
@@ -611,9 +596,9 @@ glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs)
QFixed y = overall.yoff + glyphs.offsets[i].y + bb.y;
overall.x = qMin(overall.x, x);
overall.y = qMin(overall.y, y);
- xmax = qMax(xmax, x + bb.width);
- ymax = qMax(ymax, y + bb.height);
- overall.xoff += bb.xoff;
+ xmax = qMax(xmax, x.ceil() + bb.width);
+ ymax = qMax(ymax, y.ceil() + bb.height);
+ overall.xoff += glyphs.effectiveAdvance(i);
overall.yoff += bb.yoff;
}
overall.height = qMax(overall.height, ymax - overall.y);
@@ -1062,7 +1047,7 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
{
kerning_pairs.clear();
- QByteArray tab = getSfntTable(MAKE_TAG('k', 'e', 'r', 'n'));
+ QByteArray tab = getSfntTable(QFont::Tag("kern").value());
if (tab.isEmpty())
return;
@@ -1151,7 +1136,7 @@ end:
int QFontEngine::glyphCount() const
{
- QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p'));
+ QByteArray maxpTable = getSfntTable(QFont::Tag("maxp").value());
if (maxpTable.size() < 6)
return 0;
@@ -1198,7 +1183,7 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
int tableToUse = -1;
int score = Invalid;
for (int n = 0; n < numTables; ++n) {
- quint16 platformId;
+ quint16 platformId = 0;
if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId))
return nullptr;
@@ -1249,6 +1234,7 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy
default:
break;
}
+ break;
default:
break;
}
@@ -1328,7 +1314,7 @@ resolveTable:
quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode)
{
const uchar *end = cmap + cmapSize;
- quint16 format;
+ quint16 format = 0;
if (!qSafeFromBigEndian(cmap, end, &format))
return 0;
@@ -1345,7 +1331,7 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint
if (unicode >= 0xffff)
return 0;
- quint16 segCountX2;
+ quint16 segCountX2 = 0;
if (!qSafeFromBigEndian(cmap + 6, end, &segCountX2))
return 0;
@@ -1353,7 +1339,7 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint
int i = 0;
for (; i < segCountX2/2; ++i) {
- quint16 codePoint;
+ quint16 codePoint = 0;
if (!qSafeFromBigEndian(ends + 2 * i, end, &codePoint))
return 0;
if (codePoint >= unicode)
@@ -1362,7 +1348,7 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint
const unsigned char *idx = ends + segCountX2 + 2 + 2*i;
- quint16 startIndex;
+ quint16 startIndex = 0;
if (!qSafeFromBigEndian(idx, end, &startIndex))
return 0;
if (startIndex > unicode)
@@ -1370,20 +1356,20 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint
idx += segCountX2;
- quint16 tmp;
+ quint16 tmp = 0;
if (!qSafeFromBigEndian(idx, end, &tmp))
return 0;
qint16 idDelta = qint16(tmp);
idx += segCountX2;
- quint16 idRangeoffset_t;
+ quint16 idRangeoffset_t = 0;
if (!qSafeFromBigEndian(idx, end, &idRangeoffset_t))
return 0;
- quint16 glyphIndex;
+ quint16 glyphIndex = 0;
if (idRangeoffset_t) {
- quint16 id;
+ quint16 id = 0;
if (!qSafeFromBigEndian(idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id))
return 0;
@@ -1396,17 +1382,17 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint
}
return glyphIndex;
} else if (format == 6) {
- quint16 tableSize;
+ quint16 tableSize = 0;
if (!qSafeFromBigEndian(cmap + 2, end, &tableSize))
return 0;
- quint16 firstCode6;
+ quint16 firstCode6 = 0;
if (!qSafeFromBigEndian(cmap + 6, end, &firstCode6))
return 0;
if (unicode < firstCode6)
return 0;
- quint16 entryCount6;
+ quint16 entryCount6 = 0;
if (!qSafeFromBigEndian(cmap + 8, end, &entryCount6))
return 0;
if (entryCount6 * 2 + 10 > tableSize)
@@ -1422,7 +1408,7 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint
qSafeFromBigEndian(cmap + 10 + (entryIndex6 * 2), end, &index);
return index;
} else if (format == 12) {
- quint32 nGroups;
+ quint32 nGroups = 0;
if (!qSafeFromBigEndian(cmap + 12, end, &nGroups))
return 0;
@@ -1432,19 +1418,19 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint
while (left <= right) {
int middle = left + ( ( right - left ) >> 1 );
- quint32 startCharCode;
+ quint32 startCharCode = 0;
if (!qSafeFromBigEndian(cmap + 12 * middle, end, &startCharCode))
return 0;
if (unicode < startCharCode)
right = middle - 1;
else {
- quint32 endCharCode;
+ quint32 endCharCode = 0;
if (!qSafeFromBigEndian(cmap + 12 * middle + 4, end, &endCharCode))
return 0;
if (unicode <= endCharCode) {
- quint32 index;
+ quint32 index = 0;
if (!qSafeFromBigEndian(cmap + 12 * middle + 8, end, &index))
return 0;
@@ -1486,6 +1472,17 @@ bool QFontEngine::hasUnreliableGlyphOutline() const
return glyphFormat == QFontEngine::Format_ARGB;
}
+QFixed QFontEngine::firstLeftBearing(const QGlyphLayout &glyphs)
+{
+ for (int i = 0; i < glyphs.numGlyphs; ++i) {
+ glyph_t glyph = glyphs.glyphs[i];
+ glyph_metrics_t gi = boundingBox(glyph);
+ if (gi.isValid() && gi.width > 0)
+ return gi.leftBearing();
+ }
+ return 0;
+}
+
QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs)
{
if (glyphs.numGlyphs >= 1) {
@@ -1733,7 +1730,7 @@ void QFontEngineMulti::ensureFallbackFamiliesQueried()
if (styleHint == QFont::AnyStyle && fontDef.fixedPitch)
styleHint = QFont::TypeWriter;
- setFallbackFamiliesList(qt_fallbacksForFamily(fontDef.families.first(),
+ setFallbackFamiliesList(qt_fallbacksForFamily(fontDef.families.constFirst(),
QFont::Style(fontDef.style), styleHint,
QChar::Script(m_script)));
}
@@ -1749,7 +1746,7 @@ void QFontEngineMulti::setFallbackFamiliesList(const QStringList &fallbackFamili
QFontEngine *engine = m_engines.at(0);
engine->ref.ref();
m_engines[1] = engine;
- m_fallbackFamilies << fontDef.families.first();
+ m_fallbackFamilies << fontDef.families.constFirst();
} else {
m_engines.resize(m_fallbackFamilies.size() + 1);
}
@@ -1838,6 +1835,7 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
QStringIterator it(str, str + len);
int lastFallback = -1;
+ char32_t previousUcs4 = 0;
while (it.hasNext()) {
const char32_t ucs4 = it.peekNext();
@@ -1867,7 +1865,8 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
&& ucs4 != QChar::LineSeparator
&& ucs4 != QChar::LineFeed
&& ucs4 != QChar::CarriageReturn
- && ucs4 != QChar::ParagraphSeparator) {
+ && ucs4 != QChar::ParagraphSeparator
+ && QChar::category(ucs4) != QChar::Other_Control) {
if (!m_fallbackFamiliesQueried)
const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
for (int x = 1, n = qMin(m_engines.size(), 256); x < n; ++x) {
@@ -1899,10 +1898,50 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
break;
}
}
+
+ // For variant-selectors, they are modifiers to the previous character. If we
+ // end up with different font selections for the selector and the character it
+ // modifies, we try applying the selector font to the preceding character as well
+ const int variantSelectorBlock = 0xFE00;
+ if ((ucs4 & 0xFFF0) == variantSelectorBlock && glyph_pos > 0) {
+ int selectorFontEngine = glyphs->glyphs[glyph_pos] >> 24;
+ int precedingCharacterFontEngine = glyphs->glyphs[glyph_pos - 1] >> 24;
+
+ if (selectorFontEngine != precedingCharacterFontEngine) {
+ // Emoji variant selectors are specially handled and should affect font
+ // selection. If VS-16 is used, then this means we want to select a color
+ // font. If the selected font is already a color font, we do not need search
+ // again. If the VS-15 is used, then this means we want to select a non-color
+ // font. If the selected font is not a color font, we don't do anything.
+ const QFontEngine *selectedEngine = m_engines.at(precedingCharacterFontEngine);
+ const bool colorFont = selectedEngine->isColorFont();
+ const char32_t vs15 = 0xFE0E;
+ const char32_t vs16 = 0xFE0F;
+ bool adaptVariantSelector = ucs4 < vs15
+ || (ucs4 == vs15 && colorFont)
+ || (ucs4 == vs16 && !colorFont);
+
+ if (adaptVariantSelector) {
+ QFontEngine *engine = m_engines.at(selectorFontEngine);
+ glyph_t glyph = engine->glyphIndex(previousUcs4);
+ if (glyph != 0) {
+ glyphs->glyphs[glyph_pos - 1] = glyph;
+ if (!(flags & GlyphIndicesOnly)) {
+ QGlyphLayout g = glyphs->mid(glyph_pos - 1, 1);
+ engine->recalcAdvances(&g, flags);
+ }
+
+ // set the high byte to indicate which engine the glyph came from
+ glyphs->glyphs[glyph_pos - 1] |= (selectorFontEngine << 24);
+ }
+ }
+ }
+ }
}
it.advance();
++glyph_pos;
+ previousUcs4 = ucs4;
}
*nglyphs = glyph_pos;
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 1169e0b779..af44eeab3f 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTENGINE_P_H
#define QFONTENGINE_P_H
@@ -65,13 +29,6 @@ class QFontEngineGlyphCache;
struct QGlyphLayout;
-#define MAKE_TAG(ch1, ch2, ch3, ch4) (\
- (((quint32)(ch1)) << 24) | \
- (((quint32)(ch2)) << 16) | \
- (((quint32)(ch3)) << 8) | \
- ((quint32)(ch4)) \
- )
-
// ### this only used in getPointInOutline(), refactor it and then remove these magic numbers
enum HB_Compat_Error {
Err_Ok = 0x0000,
@@ -163,11 +120,13 @@ public:
virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
struct FaceId {
- FaceId() : index(0), encoding(0) {}
+ FaceId() : index(0), instanceIndex(-1), encoding(0) {}
QByteArray filename;
QByteArray uuid;
int index;
+ int instanceIndex;
int encoding;
+ QMap<QFont::Tag, float> variableAxes;
};
virtual FaceId faceId() const { return FaceId(); }
enum SynthesizedFlags {
@@ -183,11 +142,13 @@ public:
virtual bool supportsHorizontalSubPixelPositions() const { return false; }
virtual bool supportsVerticalSubPixelPositions() const { return false; }
virtual QFixedPoint subPixelPositionFor(const QFixedPoint &position) const;
- QFixed subPixelPositionForX(const QFixed &x) const
+ QFixed subPixelPositionForX(QFixed x) const
{
return subPixelPositionFor(QFixedPoint(x, 0)).x;
}
+ bool isColorFont() const { return glyphFormat == Format_ARGB; }
+
virtual QFixed emSquareSize() const { return ascent(); }
/* returns 0 as glyph index for non existent glyphs */
@@ -225,7 +186,7 @@ public:
virtual void removeGlyphFromCache(glyph_t);
- virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) = 0;
+ virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
virtual glyph_metrics_t boundingBox(glyph_t glyph) = 0;
virtual glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix);
glyph_metrics_t tightBoundingBox(const QGlyphLayout &glyphs);
@@ -313,8 +274,8 @@ public:
explicit Holder(void *p, qt_destroy_func_t d) : ptr(p), destroy_func(d) {}
~Holder() { if (ptr && destroy_func) destroy_func(ptr); }
Holder(Holder &&other) noexcept
- : ptr(qExchange(other.ptr, nullptr)),
- destroy_func(qExchange(other.destroy_func, nullptr))
+ : ptr(std::exchange(other.ptr, nullptr)),
+ destroy_func(std::exchange(other.destroy_func, nullptr))
{
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(Holder)
@@ -368,6 +329,7 @@ public:
protected:
explicit QFontEngine(Type type);
+ QFixed firstLeftBearing(const QGlyphLayout &glyphs);
QFixed lastRightBearing(const QGlyphLayout &glyphs);
QFixed calculatedCapHeight() const;
@@ -405,13 +367,18 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QFontEngine::ShaperFlags)
inline bool operator ==(const QFontEngine::FaceId &f1, const QFontEngine::FaceId &f2)
{
- return f1.index == f2.index && f1.encoding == f2.encoding && f1.filename == f2.filename && f1.uuid == f2.uuid;
+ return f1.index == f2.index
+ && f1.encoding == f2.encoding
+ && f1.filename == f2.filename
+ && f1.uuid == f2.uuid
+ && f1.instanceIndex == f2.instanceIndex
+ && f1.variableAxes == f2.variableAxes;
}
inline size_t qHash(const QFontEngine::FaceId &f, size_t seed = 0)
noexcept(noexcept(qHash(f.filename)))
{
- return qHashMulti(seed, f.filename, f.uuid, f.index, f.encoding);
+ return qHashMulti(seed, f.filename, f.uuid, f.index, f.instanceIndex, f.encoding, f.variableAxes.keys(), f.variableAxes.values());
}
diff --git a/src/gui/text/qfontengineglyphcache.cpp b/src/gui/text/qfontengineglyphcache.cpp
index c6e6499854..3555d56fa8 100644
--- a/src/gui/text/qfontengineglyphcache.cpp
+++ b/src/gui/text/qfontengineglyphcache.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qfontengineglyphcache_p.h>
diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h
index 532be10a83..9054ea5950 100644
--- a/src/gui/text/qfontengineglyphcache_p.h
+++ b/src/gui/text/qfontengineglyphcache_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTENGINEGLYPHCACHE_P_H
#define QFONTENGINEGLYPHCACHE_P_H
@@ -51,7 +15,7 @@
// We mean it.
//
-
+#include <QtCore/qshareddata.h>
#include <QtGui/private/qtguiglobal_p.h>
#include "QtCore/qatomic.h"
#include <QtCore/qvarlengtharray.h>
diff --git a/src/gui/text/qfontinfo.h b/src/gui/text/qfontinfo.h
index ed889c2fb5..0edee5abe5 100644
--- a/src/gui/text/qfontinfo.h
+++ b/src/gui/text/qfontinfo.h
@@ -1,48 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTINFO_H
#define QFONTINFO_H
#include <QtGui/qtguiglobal.h>
#include <QtGui/qfont.h>
-#include <QtCore/qsharedpointer.h>
+
+#include <QtCore/qshareddata.h>
QT_BEGIN_NAMESPACE
@@ -56,7 +21,7 @@ public:
QFontInfo &operator=(const QFontInfo &);
- void swap(QFontInfo &other) { qSwap(d, other.d); }
+ void swap(QFontInfo &other) noexcept { d.swap(other.d); }
QString family() const;
QString styleName() const;
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 42c17ced58..f7e405f0b5 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfont.h"
#include "qpaintdevice.h"
@@ -111,15 +75,23 @@ extern void qt_format_text(const QFont& font, const QRectF &_r,
inFont(). You can also treat the character as a string, and use
the string functions on it.
- The string functions include horizontalAdvance(), to return the width of a
- string in pixels (or points, for a printer), boundingRect(), to
- return a rectangle large enough to contain the rendered string,
+ The string functions include horizontalAdvance(), to return the advance
+ width of a string in pixels (or points, for a printer), boundingRect(),
+ to return a rectangle large enough to contain the rendered string,
and size(), to return the size of that rectangle.
+ \note The advance width can be different from the width of the actual
+ rendered text. It refers to the distance from the origin of the string to
+ where you would append additional characters. As text may have overhang
+ (in the case of an italic font for instance) or padding between
+ characters, the advance width can be either smaller or larger than the
+ actual rendering of the text. This is called the right bearing of the
+ text.
+
Example:
\snippet code/src_gui_text_qfontmetrics.cpp 0
- \sa QFont, QFontInfo, QFontDatabase, {Character Map Example}
+ \sa QFont, QFontInfo, QFontDatabase
*/
/*!
@@ -509,10 +481,13 @@ int QFontMetrics::rightBearing(QChar ch) const
return qRound(rb);
}
+static constexpr QLatin1Char s_variableLengthStringSeparator('\x9c');
+
/*!
Returns the horizontal advance in pixels of the first \a len characters of \a
text. If \a len is negative (the default), the entire string is
- used.
+ used. The entire length of \a text is analysed even if \a len is substantially
+ shorter.
This is the distance appropriate for drawing a subsequent character
after \a text.
@@ -523,11 +498,13 @@ int QFontMetrics::rightBearing(QChar ch) const
*/
int QFontMetrics::horizontalAdvance(const QString &text, int len) const
{
- int pos = text.indexOf(QLatin1Char('\x9c'));
+ int pos = (len >= 0)
+ ? QStringView(text).left(len).indexOf(s_variableLengthStringSeparator)
+ : text.indexOf(s_variableLengthStringSeparator);
if (pos != -1) {
- len = (len < 0) ? pos : qMin(pos, len);
+ len = pos;
} else if (len < 0) {
- len = text.length();
+ len = text.size();
}
if (len == 0)
return 0;
@@ -537,6 +514,33 @@ int QFontMetrics::horizontalAdvance(const QString &text, int len) const
}
/*!
+ Returns the horizontal advance in pixels of \a text laid out using \a option.
+
+ The advance is the distance appropriate for drawing a subsequent
+ character after \a text.
+
+ \since 6.3
+
+ \sa boundingRect()
+*/
+int QFontMetrics::horizontalAdvance(const QString &text, const QTextOption &option) const
+{
+ int pos = text.indexOf(s_variableLengthStringSeparator);
+ int len = -1;
+ if (pos != -1) {
+ len = pos;
+ } else {
+ len = text.size();
+ }
+ if (len == 0)
+ return 0;
+
+ QStackTextEngine layout(text, QFont(d.data()));
+ layout.option = option;
+ return qRound(layout.width(0, len));
+}
+
+/*!
\overload
\image bearings.png Bearings
@@ -613,12 +617,48 @@ int QFontMetrics::horizontalAdvance(QChar ch) const
*/
QRect QFontMetrics::boundingRect(const QString &text) const
{
- if (text.length() == 0)
+ if (text.size() == 0)
+ return QRect();
+
+ QStackTextEngine layout(text, QFont(d.data()));
+ layout.itemize();
+ glyph_metrics_t gm = layout.boundingBox(0, text.size());
+ return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
+}
+
+/*!
+ Returns the bounding rectangle of the characters in the string
+ specified by \a text laid out using \a option. The bounding rectangle always
+ covers at least the set of pixels the text would cover if drawn at (0, 0).
+
+ Note that the bounding rectangle may extend to the left of (0, 0),
+ e.g. for italicized fonts, and that the width of the returned
+ rectangle might be different than what the horizontalAdvance() method
+ returns.
+
+ If you want to know the advance width of the string (to lay out
+ a set of strings next to each other), use horizontalAdvance() instead.
+
+ Newline characters are processed as normal characters, \e not as
+ linebreaks.
+
+ The height of the bounding rectangle is at least as large as the
+ value returned by height().
+
+ \since 6.3
+
+ \sa horizontalAdvance(), height(), QPainter::boundingRect(),
+ tightBoundingRect()
+*/
+QRect QFontMetrics::boundingRect(const QString &text, const QTextOption &option) const
+{
+ if (text.size() == 0)
return QRect();
QStackTextEngine layout(text, QFont(d.data()));
+ layout.option = option;
layout.itemize();
- glyph_metrics_t gm = layout.boundingBox(0, text.length());
+ glyph_metrics_t gm = layout.boundingBox(0, text.size());
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
}
@@ -758,8 +798,6 @@ QSize QFontMetrics::size(int flags, const QString &text, int tabStops, int *tabA
}
/*!
- \since 4.3
-
Returns a tight bounding rectangle around the characters in the
string specified by \a text. The bounding rectangle always covers
at least the set of pixels the text would cover if drawn at (0,
@@ -776,21 +814,53 @@ QSize QFontMetrics::size(int flags, const QString &text, int tabStops, int *tabA
Newline characters are processed as normal characters, \e not as
linebreaks.
- \warning Calling this method is very slow on Windows.
+ \since 4.3
\sa horizontalAdvance(), height(), boundingRect()
*/
QRect QFontMetrics::tightBoundingRect(const QString &text) const
{
- if (text.length() == 0)
+ if (text.size() == 0)
return QRect();
QStackTextEngine layout(text, QFont(d.data()));
layout.itemize();
- glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
+ glyph_metrics_t gm = layout.tightBoundingBox(0, text.size());
return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
}
+/*!
+ Returns a tight bounding rectangle around the characters in the
+ string specified by \a text laid out using \a option. The bounding
+ rectangle always covers at least the set of pixels the text would
+ cover if drawn at (0, 0).
+
+ Note that the bounding rectangle may extend to the left of (0, 0),
+ e.g. for italicized fonts, and that the width of the returned
+ rectangle might be different than what the horizontalAdvance() method
+ returns.
+
+ If you want to know the advance width of the string (to lay out
+ a set of strings next to each other), use horizontalAdvance() instead.
+
+ Newline characters are processed as normal characters, \e not as
+ linebreaks.
+
+ \since 6.3
+
+ \sa horizontalAdvance(), height(), boundingRect()
+*/
+QRect QFontMetrics::tightBoundingRect(const QString &text, const QTextOption &option) const
+{
+ if (text.size() == 0)
+ return QRect();
+
+ QStackTextEngine layout(text, QFont(d.data()));
+ layout.option = option;
+ layout.itemize();
+ glyph_metrics_t gm = layout.tightBoundingBox(0, text.size());
+ return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
+}
/*!
\since 4.2
@@ -819,13 +889,13 @@ QString QFontMetrics::elidedText(const QString &text, Qt::TextElideMode mode, in
QString _text = text;
if (!(flags & Qt::TextLongestVariant)) {
int posA = 0;
- int posB = _text.indexOf(QLatin1Char('\x9c'));
+ int posB = _text.indexOf(s_variableLengthStringSeparator);
while (posB >= 0) {
QString portion = _text.mid(posA, posB - posA);
if (size(flags, portion).width() <= width)
return portion;
posA = posB + 1;
- posB = _text.indexOf(QLatin1Char('\x9c'), posA);
+ posB = _text.indexOf(s_variableLengthStringSeparator, posA);
}
_text = _text.mid(posA);
}
@@ -1330,7 +1400,8 @@ qreal QFontMetricsF::rightBearing(QChar ch) const
/*!
Returns the horizontal advance in pixels of the first \a length characters of \a
text. If \a length is negative (the default), the entire string is
- used.
+ used. The entire length of \a text is analysed even if \a length is substantially
+ shorter.
The advance is the distance appropriate for drawing a subsequent
character after \a text.
@@ -1341,11 +1412,13 @@ qreal QFontMetricsF::rightBearing(QChar ch) const
*/
qreal QFontMetricsF::horizontalAdvance(const QString &text, int length) const
{
- int pos = text.indexOf(QLatin1Char('\x9c'));
+ int pos = (length >= 0)
+ ? QStringView(text).left(length).indexOf(s_variableLengthStringSeparator)
+ : text.indexOf(s_variableLengthStringSeparator);
if (pos != -1)
- length = (length < 0) ? pos : qMin(pos, length);
+ length = pos;
else if (length < 0)
- length = text.length();
+ length = text.size();
if (length == 0)
return 0;
@@ -1356,6 +1429,34 @@ qreal QFontMetricsF::horizontalAdvance(const QString &text, int length) const
}
/*!
+ Returns the horizontal advance in pixels of \a text laid out using \a option.
+
+ The advance is the distance appropriate for drawing a subsequent
+ character after \a text.
+
+ \since 6.3
+
+ \sa boundingRect()
+*/
+qreal QFontMetricsF::horizontalAdvance(const QString &text, const QTextOption &option) const
+{
+ int pos = text.indexOf(s_variableLengthStringSeparator);
+ int length = -1;
+ if (pos != -1)
+ length = pos;
+ else
+ length = text.size();
+
+ if (length == 0)
+ return 0;
+
+ QStackTextEngine layout(text, QFont(d.data()));
+ layout.option = option;
+ layout.itemize();
+ return layout.width(0, length).toReal();
+}
+
+/*!
\overload
\image bearings.png Bearings
@@ -1431,7 +1532,7 @@ qreal QFontMetricsF::horizontalAdvance(QChar ch) const
*/
QRectF QFontMetricsF::boundingRect(const QString &text) const
{
- int len = text.length();
+ int len = text.size();
if (len == 0)
return QRectF();
@@ -1443,6 +1544,42 @@ QRectF QFontMetricsF::boundingRect(const QString &text) const
}
/*!
+ Returns the bounding rectangle of the characters in the string
+ specified by \a text laid out using \a option. The bounding
+ rectangle always covers at least the set of pixels the text
+ would cover if drawn at (0, 0).
+
+ Note that the bounding rectangle may extend to the left of (0, 0),
+ e.g. for italicized fonts, and that the width of the returned
+ rectangle might be different than what the horizontalAdvance() method returns.
+
+ If you want to know the advance width of the string (to lay out
+ a set of strings next to each other), use horizontalAdvance() instead.
+
+ Newline characters are processed as normal characters, \e not as
+ linebreaks.
+
+ The height of the bounding rectangle is at least as large as the
+ value returned height().
+
+ \since 6.3
+ \sa horizontalAdvance(), height(), QPainter::boundingRect()
+*/
+QRectF QFontMetricsF::boundingRect(const QString &text, const QTextOption &option) const
+{
+ if (text.size() == 0)
+ return QRectF();
+
+ QStackTextEngine layout(text, QFont(d.data()));
+ layout.option = option;
+ layout.itemize();
+ glyph_metrics_t gm = layout.boundingBox(0, text.size());
+ return QRectF(gm.x.toReal(), gm.y.toReal(),
+ gm.width.toReal(), gm.height.toReal());
+}
+
+
+/*!
Returns the bounding rectangle of the character \a ch relative to
the left-most point on the base line.
@@ -1600,18 +1737,49 @@ QSizeF QFontMetricsF::size(int flags, const QString &text, int tabStops, int *ta
Newline characters are processed as normal characters, \e not as
linebreaks.
- \warning Calling this method is very slow on Windows.
-
\sa horizontalAdvance(), height(), boundingRect()
*/
QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
{
- if (text.length() == 0)
- return QRect();
+ if (text.size() == 0)
+ return QRectF();
+
+ QStackTextEngine layout(text, QFont(d.data()));
+ layout.itemize();
+ glyph_metrics_t gm = layout.tightBoundingBox(0, text.size());
+ return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
+}
+
+/*!
+ Returns a tight bounding rectangle around the characters in the
+ string specified by \a text laid out using \a option. The bounding
+ rectangle always covers at least the set of pixels the text would
+ cover if drawn at (0,0).
+
+ Note that the bounding rectangle may extend to the left of (0, 0),
+ e.g. for italicized fonts, and that the width of the returned
+ rectangle might be different than what the horizontalAdvance() method
+ returns.
+
+ If you want to know the advance width of the string (to lay out
+ a set of strings next to each other), use horizontalAdvance() instead.
+
+ Newline characters are processed as normal characters, \e not as
+ linebreaks.
+
+ \since 6.3
+
+ \sa horizontalAdvance(), height(), boundingRect()
+*/
+QRectF QFontMetricsF::tightBoundingRect(const QString &text, const QTextOption &option) const
+{
+ if (text.size() == 0)
+ return QRectF();
QStackTextEngine layout(text, QFont(d.data()));
+ layout.option = option;
layout.itemize();
- glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
+ glyph_metrics_t gm = layout.tightBoundingBox(0, text.size());
return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
}
@@ -1641,13 +1809,13 @@ QString QFontMetricsF::elidedText(const QString &text, Qt::TextElideMode mode, q
QString _text = text;
if (!(flags & Qt::TextLongestVariant)) {
int posA = 0;
- int posB = _text.indexOf(QLatin1Char('\x9c'));
+ int posB = _text.indexOf(s_variableLengthStringSeparator);
while (posB >= 0) {
QString portion = _text.mid(posA, posB - posA);
if (size(flags, portion).width() <= width)
return portion;
posA = posB + 1;
- posB = _text.indexOf(QLatin1Char('\x9c'), posA);
+ posB = _text.indexOf(s_variableLengthStringSeparator, posA);
}
_text = _text.mid(posA);
}
diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h
index a199e20373..1942d1fa83 100644
--- a/src/gui/text/qfontmetrics.h
+++ b/src/gui/text/qfontmetrics.h
@@ -1,55 +1,21 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTMETRICS_H
#define QFONTMETRICS_H
#include <QtGui/qtguiglobal.h>
#include <QtGui/qfont.h>
-#include <QtCore/qsharedpointer.h>
+
#ifndef QT_INCLUDE_COMPAT
#include <QtCore/qrect.h>
#endif
+#include <QtCore/qshareddata.h>
QT_BEGIN_NAMESPACE
class QRect;
+class QTextOption;
class Q_GUI_EXPORT QFontMetrics
{
@@ -63,7 +29,7 @@ public:
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QFontMetrics)
void swap(QFontMetrics &other) noexcept
- { qSwap(d, other.d); }
+ { d.swap(other.d); }
int ascent() const;
int capHeight() const;
@@ -85,11 +51,13 @@ public:
int rightBearing(QChar) const;
int horizontalAdvance(const QString &, int len = -1) const;
+ int horizontalAdvance(const QString &, const QTextOption &textOption) const;
int horizontalAdvance(QChar) const;
QRect boundingRect(QChar) const;
QRect boundingRect(const QString &text) const;
+ QRect boundingRect(const QString &text, const QTextOption &textOption) const;
QRect boundingRect(const QRect &r, int flags, const QString &text, int tabstops = 0, int *tabarray = nullptr) const;
inline QRect boundingRect(int x, int y, int w, int h, int flags, const QString &text,
int tabstops = 0, int *tabarray = nullptr) const
@@ -97,6 +65,7 @@ public:
QSize size(int flags, const QString& str, int tabstops = 0, int *tabarray = nullptr) const;
QRect tightBoundingRect(const QString &text) const;
+ QRect tightBoundingRect(const QString &text, const QTextOption &textOption) const;
QString elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags = 0) const;
@@ -132,7 +101,7 @@ public:
QFontMetricsF &operator=(const QFontMetrics &);
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QFontMetricsF)
- void swap(QFontMetricsF &other) noexcept { qSwap(d, other.d); }
+ void swap(QFontMetricsF &other) noexcept { d.swap(other.d); }
qreal ascent() const;
qreal capHeight() const;
@@ -155,13 +124,16 @@ public:
qreal horizontalAdvance(const QString &string, int length = -1) const;
qreal horizontalAdvance(QChar) const;
+ qreal horizontalAdvance(const QString &string, const QTextOption &textOption) const;
QRectF boundingRect(const QString &string) const;
+ QRectF boundingRect(const QString &text, const QTextOption &textOption) const;
QRectF boundingRect(QChar) const;
QRectF boundingRect(const QRectF &r, int flags, const QString& string, int tabstops = 0, int *tabarray = nullptr) const;
QSizeF size(int flags, const QString& str, int tabstops = 0, int *tabarray = nullptr) const;
QRectF tightBoundingRect(const QString &text) const;
+ QRectF tightBoundingRect(const QString &text, const QTextOption &textOption) const;
QString elidedText(const QString &text, Qt::TextElideMode mode, qreal width, int flags = 0) const;
diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp
index 93ab5e27db..f6c973e522 100644
--- a/src/gui/text/qfontsubset.cpp
+++ b/src/gui/text/qfontsubset.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfontsubset_p.h"
#include <qdebug.h>
@@ -49,6 +13,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#ifndef QT_NO_PDF
// This map is used for symbol fonts to get the correct glyph names for the latin range
@@ -112,24 +78,6 @@ QByteArray QFontSubset::glyphName(unsigned short unicode, bool symbol)
return buffer;
}
-QByteArray QFontSubset::glyphName(unsigned int glyph, const QList<int> &reverseMap) const
-{
- uint glyphIndex = glyph_indices[glyph];
-
- if (glyphIndex == 0)
- return "/.notdef";
-
- QByteArray ba;
- QPdf::ByteStream s(&ba);
- if (reverseMap[glyphIndex] && reverseMap[glyphIndex] < 0x10000) {
- s << '/' << glyphName(reverseMap[glyphIndex], false);
- } else {
- s << "/gl" << (int)glyphIndex;
- }
- return ba;
-}
-
-
QByteArray QFontSubset::widthArray() const
{
Q_ASSERT(!widths.isEmpty());
@@ -142,7 +90,7 @@ QByteArray QFontSubset::widthArray() const
QFixed defWidth = widths[0];
//qDebug("defWidth=%d, scale=%f", defWidth.toInt(), scale.toReal());
- for (int i = 0; i < nGlyphs(); ++i) {
+ for (qsizetype i = 0; i < nGlyphs(); ++i) {
if (defWidth != widths[i])
defWidth = 0;
}
@@ -150,10 +98,10 @@ QByteArray QFontSubset::widthArray() const
s << "/DW " << qRound(defWidth.toInt() * scale);
} else {
s << "/W [";
- for (int g = 0; g < nGlyphs();) {
+ for (qsizetype g = 0; g < nGlyphs();) {
QFixed w = widths[g];
- int start = g;
- int startLinear = 0;
+ qsizetype start = g;
+ qsizetype startLinear = 0;
++g;
while (g < nGlyphs()) {
QFixed nw = widths[g];
@@ -171,11 +119,11 @@ QByteArray QFontSubset::widthArray() const
// qDebug("start=%x startLinear=%x g-1=%x",start,startLinear,g-1);
if (g - startLinear < 10)
startLinear = 0;
- int endnonlinear = startLinear ? startLinear : g;
+ qsizetype endnonlinear = startLinear ? startLinear : g;
// qDebug(" startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
if (endnonlinear > start) {
s << start << '[';
- for (int i = start; i < endnonlinear; ++i)
+ for (qsizetype i = start; i < endnonlinear; ++i)
s << qRound(widths[i].toInt() * scale);
s << "]\n";
}
@@ -229,14 +177,14 @@ QByteArray QFontSubset::createToUnicodeMap() const
QPdf::ByteStream s(&ranges);
char buf[5];
- for (int g = 1; g < nGlyphs(); ) {
+ for (qsizetype g = 1; g < nGlyphs(); ) {
int uc0 = reverseMap.at(g);
if (!uc0) {
++g;
continue;
}
- int start = g;
- int startLinear = 0;
+ qsizetype start = g;
+ qsizetype startLinear = 0;
++g;
while (g < nGlyphs()) {
int uc = reverseMap[g];
@@ -257,7 +205,7 @@ QByteArray QFontSubset::createToUnicodeMap() const
// qDebug("start=%x startLinear=%x g-1=%x",start,startLinear,g-1);
if (g - startLinear < 10)
startLinear = 0;
- int endnonlinear = startLinear ? startLinear : g;
+ qsizetype endnonlinear = startLinear ? startLinear : g;
// qDebug(" startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
if (endnonlinear > start) {
s << '<' << QPdf::toHex((ushort)start, buf) << "> <";
@@ -266,7 +214,7 @@ QByteArray QFontSubset::createToUnicodeMap() const
s << '<' << QPdf::toHex((ushort)reverseMap[start], buf) << ">\n";
} else {
s << '[';
- for (int i = start; i < endnonlinear; ++i) {
+ for (qsizetype i = start; i < endnonlinear; ++i) {
s << '<' << QPdf::toHex((ushort)reverseMap[i], buf) << "> ";
}
s << "]\n";
@@ -275,9 +223,9 @@ QByteArray QFontSubset::createToUnicodeMap() const
}
if (startLinear) {
while (startLinear < g) {
- int len = g - startLinear;
- int uc_start = reverseMap[startLinear];
- int uc_end = uc_start + len - 1;
+ qsizetype len = g - startLinear;
+ qsizetype uc_start = reverseMap[startLinear];
+ qsizetype uc_end = uc_start + len - 1;
if ((uc_end >> 8) != (uc_start >> 8))
len = 256 - (uc_start & 0xff);
s << '<' << QPdf::toHex((ushort)startLinear, buf) << "> <";
@@ -300,14 +248,14 @@ QByteArray QFontSubset::createToUnicodeMap() const
return touc;
}
-int QFontSubset::addGlyph(uint index)
+qsizetype QFontSubset::addGlyph(uint index)
{
qsizetype idx = glyph_indices.indexOf(index);
if (idx < 0) {
idx = glyph_indices.size();
glyph_indices.append(index);
}
- return (int)idx;
+ return idx;
}
#endif // QT_NO_PDF
@@ -453,7 +401,7 @@ static QTtfTable generateHead(const qttf_head_table &head)
{
const int head_size = 54;
QTtfTable t;
- t.tag = MAKE_TAG('h', 'e', 'a', 'd');
+ t.tag = QFont::Tag("head").value();
t.data.resize(head_size);
QTtfStream s(t.data);
@@ -524,7 +472,7 @@ static QTtfTable generateHhea(const qttf_hhea_table &hhea)
{
const int hhea_size = 36;
QTtfTable t;
- t.tag = MAKE_TAG('h', 'h', 'e', 'a');
+ t.tag = QFont::Tag("hhea").value();
t.data.resize(hhea_size);
QTtfStream s(t.data);
@@ -575,7 +523,7 @@ static QTtfTable generateMaxp(const qttf_maxp_table &maxp)
{
const int maxp_size = 32;
QTtfTable t;
- t.tag = MAKE_TAG('m', 'a', 'x', 'p');
+ t.tag = QFont::Tag("maxp").value();
t.data.resize(maxp_size);
QTtfStream s(t.data);
@@ -639,8 +587,8 @@ static QTtfTable generateName(const qttf_name_table &name)
list.append(rec);
rec.nameId = 4;
rec.value = name.family;
- if (name.subfamily != QLatin1String("Regular"))
- rec.value += QLatin1Char(' ') + name.subfamily;
+ if (name.subfamily != "Regular"_L1)
+ rec.value += u' ' + name.subfamily;
list.append(rec);
rec.nameId = 6;
rec.value = name.postscript_name;
@@ -655,12 +603,12 @@ static QTtfTable generateName(const QList<QTtfNameRecord> &name)
const int char_size = 2;
QTtfTable t;
- t.tag = MAKE_TAG('n', 'a', 'm', 'e');
+ t.tag = QFont::Tag("name").value();
const int name_size = 6 + 12*name.size();
int string_size = 0;
for (int i = 0; i < name.size(); ++i) {
- string_size += name.at(i).value.length()*char_size;
+ string_size += name.at(i).value.size()*char_size;
}
t.data.resize(name_size + string_size);
@@ -676,7 +624,7 @@ static QTtfTable generateName(const QList<QTtfNameRecord> &name)
int off = 0;
for (int i = 0; i < name.size(); ++i) {
- int len = name.at(i).value.length()*char_size;
+ int len = name.at(i).value.size()*char_size;
// quint16 platformID Platform ID.
// quint16 encodingID Platform-specific encoding ID.
// quint16 languageID Language ID.
@@ -692,12 +640,8 @@ static QTtfTable generateName(const QList<QTtfNameRecord> &name)
off += len;
}
for (int i = 0; i < name.size(); ++i) {
- const QString &n = name.at(i).value;
- const ushort *uc = n.utf16();
- for (int i = 0; i < n.length(); ++i) {
- s << quint16(*uc);
- ++uc;
- }
+ for (QChar ch : name.at(i).value)
+ s << quint16(ch.unicode());
}
return t;
}
@@ -1014,15 +958,15 @@ static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QLis
tables.hhea.numberOfHMetrics = nGlyphs;
QTtfTable glyf;
- glyf.tag = MAKE_TAG('g', 'l', 'y', 'f');
+ glyf.tag = QFont::Tag("glyf").value();
QTtfTable loca;
- loca.tag = MAKE_TAG('l', 'o', 'c', 'a');
+ loca.tag = QFont::Tag("loca").value();
loca.data.resize(glyf_size < max_size_small ? (nGlyphs+1)*sizeof(quint16) : (nGlyphs+1)*sizeof(quint32));
QTtfStream ls(loca.data);
QTtfTable hmtx;
- hmtx.tag = MAKE_TAG('h', 'm', 't', 'x');
+ hmtx.tag = QFont::Tag("hmtx").value();
hmtx.data.resize(nGlyphs*4);
QTtfStream hs(hmtx.data);
@@ -1122,7 +1066,7 @@ static QByteArray bindFont(const QList<QTtfTable>& _tables)
for (int i = 0; i < tables.size(); ++i) {
const QTtfTable &t = tables.at(i);
const quint32 size = (t.data.size() + 3) & ~3;
- if (t.tag == MAKE_TAG('h', 'e', 'a', 'd'))
+ if (t.tag == QFont::Tag("head").value())
head_offset = table_offset;
f << t.tag
<< checksum(t.data)
@@ -1203,13 +1147,12 @@ QByteArray QFontSubset::toTruetype() const
font.maxp.maxCompositeContours = 0;
font.maxp.maxComponentElements = 0;
font.maxp.maxComponentDepth = 0;
- const int numGlyphs = nGlyphs();
- font.maxp.numGlyphs = numGlyphs;
+ const qsizetype numGlyphs = nGlyphs();
+ font.maxp.numGlyphs = quint16(numGlyphs);
QList<QTtfGlyph> glyphs;
glyphs.reserve(numGlyphs);
- uint sumAdvances = 0;
- for (int i = 0; i < numGlyphs; ++i) {
+ for (qsizetype i = 0; i < numGlyphs; ++i) {
glyph_t g = glyph_indices.at(i);
QPainterPath path;
glyph_metrics_t metric;
@@ -1231,9 +1174,6 @@ QByteArray QFontSubset::toTruetype() const
font.maxp.maxPoints = qMax(font.maxp.maxPoints, glyph.numPoints);
font.maxp.maxContours = qMax(font.maxp.maxContours, glyph.numContours);
- if (glyph.xMax > glyph.xMin)
- sumAdvances += glyph.xMax - glyph.xMin;
-
// qDebug("adding glyph %d size=%d", glyph.index, glyph.data.size());
glyphs.append(glyph);
widths[i] = glyph.advanceWidth;
@@ -1246,25 +1186,25 @@ QByteArray QFontSubset::toTruetype() const
tables.append(generateMaxp(font.maxp));
// name
QTtfTable name_table;
- name_table.tag = MAKE_TAG('n', 'a', 'm', 'e');
+ name_table.tag = QFont::Tag("name").value();
if (!noEmbed)
name_table.data = fontEngine->getSfntTable(name_table.tag);
if (name_table.data.isEmpty()) {
qttf_name_table name;
if (noEmbed)
- name.copyright = QLatin1String("Fake font");
+ name.copyright = "Fake font"_L1;
else
- name.copyright = QLatin1String(properties.copyright);
- name.family = fontEngine->fontDef.families.first();
- name.subfamily = QLatin1String("Regular"); // ######
- name.postscript_name = QLatin1String(properties.postscriptName);
+ name.copyright = QLatin1StringView(properties.copyright);
+ name.family = fontEngine->fontDef.families.constFirst();
+ name.subfamily = "Regular"_L1; // ######
+ name.postscript_name = QLatin1StringView(properties.postscriptName);
name_table = generateName(name);
}
tables.append(name_table);
if (!noEmbed) {
QTtfTable os2;
- os2.tag = MAKE_TAG('O', 'S', '/', '2');
+ os2.tag = QFont::Tag("OS/2").value();
os2.data = fontEngine->getSfntTable(os2.tag);
if (!os2.data.isEmpty())
tables.append(os2);
diff --git a/src/gui/text/qfontsubset_agl.cpp b/src/gui/text/qfontsubset_agl.cpp
index d96808703a..603f277d3f 100644
--- a/src/gui/text/qfontsubset_agl.cpp
+++ b/src/gui/text/qfontsubset_agl.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/* This file is autogenerated from the Adobe Glyph List database v1.7. Do not edit */
diff --git a/src/gui/text/qfontsubset_p.h b/src/gui/text/qfontsubset_p.h
index c8ff94da78..1ec47f176d 100644
--- a/src/gui/text/qfontsubset_p.h
+++ b/src/gui/text/qfontsubset_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTSUBSET_P_H
#define QFONTSUBSET_P_H
@@ -77,11 +41,10 @@ public:
QByteArray widthArray() const;
QByteArray createToUnicodeMap() const;
QList<int> getReverseMap() const;
- QByteArray glyphName(unsigned int glyph, const QList<int> &reverseMap) const;
static QByteArray glyphName(unsigned short unicode, bool symbol);
- int addGlyph(uint index);
+ qsizetype addGlyph(uint index);
#endif
const uint object_id;
bool noEmbed;
@@ -89,7 +52,7 @@ public:
QList<uint> glyph_indices;
mutable int downloaded_glyphs;
mutable bool standard_font;
- int nGlyphs() const { return glyph_indices.size(); }
+ qsizetype nGlyphs() const { return glyph_indices.size(); }
mutable QFixed emSquare;
mutable QList<QFixed> widths;
};
diff --git a/src/gui/text/qfragmentmap.cpp b/src/gui/text/qfragmentmap.cpp
index 7dd8999d58..4d55b009d7 100644
--- a/src/gui/text/qfragmentmap.cpp
+++ b/src/gui/text/qfragmentmap.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qtools_p.h>
diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h
index 1d781352f8..af884d1f62 100644
--- a/src/gui/text/qfragmentmap_p.h
+++ b/src/gui/text/qfragmentmap_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFRAGMENTMAP_P_H
#define QFRAGMENTMAP_P_H
diff --git a/src/gui/text/qglyphrun.cpp b/src/gui/text/qglyphrun.cpp
index 8982e2e1c4..4252d9e7f1 100644
--- a/src/gui/text/qglyphrun.cpp
+++ b/src/gui/text/qglyphrun.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
@@ -434,7 +398,7 @@ void QGlyphRun::setFlags(GlyphRunFlags flags)
/*!
Sets the bounding rect of the glyphs in this QGlyphRun to be \a boundingRect. This rectangle
- will be returned by boundingRect() unless it is empty, in which case the bounding rectangle of the
+ will be returned by boundingRect() unless it is null, in which case the bounding rectangle of the
glyphs in the glyph run will be returned instead.
\note Unless you are implementing text shaping, you should not have to use this function.
@@ -468,7 +432,7 @@ void QGlyphRun::setBoundingRect(const QRectF &boundingRect)
*/
QRectF QGlyphRun::boundingRect() const
{
- if (!d->boundingRect.isEmpty() || !d->rawFont.isValid())
+ if (!d->boundingRect.isNull() || !d->rawFont.isValid())
return d->boundingRect;
qreal minX, minY, maxX, maxY;
@@ -501,7 +465,80 @@ QRectF QGlyphRun::boundingRect() const
*/
bool QGlyphRun::isEmpty() const
{
- return d->glyphIndexDataSize == 0;
+ return d->glyphIndexDataSize == 0
+ && d->glyphPositionDataSize == 0
+ && d->stringIndexes.isEmpty()
+ && d->sourceString.isEmpty();
+}
+
+/*!
+ \since 6.5
+
+ Returns the string indexes corresponding to each glyph index, if the glyph run has been
+ constructed from a string and string indexes have been requested from the layout. In this case,
+ the length of the returned vector will correspond to the length of glyphIndexes(). In other
+ cases, it will be empty.
+
+ Since a single glyph may correspond to multiple characters in the source string, there may be
+ gaps in the list of string indexes. For instance, if the string "first" is processed by a font
+ which contains a ligature for the character pair "fi", then the five character string will
+ generate a glyph run consisting of only four glyphs. Then the glyph indexes may in this case be
+ (1, 2, 3, 4) (four arbitrary glyph indexes) whereas the string indexes would be (0, 2, 3, 4).
+ The glyphs are in the logical order of the string, thus it is implied that the first glyphs
+ spans characters 0 and 1 in this case.
+
+ Inversely, a single character may also generate multiple glyphs, in which case there will be
+ duplicate entries in the list of string indexes.
+
+ The string indexes correspond to the string, optionally available through sourceString().
+
+ \sa setStringIndexes(), sourceString(), QTextLayout::glyphRuns()
+*/
+QList<qsizetype> QGlyphRun::stringIndexes() const
+{
+ return d->stringIndexes;
+}
+
+/*!
+ \since 6.5
+
+ Sets the list of string indexes corresponding to the glyph indexes to \a stringIndexes
+
+ See stringIndexes() for more details on the conventions of this list.
+
+ \sa sourceString()
+ */
+void QGlyphRun::setStringIndexes(const QList<qsizetype> &stringIndexes)
+{
+ detach();
+ d->stringIndexes = stringIndexes;
+}
+
+/*!
+ \since 6.5
+
+ Returns the string corresponding to the glyph run, if the glyph run has been created from
+ a string and the string has been requested from the layout.
+
+ \sa setSourceString(), stringIndexes(), QTextLayout::glyphRuns()
+ */
+QString QGlyphRun::sourceString() const
+{
+ return d->sourceString;
+}
+
+/*!
+ \since 6.5
+
+ Set the string corresponding to the glyph run to \a sourceString. If set, the indexes returned
+ by stringIndexes() should be indexes into this string.
+
+ \sa sourceString(), stringIndexes()
+ */
+void QGlyphRun::setSourceString(const QString &sourceString)
+{
+ detach();
+ d->sourceString = sourceString;
}
QT_END_NAMESPACE
diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h
index 0e9f0ce468..88f9957dd8 100644
--- a/src/gui/text/qglyphrun.h
+++ b/src/gui/text/qglyphrun.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGLYPHRUN_H
#define QGLYPHRUN_H
@@ -43,8 +7,8 @@
#include <QtGui/qtguiglobal.h>
#include <QtCore/qlist.h>
#include <QtCore/qpoint.h>
-#include <QtCore/qsharedpointer.h>
#include <QtGui/qrawfont.h>
+#include <QtCore/qshareddata.h>
#if !defined(QT_NO_RAWFONT)
@@ -70,7 +34,7 @@ public:
QGlyphRun &operator=(const QGlyphRun &other);
~QGlyphRun();
- void swap(QGlyphRun &other) noexcept { qSwap(d, other.d); }
+ void swap(QGlyphRun &other) noexcept { d.swap(other.d); }
QRawFont rawFont() const;
void setRawFont(const QRawFont &rawFont);
@@ -110,6 +74,12 @@ public:
void setBoundingRect(const QRectF &boundingRect);
QRectF boundingRect() const;
+ QList<qsizetype> stringIndexes() const;
+ void setStringIndexes(const QList<qsizetype> &stringIndexes);
+
+ void setSourceString(const QString &sourceString);
+ QString sourceString() const;
+
bool isEmpty() const;
private:
diff --git a/src/gui/text/qglyphrun_p.h b/src/gui/text/qglyphrun_p.h
index 77943fc0c0..db160344c6 100644
--- a/src/gui/text/qglyphrun_p.h
+++ b/src/gui/text/qglyphrun_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGLYPHRUN_P_H
#define QGLYPHRUN_P_H
@@ -51,6 +15,7 @@
// We mean it.
//
+#include <QtCore/qshareddata.h>
#include <QtGui/private/qtguiglobal_p.h>
#include "qglyphrun.h"
#include "qrawfont.h"
@@ -78,8 +43,10 @@ public:
: QSharedData(other)
, glyphIndexes(other.glyphIndexes)
, glyphPositions(other.glyphPositions)
+ , stringIndexes(other.stringIndexes)
, rawFont(other.rawFont)
, boundingRect(other.boundingRect)
+ , sourceString(other.sourceString)
, flags(other.flags)
, glyphIndexData(other.glyphIndexData)
, glyphIndexDataSize(other.glyphIndexDataSize)
@@ -92,8 +59,10 @@ public:
QList<quint32> glyphIndexes;
QList<QPointF> glyphPositions;
+ QList<qsizetype> stringIndexes;
QRawFont rawFont;
QRectF boundingRect;
+ QString sourceString;
QGlyphRun::GlyphRunFlags flags;
diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp
index 66d5def056..5db6f78319 100644
--- a/src/gui/text/qharfbuzzng.cpp
+++ b/src/gui/text/qharfbuzzng.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2013 Konstantin Ritt
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2013 Konstantin Ritt
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qharfbuzzng_p.h"
@@ -242,7 +206,29 @@ static const hb_script_t _qtscript_to_hbscript[] = {
HB_SCRIPT_CHORASMIAN,
HB_SCRIPT_DIVES_AKURU,
HB_SCRIPT_KHITAN_SMALL_SCRIPT,
- HB_SCRIPT_YEZIDI
+ HB_SCRIPT_YEZIDI,
+#endif
+ // Unicode 14.0 additions (not present in harfbuzz-ng 2.9.1 and earlier)
+#if !HB_VERSION_ATLEAST(3, 0, 0)
+ hb_script_t(HB_TAG('C','p','m','n')), // Script_CyproMinoan
+ hb_script_t(HB_TAG('O','u','g','r')), // Script_OldUyghur
+ hb_script_t(HB_TAG('T','n','s','a')), // Script_Tangsa
+ hb_script_t(HB_TAG('T','o','t','o')), // Script_Toto
+ hb_script_t(HB_TAG('V','i','t','h')), // Script_Vithkuqi
+#else
+ HB_SCRIPT_CYPRO_MINOAN,
+ HB_SCRIPT_OLD_UYGHUR,
+ HB_SCRIPT_TANGSA,
+ HB_SCRIPT_TOTO,
+ HB_SCRIPT_VITHKUQI,
+#endif
+ // Unicode 15.0 additions (not present in harfbuzz-ng 5.1.0 and earlier)
+#if !HB_VERSION_ATLEAST(5, 2, 0)
+ hb_script_t(HB_TAG('K','a','w','i')), // Script_Kawi
+ hb_script_t(HB_TAG('N','a','g','m')), // Script_NagMundari
+#else
+ HB_SCRIPT_KAWI,
+ HB_SCRIPT_NAG_MUNDARI,
#endif
};
static_assert(QChar::ScriptCount == sizeof(_qtscript_to_hbscript) / sizeof(_qtscript_to_hbscript[0]));
diff --git a/src/gui/text/qharfbuzzng_p.h b/src/gui/text/qharfbuzzng_p.h
index a7cd84fedc..a46251a4c4 100644
--- a/src/gui/text/qharfbuzzng_p.h
+++ b/src/gui/text/qharfbuzzng_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2013 Konstantin Ritt
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2013 Konstantin Ritt
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QHARFBUZZNG_P_H
#define QHARFBUZZNG_P_H
diff --git a/src/gui/text/qinputcontrol.cpp b/src/gui/text/qinputcontrol.cpp
index 80d5e6af4e..4edd46ff0e 100644
--- a/src/gui/text/qinputcontrol.cpp
+++ b/src/gui/text/qinputcontrol.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qinputcontrol_p.h"
#include <QtGui/qevent.h>
@@ -79,10 +43,10 @@ bool QInputControl::isAcceptableInput(const QKeyEvent *event) const
if (c.category() == QChar::Other_PrivateUse)
return true;
- if (c.isHighSurrogate() && text.length() > 1 && text.at(1).isLowSurrogate())
+ if (c.isHighSurrogate() && text.size() > 1 && text.at(1).isLowSurrogate())
return true;
- if (m_type == TextEdit && c == QLatin1Char('\t'))
+ if (m_type == TextEdit && c == u'\t')
return true;
return false;
@@ -140,3 +104,5 @@ bool QInputControl::isCommonTextEditShortcut(const QKeyEvent *ke)
}
QT_END_NAMESPACE
+
+#include "moc_qinputcontrol_p.cpp"
diff --git a/src/gui/text/qinputcontrol_p.h b/src/gui/text/qinputcontrol_p.h
index b4c1ca8f8f..fec73e1987 100644
--- a/src/gui/text/qinputcontrol_p.h
+++ b/src/gui/text/qinputcontrol_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QINPUTCONTROL_P_H
#define QINPUTCONTROL_P_H
@@ -53,6 +17,7 @@
#include <QtCore/qobject.h>
#include <qtguiglobal.h>
+#include <private/qglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp
index 21d43a249f..a146254f68 100644
--- a/src/gui/text/qplatformfontdatabase.cpp
+++ b/src/gui/text/qplatformfontdatabase.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformfontdatabase.h"
#include <QtGui/private/qfontengine_p.h>
@@ -53,6 +17,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcQpaFonts, "qt.qpa.fonts")
void qt_registerFont(const QString &familyname, const QString &stylename,
@@ -162,11 +128,31 @@ QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWr
return *this;
}
+bool operator==(const QSupportedWritingSystems &lhs, const QSupportedWritingSystems &rhs)
+{
+ return !(lhs != rhs);
+}
+
+bool operator!=(const QSupportedWritingSystems &lhs, const QSupportedWritingSystems &rhs)
+{
+ if (lhs.d == rhs.d)
+ return false;
+
+ Q_ASSERT(lhs.d->list.size() == rhs.d->list.size());
+ Q_ASSERT(lhs.d->list.size() == QFontDatabase::WritingSystemsCount);
+ for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
+ if (lhs.d->list.at(i) != rhs.d->list.at(i))
+ return true;
+ }
+
+ return false;
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QSupportedWritingSystems &sws)
{
- QMetaObject mo = QFontDatabase::staticMetaObject;
- QMetaEnum me = mo.enumerator(mo.indexOfEnumerator("WritingSystem"));
+ const QMetaObject *mo = &QFontDatabase::staticMetaObject;
+ QMetaEnum me = mo->enumerator(mo->indexOfEnumerator("WritingSystem"));
QDebugStateSaver saver(debug);
debug.nospace() << "QSupportedWritingSystems(";
@@ -293,6 +279,17 @@ QFontEngineMulti *QPlatformFontDatabase::fontEngineMulti(QFontEngine *fontEngine
/*!
Returns the font engine that can be used to render the font described by
the font definition, \a fontDef, in the specified \a script.
+
+ This function is called by QFontDatabase both for system fonts provided
+ by the platform font database, as well as for application fonts added by
+ the application developer.
+
+ The handle is the QPlatformFontDatabase specific handle passed when
+ registering the font family via QPlatformFontDatabase::registerFont.
+
+ The function is called for both fonts added via a filename as well
+ as fonts added from QByteArray data. Subclasses will need to handle
+ both cases via its platform specific handle.
*/
QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{
@@ -302,6 +299,13 @@ QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, void *ha
return nullptr;
}
+/*!
+ Returns the font engine that will be used to back a QRawFont,
+ based on the given \fontData, \a pixelSize, and \a hintingPreference.
+
+ This function is called by QRawFont, and does not play a part in
+ the normal operations of QFontDatabase.
+*/
QFontEngine *QPlatformFontDatabase::fontEngine(const QByteArray &fontData, qreal pixelSize,
QFont::HintingPreference hintingPreference)
{
@@ -357,7 +361,7 @@ QString QPlatformFontDatabase::fontDir() const
{
QString fontpath = QString::fromLocal8Bit(qgetenv("QT_QPA_FONTDIR"));
if (fontpath.isEmpty())
- fontpath = QLibraryInfo::path(QLibraryInfo::LibrariesPath) + QLatin1String("/fonts");
+ fontpath = QLibraryInfo::path(QLibraryInfo::LibrariesPath) + "/fonts"_L1;
return fontpath;
}
@@ -381,7 +385,7 @@ bool QPlatformFontDatabase::isPrivateFontFamily(const QString &family) const
QFont QPlatformFontDatabase::defaultFont() const
{
- return QFont(QLatin1String("Helvetica"));
+ return QFont("Helvetica"_L1);
}
@@ -614,6 +618,24 @@ void QPlatformFontDatabase::registerAliasToFontFamily(const QString &familyName,
}
/*!
+ Requests that the platform font database should be repopulated.
+
+ This will result in invalidating the entire font database.
+
+ The next time the font database is accessed it will be repopulated
+ via a call to QPlatformFontDatabase::populate().
+
+ Application fonts will not be removed, and will be automatically
+ populated when the font database is repopulated.
+
+ \since 6.4
+*/
+void QPlatformFontDatabase::repopulateFontDatabase()
+{
+ QFontDatabasePrivate::instance()->invalidate();
+}
+
+/*!
Helper function that returns true if the font family has already been registered and populated.
\since 5.14
@@ -624,6 +646,18 @@ bool QPlatformFontDatabase::isFamilyPopulated(const QString &familyName)
}
/*!
+ Returns true if this font database supports loading named instances from variable application
+ fonts.
+
+ \since 6.7
+*/
+bool QPlatformFontDatabase::supportsVariableApplicationFonts() const
+{
+ return false;
+}
+
+
+/*!
\class QPlatformFontDatabase
\since 5.0
\internal
diff --git a/src/gui/text/qplatformfontdatabase.h b/src/gui/text/qplatformfontdatabase.h
index 74b9e1ba12..3007a11838 100644
--- a/src/gui/text/qplatformfontdatabase.h
+++ b/src/gui/text/qplatformfontdatabase.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMFONTDATABASE_H
#define QPLATFORMFONTDATABASE_H
@@ -61,7 +25,7 @@
QT_BEGIN_NAMESPACE
-Q_DECLARE_LOGGING_CATEGORY(lcQpaFonts)
+Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcQpaFonts, Q_GUI_EXPORT)
class QWritingSystemsPrivate;
@@ -108,13 +72,13 @@ public:
virtual void populateFamily(const QString &familyName);
virtual void invalidate();
- virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script);
- virtual QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
virtual QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const;
virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *font = nullptr);
- virtual void releaseHandle(void *handle);
+ virtual QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
virtual QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
+ virtual QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script);
+ virtual void releaseHandle(void *handle);
virtual QString fontDir() const;
@@ -125,6 +89,8 @@ public:
virtual bool fontsAlwaysScalable() const;
virtual QList<int> standardSizes() const;
+ virtual bool supportsVariableApplicationFonts() const;
+
// helper
static QSupportedWritingSystems writingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2]);
static QSupportedWritingSystems writingSystemsFromOS2Table(const char *os2Table, size_t length);
@@ -139,6 +105,8 @@ public:
static void registerFontFamily(const QString &familyName);
static void registerAliasToFontFamily(const QString &familyName, const QString &alias);
+ static void repopulateFontDatabase();
+
static bool isFamilyPopulated(const QString &familyName);
};
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index 462c60b1f6..c5a92f95cb 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
@@ -476,7 +440,7 @@ qreal QRawFont::underlinePosition() const
*/
QString QRawFont::familyName() const
{
- return d->isValid() ? d->fontEngine->fontDef.families.first() : QString();
+ return d->isValid() ? d->fontEngine->fontDef.families.constFirst() : QString();
}
/*!
@@ -668,17 +632,33 @@ QFont::HintingPreference QRawFont::hintingPreference() const
}
/*!
- Retrieves the sfnt table named \a tagName from the underlying physical font, or an empty
- byte array if no such table was found. The returned font table's byte order is Big Endian, like
- the sfnt format specifies. The \a tagName must be four characters long and should be formatted
- in the default endianness of the current platform.
+ \fn QByteArray QRawFont::fontTable(const char *tag) const
+ \overload fontTable(QFont::Tag)
+
+ The name must be a four-character string.
+*/
+
+/*!
+ \fn QByteArray QRawFont::fontTable(QFont::Tag tag) const
+ \since 6.7
+
+ Retrieves the sfnt table specified by \a tag from the underlying physical font,
+ or an empty byte array if no such table was found. The returned font table's byte order is
+ Big Endian, like the sfnt format specifies.
*/
-QByteArray QRawFont::fontTable(const char *tagName) const
+QByteArray QRawFont::fontTable(const char *tag) const
+{
+ if (auto maybeTag = QFont::Tag::fromString(tag))
+ return fontTable(*maybeTag);
+ return QByteArray();
+}
+
+QByteArray QRawFont::fontTable(QFont::Tag tag) const
{
if (!d->isValid())
return QByteArray();
- return d->fontEngine->getSfntTable(MAKE_TAG(tagName[0], tagName[1], tagName[2], tagName[3]));
+ return d->fontEngine->getSfntTable(tag.value());
}
/*!
@@ -770,7 +750,7 @@ QRawFont QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writ
QFontDef request(multiEngine->fontDef);
request.styleStrategy |= QFont::NoFontMerging;
- if (QFontEngine *engine = QFontDatabasePrivate::findFont(request, script)) {
+ if (QFontEngine *engine = QFontDatabasePrivate::findFont(request, script, true)) {
if (request.weight > QFont::Normal)
engine->fontDef.weight = request.weight;
if (request.style > QFont::StyleNormal)
diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h
index 51f7ba8044..d23d0c1493 100644
--- a/src/gui/text/qrawfont.h
+++ b/src/gui/text/qrawfont.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRAWFONT_H
#define QRAWFONT_H
@@ -83,7 +47,7 @@ public:
QRawFont &operator=(const QRawFont &other);
~QRawFont();
- void swap(QRawFont &other) noexcept { qSwap(d, other.d); }
+ void swap(QRawFont &other) noexcept { d.swap(other.d); }
bool isValid() const;
@@ -141,6 +105,7 @@ public:
QList<QFontDatabase::WritingSystem> supportedWritingSystems() const;
QByteArray fontTable(const char *tagName) const;
+ QByteArray fontTable(QFont::Tag tag) const;
static QRawFont fromFont(const QFont &font,
QFontDatabase::WritingSystem writingSystem = QFontDatabase::Any);
@@ -163,7 +128,7 @@ inline QList<QPointF> QRawFont::advancesForGlyphIndexes(const QList<quint32> &gl
QRawFont::LayoutFlags layoutFlags) const
{
QList<QPointF> advances(glyphIndexes.size());
- if (advancesForGlyphIndexes(glyphIndexes.constData(), advances.data(), glyphIndexes.size(), layoutFlags))
+ if (advancesForGlyphIndexes(glyphIndexes.constData(), advances.data(), int(glyphIndexes.size()), layoutFlags))
return advances;
return QList<QPointF>();
}
diff --git a/src/gui/text/qrawfont_p.h b/src/gui/text/qrawfont_p.h
index 03259a94ed..c69ea6dad2 100644
--- a/src/gui/text/qrawfont_p.h
+++ b/src/gui/text/qrawfont_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QRAWFONTPRIVATE_P_H
#define QRAWFONTPRIVATE_P_H
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
index b702764688..eb7d19d64e 100644
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qstatictext.h"
#include "qstatictext_p.h"
@@ -46,6 +10,8 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QStaticText)
+
QStaticTextUserData::~QStaticTextUserData()
{
}
diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h
index 778861ed79..7c8d8f8734 100644
--- a/src/gui/text/qstatictext.h
+++ b/src/gui/text/qstatictext.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTATICTEXT_H
#define QSTATICTEXT_H
@@ -68,7 +32,7 @@ public:
QStaticText &operator=(const QStaticText &);
~QStaticText();
- void swap(QStaticText &other) noexcept { qSwap(data, other.data); }
+ void swap(QStaticText &other) noexcept { data.swap(other.data); }
void setText(const QString &text);
QString text() const;
@@ -103,6 +67,6 @@ Q_DECLARE_SHARED(QStaticText)
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QStaticText)
+QT_DECL_METATYPE_EXTERN(QStaticText, Q_GUI_EXPORT)
#endif // QSTATICTEXT_H
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
index 1d79148bdc..cbf13e7b06 100644
--- a/src/gui/text/qstatictext_p.h
+++ b/src/gui/text/qstatictext_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSTATICTEXT_P_H
#define QSTATICTEXT_P_H
diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp
index 9e7a7c4d2c..6c1e2e74fc 100644
--- a/src/gui/text/qsyntaxhighlighter.cpp
+++ b/src/gui/text/qsyntaxhighlighter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qsyntaxhighlighter.h"
@@ -102,7 +66,7 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
QList<QTextLayout::FormatRange> ranges = layout->formats();
const int preeditAreaStart = layout->preeditAreaPosition();
- const int preeditAreaLength = layout->preeditAreaText().length();
+ const int preeditAreaLength = layout->preeditAreaText().size();
if (preeditAreaLength != 0) {
auto isOutsidePreeditArea = [=](const QTextLayout::FormatRange &range) {
@@ -117,22 +81,22 @@ void QSyntaxHighlighterPrivate::applyFormatChanges()
}
int i = 0;
- while (i < formatChanges.count()) {
+ while (i < formatChanges.size()) {
QTextLayout::FormatRange r;
- while (i < formatChanges.count() && formatChanges.at(i) == r.format)
+ while (i < formatChanges.size() && formatChanges.at(i) == r.format)
++i;
- if (i == formatChanges.count())
+ if (i == formatChanges.size())
break;
r.start = i;
r.format = formatChanges.at(i);
- while (i < formatChanges.count() && formatChanges.at(i) == r.format)
+ while (i < formatChanges.size() && formatChanges.at(i) == r.format)
++i;
- Q_ASSERT(i <= formatChanges.count());
+ Q_ASSERT(i <= formatChanges.size());
r.length = i - r.start;
if (preeditAreaLength != 0) {
@@ -255,7 +219,7 @@ void QSyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block)
an int value. If no state is set, the returned value is -1. You
can designate any other value to identify any given state using
the setCurrentBlockState() function. Once the state is set the
- QTextBlock keeps that value until it is set set again or until the
+ QTextBlock keeps that value until it is set again or until the
corresponding paragraph of text is deleted.
For example, if you're writing a simple C++ syntax highlighter,
@@ -439,10 +403,10 @@ void QSyntaxHighlighter::rehighlightBlock(const QTextBlock &block)
void QSyntaxHighlighter::setFormat(int start, int count, const QTextCharFormat &format)
{
Q_D(QSyntaxHighlighter);
- if (start < 0 || start >= d->formatChanges.count())
+ if (start < 0 || start >= d->formatChanges.size())
return;
- const int end = qMin(start + count, d->formatChanges.count());
+ const int end = qMin(start + count, d->formatChanges.size());
for (int i = start; i < end; ++i)
d->formatChanges[i] = format;
}
@@ -492,7 +456,7 @@ void QSyntaxHighlighter::setFormat(int start, int count, const QFont &font)
QTextCharFormat QSyntaxHighlighter::format(int pos) const
{
Q_D(const QSyntaxHighlighter);
- if (pos < 0 || pos >= d->formatChanges.count())
+ if (pos < 0 || pos >= d->formatChanges.size())
return QTextCharFormat();
return d->formatChanges.at(pos);
}
diff --git a/src/gui/text/qsyntaxhighlighter.h b/src/gui/text/qsyntaxhighlighter.h
index ad0d50a4c0..3ce0e60e15 100644
--- a/src/gui/text/qsyntaxhighlighter.h
+++ b/src/gui/text/qsyntaxhighlighter.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QSYNTAXHIGHLIGHTER_H
#define QSYNTAXHIGHLIGHTER_H
diff --git a/src/gui/text/qt_attribution.json b/src/gui/text/qt_attribution.json
index c3a57267e2..f4998da6ea 100644
--- a/src/gui/text/qt_attribution.json
+++ b/src/gui/text/qt_attribution.json
@@ -5,7 +5,7 @@
"QDocModule": "qtgui",
"Description": "Provides standardized names for glyphs.",
"QtUsage": "Used by PDF generator to make it easier for reader applications to resolve the original contents of rendered text.",
- "Path": "qfontsubset_agl.cpp",
+ "Files": "qfontsubset_agl.cpp",
"Homepage": "https://github.com/adobe-type-tools/agl-aglfn",
"Version": "1.7",
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index a27ef81500..5730f55e6a 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextcursor.h"
#include "qtextcursor_p.h"
@@ -612,7 +576,7 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor
++row;
}
cell = table->cellAt(row, column);
- // note we also continue while we have not reached a cell thats not merged with one above us
+ // note we also continue while we have not reached a cell that's not merged with one above us
} while (cell.isValid()
&& ((op == QTextCursor::NextRow && currentRow == cell.row())
|| cell.row() < row));
@@ -625,7 +589,7 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor
--row;
}
cell = table->cellAt(row, column);
- // note we also continue while we have not reached a cell thats not merged with one above us
+ // note we also continue while we have not reached a cell that's not merged with one above us
} while (cell.isValid()
&& ((op == QTextCursor::PreviousRow && currentRow == cell.row())
|| cell.row() < row));
@@ -1459,28 +1423,28 @@ void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format
QTextBlockFormat blockFmt = blockFormat();
- int textStart = d->priv->text.length();
+ int textStart = d->priv->text.size();
int blockStart = 0;
d->priv->text += text;
- int textEnd = d->priv->text.length();
+ int textEnd = d->priv->text.size();
- for (int i = 0; i < text.length(); ++i) {
+ for (int i = 0; i < text.size(); ++i) {
QChar ch = text.at(i);
const int blockEnd = i;
- if (ch == QLatin1Char('\r')
- && (i + 1) < text.length()
- && text.at(i + 1) == QLatin1Char('\n')) {
+ if (ch == u'\r'
+ && (i + 1) < text.size()
+ && text.at(i + 1) == u'\n') {
++i;
ch = text.at(i);
}
- if (ch == QLatin1Char('\n')
+ if (ch == u'\n'
|| ch == QChar::ParagraphSeparator
|| ch == QTextBeginningOfFrame
|| ch == QTextEndOfFrame
- || ch == QLatin1Char('\r')) {
+ || ch == u'\r') {
if (!hasEditBlock) {
hasEditBlock = true;
@@ -1715,7 +1679,7 @@ static void getText(QString &text, QTextDocumentPrivate *priv, const QString &do
const int offsetInFragment = qMax(0, pos - fragIt.position());
const int len = qMin(int(frag->size_array[0] - offsetInFragment), end - pos);
- text += QString(docText.constData() + frag->stringPosition + offsetInFragment, len);
+ text += QStringView(docText.constData() + frag->stringPosition + offsetInFragment, len);
pos += len;
}
}
@@ -2291,6 +2255,28 @@ void QTextCursor::insertHtml(const QString &html)
#endif // QT_NO_TEXTHTMLPARSER
/*!
+ \since 6.4
+ Inserts the \a markdown text at the current position(),
+ with the specified Markdown \a features. The default is GitHub dialect.
+*/
+
+#if QT_CONFIG(textmarkdownreader)
+
+void QTextCursor::insertMarkdown(const QString &markdown, QTextDocument::MarkdownFeatures features)
+{
+ if (!d || !d->priv)
+ return;
+ QTextDocumentFragment fragment = QTextDocumentFragment::fromMarkdown(markdown, features);
+ if (markdown.startsWith(QLatin1Char('\n')))
+ insertBlock(fragment.d->doc->firstBlock().blockFormat());
+ insertFragment(fragment);
+ if (!atEnd() && markdown.endsWith(QLatin1Char('\n')))
+ insertText(QLatin1String("\n"));
+}
+
+#endif // textmarkdownreader
+
+/*!
\overload
\since 4.2
@@ -2314,7 +2300,7 @@ void QTextCursor::insertImage(const QTextImageFormat &format, QTextFrameFormat::
d->priv->beginEditBlock();
d->remove();
const int idx = d->priv->formatCollection()->indexForFormat(fmt);
- d->priv->insert(d->position, QString(QChar(QChar::ObjectReplacementCharacter)), idx);
+ d->priv->insert(d->position, QChar(QChar::ObjectReplacementCharacter), idx);
d->priv->endEditBlock();
}
diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h
index 59b32e0874..92c00c0189 100644
--- a/src/gui/text/qtextcursor.h
+++ b/src/gui/text/qtextcursor.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTCURSOR_H
#define QTEXTCURSOR_H
@@ -43,12 +7,11 @@
#include <QtGui/qtguiglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qshareddata.h>
+#include <QtGui/qtextdocument.h>
#include <QtGui/qtextformat.h>
QT_BEGIN_NAMESPACE
-
-class QTextDocument;
class QTextCursorPrivate;
class QTextDocumentFragment;
class QTextCharFormat;
@@ -77,7 +40,7 @@ public:
QTextCursor &operator=(const QTextCursor &other);
~QTextCursor();
- void swap(QTextCursor &other) noexcept { qSwap(d, other.d); }
+ void swap(QTextCursor &other) noexcept { d.swap(other.d); }
bool isNull() const;
@@ -201,6 +164,10 @@ public:
#ifndef QT_NO_TEXTHTMLPARSER
void insertHtml(const QString &html);
#endif // QT_NO_TEXTHTMLPARSER
+#if QT_CONFIG(textmarkdownreader)
+ void insertMarkdown(const QString &markdown,
+ QTextDocument::MarkdownFeatures features = QTextDocument::MarkdownDialectGitHub);
+#endif // textmarkdownreader
void insertImage(const QTextImageFormat &format, QTextFrameFormat::Position alignment);
void insertImage(const QTextImageFormat &format);
diff --git a/src/gui/text/qtextcursor_p.h b/src/gui/text/qtextcursor_p.h
index 3569317b6d..f035ba6acf 100644
--- a/src/gui/text/qtextcursor_p.h
+++ b/src/gui/text/qtextcursor_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTCURSOR_P_H
#define QTEXTCURSOR_P_H
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index d3bec57bd4..15a313e13d 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextdocument.h"
#include <qtextformat.h>
@@ -47,6 +11,7 @@
#include "qtexttable.h"
#include "qtextlist.h"
#include <qdebug.h>
+#include <qloggingcategory.h>
#if QT_CONFIG(regularexpression)
#include <qregularexpression.h>
#endif
@@ -78,6 +43,10 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcLayout);
+
+using namespace Qt::StringLiterals;
+
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION unsigned int qt_int_sqrt(unsigned int n);
namespace {
@@ -85,6 +54,8 @@ namespace {
};
/*!
+ \fn bool Qt::mightBeRichText(QAnyStringView text)
+
Returns \c true if the string \a text is likely to be rich text;
otherwise returns \c false.
@@ -94,57 +65,61 @@ namespace {
for common cases, there is no guarantee.
This function is defined in the \c <QTextDocument> header file.
-*/
-bool Qt::mightBeRichText(const QString& text)
+
+ \note In Qt versions prior to 6.7, this function took QString only.
+ */
+template <typename T>
+static bool mightBeRichTextImpl(T text)
{
if (text.isEmpty())
return false;
- int start = 0;
+ qsizetype start = 0;
- while (start < text.length() && text.at(start).isSpace())
+ while (start < text.size() && QChar(text.at(start)).isSpace())
++start;
// skip a leading <?xml ... ?> as for example with xhtml
- if (QStringView{text}.mid(start, 5).compare(QLatin1String("<?xml")) == 0) {
- while (start < text.length()) {
- if (text.at(start) == QLatin1Char('?')
- && start + 2 < text.length()
- && text.at(start + 1) == QLatin1Char('>')) {
+ if (text.mid(start, 5).compare("<?xml"_L1) == 0) {
+ while (start < text.size()) {
+ if (text.at(start) == u'?'
+ && start + 2 < text.size()
+ && text.at(start + 1) == u'>') {
start += 2;
break;
}
++start;
}
- while (start < text.length() && text.at(start).isSpace())
+ while (start < text.size() && QChar(text.at(start)).isSpace())
++start;
}
- if (QStringView{text}.mid(start, 5).compare(QLatin1String("<!doc"), Qt::CaseInsensitive) == 0)
+ if (text.mid(start, 5).compare("<!doc"_L1, Qt::CaseInsensitive) == 0)
return true;
- int open = start;
- while (open < text.length() && text.at(open) != QLatin1Char('<')
- && text.at(open) != QLatin1Char('\n')) {
- if (text.at(open) == QLatin1Char('&') && QStringView{text}.mid(open + 1, 3) == QLatin1String("lt;"))
+ qsizetype open = start;
+ while (open < text.size() && text.at(open) != u'<'
+ && text.at(open) != u'\n') {
+ if (text.at(open) == u'&' && text.mid(open + 1, 3) == "lt;"_L1)
return true; // support desperate attempt of user to see <...>
++open;
}
- if (open < text.length() && text.at(open) == QLatin1Char('<')) {
- const int close = text.indexOf(QLatin1Char('>'), open);
+ if (open < text.size() && text.at(open) == u'<') {
+ const qsizetype close = text.indexOf(u'>', open);
if (close > -1) {
- QString tag;
- for (int i = open+1; i < close; ++i) {
- if (text[i].isDigit() || text[i].isLetter())
- tag += text[i];
- else if (!tag.isEmpty() && text[i].isSpace())
+ QVarLengthArray<char16_t> tag;
+ for (qsizetype i = open + 1; i < close; ++i) {
+ const auto current = QChar(text[i]);
+ if (current.isDigit() || current.isLetter())
+ tag.append(current.toLower().unicode());
+ else if (!tag.isEmpty() && current.isSpace())
break;
- else if (!tag.isEmpty() && text[i] == QLatin1Char('/') && i + 1 == close)
+ else if (!tag.isEmpty() && current == u'/' && i + 1 == close)
break;
- else if (!text[i].isSpace() && (!tag.isEmpty() || text[i] != QLatin1Char('!')))
+ else if (!current.isSpace() && (!tag.isEmpty() || current != u'!'))
return false; // that's not a tag
}
#ifndef QT_NO_TEXTHTMLPARSER
- return QTextHtmlParser::lookupElement(std::move(tag).toLower()) != -1;
+ return QTextHtmlParser::lookupElement(tag) != -1;
#else
return false;
#endif // QT_NO_TEXTHTMLPARSER
@@ -153,6 +128,16 @@ bool Qt::mightBeRichText(const QString& text)
return false;
}
+static bool mightBeRichTextImpl(QUtf8StringView text)
+{
+ return mightBeRichTextImpl(QLatin1StringView(QByteArrayView(text)));
+}
+
+bool Qt::mightBeRichText(QAnyStringView text)
+{
+ return text.visit([](auto text) { return mightBeRichTextImpl(text); });
+}
+
/*!
Converts the plain text string \a plain to an HTML-formatted
paragraph while preserving most of its look.
@@ -165,27 +150,27 @@ bool Qt::mightBeRichText(const QString& text)
*/
QString Qt::convertFromPlainText(const QString &plain, Qt::WhiteSpaceMode mode)
{
- int col = 0;
+ qsizetype col = 0;
QString rich;
- rich += QLatin1String("<p>");
- for (int i = 0; i < plain.length(); ++i) {
- if (plain[i] == QLatin1Char('\n')){
- int c = 1;
- while (i+1 < plain.length() && plain[i+1] == QLatin1Char('\n')) {
+ rich += "<p>"_L1;
+ for (qsizetype i = 0; i < plain.size(); ++i) {
+ if (plain[i] == u'\n'){
+ qsizetype c = 1;
+ while (i+1 < plain.size() && plain[i+1] == u'\n') {
i++;
c++;
}
if (c == 1)
- rich += QLatin1String("<br>\n");
+ rich += "<br>\n"_L1;
else {
- rich += QLatin1String("</p>\n");
+ rich += "</p>\n"_L1;
while (--c > 1)
- rich += QLatin1String("<br>\n");
- rich += QLatin1String("<p>");
+ rich += "<br>\n"_L1;
+ rich += "<p>"_L1;
}
col = 0;
} else {
- if (mode == Qt::WhiteSpacePre && plain[i] == QLatin1Char('\t')){
+ if (mode == Qt::WhiteSpacePre && plain[i] == u'\t'){
rich += QChar::Nbsp;
++col;
while (col % 8) {
@@ -195,19 +180,19 @@ QString Qt::convertFromPlainText(const QString &plain, Qt::WhiteSpaceMode mode)
}
else if (mode == Qt::WhiteSpacePre && plain[i].isSpace())
rich += QChar::Nbsp;
- else if (plain[i] == QLatin1Char('<'))
- rich += QLatin1String("&lt;");
- else if (plain[i] == QLatin1Char('>'))
- rich += QLatin1String("&gt;");
- else if (plain[i] == QLatin1Char('&'))
- rich += QLatin1String("&amp;");
+ else if (plain[i] == u'<')
+ rich += "&lt;"_L1;
+ else if (plain[i] == u'>')
+ rich += "&gt;"_L1;
+ else if (plain[i] == u'&')
+ rich += "&amp;"_L1;
else
rich += plain[i];
++col;
}
}
if (col != 0)
- rich += QLatin1String("</p>");
+ rich += "</p>"_L1;
return rich;
}
@@ -269,7 +254,7 @@ QString Qt::convertFromPlainText(const QString &plain, Qt::WhiteSpaceMode mode)
\li Text block group format changes.
\endlist
- \sa QTextCursor, QTextEdit, {Rich Text Processing}, {Text Object Example}
+ \sa QTextCursor, QTextEdit, {Rich Text Processing}
*/
/*!
@@ -351,6 +336,7 @@ QTextDocument *QTextDocument::clone(QObject *parent) const
QTextDocumentPrivate *priv = doc->d_func();
priv->title = d->title;
priv->url = d->url;
+ priv->cssMedia = d->cssMedia;
priv->pageSize = d->pageSize;
priv->indentWidth = d->indentWidth;
priv->defaultTextOption = d->defaultTextOption;
@@ -668,6 +654,40 @@ bool QTextDocument::useDesignMetrics() const
}
/*!
+ \property QTextDocument::layoutEnabled
+ \since 6.4
+ \brief whether QTextDocument should recalculate the layout after every change
+
+ If this property is set to true, any change to the document triggers a layout,
+ which makes everything work as expected but takes time.
+
+ Temporarily disabling the layout can save time when making multiple changes
+ (not just text content, but also default font, default text option....)
+ so that the document is only laid out once at the end. This can be useful when
+ the text width or page size isn't yet known, for instance.
+
+ By default, this property is \c true.
+
+ \sa setTextWidth
+*/
+
+void QTextDocument::setLayoutEnabled(bool b)
+{
+ Q_D(QTextDocument);
+ if (d->layoutEnabled == b)
+ return;
+ d->layoutEnabled = b;
+ if (b && d->lout)
+ d->lout->documentChanged(0, 0, d->length());
+}
+
+bool QTextDocument::isLayoutEnabled() const
+{
+ Q_D(const QTextDocument);
+ return d->layoutEnabled;
+}
+
+/*!
\since 4.2
Draws the content of the document with painter \a p, clipped to \a rect.
@@ -710,6 +730,8 @@ void QTextDocument::setTextWidth(qreal width)
{
Q_D(QTextDocument);
QSizeF sz = d->pageSize;
+
+ qCDebug(lcLayout) << "page size" << sz << "-> width" << width;
sz.setWidth(width);
sz.setHeight(-1);
setPageSize(sz);
@@ -816,7 +838,7 @@ void QTextDocument::adjustSize()
// Pull this private function in from qglobal.cpp
QFont f = defaultFont();
QFontMetrics fm(f);
- int mw = fm.horizontalAdvance(QLatin1Char('x')) * 80;
+ int mw = fm.horizontalAdvance(u'x') * 80;
int w = mw;
setTextWidth(w);
QSizeF size = documentLayout()->documentSize();
@@ -1135,6 +1157,10 @@ QString QTextDocument::metaInformation(MetaInformation info) const
return d->title;
case DocumentUrl:
return d->url;
+ case CssMedia:
+ return d->cssMedia;
+ case FrontMatter:
+ return d->frontMatter;
}
return QString();
}
@@ -1155,6 +1181,12 @@ void QTextDocument::setMetaInformation(MetaInformation info, const QString &stri
case DocumentUrl:
d->url = string;
break;
+ case CssMedia:
+ d->cssMedia = string;
+ break;
+ case FrontMatter:
+ d->frontMatter = string;
+ break;
}
}
@@ -1194,19 +1226,27 @@ QString QTextDocument::toPlainText() const
Q_D(const QTextDocument);
QString txt = d->plainText();
+ constexpr char16_t delims[] = { 0xfdd0, 0xfdd1,
+ QChar::ParagraphSeparator, QChar::LineSeparator, QChar::Nbsp };
+
+ const size_t pos = std::u16string_view(txt).find_first_of(
+ std::u16string_view(delims, std::size(delims)));
+ if (pos == std::u16string_view::npos)
+ return txt;
+
QChar *uc = txt.data();
- QChar *e = uc + txt.size();
+ QChar *const e = uc + txt.size();
- for (; uc != e; ++uc) {
+ for (uc += pos; uc != e; ++uc) {
switch (uc->unicode()) {
case 0xfdd0: // QTextBeginningOfFrame
case 0xfdd1: // QTextEndOfFrame
case QChar::ParagraphSeparator:
case QChar::LineSeparator:
- *uc = QLatin1Char('\n');
+ *uc = u'\n';
break;
case QChar::Nbsp:
- *uc = QLatin1Char(' ');
+ *uc = u' ';
break;
default:
;
@@ -1242,11 +1282,14 @@ void QTextDocument::setPlainText(const QString &text)
"<b>bold</b> text" will produce text where the first word has a font
weight that gives it a bold appearance: "\b{bold} text".
+ To select a css media rule other than the default "screen" rule,
+ use setMetaInformation() with 'CssMedia' as "info" parameter.
+
\note It is the responsibility of the caller to make sure that the
text is correctly decoded when a QString containing HTML is created
and passed to setHtml().
- \sa setPlainText(), {Supported HTML Subset}
+ \sa setPlainText(), {Supported HTML Subset}, setMetaInformation()
*/
#ifndef QT_NO_TEXTHTMLPARSER
@@ -1258,6 +1301,8 @@ void QTextDocument::setHtml(const QString &html)
d->enableUndoRedo(false);
d->beginEditBlock();
d->clear();
+ // ctor calls parse() to build up QTextHtmlParser::nodes list
+ // then import() populates the QTextDocument from those
QTextHtmlImporter(this, html, QTextHtmlImporter::ImportToDocument).import();
d->endEditBlock();
d->enableUndoRedo(previousState);
@@ -1286,19 +1331,26 @@ void QTextDocument::setHtml(const QString &html)
\value DocumentTitle The title of the document.
\value DocumentUrl The url of the document. The loadResource() function uses
this url as the base when loading relative resources.
+ \value CssMedia This value is used to select the corresponding '@media'
+ rule, if any, from a specified CSS stylesheet when setHtml()
+ is called. This enum value has been introduced in Qt 6.3.
+ \value FrontMatter This value is used to select header material, if any was
+ extracted during parsing of the source file (currently
+ only from Markdown format). This enum value has been
+ introduced in Qt 6.8.
- \sa metaInformation(), setMetaInformation()
+ \sa metaInformation(), setMetaInformation(), setHtml()
*/
static bool findInBlock(const QTextBlock &block, const QString &expression, int offset,
QTextDocument::FindFlags options, QTextCursor *cursor)
{
QString text = block.text();
- text.replace(QChar::Nbsp, QLatin1Char(' '));
+ text.replace(QChar::Nbsp, u' ');
Qt::CaseSensitivity sensitivity = options & QTextDocument::FindCaseSensitively ? Qt::CaseSensitive : Qt::CaseInsensitive;
int idx = -1;
- while (offset >= 0 && offset <= text.length()) {
+ while (offset >= 0 && offset <= text.size()) {
idx = (options & QTextDocument::FindBackward) ?
text.lastIndexOf(expression, offset, sensitivity) : text.indexOf(expression, offset, sensitivity);
if (idx == -1)
@@ -1306,9 +1358,9 @@ static bool findInBlock(const QTextBlock &block, const QString &expression, int
if (options & QTextDocument::FindWholeWords) {
const int start = idx;
- const int end = start + expression.length();
+ const int end = start + expression.size();
if ((start != 0 && text.at(start - 1).isLetterOrNumber())
- || (end != text.length() && text.at(end).isLetterOrNumber())) {
+ || (end != text.size() && text.at(end).isLetterOrNumber())) {
//if this is not a whole word, continue the search in the string
offset = (options & QTextDocument::FindBackward) ? idx-1 : end+1;
idx = -1;
@@ -1318,7 +1370,7 @@ static bool findInBlock(const QTextBlock &block, const QString &expression, int
//we have a hit, return the cursor for that.
*cursor = QTextCursorPrivate::fromPosition(const_cast<QTextDocumentPrivate *>(QTextDocumentPrivate::get(block)),
block.position() + idx);
- cursor->setPosition(cursor->position() + expression.length(), QTextCursor::KeepAnchor);
+ cursor->setPosition(cursor->position() + expression.size(), QTextCursor::KeepAnchor);
return true;
}
return false;
@@ -1414,11 +1466,11 @@ static bool findInBlock(const QTextBlock &block, const QRegularExpression &expr,
QTextDocument::FindFlags options, QTextCursor *cursor)
{
QString text = block.text();
- text.replace(QChar::Nbsp, QLatin1Char(' '));
+ text.replace(QChar::Nbsp, u' ');
QRegularExpressionMatch match;
int idx = -1;
- while (offset >= 0 && offset <= text.length()) {
+ while (offset >= 0 && offset <= text.size()) {
idx = (options & QTextDocument::FindBackward) ?
text.lastIndexOf(expr, offset, &match) : text.indexOf(expr, offset, &match);
if (idx == -1)
@@ -1428,7 +1480,7 @@ static bool findInBlock(const QTextBlock &block, const QRegularExpression &expr,
const int start = idx;
const int end = start + match.capturedLength();
if ((start != 0 && text.at(start - 1).isLetterOrNumber())
- || (end != text.length() && text.at(end).isLetterOrNumber())) {
+ || (end != text.size() && text.at(end).isLetterOrNumber())) {
//if this is not a whole word, continue the search in the string
offset = (options & QTextDocument::FindBackward) ? idx-1 : end+1;
idx = -1;
@@ -1459,6 +1511,10 @@ static bool findInBlock(const QTextBlock &block, const QRegularExpression &expr,
If the \a from position is 0 (the default) the search begins from the beginning
of the document; otherwise it begins at the specified position.
+
+ \warning For historical reasons, the case sensitivity option set on
+ \a expr is ignored. Instead, the \a options are used to determine
+ if the search is case sensitive or not.
*/
QTextCursor QTextDocument::find(const QRegularExpression &expr, int from, FindFlags options) const
{
@@ -1814,9 +1870,10 @@ void QTextDocument::setBaselineOffset(qreal baseline)
\fn qreal QTextDocument::baselineOffset() const
\since 6.0
- Returns the the baseline offset in % used in the document layout.
+ Returns the baseline offset in % used in the document layout.
- \sa setBaselineOffset(), setSubScriptBaseline(), subScriptBaseline(), setSuperScriptBaseline(), superScriptBaseline()
+ \sa setBaselineOffset(), setSubScriptBaseline(), subScriptBaseline(), setSuperScriptBaseline(),
+ superScriptBaseline()
*/
qreal QTextDocument::baselineOffset() const
{
@@ -2223,12 +2280,13 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name)
int index = me->indexOfMethod("loadResource(int,QUrl)");
if (index >= 0) {
QMetaMethod loader = me->method(index);
- loader.invoke(p, Q_RETURN_ARG(QVariant, r), Q_ARG(int, type), Q_ARG(QUrl, name));
+ // don't invoke() via a queued connection: this function needs to return a value
+ loader.invoke(p, Qt::DirectConnection, Q_RETURN_ARG(QVariant, r), Q_ARG(int, type), Q_ARG(QUrl, name));
}
}
// handle data: URLs
- if (r.isNull() && name.scheme().compare(QLatin1String("data"), Qt::CaseInsensitive) == 0) {
+ if (r.isNull() && name.scheme().compare("data"_L1, Qt::CaseInsensitive) == 0) {
QString mimetype;
QByteArray payload;
if (qDecodeDataUrl(name, mimetype, payload))
@@ -2244,7 +2302,7 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name)
// For the second case QUrl can merge "#someanchor" with "foo.html"
// correctly to "foo.html#someanchor"
if (!(currentURL.isRelative()
- || (currentURL.scheme() == QLatin1String("file")
+ || (currentURL.scheme() == "file"_L1
&& !QFileInfo(currentURL.toLocalFile()).isAbsolute()))
|| (name.hasFragment() && name.path().isEmpty())) {
resourceUrl = currentURL.resolved(name);
@@ -2257,7 +2315,7 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name)
resourceUrl =
QUrl::fromLocalFile(fi.absolutePath() + QDir::separator()).resolved(name);
} else if (currentURL.isEmpty()) {
- resourceUrl.setScheme(QLatin1String("file"));
+ resourceUrl.setScheme("file"_L1);
}
}
}
@@ -2311,16 +2369,16 @@ static QString colorValue(QColor color)
result = color.name();
} else if (color.alpha()) {
QString alphaValue = QString::number(color.alphaF(), 'f', 6);
- while (alphaValue.length() > 1 && alphaValue.at(alphaValue.size() - 1) == QLatin1Char('0'))
+ while (alphaValue.size() > 1 && alphaValue.at(alphaValue.size() - 1) == u'0')
alphaValue.chop(1);
- if (alphaValue.at(alphaValue.size() - 1) == QLatin1Char('.'))
+ if (alphaValue.at(alphaValue.size() - 1) == u'.')
alphaValue.chop(1);
result = QString::fromLatin1("rgba(%1,%2,%3,%4)").arg(color.red())
.arg(color.green())
.arg(color.blue())
.arg(alphaValue);
} else {
- result = QLatin1String("transparent");
+ result = "transparent"_L1;
}
return result;
@@ -2345,88 +2403,94 @@ static QStringList resolvedFontFamilies(const QTextCharFormat &format)
*/
QString QTextHtmlExporter::toHtml(ExportMode mode)
{
- html = QLatin1String("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
- "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
- "<html><head><meta name=\"qrichtext\" content=\"1\" />");
+ html = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" "
+ "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
+ "<html><head><meta name=\"qrichtext\" content=\"1\" />"_L1;
html.reserve(QTextDocumentPrivate::get(doc)->length());
fragmentMarkers = (mode == ExportFragment);
- html += QString::fromLatin1("<meta charset=\"utf-8\" />");
+ html += "<meta charset=\"utf-8\" />"_L1;
QString title = doc->metaInformation(QTextDocument::DocumentTitle);
- if (!title.isEmpty())
- html += QString::fromLatin1("<title>") + title + QString::fromLatin1("</title>");
- html += QLatin1String("<style type=\"text/css\">\n");
- html += QLatin1String("p, li { white-space: pre-wrap; }\n");
- html += QLatin1String("</style>");
- html += QLatin1String("</head><body");
+ if (!title.isEmpty()) {
+ html += "<title>"_L1;
+ html += title;
+ html += "</title>"_L1;
+ }
+ html += "<style type=\"text/css\">\n"_L1;
+ html += "p, li { white-space: pre-wrap; }\n"_L1;
+ html += "hr { height: 1px; border-width: 0; }\n"_L1;
+ html += "li.unchecked::marker { content: \"\\2610\"; }\n"_L1;
+ html += "li.checked::marker { content: \"\\2612\"; }\n"_L1;
+ html += "</style>"_L1;
+ html += "</head><body"_L1;
if (mode == ExportEntireDocument) {
- html += QLatin1String(" style=\"");
+ html += " style=\""_L1;
emitFontFamily(resolvedFontFamilies(defaultCharFormat));
if (defaultCharFormat.hasProperty(QTextFormat::FontPointSize)) {
- html += QLatin1String(" font-size:");
+ html += " font-size:"_L1;
html += QString::number(defaultCharFormat.fontPointSize());
- html += QLatin1String("pt;");
+ html += "pt;"_L1;
} else if (defaultCharFormat.hasProperty(QTextFormat::FontPixelSize)) {
- html += QLatin1String(" font-size:");
+ html += " font-size:"_L1;
html += QString::number(defaultCharFormat.intProperty(QTextFormat::FontPixelSize));
- html += QLatin1String("px;");
+ html += "px;"_L1;
}
- html += QLatin1String(" font-weight:");
+ html += " font-weight:"_L1;
html += QString::number(defaultCharFormat.fontWeight());
- html += QLatin1Char(';');
+ html += u';';
- html += QLatin1String(" font-style:");
- html += (defaultCharFormat.fontItalic() ? QLatin1String("italic") : QLatin1String("normal"));
- html += QLatin1Char(';');
+ html += " font-style:"_L1;
+ html += (defaultCharFormat.fontItalic() ? "italic"_L1 : "normal"_L1);
+ html += u';';
const bool percentSpacing = (defaultCharFormat.fontLetterSpacingType() == QFont::PercentageSpacing);
if (defaultCharFormat.hasProperty(QTextFormat::FontLetterSpacing) &&
(!percentSpacing || defaultCharFormat.fontLetterSpacing() != 0.0)) {
- html += QLatin1String(" letter-spacing:");
+ html += " letter-spacing:"_L1;
qreal value = defaultCharFormat.fontLetterSpacing();
if (percentSpacing) // Map to em (100% == 0em)
value = (value / 100) - 1;
html += QString::number(value);
- html += percentSpacing ? QLatin1String("em;") : QLatin1String("px;");
+ html += percentSpacing ? "em;"_L1 : "px;"_L1;
}
if (defaultCharFormat.hasProperty(QTextFormat::FontWordSpacing) &&
defaultCharFormat.fontWordSpacing() != 0.0) {
- html += QLatin1String(" word-spacing:");
+ html += " word-spacing:"_L1;
html += QString::number(defaultCharFormat.fontWordSpacing());
- html += QLatin1String("px;");
+ html += "px;"_L1;
}
- QString decorationTag(QLatin1String(" text-decoration:"));
+ QString decorationTag(" text-decoration:"_L1);
bool atLeastOneDecorationSet = false;
if (defaultCharFormat.hasProperty(QTextFormat::FontUnderline) || defaultCharFormat.hasProperty(QTextFormat::TextUnderlineStyle)) {
if (defaultCharFormat.fontUnderline()) {
- decorationTag += QLatin1String(" underline");
+ decorationTag += " underline"_L1;
atLeastOneDecorationSet = true;
}
}
if (defaultCharFormat.hasProperty(QTextFormat::FontOverline)) {
if (defaultCharFormat.fontOverline()) {
- decorationTag += QLatin1String(" overline");
+ decorationTag += " overline"_L1;
atLeastOneDecorationSet = true;
}
}
if (defaultCharFormat.hasProperty(QTextFormat::FontStrikeOut)) {
if (defaultCharFormat.fontStrikeOut()) {
- decorationTag += QLatin1String(" line-through");
+ decorationTag += " line-through"_L1;
atLeastOneDecorationSet = true;
}
}
if (atLeastOneDecorationSet)
- html += decorationTag + QLatin1Char(';');
+ html += decorationTag + u';';
- html += QLatin1Char('\"');
+ html += u'\"';
const QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
emitBackgroundAttribute(fmt);
@@ -2434,7 +2498,7 @@ QString QTextHtmlExporter::toHtml(ExportMode mode)
} else {
defaultCharFormat = QTextCharFormat();
}
- html += QLatin1Char('>');
+ html += u'>';
QTextFrameFormat rootFmt = doc->rootFrame()->frameFormat();
rootFmt.clearProperty(QTextFormat::BackgroundBrush);
@@ -2447,17 +2511,17 @@ QString QTextHtmlExporter::toHtml(ExportMode mode)
else
emitTextFrame(doc->rootFrame());
- html += QLatin1String("</body></html>");
+ html += "</body></html>"_L1;
return html;
}
void QTextHtmlExporter::emitAttribute(const char *attribute, const QString &value)
{
- html += QLatin1Char(' ');
- html += QLatin1String(attribute);
- html += QLatin1String("=\"");
+ html += u' ';
+ html += QLatin1StringView(attribute);
+ html += "=\""_L1;
html += value.toHtmlEscaped();
- html += QLatin1Char('"');
+ html += u'"';
}
bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
@@ -2474,9 +2538,9 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
if (format.hasProperty(QTextFormat::FontPointSize)
&& format.fontPointSize() != defaultCharFormat.fontPointSize()) {
- html += QLatin1String(" font-size:");
+ html += " font-size:"_L1;
html += QString::number(format.fontPointSize());
- html += QLatin1String("pt;");
+ html += "pt;"_L1;
attributesEmitted = true;
} else if (format.hasProperty(QTextFormat::FontSizeAdjustment)) {
static const char sizeNameData[] =
@@ -2496,35 +2560,37 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
name = sizeNameData + sizeNameOffsets[idx];
}
if (name) {
- html += QLatin1String(" font-size:");
- html += QLatin1String(name);
- html += QLatin1Char(';');
+ html += " font-size:"_L1;
+ html += QLatin1StringView(name);
+ html += u';';
attributesEmitted = true;
}
- } else if (format.hasProperty(QTextFormat::FontPixelSize)) {
- html += QLatin1String(" font-size:");
+ } else if (format.hasProperty(QTextFormat::FontPixelSize)
+ && format.property(QTextFormat::FontPixelSize)
+ != defaultCharFormat.property(QTextFormat::FontPixelSize)) {
+ html += " font-size:"_L1;
html += QString::number(format.intProperty(QTextFormat::FontPixelSize));
- html += QLatin1String("px;");
+ html += "px;"_L1;
attributesEmitted = true;
}
if (format.hasProperty(QTextFormat::FontWeight)
&& format.fontWeight() != defaultCharFormat.fontWeight()) {
- html += QLatin1String(" font-weight:");
+ html += " font-weight:"_L1;
html += QString::number(format.fontWeight());
- html += QLatin1Char(';');
+ html += u';';
attributesEmitted = true;
}
if (format.hasProperty(QTextFormat::FontItalic)
&& format.fontItalic() != defaultCharFormat.fontItalic()) {
- html += QLatin1String(" font-style:");
- html += (format.fontItalic() ? QLatin1String("italic") : QLatin1String("normal"));
- html += QLatin1Char(';');
+ html += " font-style:"_L1;
+ html += (format.fontItalic() ? "italic"_L1 : "normal"_L1);
+ html += u';';
attributesEmitted = true;
}
- QLatin1String decorationTag(" text-decoration:");
+ const auto decorationTag = " text-decoration:"_L1;
html += decorationTag;
bool hasDecoration = false;
bool atLeastOneDecorationSet = false;
@@ -2533,7 +2599,7 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
&& format.fontUnderline() != defaultCharFormat.fontUnderline()) {
hasDecoration = true;
if (format.fontUnderline()) {
- html += QLatin1String(" underline");
+ html += " underline"_L1;
atLeastOneDecorationSet = true;
}
}
@@ -2542,7 +2608,7 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
&& format.fontOverline() != defaultCharFormat.fontOverline()) {
hasDecoration = true;
if (format.fontOverline()) {
- html += QLatin1String(" overline");
+ html += " overline"_L1;
atLeastOneDecorationSet = true;
}
}
@@ -2551,19 +2617,19 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
&& format.fontStrikeOut() != defaultCharFormat.fontStrikeOut()) {
hasDecoration = true;
if (format.fontStrikeOut()) {
- html += QLatin1String(" line-through");
+ html += " line-through"_L1;
atLeastOneDecorationSet = true;
}
}
if (hasDecoration) {
if (!atLeastOneDecorationSet)
- html += QLatin1String("none");
- html += QLatin1Char(';');
+ html += "none"_L1;
+ html += u';';
if (format.hasProperty(QTextFormat::TextUnderlineColor)) {
- html += QLatin1String(" text-decoration-color:");
+ html += " text-decoration-color:"_L1;
html += colorValue(format.underlineColor());
- html += QLatin1Char(';');
+ html += u';';
}
attributesEmitted = true;
} else {
@@ -2577,61 +2643,120 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
const bool isPixmap = qHasPixmapTexture(brush);
const qint64 cacheKey = isPixmap ? brush.texture().cacheKey() : brush.textureImage().cacheKey();
- html += QLatin1String(" -qt-fg-texture-cachekey:");
+ html += " -qt-fg-texture-cachekey:"_L1;
html += QString::number(cacheKey);
- html += QLatin1String(";");
+ html += ";"_L1;
+ } else if (brush.style() == Qt::LinearGradientPattern
+ || brush.style() == Qt::RadialGradientPattern
+ || brush.style() == Qt::ConicalGradientPattern) {
+ const QGradient *gradient = brush.gradient();
+ if (gradient->type() == QGradient::LinearGradient) {
+ const QLinearGradient *linearGradient = static_cast<const QLinearGradient *>(brush.gradient());
+
+ html += " -qt-foreground: qlineargradient("_L1;
+ html += "x1:"_L1 + QString::number(linearGradient->start().x()) + u',';
+ html += "y1:"_L1 + QString::number(linearGradient->start().y()) + u',';
+ html += "x2:"_L1 + QString::number(linearGradient->finalStop().x()) + u',';
+ html += "y2:"_L1 + QString::number(linearGradient->finalStop().y()) + u',';
+ } else if (gradient->type() == QGradient::RadialGradient) {
+ const QRadialGradient *radialGradient = static_cast<const QRadialGradient *>(brush.gradient());
+
+ html += " -qt-foreground: qradialgradient("_L1;
+ html += "cx:"_L1 + QString::number(radialGradient->center().x()) + u',';
+ html += "cy:"_L1 + QString::number(radialGradient->center().y()) + u',';
+ html += "fx:"_L1 + QString::number(radialGradient->focalPoint().x()) + u',';
+ html += "fy:"_L1 + QString::number(radialGradient->focalPoint().y()) + u',';
+ html += "radius:"_L1 + QString::number(radialGradient->radius()) + u',';
+ } else {
+ const QConicalGradient *conicalGradient = static_cast<const QConicalGradient *>(brush.gradient());
+
+ html += " -qt-foreground: qconicalgradient("_L1;
+ html += "cx:"_L1 + QString::number(conicalGradient->center().x()) + u',';
+ html += "cy:"_L1 + QString::number(conicalGradient->center().y()) + u',';
+ html += "angle:"_L1 + QString::number(conicalGradient->angle()) + u',';
+ }
+
+ const QStringList coordinateModes = { "logical"_L1, "stretchtodevice"_L1, "objectbounding"_L1, "object"_L1 };
+ html += "coordinatemode:"_L1;
+ html += coordinateModes.at(int(gradient->coordinateMode()));
+ html += u',';
+
+ const QStringList spreads = { "pad"_L1, "reflect"_L1, "repeat"_L1 };
+ html += "spread:"_L1;
+ html += spreads.at(int(gradient->spread()));
+
+ for (const QGradientStop &stop : gradient->stops()) {
+ html += ",stop:"_L1;
+ html += QString::number(stop.first);
+ html += u' ';
+ html += colorValue(stop.second);
+ }
+
+ html += ");"_L1;
} else {
- html += QLatin1String(" color:");
+ html += " color:"_L1;
html += colorValue(brush.color());
- html += QLatin1Char(';');
+ html += u';';
}
attributesEmitted = true;
}
if (format.background() != defaultCharFormat.background()
&& format.background().style() == Qt::SolidPattern) {
- html += QLatin1String(" background-color:");
+ html += " background-color:"_L1;
html += colorValue(format.background().color());
- html += QLatin1Char(';');
+ html += u';';
attributesEmitted = true;
}
if (format.verticalAlignment() != defaultCharFormat.verticalAlignment()
&& format.verticalAlignment() != QTextCharFormat::AlignNormal)
{
- html += QLatin1String(" vertical-align:");
+ html += " vertical-align:"_L1;
QTextCharFormat::VerticalAlignment valign = format.verticalAlignment();
if (valign == QTextCharFormat::AlignSubScript)
- html += QLatin1String("sub");
+ html += "sub"_L1;
else if (valign == QTextCharFormat::AlignSuperScript)
- html += QLatin1String("super");
+ html += "super"_L1;
else if (valign == QTextCharFormat::AlignMiddle)
- html += QLatin1String("middle");
+ html += "middle"_L1;
else if (valign == QTextCharFormat::AlignTop)
- html += QLatin1String("top");
+ html += "top"_L1;
else if (valign == QTextCharFormat::AlignBottom)
- html += QLatin1String("bottom");
+ html += "bottom"_L1;
- html += QLatin1Char(';');
+ html += u';';
attributesEmitted = true;
}
if (format.fontCapitalization() != QFont::MixedCase) {
const QFont::Capitalization caps = format.fontCapitalization();
if (caps == QFont::AllUppercase)
- html += QLatin1String(" text-transform:uppercase;");
+ html += " text-transform:uppercase;"_L1;
else if (caps == QFont::AllLowercase)
- html += QLatin1String(" text-transform:lowercase;");
+ html += " text-transform:lowercase;"_L1;
else if (caps == QFont::SmallCaps)
- html += QLatin1String(" font-variant:small-caps;");
+ html += " font-variant:small-caps;"_L1;
attributesEmitted = true;
}
if (format.fontWordSpacing() != 0.0) {
- html += QLatin1String(" word-spacing:");
+ html += " word-spacing:"_L1;
html += QString::number(format.fontWordSpacing());
- html += QLatin1String("px;");
+ html += "px;"_L1;
+ attributesEmitted = true;
+ }
+
+ if (format.hasProperty(QTextFormat::TextOutline)) {
+ QPen outlinePen = format.textOutline();
+ html += " -qt-stroke-color:"_L1;
+ html += colorValue(outlinePen.color());
+ html += u';';
+
+ html += " -qt-stroke-width:"_L1;
+ html += QString::number(outlinePen.widthF());
+ html += "px;"_L1;
attributesEmitted = true;
}
@@ -2643,15 +2768,15 @@ void QTextHtmlExporter::emitTextLength(const char *attribute, const QTextLength
if (length.type() == QTextLength::VariableLength) // default
return;
- html += QLatin1Char(' ');
- html += QLatin1String(attribute);
- html += QLatin1String("=\"");
+ html += u' ';
+ html += QLatin1StringView(attribute);
+ html += "=\""_L1;
html += QString::number(length.rawValue());
if (length.type() == QTextLength::PercentageLength)
- html += QLatin1String("%\"");
+ html += "%\""_L1;
else
- html += QLatin1Char('\"');
+ html += u'\"';
}
void QTextHtmlExporter::emitAlignment(Qt::Alignment align)
@@ -2659,11 +2784,11 @@ void QTextHtmlExporter::emitAlignment(Qt::Alignment align)
if (align & Qt::AlignLeft)
return;
else if (align & Qt::AlignRight)
- html += QLatin1String(" align=\"right\"");
+ html += " align=\"right\""_L1;
else if (align & Qt::AlignHCenter)
- html += QLatin1String(" align=\"center\"");
+ html += " align=\"center\""_L1;
else if (align & Qt::AlignJustify)
- html += QLatin1String(" align=\"justify\"");
+ html += " align=\"justify\""_L1;
}
void QTextHtmlExporter::emitFloatStyle(QTextFrameFormat::Position pos, StyleMode mode)
@@ -2672,108 +2797,108 @@ void QTextHtmlExporter::emitFloatStyle(QTextFrameFormat::Position pos, StyleMode
return;
if (mode == EmitStyleTag)
- html += QLatin1String(" style=\"float:");
+ html += " style=\"float:"_L1;
else
- html += QLatin1String(" float:");
+ html += " float:"_L1;
if (pos == QTextFrameFormat::FloatLeft)
- html += QLatin1String(" left;");
+ html += " left;"_L1;
else if (pos == QTextFrameFormat::FloatRight)
- html += QLatin1String(" right;");
+ html += " right;"_L1;
else
Q_ASSERT_X(0, "QTextHtmlExporter::emitFloatStyle()", "pos should be a valid enum type");
if (mode == EmitStyleTag)
- html += QLatin1Char('\"');
+ html += u'\"';
}
-static QLatin1String richtextBorderStyleToHtmlBorderStyle(QTextFrameFormat::BorderStyle style)
+static QLatin1StringView richtextBorderStyleToHtmlBorderStyle(QTextFrameFormat::BorderStyle style)
{
switch (style) {
case QTextFrameFormat::BorderStyle_None:
- return QLatin1String("none");
+ return "none"_L1;
case QTextFrameFormat::BorderStyle_Dotted:
- return QLatin1String("dotted");
+ return "dotted"_L1;
case QTextFrameFormat::BorderStyle_Dashed:
- return QLatin1String("dashed");
+ return "dashed"_L1;
case QTextFrameFormat::BorderStyle_Solid:
- return QLatin1String("solid");
+ return "solid"_L1;
case QTextFrameFormat::BorderStyle_Double:
- return QLatin1String("double");
+ return "double"_L1;
case QTextFrameFormat::BorderStyle_DotDash:
- return QLatin1String("dot-dash");
+ return "dot-dash"_L1;
case QTextFrameFormat::BorderStyle_DotDotDash:
- return QLatin1String("dot-dot-dash");
+ return "dot-dot-dash"_L1;
case QTextFrameFormat::BorderStyle_Groove:
- return QLatin1String("groove");
+ return "groove"_L1;
case QTextFrameFormat::BorderStyle_Ridge:
- return QLatin1String("ridge");
+ return "ridge"_L1;
case QTextFrameFormat::BorderStyle_Inset:
- return QLatin1String("inset");
+ return "inset"_L1;
case QTextFrameFormat::BorderStyle_Outset:
- return QLatin1String("outset");
+ return "outset"_L1;
default:
Q_UNREACHABLE();
};
- return QLatin1String("");
+ return ""_L1;
}
void QTextHtmlExporter::emitBorderStyle(QTextFrameFormat::BorderStyle style)
{
Q_ASSERT(style <= QTextFrameFormat::BorderStyle_Outset);
- html += QLatin1String(" border-style:");
+ html += " border-style:"_L1;
html += richtextBorderStyleToHtmlBorderStyle(style);
- html += QLatin1Char(';');
+ html += u';';
}
void QTextHtmlExporter::emitPageBreakPolicy(QTextFormat::PageBreakFlags policy)
{
if (policy & QTextFormat::PageBreak_AlwaysBefore)
- html += QLatin1String(" page-break-before:always;");
+ html += " page-break-before:always;"_L1;
if (policy & QTextFormat::PageBreak_AlwaysAfter)
- html += QLatin1String(" page-break-after:always;");
+ html += " page-break-after:always;"_L1;
}
void QTextHtmlExporter::emitFontFamily(const QStringList &families)
{
- html += QLatin1String(" font-family:");
+ html += " font-family:"_L1;
bool first = true;
for (const QString &family : families) {
- QLatin1String quote("\'");
- if (family.contains(QLatin1Char('\'')))
- quote = QLatin1String("&quot;");
+ auto quote = "\'"_L1;
+ if (family.contains(u'\''))
+ quote = "&quot;"_L1;
if (!first)
- html += QLatin1String(",");
+ html += ","_L1;
else
first = false;
html += quote;
html += family.toHtmlEscaped();
html += quote;
}
- html += QLatin1Char(';');
+ html += u';';
}
void QTextHtmlExporter::emitMargins(const QString &top, const QString &bottom, const QString &left, const QString &right)
{
- html += QLatin1String(" margin-top:");
+ html += " margin-top:"_L1;
html += top;
- html += QLatin1String("px;");
+ html += "px;"_L1;
- html += QLatin1String(" margin-bottom:");
+ html += " margin-bottom:"_L1;
html += bottom;
- html += QLatin1String("px;");
+ html += "px;"_L1;
- html += QLatin1String(" margin-left:");
+ html += " margin-left:"_L1;
html += left;
- html += QLatin1String("px;");
+ html += "px;"_L1;
- html += QLatin1String(" margin-right:");
+ html += " margin-right:"_L1;
html += right;
- html += QLatin1String("px;");
+ html += "px;"_L1;
}
void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
@@ -2785,15 +2910,15 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
if (format.isAnchor()) {
const auto names = format.anchorNames();
if (!names.isEmpty()) {
- html += QLatin1String("<a name=\"");
+ html += "<a name=\""_L1;
html += names.constFirst().toHtmlEscaped();
- html += QLatin1String("\"></a>");
+ html += "\"></a>"_L1;
}
const QString href = format.anchorHref();
if (!href.isEmpty()) {
- html += QLatin1String("<a href=\"");
+ html += "<a href=\""_L1;
html += href.toHtmlEscaped();
- html += QLatin1String("\">");
+ html += "\">"_L1;
closeAnchor = true;
}
}
@@ -2802,22 +2927,22 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
const bool isObject = txt.contains(QChar::ObjectReplacementCharacter);
const bool isImage = isObject && format.isImageFormat();
- QLatin1String styleTag("<span style=\"");
+ const auto styleTag = "<span style=\""_L1;
html += styleTag;
bool attributesEmitted = false;
if (!isImage)
attributesEmitted = emitCharFormatStyle(format);
if (attributesEmitted)
- html += QLatin1String("\">");
+ html += "\">"_L1;
else
html.chop(styleTag.size());
if (isObject) {
- for (int i = 0; isImage && i < txt.length(); ++i) {
+ for (int i = 0; isImage && i < txt.size(); ++i) {
QTextImageFormat imgFmt = format.toImageFormat();
- html += QLatin1String("<img");
+ html += "<img"_L1;
if (imgFmt.hasProperty(QTextFormat::ImageName))
emitAttribute("src", imgFmt.name());
@@ -2835,14 +2960,14 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
emitAttribute("height", QString::number(imgFmt.height()));
if (imgFmt.verticalAlignment() == QTextCharFormat::AlignMiddle)
- html += QLatin1String(" style=\"vertical-align: middle;\"");
+ html += " style=\"vertical-align: middle;\""_L1;
else if (imgFmt.verticalAlignment() == QTextCharFormat::AlignTop)
- html += QLatin1String(" style=\"vertical-align: top;\"");
+ html += " style=\"vertical-align: top;\""_L1;
if (QTextFrame *imageFrame = qobject_cast<QTextFrame *>(doc->objectForFormat(imgFmt)))
emitFloatStyle(imageFrame->frameFormat().position());
- html += QLatin1String(" />");
+ html += " />"_L1;
}
} else {
Q_ASSERT(!txt.contains(QChar::ObjectReplacementCharacter));
@@ -2851,16 +2976,16 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
// split for [\n{LineSeparator}]
// space in BR on purpose for compatibility with old-fashioned browsers
- txt.replace(QLatin1Char('\n'), QLatin1String("<br />"));
- txt.replace(QChar::LineSeparator, QLatin1String("<br />"));
+ txt.replace(u'\n', "<br />"_L1);
+ txt.replace(QChar::LineSeparator, "<br />"_L1);
html += txt;
}
if (attributesEmitted)
- html += QLatin1String("</span>");
+ html += "</span>"_L1;
if (closeAnchor)
- html += QLatin1String("</a>");
+ html += "</a>"_L1;
}
static bool isOrderedList(int style)
@@ -2878,16 +3003,16 @@ void QTextHtmlExporter::emitBlockAttributes(const QTextBlock &block)
emitAlignment(format.alignment());
// assume default to not bloat the html too much
- // html += QLatin1String(" dir='ltr'");
+ // html += " dir='ltr'"_L1;
if (block.textDirection() == Qt::RightToLeft)
- html += QLatin1String(" dir='rtl'");
+ html += " dir='rtl'"_L1;
- QLatin1String style(" style=\"");
+ const auto style = " style=\""_L1;
html += style;
const bool emptyBlock = block.begin().atEnd();
if (emptyBlock) {
- html += QLatin1String("-qt-paragraph-type:empty;");
+ html += "-qt-paragraph-type:empty;"_L1;
}
emitMargins(QString::number(format.topMargin()),
@@ -2895,38 +3020,38 @@ void QTextHtmlExporter::emitBlockAttributes(const QTextBlock &block)
QString::number(format.leftMargin()),
QString::number(format.rightMargin()));
- html += QLatin1String(" -qt-block-indent:");
+ html += " -qt-block-indent:"_L1;
html += QString::number(format.indent());
- html += QLatin1Char(';');
+ html += u';';
- html += QLatin1String(" text-indent:");
+ html += " text-indent:"_L1;
html += QString::number(format.textIndent());
- html += QLatin1String("px;");
+ html += "px;"_L1;
if (block.userState() != -1) {
- html += QLatin1String(" -qt-user-state:");
+ html += " -qt-user-state:"_L1;
html += QString::number(block.userState());
- html += QLatin1Char(';');
+ html += u';';
}
if (format.lineHeightType() != QTextBlockFormat::SingleHeight) {
- html += QLatin1String(" line-height:")
+ html += " line-height:"_L1
+ QString::number(format.lineHeight());
switch (format.lineHeightType()) {
case QTextBlockFormat::ProportionalHeight:
- html += QLatin1String("%;");
+ html += "%;"_L1;
break;
case QTextBlockFormat::FixedHeight:
- html += QLatin1String("; -qt-line-height-type: fixed;");
+ html += "; -qt-line-height-type: fixed;"_L1;
break;
case QTextBlockFormat::MinimumHeight:
- html += QLatin1String("px;");
+ html += "px;"_L1;
break;
case QTextBlockFormat::LineDistanceHeight:
- html += QLatin1String("; -qt-line-height-type: line-distance;");
+ html += "; -qt-line-height-type: line-distance;"_L1;
break;
default:
- html += QLatin1String(";");
+ html += ";"_L1;
break; // Should never reach here
}
}
@@ -2949,7 +3074,7 @@ void QTextHtmlExporter::emitBlockAttributes(const QTextBlock &block)
if (!diff.properties().isEmpty())
emitCharFormatStyle(diff);
- html += QLatin1Char('"');
+ html += u'"';
}
@@ -2968,7 +3093,7 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block)
return;
}
- html += QLatin1Char('\n');
+ html += u'\n';
// save and later restore, in case we 'change' the default format by
// emitting block char format information
@@ -2979,130 +3104,157 @@ void QTextHtmlExporter::emitBlock(const QTextBlock &block)
if (list->itemNumber(block) == 0) { // first item? emit <ul> or appropriate
const QTextListFormat format = list->format();
const int style = format.style();
+ bool ordered = false;
switch (style) {
- case QTextListFormat::ListDecimal: html += QLatin1String("<ol"); break;
- case QTextListFormat::ListDisc: html += QLatin1String("<ul"); break;
- case QTextListFormat::ListCircle: html += QLatin1String("<ul type=\"circle\""); break;
- case QTextListFormat::ListSquare: html += QLatin1String("<ul type=\"square\""); break;
- case QTextListFormat::ListLowerAlpha: html += QLatin1String("<ol type=\"a\""); break;
- case QTextListFormat::ListUpperAlpha: html += QLatin1String("<ol type=\"A\""); break;
- case QTextListFormat::ListLowerRoman: html += QLatin1String("<ol type=\"i\""); break;
- case QTextListFormat::ListUpperRoman: html += QLatin1String("<ol type=\"I\""); break;
- default: html += QLatin1String("<ul"); // ### should not happen
+ case QTextListFormat::ListDisc: html += "<ul"_L1; break;
+ case QTextListFormat::ListCircle: html += "<ul type=\"circle\""_L1; break;
+ case QTextListFormat::ListSquare: html += "<ul type=\"square\""_L1; break;
+ case QTextListFormat::ListDecimal: html += "<ol"_L1; ordered = true; break;
+ case QTextListFormat::ListLowerAlpha: html += "<ol type=\"a\""_L1; ordered = true; break;
+ case QTextListFormat::ListUpperAlpha: html += "<ol type=\"A\""_L1; ordered = true; break;
+ case QTextListFormat::ListLowerRoman: html += "<ol type=\"i\""_L1; ordered = true; break;
+ case QTextListFormat::ListUpperRoman: html += "<ol type=\"I\""_L1; ordered = true; break;
+ default: html += "<ul"_L1; // ### should not happen
}
- QString styleString = QString::fromLatin1("margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;");
+ if (ordered && format.start() != 1) {
+ html += " start=\""_L1;
+ html += QString::number(format.start());
+ html += u'"';
+ }
+
+ QString styleString;
+ styleString += "margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px;"_L1;
if (format.hasProperty(QTextFormat::ListIndent)) {
- styleString += QLatin1String(" -qt-list-indent: ");
+ styleString += " -qt-list-indent: "_L1;
styleString += QString::number(format.indent());
- styleString += QLatin1Char(';');
+ styleString += u';';
}
if (format.hasProperty(QTextFormat::ListNumberPrefix)) {
QString numberPrefix = format.numberPrefix();
- numberPrefix.replace(QLatin1Char('"'), QLatin1String("\\22"));
- numberPrefix.replace(QLatin1Char('\''), QLatin1String("\\27")); // FIXME: There's a problem in the CSS parser the prevents this from being correctly restored
- styleString += QLatin1String(" -qt-list-number-prefix: ");
- styleString += QLatin1Char('\'');
+ numberPrefix.replace(u'"', "\\22"_L1);
+ numberPrefix.replace(u'\'', "\\27"_L1); // FIXME: There's a problem in the CSS parser the prevents this from being correctly restored
+ styleString += " -qt-list-number-prefix: "_L1;
+ styleString += u'\'';
styleString += numberPrefix;
- styleString += QLatin1Char('\'');
- styleString += QLatin1Char(';');
+ styleString += u'\'';
+ styleString += u';';
}
if (format.hasProperty(QTextFormat::ListNumberSuffix)) {
- if (format.numberSuffix() != QLatin1String(".")) { // this is our default
+ if (format.numberSuffix() != "."_L1) { // this is our default
QString numberSuffix = format.numberSuffix();
- numberSuffix.replace(QLatin1Char('"'), QLatin1String("\\22"));
- numberSuffix.replace(QLatin1Char('\''), QLatin1String("\\27")); // see above
- styleString += QLatin1String(" -qt-list-number-suffix: ");
- styleString += QLatin1Char('\'');
+ numberSuffix.replace(u'"', "\\22"_L1);
+ numberSuffix.replace(u'\'', "\\27"_L1); // see above
+ styleString += " -qt-list-number-suffix: "_L1;
+ styleString += u'\'';
styleString += numberSuffix;
- styleString += QLatin1Char('\'');
- styleString += QLatin1Char(';');
+ styleString += u'\'';
+ styleString += u';';
}
}
- html += QLatin1String(" style=\"");
+ html += " style=\""_L1;
html += styleString;
- html += QLatin1String("\">");
+ html += "\">\n"_L1;
}
- html += QLatin1String("<li");
+ html += "<li"_L1;
const QTextCharFormat blockFmt = formatDifference(defaultCharFormat, block.charFormat()).toCharFormat();
if (!blockFmt.properties().isEmpty()) {
- html += QLatin1String(" style=\"");
+ html += " style=\""_L1;
emitCharFormatStyle(blockFmt);
- html += QLatin1Char('\"');
+ html += u'\"';
defaultCharFormat.merge(block.charFormat());
}
+ if (block.blockFormat().hasProperty(QTextFormat::BlockMarker)) {
+ switch (block.blockFormat().marker()) {
+ case QTextBlockFormat::MarkerType::Checked:
+ html += " class=\"checked\""_L1;
+ break;
+ case QTextBlockFormat::MarkerType::Unchecked:
+ html += " class=\"unchecked\""_L1;
+ break;
+ case QTextBlockFormat::MarkerType::NoMarker:
+ break;
+ }
+ }
}
const QTextBlockFormat blockFormat = block.blockFormat();
if (blockFormat.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) {
- html += QLatin1String("<hr");
+ html += "<hr"_L1;
QTextLength width = blockFormat.lengthProperty(QTextFormat::BlockTrailingHorizontalRulerWidth);
if (width.type() != QTextLength::VariableLength)
emitTextLength("width", width);
- else
- html += QLatin1Char(' ');
+ html += u' ';
+
+ if (blockFormat.hasProperty(QTextFormat::BackgroundBrush)) {
+ html += "style=\""_L1;
+ html += "background-color:"_L1;
+ html += colorValue(qvariant_cast<QBrush>(blockFormat.property(QTextFormat::BackgroundBrush)).color());
+ html += u';';
+ html += u'\"';
+ }
- html += QLatin1String("/>");
+ html += "/>"_L1;
return;
}
const bool pre = blockFormat.nonBreakableLines();
if (pre) {
if (list)
- html += QLatin1Char('>');
- html += QLatin1String("<pre");
+ html += u'>';
+ html += "<pre"_L1;
} else if (!list) {
int headingLevel = blockFormat.headingLevel();
if (headingLevel > 0 && headingLevel <= 6)
- html += QLatin1String("<h") + QString::number(headingLevel);
+ html += "<h"_L1 + QString::number(headingLevel);
else
- html += QLatin1String("<p");
+ html += "<p"_L1;
}
emitBlockAttributes(block);
- html += QLatin1Char('>');
+ html += u'>';
if (block.begin().atEnd())
- html += QLatin1String("<br />");
+ html += "<br />"_L1;
QTextBlock::Iterator it = block.begin();
if (fragmentMarkers && !it.atEnd() && block == doc->begin())
- html += QLatin1String("<!--StartFragment-->");
+ html += "<!--StartFragment-->"_L1;
for (; !it.atEnd(); ++it)
emitFragment(it.fragment());
if (fragmentMarkers && block.position() + block.length() == QTextDocumentPrivate::get(doc)->length())
- html += QLatin1String("<!--EndFragment-->");
+ html += "<!--EndFragment-->"_L1;
QString closeTags;
if (pre)
- html += QLatin1String("</pre>");
+ html += "</pre>"_L1;
else if (list)
- closeTags += QLatin1String("</li>");
+ closeTags += "</li>"_L1;
else {
int headingLevel = blockFormat.headingLevel();
if (headingLevel > 0 && headingLevel <= 6)
- html += QLatin1String("</h") + QString::number(headingLevel) + QLatin1Char('>');
+ html += QString::asprintf("</h%d>", headingLevel);
else
- html += QLatin1String("</p>");
+ html += "</p>"_L1;
}
if (list) {
if (list->itemNumber(block) == list->count() - 1) { // last item? close list
if (isOrderedList(list->format().style()))
- closeTags += QLatin1String("</ol>");
+ closeTags += "</ol>"_L1;
else
- closeTags += QLatin1String("</ul>");
+ closeTags += "</ul>"_L1;
}
const QTextBlock nextBlock = block.next();
// If the next block is the beginning of a new deeper nested list, then we don't
@@ -3198,7 +3350,7 @@ void QTextHtmlExporter::emitTable(const QTextTable *table)
{
QTextTableFormat format = table->format();
- html += QLatin1String("\n<table");
+ html += "\n<table"_L1;
if (format.hasProperty(QTextFormat::FrameBorder))
emitAttribute("border", QString::number(format.border()));
@@ -3215,7 +3367,7 @@ void QTextHtmlExporter::emitTable(const QTextTable *table)
emitBackgroundAttribute(format);
- html += QLatin1Char('>');
+ html += u'>';
const int rows = table->rows();
const int columns = table->columns();
@@ -3225,7 +3377,7 @@ void QTextHtmlExporter::emitTable(const QTextTable *table)
columnWidths.resize(columns);
columnWidths.fill(QTextLength());
}
- Q_ASSERT(columnWidths.count() == columns);
+ Q_ASSERT(columnWidths.size() == columns);
QVarLengthArray<bool> widthEmittedForColumn(columns);
for (int i = 0; i < columns; ++i)
@@ -3233,10 +3385,10 @@ void QTextHtmlExporter::emitTable(const QTextTable *table)
const int headerRowCount = qMin(format.headerRowCount(), rows);
if (headerRowCount > 0)
- html += QLatin1String("<thead>");
+ html += "<thead>"_L1;
for (int row = 0; row < rows; ++row) {
- html += QLatin1String("\n<tr>");
+ html += "\n<tr>"_L1;
for (int col = 0; col < columns; ++col) {
const QTextTableCell cell = table->cellAt(row, col);
@@ -3248,7 +3400,7 @@ void QTextHtmlExporter::emitTable(const QTextTable *table)
if (cell.column() != col)
continue;
- html += QLatin1String("\n<td");
+ html += "\n<td"_L1;
if (!widthEmittedForColumn[col] && cell.columnSpan() == 1) {
emitTextLength("width", columnWidths.at(col));
@@ -3270,21 +3422,21 @@ void QTextHtmlExporter::emitTable(const QTextTable *table)
QString styleString;
if (valign >= QTextCharFormat::AlignMiddle && valign <= QTextCharFormat::AlignBottom) {
- styleString += QLatin1String(" vertical-align:");
+ styleString += " vertical-align:"_L1;
switch (valign) {
case QTextCharFormat::AlignMiddle:
- styleString += QLatin1String("middle");
+ styleString += "middle"_L1;
break;
case QTextCharFormat::AlignTop:
- styleString += QLatin1String("top");
+ styleString += "top"_L1;
break;
case QTextCharFormat::AlignBottom:
- styleString += QLatin1String("bottom");
+ styleString += "bottom"_L1;
break;
default:
break;
}
- styleString += QLatin1Char(';');
+ styleString += u';';
QTextCharFormat temp;
temp.setVerticalAlignment(valign);
@@ -3292,59 +3444,59 @@ void QTextHtmlExporter::emitTable(const QTextTable *table)
}
if (cellFormat.hasProperty(QTextFormat::TableCellLeftPadding))
- styleString += QLatin1String(" padding-left:") + QString::number(cellFormat.leftPadding()) + QLatin1Char(';');
+ styleString += " padding-left:"_L1 + QString::number(cellFormat.leftPadding()) + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellRightPadding))
- styleString += QLatin1String(" padding-right:") + QString::number(cellFormat.rightPadding()) + QLatin1Char(';');
+ styleString += " padding-right:"_L1 + QString::number(cellFormat.rightPadding()) + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellTopPadding))
- styleString += QLatin1String(" padding-top:") + QString::number(cellFormat.topPadding()) + QLatin1Char(';');
+ styleString += " padding-top:"_L1 + QString::number(cellFormat.topPadding()) + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellBottomPadding))
- styleString += QLatin1String(" padding-bottom:") + QString::number(cellFormat.bottomPadding()) + QLatin1Char(';');
+ styleString += " padding-bottom:"_L1 + QString::number(cellFormat.bottomPadding()) + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellTopBorder))
- styleString += QLatin1String(" border-top:") + QString::number(cellFormat.topBorder()) + QLatin1String("px;");
+ styleString += " border-top:"_L1 + QString::number(cellFormat.topBorder()) + "px;"_L1;
if (cellFormat.hasProperty(QTextFormat::TableCellRightBorder))
- styleString += QLatin1String(" border-right:") + QString::number(cellFormat.rightBorder()) + QLatin1String("px;");
+ styleString += " border-right:"_L1 + QString::number(cellFormat.rightBorder()) + "px;"_L1;
if (cellFormat.hasProperty(QTextFormat::TableCellBottomBorder))
- styleString += QLatin1String(" border-bottom:") + QString::number(cellFormat.bottomBorder()) + QLatin1String("px;");
+ styleString += " border-bottom:"_L1 + QString::number(cellFormat.bottomBorder()) + "px;"_L1;
if (cellFormat.hasProperty(QTextFormat::TableCellLeftBorder))
- styleString += QLatin1String(" border-left:") + QString::number(cellFormat.leftBorder()) + QLatin1String("px;");
+ styleString += " border-left:"_L1 + QString::number(cellFormat.leftBorder()) + "px;"_L1;
if (cellFormat.hasProperty(QTextFormat::TableCellTopBorderBrush))
- styleString += QLatin1String(" border-top-color:") + cellFormat.topBorderBrush().color().name() + QLatin1Char(';');
+ styleString += " border-top-color:"_L1 + cellFormat.topBorderBrush().color().name() + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellRightBorderBrush))
- styleString += QLatin1String(" border-right-color:") + cellFormat.rightBorderBrush().color().name() + QLatin1Char(';');
+ styleString += " border-right-color:"_L1 + cellFormat.rightBorderBrush().color().name() + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellBottomBorderBrush))
- styleString += QLatin1String(" border-bottom-color:") + cellFormat.bottomBorderBrush().color().name() + QLatin1Char(';');
+ styleString += " border-bottom-color:"_L1 + cellFormat.bottomBorderBrush().color().name() + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellLeftBorderBrush))
- styleString += QLatin1String(" border-left-color:") + cellFormat.leftBorderBrush().color().name() + QLatin1Char(';');
+ styleString += " border-left-color:"_L1 + cellFormat.leftBorderBrush().color().name() + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellTopBorderStyle))
- styleString += QLatin1String(" border-top-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.topBorderStyle()) + QLatin1Char(';');
+ styleString += " border-top-style:"_L1 + richtextBorderStyleToHtmlBorderStyle(cellFormat.topBorderStyle()) + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellRightBorderStyle))
- styleString += QLatin1String(" border-right-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.rightBorderStyle()) + QLatin1Char(';');
+ styleString += " border-right-style:"_L1 + richtextBorderStyleToHtmlBorderStyle(cellFormat.rightBorderStyle()) + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellBottomBorderStyle))
- styleString += QLatin1String(" border-bottom-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.bottomBorderStyle()) + QLatin1Char(';');
+ styleString += " border-bottom-style:"_L1 + richtextBorderStyleToHtmlBorderStyle(cellFormat.bottomBorderStyle()) + u';';
if (cellFormat.hasProperty(QTextFormat::TableCellLeftBorderStyle))
- styleString += QLatin1String(" border-left-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.leftBorderStyle()) + QLatin1Char(';');
+ styleString += " border-left-style:"_L1 + richtextBorderStyleToHtmlBorderStyle(cellFormat.leftBorderStyle()) + u';';
if (!styleString.isEmpty())
- html += QLatin1String(" style=\"") + styleString + QLatin1Char('\"');
+ html += " style=\""_L1 + styleString + u'\"';
- html += QLatin1Char('>');
+ html += u'>';
emitFrame(cell.begin());
- html += QLatin1String("</td>");
+ html += "</td>"_L1;
defaultCharFormat = oldDefaultCharFormat;
}
- html += QLatin1String("</tr>");
+ html += "</tr>"_L1;
if (headerRowCount > 0 && row == headerRowCount - 1)
- html += QLatin1String("</thead>");
+ html += "</thead>"_L1;
}
- html += QLatin1String("</table>");
+ html += "</table>"_L1;
}
void QTextHtmlExporter::emitFrame(const QTextFrame::Iterator &frameIt)
@@ -3377,7 +3529,7 @@ void QTextHtmlExporter::emitTextFrame(const QTextFrame *f)
{
FrameType frameType = f->parentFrame() ? TextFrame : RootFrame;
- html += QLatin1String("\n<table");
+ html += "\n<table"_L1;
QTextFrameFormat format = f->frameFormat();
if (format.hasProperty(QTextFormat::FrameBorder))
@@ -3392,22 +3544,22 @@ void QTextHtmlExporter::emitTextFrame(const QTextFrame *f)
if (frameType != RootFrame)
emitBackgroundAttribute(format);
- html += QLatin1Char('>');
- html += QLatin1String("\n<tr>\n<td style=\"border: none;\">");
+ html += u'>';
+ html += "\n<tr>\n<td style=\"border: none;\">"_L1;
emitFrame(f->begin());
- html += QLatin1String("</td></tr></table>");
+ html += "</td></tr></table>"_L1;
}
void QTextHtmlExporter::emitFrameStyle(const QTextFrameFormat &format, FrameType frameType)
{
- QLatin1String styleAttribute(" style=\"");
+ const auto styleAttribute = " style=\""_L1;
html += styleAttribute;
- const int originalHtmlLength = html.length();
+ const qsizetype originalHtmlLength = html.size();
if (frameType == TextFrame)
- html += QLatin1String("-qt-table-type: frame;");
+ html += "-qt-table-type: frame;"_L1;
else if (frameType == RootFrame)
- html += QLatin1String("-qt-table-type: root;");
+ html += "-qt-table-type: root;"_L1;
const QTextFrameFormat defaultFormat;
@@ -3415,9 +3567,9 @@ void QTextHtmlExporter::emitFrameStyle(const QTextFrameFormat &format, FrameType
emitPageBreakPolicy(format.pageBreakPolicy());
if (format.borderBrush() != defaultFormat.borderBrush()) {
- html += QLatin1String(" border-color:");
+ html += " border-color:"_L1;
html += colorValue(format.borderBrush().color());
- html += QLatin1Char(';');
+ html += u';';
}
if (format.borderStyle() != defaultFormat.borderStyle())
@@ -3434,12 +3586,12 @@ void QTextHtmlExporter::emitFrameStyle(const QTextFrameFormat &format, FrameType
QString::number(format.rightMargin()));
if (format.property(QTextFormat::TableBorderCollapse).toBool())
- html += QLatin1String(" border-collapse:collapse;");
+ html += " border-collapse:collapse;"_L1;
- if (html.length() == originalHtmlLength) // nothing emitted?
+ if (html.size() == originalHtmlLength) // nothing emitted?
html.chop(styleAttribute.size());
else
- html += QLatin1Char('\"');
+ html += u'\"';
}
/*!
@@ -3511,7 +3663,7 @@ QString QTextDocument::toMarkdown(QTextDocument::MarkdownFeatures features) cons
#if QT_CONFIG(textmarkdownreader)
void QTextDocument::setMarkdown(const QString &markdown, QTextDocument::MarkdownFeatures features)
{
- QTextMarkdownImporter(features).import(this, markdown);
+ QTextMarkdownImporter(this, features).import(markdown);
}
#endif
@@ -3532,3 +3684,5 @@ QList<QTextFormat> QTextDocument::allFormats() const
*/
QT_END_NAMESPACE
+
+#include "moc_qtextdocument.cpp"
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index dc4d15f3a8..b6253bfa46 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTDOCUMENT_H
#define QTEXTDOCUMENT_H
@@ -71,7 +35,10 @@ class QTextCursor;
namespace Qt
{
+#if QT_GUI_REMOVED_SINCE(6, 7)
Q_GUI_EXPORT bool mightBeRichText(const QString&);
+#endif
+ Q_GUI_EXPORT bool mightBeRichText(QAnyStringView);
Q_GUI_EXPORT QString convertFromPlainText(const QString &plain, WhiteSpaceMode mode = WhiteSpacePre);
}
@@ -98,6 +65,7 @@ class Q_GUI_EXPORT QTextDocument : public QObject
Q_PROPERTY(QSizeF pageSize READ pageSize WRITE setPageSize)
Q_PROPERTY(QFont defaultFont READ defaultFont WRITE setDefaultFont)
Q_PROPERTY(bool useDesignMetrics READ useDesignMetrics WRITE setUseDesignMetrics)
+ Q_PROPERTY(bool layoutEnabled READ isLayoutEnabled WRITE setLayoutEnabled)
Q_PROPERTY(QSizeF size READ size)
Q_PROPERTY(qreal textWidth READ textWidth WRITE setTextWidth)
Q_PROPERTY(int blockCount READ blockCount)
@@ -136,7 +104,9 @@ public:
enum MetaInformation {
DocumentTitle,
- DocumentUrl
+ DocumentUrl,
+ CssMedia,
+ FrontMatter,
};
void setMetaInformation(MetaInformation info, const QString &);
QString metaInformation(MetaInformation info) const;
@@ -150,7 +120,7 @@ public:
enum MarkdownFeature {
MarkdownNoHTML = 0x0020 | 0x0040,
MarkdownDialectCommonMark = 0,
- MarkdownDialectGitHub = 0x0004 | 0x0008 | 0x0400 | 0x0100 | 0x0200 | 0x0800 | 0x4000
+ MarkdownDialectGitHub = 0x0004 | 0x0008 | 0x0400 | 0x0100 | 0x0200 | 0x0800 | 0x4000 | 0x100000
};
Q_DECLARE_FLAGS(MarkdownFeatures, MarkdownFeature)
Q_FLAG(MarkdownFeatures)
@@ -253,6 +223,9 @@ public:
void setUseDesignMetrics(bool b);
bool useDesignMetrics() const;
+ void setLayoutEnabled(bool b);
+ bool isLayoutEnabled() const;
+
void drawContents(QPainter *painter, const QRectF &rect = QRectF());
void setTextWidth(qreal width);
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index c902b878bf..3c1fc04d4b 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qtools_p.h>
#include <qdebug.h>
@@ -59,7 +23,7 @@ QT_BEGIN_NAMESPACE
#define PMDEBUG if(0) qDebug
-// The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 }
+// The VxWorks DIAB compiler crashes when initializing the anonymous union with { a7 }
#if !defined(Q_CC_DIAB)
# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \
QTextUndoCommand c = { a1, a2, 0, 0, quint8(a3), a4, quint32(a5), quint32(a6), { int(a7) }, quint32(a8) }
@@ -187,7 +151,8 @@ QTextDocumentPrivate::QTextDocumentPrivate()
framesDirty(true),
rtFrame(nullptr),
initialBlockCharFormatIndex(-1), // set correctly later in init()
- resourceProvider(nullptr)
+ resourceProvider(nullptr),
+ cssMedia(QStringLiteral("screen"))
{
editBlock = 0;
editBlockCursorPosition = -1;
@@ -237,7 +202,7 @@ void QTextDocumentPrivate::clear()
{
Q_Q(QTextDocument);
- for (QTextCursorPrivate *curs : qAsConst(cursors)) {
+ for (QTextCursorPrivate *curs : std::as_const(cursors)) {
curs->setPosition(0);
curs->currentCharFormat = -1;
curs->anchor = 0;
@@ -290,7 +255,7 @@ void QTextDocumentPrivate::clear()
QTextDocumentPrivate::~QTextDocumentPrivate()
{
- for (QTextCursorPrivate *curs : qAsConst(cursors))
+ for (QTextCursorPrivate *curs : std::as_const(cursors))
curs->priv = nullptr;
cursors.clear();
undoState = 0;
@@ -382,8 +347,13 @@ int QTextDocumentPrivate::insert_block(int pos, uint strPos, int format, int blo
Q_ASSERT(blocks.length() == fragments.length());
QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(blockFormat));
- if (group)
+ if (group) {
group->blockInserted(QTextBlock(this, b));
+ if (command != QTextUndoCommand::BlockDeleted) {
+ docChangeOldLength--;
+ docChangeLength--;
+ }
+ }
QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(formats.format(format)));
if (frame) {
@@ -405,7 +375,7 @@ int QTextDocumentPrivate::insertBlock(QChar blockSeparator,
beginEditBlock();
- int strPos = text.length();
+ int strPos = text.size();
text.append(blockSeparator);
int ob = blocks.findNode(pos);
@@ -475,16 +445,16 @@ void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format
finishEdit();
}
-void QTextDocumentPrivate::insert(int pos, const QString &str, int format)
+void QTextDocumentPrivate::insert(int pos, QStringView str, int format)
{
if (str.size() == 0)
return;
Q_ASSERT(noBlockInString(str));
- int strPos = text.length();
+ int strPos = text.size();
text.append(str);
- insert(pos, strPos, str.length(), format);
+ insert(pos, strPos, str.size(), format);
}
int QTextDocumentPrivate::remove_string(int pos, uint length, QTextUndoCommand::Operation op)
@@ -678,7 +648,7 @@ void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operati
blockCursorAdjustment = true;
move(pos, -1, length, op);
blockCursorAdjustment = false;
- for (QTextCursorPrivate *curs : qAsConst(cursors)) {
+ for (QTextCursorPrivate *curs : std::as_const(cursors)) {
if (curs->adjustPosition(pos, -length, op) == QTextCursorPrivate::CursorMoved) {
curs->changed = true;
}
@@ -1236,13 +1206,13 @@ void QTextDocumentPrivate::finishEdit()
}
QList<QTextCursor> changedCursors;
- for (QTextCursorPrivate *curs : qAsConst(cursors)) {
+ for (QTextCursorPrivate *curs : std::as_const(cursors)) {
if (curs->changed) {
curs->changed = false;
changedCursors.append(QTextCursor(curs));
}
}
- for (const QTextCursor &cursor : qAsConst(changedCursors))
+ for (const QTextCursor &cursor : std::as_const(changedCursors))
emit q->cursorPositionChanged(cursor);
contentsChanged();
@@ -1288,7 +1258,7 @@ void QTextDocumentPrivate::adjustDocumentChangesAndCursors(int from, int addedOr
if (blockCursorAdjustment) {
; // postpone, will be called again from QTextDocumentPrivate::remove()
} else {
- for (QTextCursorPrivate *curs : qAsConst(cursors)) {
+ for (QTextCursorPrivate *curs : std::as_const(cursors)) {
if (curs->adjustPosition(from, addedOrRemoved, op) == QTextCursorPrivate::CursorMoved) {
curs->changed = true;
}
@@ -1451,6 +1421,16 @@ QTextFrame *QTextDocumentPrivate::rootFrame() const
return rtFrame;
}
+void QTextDocumentPrivate::addCursor(QTextCursorPrivate *c)
+{
+ cursors.insert(c);
+}
+
+void QTextDocumentPrivate::removeCursor(QTextCursorPrivate *c)
+{
+ cursors.remove(c);
+}
+
QTextFrame *QTextDocumentPrivate::frameAt(int pos) const
{
QTextFrame *f = rootFrame();
@@ -1465,7 +1445,7 @@ QTextFrame *QTextDocumentPrivate::frameAt(int pos) const
void QTextDocumentPrivate::clearFrame(QTextFrame *f)
{
- for (int i = 0; i < f->d_func()->childFrames.count(); ++i)
+ for (int i = 0; i < f->d_func()->childFrames.size(); ++i)
clearFrame(f->d_func()->childFrames.at(i));
f->d_func()->childFrames.clear();
f->d_func()->parentFrame = nullptr;
@@ -1735,7 +1715,7 @@ bool QTextDocumentPrivate::ensureMaximumBlockCount()
void QTextDocumentPrivate::aboutToRemoveCell(int from, int to)
{
Q_ASSERT(from <= to);
- for (QTextCursorPrivate *curs : qAsConst(cursors))
+ for (QTextCursorPrivate *curs : std::as_const(cursors))
curs->aboutToRemoveCell(from, to);
}
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index b26d7657ec..1c4edc4329 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTDOCUMENT_P_H
#define QTEXTDOCUMENT_P_H
@@ -65,7 +29,9 @@
#include "QtCore/qurl.h"
#include "QtCore/qvariant.h"
+#if QT_CONFIG(cssparser)
#include "private/qcssparser_p.h"
+#endif
#include "private/qfragmentmap_p.h"
#include "private/qobject_p.h"
#include "private/qtextformat_p.h"
@@ -176,7 +142,9 @@ public:
void setLayout(QAbstractTextDocumentLayout *layout);
- void insert(int pos, const QString &text, int format);
+ void insert(int pos, QStringView text, int format);
+ void insert(int pos, QChar c, int format)
+ { insert(pos, QStringView(&c, 1), format); }
void insert(int pos, int strPos, int strLength, int format);
int insertBlock(int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation = QTextUndoCommand::MoveCursor);
int insertBlock(QChar blockSeparator, int pos, int blockFormat, int charFormat,
@@ -279,8 +247,8 @@ private:
public:
void documentChange(int from, int length);
- inline void addCursor(QTextCursorPrivate *c) { cursors.insert(c); }
- inline void removeCursor(QTextCursorPrivate *c) { cursors.remove(c); }
+ void addCursor(QTextCursorPrivate *c);
+ void removeCursor(QTextCursorPrivate *c);
QTextFrame *frameAt(int pos) const;
QTextFrame *rootFrame() const;
@@ -327,6 +295,8 @@ public:
return get(object->document());
}
+ bool canLayout() const { return layoutEnabled && !pageSize.isNull(); }
+
private:
QTextDocumentPrivate(const QTextDocumentPrivate& m);
QTextDocumentPrivate& operator= (const QTextDocumentPrivate& m);
@@ -373,6 +343,7 @@ private:
public:
bool inContentsChange;
+ bool layoutEnabled = true;
QTextOption defaultTextOption;
Qt::CursorMoveStyle defaultCursorMoveStyle;
#ifndef QT_NO_CSSPARSER
@@ -384,6 +355,8 @@ public:
QSizeF pageSize;
QString title;
QString url;
+ QString cssMedia;
+ QString frontMatter;
qreal indentWidth;
qreal documentMargin;
QUrl baseUrl;
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index 24f2198d4e..1b6e76c201 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -1,46 +1,16 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextdocumentfragment.h"
#include "qtextdocumentfragment_p.h"
#include "qtextcursor_p.h"
#include "qtextlist.h"
+#if QT_CONFIG(textmarkdownreader)
+#include "qtextmarkdownimporter_p.h"
+#endif
+#if QT_CONFIG(textmarkdownwriter)
+#include "qtextmarkdownwriter_p.h"
+#endif
#include <qdebug.h>
#include <qbytearray.h>
@@ -49,6 +19,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
QTextCopyHelper::QTextCopyHelper(const QTextCursor &_source, const QTextCursor &_destination, bool forceCharFormat, const QTextCharFormat &fmt)
#if defined(Q_CC_DIAB) // compiler bug
: formatCollection(*_destination.d->priv->formatCollection()), originalText((const QString)_source.d->priv->buffer())
@@ -112,7 +84,7 @@ int QTextCopyHelper::appendFragment(int pos, int endPos, int objectIndex)
}
QString txtToInsert(originalText.constData() + frag->stringPosition + inFragmentOffset, charsToCopy);
- if (txtToInsert.length() == 1
+ if (txtToInsert.size() == 1
&& (txtToInsert.at(0) == QChar::ParagraphSeparator
|| txtToInsert.at(0) == QTextBeginningOfFrame
|| txtToInsert.at(0) == QTextEndOfFrame
@@ -137,7 +109,7 @@ int QTextCopyHelper::appendFragment(int pos, int endPos, int objectIndex)
const int userState = nextBlock.userState();
if (userState != -1)
dst->blocksFind(insertPos).setUserState(userState);
- insertPos += txtToInsert.length();
+ insertPos += txtToInsert.size();
}
return charsToCopy;
@@ -266,12 +238,11 @@ void QTextDocumentFragmentPrivate::insert(QTextCursor &_cursor) const
document fragment. Document fragments can also be created by the
static functions, fromPlainText() and fromHtml().
- The contents of a document fragment can be obtained as plain text
- by using the toPlainText() function, or it can be obtained as HTML
- with toHtml().
+ The contents of a document fragment can be obtained as raw text
+ by using the toRawText() function, as ASCII with toPlainText(),
+ as HTML with toHtml(), or as Markdown with toMarkdown().
*/
-
/*!
Constructs an empty QTextDocumentFragment.
@@ -358,10 +329,15 @@ bool QTextDocumentFragment::isEmpty() const
}
/*!
- Returns the document fragment's text as plain text (i.e. with no
- formatting information).
-
- \sa toHtml()
+ This function returns the same as toRawText(), but will replace
+ some unicode characters with ASCII alternatives.
+ In particular, no-break space (U+00A0) is replaced by a regular
+ space (U+0020), and both paragraph (U+2029) and line (U+2028)
+ separators are replaced by line feed (U+000A).
+ If you need the precise contents of the document, use toRawText()
+ instead.
+
+ \sa toHtml(), toMarkdown(), toRawText()
*/
QString QTextDocumentFragment::toPlainText() const
{
@@ -371,6 +347,21 @@ QString QTextDocumentFragment::toPlainText() const
return d->doc->toPlainText();
}
+/*!
+ Returns the document fragment's text as raw text (i.e. with no
+ formatting information).
+
+ \since 6.4
+ \sa toHtml(), toMarkdown(), toPlainText()
+*/
+QString QTextDocumentFragment::toRawText() const
+{
+ if (!d)
+ return QString();
+
+ return d->doc->toRawText();
+}
+
#ifndef QT_NO_TEXTHTMLPARSER
/*!
@@ -378,7 +369,7 @@ QString QTextDocumentFragment::toPlainText() const
Returns the contents of the document fragment as HTML.
- \sa toPlainText(), QTextDocument::toHtml()
+ \sa toPlainText(), toMarkdown(), QTextDocument::toHtml()
*/
QString QTextDocumentFragment::toHtml() const
{
@@ -390,6 +381,26 @@ QString QTextDocumentFragment::toHtml() const
#endif // QT_NO_TEXTHTMLPARSER
+#if QT_CONFIG(textmarkdownwriter)
+
+/*!
+ \since 6.4
+
+ Returns the contents of the document fragment as Markdown,
+ with the specified \a features. The default is GitHub dialect.
+
+ \sa toPlainText(), QTextDocument::toMarkdown()
+*/
+QString QTextDocumentFragment::toMarkdown(QTextDocument::MarkdownFeatures features) const
+{
+ if (!d)
+ return QString();
+
+ return d->doc->toMarkdown(features);
+}
+
+#endif // textmarkdownwriter
+
/*!
Returns a document fragment that contains the given \a plainText.
@@ -425,14 +436,14 @@ QTextHtmlImporter::QTextHtmlImporter(QTextDocument *_doc, const QString &_html,
wsm = QTextHtmlParserNode::WhiteSpaceNormal;
QString html = _html;
- const int startFragmentPos = html.indexOf(QLatin1String("<!--StartFragment-->"));
+ const int startFragmentPos = html.indexOf("<!--StartFragment-->"_L1);
if (startFragmentPos != -1) {
- const QLatin1String qt3RichTextHeader("<meta name=\"qrichtext\" content=\"1\" />");
+ const auto qt3RichTextHeader = "<meta name=\"qrichtext\" content=\"1\" />"_L1;
// Hack for Qt3
const bool hasQtRichtextMetaTag = html.contains(qt3RichTextHeader);
- const int endFragmentPos = html.indexOf(QLatin1String("<!--EndFragment-->"));
+ const int endFragmentPos = html.indexOf("<!--EndFragment-->"_L1);
if (startFragmentPos < endFragmentPos)
html = html.mid(startFragmentPos, endFragmentPos - startFragmentPos);
else
@@ -477,7 +488,8 @@ void QTextHtmlImporter::import()
* means there was a tag closing in the input html
*/
if (currentNodeIdx > 0 && (currentNode->parent != currentNodeIdx - 1)) {
- blockTagClosed = closeTag();
+ const bool lastBlockTagClosed = closeTag();
+ blockTagClosed = blockTagClosed || lastBlockTagClosed;
// visually collapse subsequent block tags, but if the element after the closed block tag
// is for example an inline element (!isBlock) we have to make sure we start a new paragraph by setting
// hasBlock to false.
@@ -529,6 +541,7 @@ void QTextHtmlImporter::import()
appendBlock(block, currentNode->charFormat);
+ blockTagClosed = false;
hasBlock = true;
}
@@ -564,19 +577,17 @@ bool QTextHtmlImporter::appendNodeText()
if (wsm == QTextHtmlParserNode::WhiteSpacePre || wsm == QTextHtmlParserNode::WhiteSpacePreWrap)
compressNextWhitespace = PreserveWhiteSpace;
- QString text = currentNode->text;
+ const QString text = currentNode->text;
QString textToInsert;
textToInsert.reserve(text.size());
- for (int i = 0; i < text.length(); ++i) {
- QChar ch = text.at(i);
-
+ for (QChar ch : text) {
if (ch.isSpace()
&& ch != QChar::Nbsp
&& ch != QChar::ParagraphSeparator) {
- if (wsm == QTextHtmlParserNode::WhiteSpacePreLine && (ch == QLatin1Char('\n') || ch == QLatin1Char('\r')))
+ if (wsm == QTextHtmlParserNode::WhiteSpacePreLine && (ch == u'\n' || ch == u'\r'))
compressNextWhitespace = PreserveWhiteSpace;
if (compressNextWhitespace == CollapseWhiteSpace)
@@ -587,30 +598,30 @@ bool QTextHtmlImporter::appendNodeText()
if (wsm == QTextHtmlParserNode::WhiteSpacePre
|| textEditMode
) {
- if (ch == QLatin1Char('\n')) {
+ if (ch == u'\n') {
if (textEditMode)
continue;
- } else if (ch == QLatin1Char('\r')) {
+ } else if (ch == u'\r') {
continue;
}
} else if (wsm != QTextHtmlParserNode::WhiteSpacePreWrap) {
compressNextWhitespace = RemoveWhiteSpace;
- if (wsm == QTextHtmlParserNode::WhiteSpacePreLine && (ch == QLatin1Char('\n') || ch == QLatin1Char('\r')))
+ if (wsm == QTextHtmlParserNode::WhiteSpacePreLine && (ch == u'\n' || ch == u'\r'))
{ }
else if (wsm == QTextHtmlParserNode::WhiteSpaceNoWrap)
ch = QChar::Nbsp;
else
- ch = QLatin1Char(' ');
+ ch = u' ';
}
} else {
compressNextWhitespace = PreserveWhiteSpace;
}
- if (ch == QLatin1Char('\n')
+ if (ch == u'\n'
|| ch == QChar::ParagraphSeparator) {
if (!textToInsert.isEmpty()) {
- if (wsm == QTextHtmlParserNode::WhiteSpacePreLine && textToInsert.at(textToInsert.length() - 1) == QLatin1Char(' '))
+ if (wsm == QTextHtmlParserNode::WhiteSpacePreLine && textToInsert.at(textToInsert.size() - 1) == u' ')
textToInsert = textToInsert.chopped(1);
cursor.insertText(textToInsert, format);
textToInsert.clear();
@@ -688,6 +699,8 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes()
listFmt.setNumberPrefix(currentNode->textListNumberPrefix);
if (!currentNode->textListNumberSuffix.isNull())
listFmt.setNumberSuffix(currentNode->textListNumberSuffix);
+ if (currentNode->listStart != 1)
+ listFmt.setStart(currentNode->listStart);
++indent;
if (currentNode->hasCssListIndent)
@@ -895,7 +908,7 @@ QTextHtmlImporter::Table QTextHtmlImporter::scanTable(int tableNodeIdx)
int tableHeaderRowCount = 0;
QList<int> rowNodes;
- rowNodes.reserve(at(tableNodeIdx).children.count());
+ rowNodes.reserve(at(tableNodeIdx).children.size());
for (int row : at(tableNodeIdx).children) {
switch (at(row).id) {
case Html_tr:
@@ -920,7 +933,7 @@ QTextHtmlImporter::Table QTextHtmlImporter::scanTable(int tableNodeIdx)
QList<RowColSpanInfo> rowColSpanForColumn;
int effectiveRow = 0;
- for (int row : qAsConst(rowNodes)) {
+ for (int row : std::as_const(rowNodes)) {
int colsInRow = 0;
for (int cell : at(row).children) {
@@ -948,7 +961,7 @@ QTextHtmlImporter::Table QTextHtmlImporter::scanTable(int tableNodeIdx)
if (spanInfo.colSpan > 1 || spanInfo.rowSpan > 1)
rowColSpans.append(spanInfo);
- columnWidths.resize(qMax(columnWidths.count(), colsInRow));
+ columnWidths.resize(qMax(columnWidths.size(), colsInRow));
rowColSpanForColumn.resize(columnWidths.size());
for (int i = currentColumn; i < currentColumn + c.tableCellColSpan; ++i) {
if (columnWidths.at(i).type() == QTextLength::VariableLength) {
@@ -1030,7 +1043,7 @@ QTextHtmlImporter::Table QTextHtmlImporter::scanTable(int tableNodeIdx)
QTextTable *textTable = cursor.insertTable(table.rows, table.columns, fmt.toTableFormat());
table.frame = textTable;
- for (int i = 0; i < rowColSpans.count(); ++i) {
+ for (int i = 0; i < rowColSpans.size(); ++i) {
const RowColSpanInfo &nfo = rowColSpans.at(i);
textTable->mergeCells(nfo.row, nfo.col, nfo.rowSpan, nfo.colSpan);
}
@@ -1255,9 +1268,6 @@ void QTextHtmlImporter::appendBlock(const QTextBlockFormat &format, QTextCharFor
compressNextWhitespace = RemoveWhiteSpace;
}
-#endif // QT_NO_TEXTHTMLPARSER
-
-#ifndef QT_NO_TEXTHTMLPARSER
/*!
\fn QTextDocumentFragment QTextDocumentFragment::fromHtml(const QString &text, const QTextDocument *resourceProvider)
\since 4.2
@@ -1283,4 +1293,30 @@ QTextDocumentFragment QTextDocumentFragment::fromHtml(const QString &html, const
#endif // QT_NO_TEXTHTMLPARSER
+#if QT_CONFIG(textmarkdownreader)
+
+/*!
+ \fn QTextDocumentFragment QTextDocumentFragment::fromMarkdown(const QString &markdown, QTextDocument::MarkdownFeatures features)
+ \since 6.4
+
+ Returns a QTextDocumentFragment based on the given \a markdown text with
+ the specified \a features. The default is GitHub dialect.
+
+ The formatting is preserved as much as possible; for example, \c {**bold**}
+ will become a document fragment containing the text "bold" with a bold
+ character style.
+
+ \note Loading external resources is not supported.
+*/
+QTextDocumentFragment QTextDocumentFragment::fromMarkdown(const QString &markdown, QTextDocument::MarkdownFeatures features)
+{
+ QTextDocumentFragment res;
+ res.d = new QTextDocumentFragmentPrivate;
+
+ QTextMarkdownImporter(res.d->doc, features).import(markdown);
+ return res;
+}
+
+#endif // textmarkdownreader
+
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextdocumentfragment.h b/src/gui/text/qtextdocumentfragment.h
index 2283b06c6c..a618ff15ff 100644
--- a/src/gui/text/qtextdocumentfragment.h
+++ b/src/gui/text/qtextdocumentfragment.h
@@ -1,53 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTDOCUMENTFRAGMENT_H
#define QTEXTDOCUMENTFRAGMENT_H
#include <QtGui/qtguiglobal.h>
+#include <QtGui/qtextdocument.h>
#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
class QTextStream;
-class QTextDocument;
class QTextDocumentFragmentPrivate;
class QTextCursor;
@@ -64,14 +28,22 @@ public:
bool isEmpty() const;
QString toPlainText() const;
+ QString toRawText() const;
#ifndef QT_NO_TEXTHTMLPARSER
QString toHtml() const;
#endif // QT_NO_TEXTHTMLPARSER
+#if QT_CONFIG(textmarkdownwriter)
+ QString toMarkdown(QTextDocument::MarkdownFeatures features = QTextDocument::MarkdownDialectGitHub) const;
+#endif
static QTextDocumentFragment fromPlainText(const QString &plainText);
#ifndef QT_NO_TEXTHTMLPARSER
static QTextDocumentFragment fromHtml(const QString &html, const QTextDocument *resourceProvider = nullptr);
#endif // QT_NO_TEXTHTMLPARSER
+#if QT_CONFIG(textmarkdownreader)
+ static QTextDocumentFragment fromMarkdown(const QString &markdown,
+ QTextDocument::MarkdownFeatures features = QTextDocument::MarkdownDialectGitHub);
+#endif
private:
QTextDocumentFragmentPrivate *d;
diff --git a/src/gui/text/qtextdocumentfragment_p.h b/src/gui/text/qtextdocumentfragment_p.h
index a321b84c5a..0d130003bc 100644
--- a/src/gui/text/qtextdocumentfragment_p.h
+++ b/src/gui/text/qtextdocumentfragment_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTDOCUMENTFRAGMENT_P_H
#define QTEXTDOCUMENTFRAGMENT_P_H
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index f8b4474e09..452f814231 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextdocumentlayout_p.h"
#include "qtextdocument_p.h"
@@ -43,7 +7,9 @@
#include "qtexttable.h"
#include "qtextlist.h"
#include "qtextengine_p.h"
+#if QT_CONFIG(cssparser)
#include "private/qcssutil_p.h"
+#endif
#include "private/qguiapplication_p.h"
#include "qabstracttextdocumentlayout_p.h"
@@ -59,6 +25,7 @@
#include <qbasictimer.h>
#include "private/qfunctions_p.h"
#include <qloggingcategory.h>
+#include <QtCore/qpointer.h>
#include <algorithm>
@@ -581,7 +548,7 @@ public:
QTextLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, const QTextBlockFormat *previousBlockFormat);
void layoutFlow(QTextFrame::Iterator it, QTextLayoutStruct *layoutStruct, int layoutFrom, int layoutTo, QFixed width = 0);
- void floatMargins(const QFixed &y, const QTextLayoutStruct *layoutStruct, QFixed *left, QFixed *right) const;
+ void floatMargins(QFixed y, const QTextLayoutStruct *layoutStruct, QFixed *left, QFixed *right) const;
QFixed findY(QFixed yFrom, const QTextLayoutStruct *layoutStruct, QFixed requiredWidth) const;
QList<QCheckPoint> checkPoints;
@@ -830,7 +797,7 @@ QTextDocumentLayoutPrivate::hitTest(const QTextBlock &bl, const QFixedPoint &poi
textrect.translate(tl->position());
qCDebug(lcHit) << " checking block" << bl.position() << "point=" << point.toPointF() << " tlrect" << textrect;
*position = bl.position();
- if (point.y.toReal() < textrect.top()) {
+ if (point.y.toReal() < textrect.top() - bl.blockFormat().topMargin()) {
qCDebug(lcHit) << " before pos=" << *position;
return PointBefore;
} else if (point.y.toReal() > textrect.bottom()) {
@@ -1211,7 +1178,7 @@ void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *pain
it = frameIteratorForYPosition(QFixed::fromReal(context.clip.top()));
QList<QTextFrame *> floats;
- const int numFloats = fd->floats.count();
+ const int numFloats = fd->floats.size();
floats.reserve(numFloats);
for (int i = 0; i < numFloats; ++i)
floats.append(fd->floats.at(i));
@@ -1245,8 +1212,7 @@ static inline QTextFormat::Property borderPropertyForEdge(QCss::Edge edge)
case QCss::RightEdge:
return QTextFormat::TableCellRightBorder;
default:
- Q_UNREACHABLE();
- return QTextFormat::UserProperty;
+ Q_UNREACHABLE_RETURN(QTextFormat::UserProperty);
}
}
@@ -1262,8 +1228,7 @@ static inline QTextFormat::Property borderStylePropertyForEdge(QCss::Edge edge)
case QCss::RightEdge:
return QTextFormat::TableCellRightBorderStyle;
default:
- Q_UNREACHABLE();
- return QTextFormat::UserProperty;
+ Q_UNREACHABLE_RETURN(QTextFormat::UserProperty);
}
}
@@ -1279,8 +1244,7 @@ static inline QCss::Edge adjacentEdge(QCss::Edge edge)
case QCss::LeftEdge:
return QCss::RightEdge;
default:
- Q_UNREACHABLE();
- return QCss::NumEdges;
+ Q_UNREACHABLE_RETURN(QCss::NumEdges);
}
}
@@ -1359,8 +1323,7 @@ static inline bool sharesAxis(const QTextTableCell &cell, QCss::Edge edge,
return cell.column() + cell.columnSpan() ==
competingCell.column() + (competingCellEdge == QCss::LeftEdge ? 0 : competingCell.columnSpan());
default:
- Q_UNREACHABLE();
- return false;
+ Q_UNREACHABLE_RETURN(false);
}
}
@@ -1519,7 +1482,7 @@ static inline qreal collapseOffset(const QTextDocumentLayoutPrivate *p, const Ed
// there was no edge B (due to a rowspan or the axis C-D being the table's right
// border).
//
-// ignoreEdgesAbove: true if an egde (left, right or top) for the first row
+// ignoreEdgesAbove: true if an edge (left, right or top) for the first row
// after a table page break should be painted. In this case the edges of the
// row above must be ignored.
static inline double prioritizedEdgeAnchorOffset(const QTextDocumentLayoutPrivate *p,
@@ -1855,11 +1818,20 @@ void QTextDocumentLayoutPrivate::drawTableCell(const QRectF &cellRect, QPainter
if (r >= headerRowCount)
topMargin += td->headerHeight.toReal();
- if (!td->borderCollapse && td->border != 0) {
+ // If cell border configured, don't draw default border for cells. It will be taken care later by
+ // drawTableCellBorder().
+ bool cellBorderConfigured = (cell.format().hasProperty(QTextFormat::TableCellLeftBorder) ||
+ cell.format().hasProperty(QTextFormat::TableCellTopBorder) ||
+ cell.format().hasProperty(QTextFormat::TableCellRightBorder) ||
+ cell.format().hasProperty(QTextFormat::TableCellBottomBorder));
+
+ if (!td->borderCollapse && td->border != 0 && !cellBorderConfigured) {
const QBrush oldBrush = painter->brush();
const QPen oldPen = painter->pen();
- const qreal border = td->border.toReal();
+ // If border is configured for the table (and not explicitly for the cell), then
+ // always draw 1px border around the cell
+ const qreal border = 1;
QRectF borderRect(cellRect.left() - border, cellRect.top() - border, cellRect.width() + border, cellRect.height() + border);
@@ -1922,7 +1894,8 @@ void QTextDocumentLayoutPrivate::drawTableCell(const QRectF &cellRect, QPainter
}
// paint over the background - otherwise we would have to adjust the background paint cellRect for the border values
- drawTableCellBorder(cellRect, painter, table, td, cell);
+ if (cellBorderConfigured)
+ drawTableCellBorder(cellRect, painter, table, td, cell);
const QFixed verticalOffset = td->cellVerticalOffsets.at(c + r * table->columns());
@@ -2003,7 +1976,7 @@ void QTextDocumentLayoutPrivate::drawFlow(const QPointF &offset, QPainter *paint
previousFrame = c;
}
- for (int i = 0; i < floats.count(); ++i) {
+ for (int i = 0; i < floats.size(); ++i) {
QTextFrame *frame = floats.at(i);
if (!isFrameFromInlineObject(frame)
|| frame->frameFormat().position() == QTextFrameFormat::InFlow)
@@ -2044,7 +2017,9 @@ void QTextDocumentLayoutPrivate::drawBlock(const QPointF &offset, QPainter *pain
rect.setRight((fd->size.width - fd->rightMargin).toReal());
}
- fillBackground(painter, rect, bg, r.topLeft());
+ // in the case of <hr>, the background-color CSS style fills only the rule's thickness instead of the whole line
+ if (!blockFormat.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth))
+ fillBackground(painter, rect, bg, r.topLeft());
}
QList<QTextLayout::FormatRange> selections;
@@ -2104,7 +2079,10 @@ void QTextDocumentLayoutPrivate::drawBlock(const QPointF &offset, QPainter *pain
if (blockFormat.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) {
const qreal width = blockFormat.lengthProperty(QTextFormat::BlockTrailingHorizontalRulerWidth).value(r.width());
- painter->setPen(context.palette.color(QPalette::Dark));
+ const auto color = blockFormat.hasProperty(QTextFormat::BackgroundBrush)
+ ? qvariant_cast<QBrush>(blockFormat.property(QTextFormat::BackgroundBrush)).color()
+ : context.palette.color(QPalette::Inactive, QPalette::WindowText);
+ painter->setPen(color);
qreal y = r.bottom();
if (bl.length() == 1)
y = r.top() + r.height() / 2;
@@ -2123,7 +2101,7 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
{
Q_Q(const QTextDocumentLayout);
const QTextBlockFormat blockFormat = bl.blockFormat();
- const QTextCharFormat charFormat = QTextCursor(bl).charFormat();
+ const QTextCharFormat charFormat = bl.charFormat();
QFont font(charFormat.font());
if (q->paintDevice())
font = QFont(font, q->paintDevice());
@@ -2177,7 +2155,7 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
QRectF r(pos, size);
- qreal xoff = fontMetrics.horizontalAdvance(QLatin1Char(' '));
+ qreal xoff = fontMetrics.horizontalAdvance(u' ');
if (dir == Qt::LeftToRight)
xoff = -xoff - size.width();
r.translate( xoff, (fontMetrics.height() / 2) - (size.height() / 2));
@@ -2238,17 +2216,15 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
}
case QTextListFormat::ListSquare:
if (!marker)
- painter->fillRect(r, brush);
+ painter->fillRect(r, painter->pen().brush());
break;
case QTextListFormat::ListCircle:
- if (!marker) {
- painter->setPen(QPen(brush, 0));
+ if (!marker)
painter->drawEllipse(r.translated(0.5, 0.5)); // pixel align for sharper rendering
- }
break;
case QTextListFormat::ListDisc:
if (!marker) {
- painter->setBrush(brush);
+ painter->setBrush(painter->pen().brush());
painter->setPen(Qt::NoPen);
painter->drawEllipse(r);
}
@@ -2361,9 +2337,10 @@ QTextLayoutStruct QTextDocumentLayoutPrivate::layoutCell(QTextTable *t, const QT
floatMinWidth = qMax(floatMinWidth, cd->minimumWidth);
}
- // constraint the maximumWidth by the minimum width of the fixed size floats, to
- // keep them visible
+ // constraint the maximum/minimumWidth by the minimum width of the fixed size floats,
+ // to keep them visible
layoutStruct.maximumWidth = qMax(layoutStruct.maximumWidth, floatMinWidth);
+ layoutStruct.minimumWidth = qMax(layoutStruct.minimumWidth, floatMinWidth);
// as floats in cells get added to the table's float list but must not affect
// floats in other cells we must clear the list here.
@@ -2398,7 +2375,7 @@ QRectF QTextDocumentLayoutPrivate::layoutTable(QTextTable *table, int layoutFrom
td->childFrameMap.clear();
{
const QList<QTextFrame *> children = table->childFrames();
- for (int i = 0; i < children.count(); ++i) {
+ for (int i = 0; i < children.size(); ++i) {
QTextFrame *frame = children.at(i);
QTextTableCell cell = table->cellAt(frame->firstPosition());
td->childFrameMap.insert(cell.row() + cell.column() * rows, frame);
@@ -2408,7 +2385,7 @@ QRectF QTextDocumentLayoutPrivate::layoutTable(QTextTable *table, int layoutFrom
QList<QTextLength> columnWidthConstraints = fmt.columnWidthConstraints();
if (columnWidthConstraints.size() != columns)
columnWidthConstraints.resize(columns);
- Q_ASSERT(columnWidthConstraints.count() == columns);
+ Q_ASSERT(columnWidthConstraints.size() == columns);
// borderCollapse will disable drawing the html4 style table cell borders
// and draw a 1px grid instead. This also sets a fixed cellspacing
@@ -2540,6 +2517,8 @@ recalc_minmax_widths:
for (int n = 0; n < cspan; ++n) {
const int col = i + n;
QFixed w = widthToDistribute / (cspan - n);
+ if (td->maxWidths[col] != QFIXED_MAX)
+ w = qMax(td->maxWidths[col], w);
td->maxWidths[col] = qMax(td->minWidths.at(col), w);
widthToDistribute -= td->maxWidths.at(col);
if (widthToDistribute <= 0)
@@ -2581,8 +2560,9 @@ recalc_minmax_widths:
const QFixed allottedPercentage = QFixed::fromReal(columnWidthConstraints.at(i).rawValue());
const QFixed percentWidth = totalPercentagedWidth * allottedPercentage / totalPercentage;
- if (percentWidth >= td->minWidths.at(i)) {
- td->widths[i] = qBound(td->minWidths.at(i), percentWidth, remainingWidth - remainingMinWidths);
+ QFixed maxWidth = remainingWidth - remainingMinWidths;
+ if (percentWidth >= td->minWidths.at(i) && maxWidth > td->minWidths.at(i)) {
+ td->widths[i] = qBound(td->minWidths.at(i), percentWidth, maxWidth);
} else {
td->widths[i] = td->minWidths.at(i);
}
@@ -2603,9 +2583,9 @@ recalc_minmax_widths:
QFixed lastRemainingWidth = remainingWidth;
while (remainingWidth > 0) {
- for (int k = 0; k < columnsWithProperMaxSize.count(); ++k) {
+ for (int k = 0; k < columnsWithProperMaxSize.size(); ++k) {
const int col = columnsWithProperMaxSize[k];
- const int colsLeft = columnsWithProperMaxSize.count() - k;
+ const int colsLeft = columnsWithProperMaxSize.size() - k;
const QFixed w = qMin(td->maxWidths.at(col) - td->widths.at(col), remainingWidth / colsLeft);
td->widths[col] += w;
remainingWidth -= w;
@@ -3140,7 +3120,7 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
QTextBlockFormat previousBlockFormat = previousIt.currentBlock().blockFormat();
QFixed maximumBlockWidth = 0;
- while (!it.atEnd()) {
+ while (!it.atEnd() && layoutStruct->absoluteY() < QFIXED_MAX) {
QTextFrame *c = it.currentFrame();
int docPos;
@@ -3377,7 +3357,7 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
// and not per cell and layoutCell already takes care of doing the same as we do here
if (!qobject_cast<QTextTable *>(layoutStruct->frame)) {
QList<QTextFrame *> children = layoutStruct->frame->childFrames();
- for (int i = 0; i < children.count(); ++i) {
+ for (int i = 0; i < children.size(); ++i) {
QTextFrameData *fd = data(children.at(i));
if (!fd->layoutDirty && children.at(i)->frameFormat().position() != QTextFrameFormat::InFlow)
layoutStruct->y = qMax(layoutStruct->y, fd->position.y + fd->size.height);
@@ -3390,7 +3370,7 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
if (!fd->floats.isEmpty())
contentHasAlignment = true;
- if (it.atEnd()) {
+ if (it.atEnd() || layoutStruct->absoluteY() >= QFIXED_MAX) {
//qDebug("layout done!");
currentLazyLayoutPosition = -1;
QCheckPoint cp;
@@ -3415,19 +3395,21 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
static inline void getLineHeightParams(const QTextBlockFormat &blockFormat, const QTextLine &line, qreal scaling,
QFixed *lineAdjustment, QFixed *lineBreakHeight, QFixed *lineHeight, QFixed *lineBottom)
{
+ const qreal height = line.height();
+ const int lineHeightType = blockFormat.lineHeightType();
qreal rawHeight = qCeil(line.ascent() + line.descent() + line.leading());
*lineHeight = QFixed::fromReal(blockFormat.lineHeight(rawHeight, scaling));
- *lineBottom = QFixed::fromReal(blockFormat.lineHeight(line.height(), scaling));
+ *lineBottom = QFixed::fromReal(blockFormat.lineHeight(height, scaling));
- if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight || blockFormat.lineHeightType() == QTextBlockFormat::MinimumHeight) {
+ if (lineHeightType == QTextBlockFormat::FixedHeight || lineHeightType == QTextBlockFormat::MinimumHeight) {
*lineBreakHeight = *lineBottom;
- if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight)
+ if (lineHeightType == QTextBlockFormat::FixedHeight)
*lineAdjustment = QFixed::fromReal(line.ascent() + qMax(line.leading(), qreal(0.0))) - ((*lineHeight * 4) / 5);
else
- *lineAdjustment = QFixed::fromReal(line.height()) - *lineHeight;
+ *lineAdjustment = QFixed::fromReal(height) - *lineHeight;
}
else {
- *lineBreakHeight = QFixed::fromReal(line.height());
+ *lineBreakHeight = QFixed::fromReal(height);
*lineAdjustment = 0;
}
}
@@ -3574,6 +3556,11 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
while (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineBreakHeight > layoutStruct->pageBottom &&
layoutStruct->contentHeight() >= lineBreakHeight) {
+ if (layoutStruct->pageHeight == QFIXED_MAX) {
+ layoutStruct->y = QFIXED_MAX - layoutStruct->frameY;
+ break;
+ }
+
layoutStruct->newPage();
floatMargins(layoutStruct->y, layoutStruct, &left, &right);
@@ -3657,7 +3644,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
}
}
-void QTextDocumentLayoutPrivate::floatMargins(const QFixed &y, const QTextLayoutStruct *layoutStruct,
+void QTextDocumentLayoutPrivate::floatMargins(QFixed y, const QTextLayoutStruct *layoutStruct,
QFixed *left, QFixed *right) const
{
// qDebug() << "floatMargins y=" << y;
@@ -3780,7 +3767,7 @@ void QTextDocumentLayout::documentChanged(int from, int oldLength, int length)
for (; blockIt.isValid() && blockIt != endIt; blockIt = blockIt.next())
blockIt.clearLayout();
- if (d->docPrivate->pageSize.isNull())
+ if (!d->docPrivate->canLayout())
return;
QRectF updateRect;
@@ -3876,7 +3863,7 @@ int QTextDocumentLayout::hitTest(const QPointF &point, Qt::HitTestAccuracy accur
// ensure we stay within document bounds
int lastPos = f->lastPosition();
if (l && !l->preeditAreaText().isEmpty())
- lastPos += l->preeditAreaText().length();
+ lastPos += l->preeditAreaText().size();
if (position > lastPos)
position = lastPos;
else if (position < 0)
@@ -4058,7 +4045,7 @@ QRectF QTextDocumentLayout::tableCellBoundingRect(QTextTable *table, const QText
QRectF QTextDocumentLayout::tableBoundingRect(QTextTable *table) const
{
Q_D(const QTextDocumentLayout);
- if (d->docPrivate->pageSize.isNull())
+ if (!d->docPrivate->canLayout())
return QRectF();
d->ensureLayoutFinished();
@@ -4085,7 +4072,7 @@ QRectF QTextDocumentLayout::tableBoundingRect(QTextTable *table) const
QRectF QTextDocumentLayout::frameBoundingRect(QTextFrame *frame) const
{
Q_D(const QTextDocumentLayout);
- if (d->docPrivate->pageSize.isNull())
+ if (!d->docPrivate->canLayout())
return QRectF();
d->ensureLayoutFinished();
return d->frameBoundingRectInternal(frame);
@@ -4114,7 +4101,7 @@ QRectF QTextDocumentLayoutPrivate::frameBoundingRectInternal(QTextFrame *frame)
QRectF QTextDocumentLayout::blockBoundingRect(const QTextBlock &block) const
{
Q_D(const QTextDocumentLayout);
- if (d->docPrivate->pageSize.isNull() || !block.isValid() || !block.isVisible())
+ if (!d->docPrivate->canLayout() || !block.isValid() || !block.isVisible())
return QRectF();
d->ensureLayoutedByPosition(block.position() + block.length());
QTextFrame *frame = d->document->frameAt(block.position());
diff --git a/src/gui/text/qtextdocumentlayout_p.h b/src/gui/text/qtextdocumentlayout_p.h
index 2054ebaa35..9f21d8ed39 100644
--- a/src/gui/text/qtextdocumentlayout_p.h
+++ b/src/gui/text/qtextdocumentlayout_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTDOCUMENTLAYOUT_P_H
#define QTEXTDOCUMENTLAYOUT_P_H
diff --git a/src/gui/text/qtextdocumentwriter.cpp b/src/gui/text/qtextdocumentwriter.cpp
index b81c9d958b..55f8414bd5 100644
--- a/src/gui/text/qtextdocumentwriter.cpp
+++ b/src/gui/text/qtextdocumentwriter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextdocumentwriter.h"
#include <QtCore/qfile.h>
@@ -77,7 +41,6 @@ public:
\inmodule QtGui
\ingroup richtext-processing
- \ingroup io
To write a document, construct a QTextDocumentWriter object with either a
file name or a device object, and specify the document format to be
diff --git a/src/gui/text/qtextdocumentwriter.h b/src/gui/text/qtextdocumentwriter.h
index cb34da7e8e..c52c681f7d 100644
--- a/src/gui/text/qtextdocumentwriter.h
+++ b/src/gui/text/qtextdocumentwriter.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTDOCUMENTWRITER_H
#define QTEXTDOCUMENTWRITER_H
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 74967aeac9..cb945b73ce 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/private/qtguiglobal_p.h>
#include "qdebug.h"
@@ -43,6 +7,7 @@
#include "qtextformat_p.h"
#include "qtextengine_p.h"
#include "qabstracttextdocumentlayout.h"
+#include "qabstracttextdocumentlayout_p.h"
#include "qtextlayout.h"
#include "qtextboundaryfinder.h"
#include <QtCore/private/qunicodetables_p.h>
@@ -71,17 +36,12 @@ public:
Itemizer(const QString &string, const QScriptAnalysis *analysis, QScriptItemArray &items)
: m_string(string),
m_analysis(analysis),
- m_items(items),
- m_splitter(nullptr)
+ m_items(items)
{
}
- ~Itemizer()
- {
- delete m_splitter;
- }
-
+ ~Itemizer() = default;
/// generate the script items
- /// The caps parameter is used to choose the algoritm of splitting text and assiging roles to the textitems
+ /// The caps parameter is used to choose the algorithm of splitting text and assigning roles to the textitems
void generate(int start, int length, QFont::Capitalization caps)
{
if (caps == QFont::SmallCaps)
@@ -120,7 +80,7 @@ private:
for (int i = start + 1; i < end; ++i) {
if (m_analysis[i].bidiLevel == m_analysis[start].bidiLevel
&& m_analysis[i].flags == m_analysis[start].flags
- && (m_analysis[i].script == m_analysis[start].script || m_string[i] == QLatin1Char('.'))
+ && (m_analysis[i].script == m_analysis[start].script || m_string[i] == u'.')
&& m_analysis[i].flags < QScriptAnalysis::SpaceTabOrObject
&& i - start < MaxItemLength)
continue;
@@ -136,8 +96,8 @@ private:
return;
if (!m_splitter)
- m_splitter = new QTextBoundaryFinder(QTextBoundaryFinder::Word,
- m_string.constData(), m_string.length(),
+ m_splitter = std::make_unique<QTextBoundaryFinder>(QTextBoundaryFinder::Word,
+ m_string.constData(), m_string.size(),
/*buffer*/nullptr, /*buffer size*/0);
m_splitter->setPosition(start);
@@ -206,7 +166,7 @@ private:
const QString &m_string;
const QScriptAnalysis * const m_analysis;
QScriptItemArray &m_items;
- QTextBoundaryFinder *m_splitter;
+ std::unique_ptr<QTextBoundaryFinder> m_splitter;
};
// -----------------------------------------------------------------------------------------------------
@@ -1247,9 +1207,9 @@ enum JustificationClass {
Adds an inter character justification opportunity after the number or letter
character and a space justification opportunity after the space character.
*/
-static inline void qt_getDefaultJustificationOpportunities(const ushort *string, int length, const QGlyphLayout &g, ushort *log_clusters, int spaceAs)
+static inline void qt_getDefaultJustificationOpportunities(const ushort *string, qsizetype length, const QGlyphLayout &g, ushort *log_clusters, int spaceAs)
{
- int str_pos = 0;
+ qsizetype str_pos = 0;
while (str_pos < length) {
int glyph_pos = log_clusters[str_pos];
@@ -1281,7 +1241,7 @@ static inline void qt_getDefaultJustificationOpportunities(const ushort *string,
}
}
-static inline void qt_getJustificationOpportunities(const ushort *string, int length, const QScriptItem &si, const QGlyphLayout &g, ushort *log_clusters)
+static inline void qt_getJustificationOpportunities(const ushort *string, qsizetype length, const QScriptItem &si, const QGlyphLayout &g, ushort *log_clusters)
{
Q_ASSERT(length > 0 && g.numGlyphs > 0);
@@ -1354,10 +1314,6 @@ void QTextEngine::shapeLine(const QScriptLine &line)
}
}
-#if QT_CONFIG(harfbuzz)
-extern bool qt_useHarfbuzzNG(); // defined in qfontengine.cpp
-#endif
-
static void applyVisibilityRules(ushort ucs, QGlyphLayout *glyphs, uint glyphPosition, QFontEngine *fontEngine)
{
// hide characters that should normally be invisible
@@ -1435,36 +1391,42 @@ void QTextEngine::shapeText(int item) const
}
if (Q_UNLIKELY(!ensureSpace(itemLength))) {
- Q_UNREACHABLE(); // ### report OOM error somehow
- return;
+ Q_UNREACHABLE_RETURN(); // ### report OOM error somehow
}
QFontEngine *fontEngine = this->fontEngine(si, &si.ascent, &si.descent, &si.leading);
bool kerningEnabled;
bool letterSpacingIsAbsolute;
- bool shapingEnabled;
+ bool shapingEnabled = false;
+ QHash<QFont::Tag, quint32> features;
QFixed letterSpacing, wordSpacing;
#ifndef QT_NO_RAWFONT
if (useRawFont) {
QTextCharFormat f = format(&si);
QFont font = f.font();
kerningEnabled = font.kerning();
+# if QT_CONFIG(harfbuzz)
shapingEnabled = QFontEngine::scriptRequiresOpenType(QChar::Script(si.analysis.script))
|| (font.styleStrategy() & QFont::PreferNoShaping) == 0;
+# endif
wordSpacing = QFixed::fromReal(font.wordSpacing());
letterSpacing = QFixed::fromReal(font.letterSpacing());
letterSpacingIsAbsolute = true;
+ features = font.d->features;
} else
#endif
{
QFont font = this->font(si);
kerningEnabled = font.d->kerning;
+#if QT_CONFIG(harfbuzz)
shapingEnabled = QFontEngine::scriptRequiresOpenType(QChar::Script(si.analysis.script))
|| (font.d->request.styleStrategy & QFont::PreferNoShaping) == 0;
+#endif
letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute;
letterSpacing = font.d->letterSpacing;
wordSpacing = font.d->wordSpacing;
+ features = font.d->features;
if (letterSpacingIsAbsolute && letterSpacing.value())
letterSpacing *= font.d->dpi / qt_defaultDpiY();
@@ -1472,8 +1434,7 @@ void QTextEngine::shapeText(int item) const
// split up the item into parts that come from different font engines
// k * 3 entries, array[k] == index in string, array[k + 1] == index in glyphs, array[k + 2] == engine index
- QList<uint> itemBoundaries;
- itemBoundaries.reserve(24);
+ QVarLengthArray<uint, 24> itemBoundaries;
QGlyphLayout initialGlyphs = availableGlyphs(&si);
int nGlyphs = initialGlyphs.numGlyphs;
@@ -1493,9 +1454,9 @@ void QTextEngine::shapeText(int item) const
for (int i = 0, glyph_pos = 0; i < itemLength; ++i, ++glyph_pos) {
const uint engineIdx = initialGlyphs.glyphs[glyph_pos] >> 24;
if (lastEngine != engineIdx) {
- itemBoundaries.append(i);
- itemBoundaries.append(glyph_pos);
- itemBoundaries.append(engineIdx);
+ itemBoundaries.push_back(i);
+ itemBoundaries.push_back(glyph_pos);
+ itemBoundaries.push_back(engineIdx);
if (engineIdx != 0) {
QFontEngine *actualFontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
@@ -1511,14 +1472,21 @@ void QTextEngine::shapeText(int item) const
++i;
}
} else {
- itemBoundaries.append(0);
- itemBoundaries.append(0);
- itemBoundaries.append(0);
+ itemBoundaries.push_back(0);
+ itemBoundaries.push_back(0);
+ itemBoundaries.push_back(0);
}
#if QT_CONFIG(harfbuzz)
- if (Q_LIKELY(shapingEnabled && qt_useHarfbuzzNG())) {
- si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled, letterSpacing != 0);
+ if (Q_LIKELY(shapingEnabled)) {
+ si.num_glyphs = shapeTextWithHarfbuzzNG(si,
+ string,
+ itemLength,
+ fontEngine,
+ itemBoundaries,
+ kerningEnabled,
+ letterSpacing != 0,
+ features);
} else
#endif
{
@@ -1564,6 +1532,12 @@ void QTextEngine::shapeText(int item) const
// Overwrite with 0 token to indicate failure
QGlyphLayout g = availableGlyphs(&si);
g.glyphs[0] = 0;
+ g.attributes[0].clusterStart = true;
+
+ ushort *log_clusters = logClusters(&si);
+ for (int i = 0; i < itemLength; ++i)
+ log_clusters[i] = 0;
+
return;
}
@@ -1572,8 +1546,7 @@ void QTextEngine::shapeText(int item) const
QGlyphLayout glyphs = shapedGlyphs(&si);
#if QT_CONFIG(harfbuzz)
- if (Q_LIKELY(qt_useHarfbuzzNG()))
- qt_getJustificationOpportunities(string, itemLength, si, glyphs, logClusters(&si));
+ qt_getJustificationOpportunities(string, itemLength, si, glyphs, logClusters(&si));
#endif
if (letterSpacing != 0) {
@@ -1623,9 +1596,10 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
const ushort *string,
int itemLength,
QFontEngine *fontEngine,
- const QList<uint> &itemBoundaries,
+ QSpan<uint> itemBoundaries,
bool kerningEnabled,
- bool hasLetterSpacing) const
+ bool hasLetterSpacing,
+ const QHash<QFont::Tag, quint32> &fontFeatures) const
{
uint glyphs_shaped = 0;
@@ -1644,7 +1618,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
// ### TODO get_default_for_script?
props.language = hb_language_get_default(); // use default language from locale
- for (int k = 0; k < itemBoundaries.size(); k += 3) {
+ for (qsizetype k = 0; k < itemBoundaries.size(); k += 3) {
const uint item_pos = itemBoundaries[k];
const uint item_length = (k + 4 < itemBoundaries.size() ? itemBoundaries[k + 3] : itemLength) - item_pos;
const uint engineIdx = itemBoundaries[k + 2];
@@ -1679,14 +1653,24 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
|| script == QChar::Script_Khmer || script == QChar::Script_Nko);
bool dontLigate = hasLetterSpacing && !scriptRequiresOpenType;
- const hb_feature_t features[5] = {
- { HB_TAG('k','e','r','n'), !!kerningEnabled, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END },
- { HB_TAG('l','i','g','a'), false, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END },
- { HB_TAG('c','l','i','g'), false, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END },
- { HB_TAG('d','l','i','g'), false, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END },
- { HB_TAG('h','l','i','g'), false, HB_FEATURE_GLOBAL_START, HB_FEATURE_GLOBAL_END }
- };
- const int num_features = dontLigate ? 5 : 1;
+
+ QHash<QFont::Tag, quint32> features;
+ features.insert(QFont::Tag("kern"), !!kerningEnabled);
+ if (dontLigate) {
+ features.insert(QFont::Tag("liga"), false);
+ features.insert(QFont::Tag("clig"), false);
+ features.insert(QFont::Tag("dlig"), false);
+ features.insert(QFont::Tag("hlig"), false);
+ }
+ features.insert(fontFeatures);
+
+ QVarLengthArray<hb_feature_t, 16> featureArray;
+ for (auto it = features.constBegin(); it != features.constEnd(); ++it) {
+ featureArray.append({ it.key().value(),
+ it.value(),
+ HB_FEATURE_GLOBAL_START,
+ HB_FEATURE_GLOBAL_END });
+ }
// whitelist cross-platforms shapers only
static const char *shaper_list[] = {
@@ -1696,7 +1680,11 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
nullptr
};
- bool shapedOk = hb_shape_full(hb_font, buffer, features, num_features, shaper_list);
+ bool shapedOk = hb_shape_full(hb_font,
+ buffer,
+ featureArray.constData(),
+ features.size(),
+ shaper_list);
if (Q_UNLIKELY(!shapedOk)) {
hb_buffer_destroy(buffer);
return 0;
@@ -1706,9 +1694,14 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
hb_buffer_reverse(buffer);
}
- const uint num_glyphs = hb_buffer_get_length(buffer);
+ uint num_glyphs = hb_buffer_get_length(buffer);
+ const bool has_glyphs = num_glyphs > 0;
+ // If Harfbuzz returns zero glyphs, we have to manually add a missing glyph
+ if (Q_UNLIKELY(!has_glyphs))
+ num_glyphs = 1;
+
// ensure we have enough space for shaped glyphs and metrics
- if (Q_UNLIKELY(num_glyphs == 0 || !ensureSpace(glyphs_shaped + num_glyphs))) {
+ if (Q_UNLIKELY(!ensureSpace(glyphs_shaped + num_glyphs))) {
hb_buffer_destroy(buffer);
return 0;
}
@@ -1716,35 +1709,44 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
// fetch the shaped glyphs and metrics
QGlyphLayout g = availableGlyphs(&si).mid(glyphs_shaped, num_glyphs);
ushort *log_clusters = logClusters(&si) + item_pos;
-
- hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, nullptr);
- hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, nullptr);
- uint str_pos = 0;
- uint last_cluster = ~0u;
- uint last_glyph_pos = glyphs_shaped;
- for (uint i = 0; i < num_glyphs; ++i, ++infos, ++positions) {
- g.glyphs[i] = infos->codepoint;
-
- g.advances[i] = QFixed::fromFixed(positions->x_advance);
- g.offsets[i].x = QFixed::fromFixed(positions->x_offset);
- g.offsets[i].y = QFixed::fromFixed(positions->y_offset);
-
- uint cluster = infos->cluster;
- if (Q_LIKELY(last_cluster != cluster)) {
- g.attributes[i].clusterStart = true;
-
- // fix up clusters so that the cluster indices will be monotonic
- // and thus we never return out-of-order indices
- while (last_cluster++ < cluster && str_pos < item_length)
- log_clusters[str_pos++] = last_glyph_pos;
- last_glyph_pos = i + glyphs_shaped;
- last_cluster = cluster;
-
- applyVisibilityRules(string[item_pos + str_pos], &g, i, actualFontEngine);
+ if (Q_LIKELY(has_glyphs)) {
+ hb_glyph_info_t *infos = hb_buffer_get_glyph_infos(buffer, nullptr);
+ hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer, nullptr);
+ uint str_pos = 0;
+ uint last_cluster = ~0u;
+ uint last_glyph_pos = glyphs_shaped;
+ for (uint i = 0; i < num_glyphs; ++i, ++infos, ++positions) {
+ g.glyphs[i] = infos->codepoint;
+
+ g.advances[i] = QFixed::fromFixed(positions->x_advance);
+ g.offsets[i].x = QFixed::fromFixed(positions->x_offset);
+ g.offsets[i].y = QFixed::fromFixed(positions->y_offset);
+
+ uint cluster = infos->cluster;
+ if (Q_LIKELY(last_cluster != cluster)) {
+ g.attributes[i].clusterStart = true;
+
+ // fix up clusters so that the cluster indices will be monotonic
+ // and thus we never return out-of-order indices
+ while (last_cluster++ < cluster && str_pos < item_length)
+ log_clusters[str_pos++] = last_glyph_pos;
+ last_glyph_pos = i + glyphs_shaped;
+ last_cluster = cluster;
+
+ applyVisibilityRules(string[item_pos + str_pos], &g, i, actualFontEngine);
+ }
}
+ while (str_pos < item_length)
+ log_clusters[str_pos++] = last_glyph_pos;
+ } else { // Harfbuzz did not return a glyph for the character, so we add a placeholder
+ g.glyphs[0] = 0;
+ g.advances[0] = QFixed{};
+ g.offsets[0].x = QFixed{};
+ g.offsets[0].y = QFixed{};
+ g.attributes[0].clusterStart = true;
+ g.attributes[0].dontPrint = true;
+ log_clusters[0] = glyphs_shaped;
}
- while (str_pos < item_length)
- log_clusters[str_pos++] = last_glyph_pos;
if (Q_UNLIKELY(engineIdx != 0)) {
for (quint32 i = 0; i < num_glyphs; ++i)
@@ -1752,8 +1754,10 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
}
if (!actualFontEngine->supportsHorizontalSubPixelPositions()) {
- for (uint i = 0; i < num_glyphs; ++i)
+ for (uint i = 0; i < num_glyphs; ++i) {
g.advances[i] = g.advances[i].round();
+ g.offsets[i].x = g.offsets[i].x.round();
+ }
}
glyphs_shaped += num_glyphs;
@@ -1812,7 +1816,7 @@ const QCharAttributes *QTextEngine::attributes() const
return (QCharAttributes *) layoutData->memory;
itemize();
- if (! ensureSpace(layoutData->string.length()))
+ if (! ensureSpace(layoutData->string.size()))
return nullptr;
QVarLengthArray<QUnicodeTools::ScriptItem> scriptItems(layoutData->items.size());
@@ -1919,7 +1923,7 @@ void QTextEngine::itemize() const
if (layoutData->items.size())
return;
- int length = layoutData->string.length();
+ int length = layoutData->string.size();
if (!length)
return;
@@ -1936,9 +1940,9 @@ void QTextEngine::itemize() const
{
QUnicodeTools::ScriptItemArray scriptItems;
QUnicodeTools::initScripts(layoutData->string, &scriptItems);
- for (int i = 0; i < scriptItems.length(); ++i) {
+ for (int i = 0; i < scriptItems.size(); ++i) {
const auto &item = scriptItems.at(i);
- int end = i < scriptItems.length() - 1 ? scriptItems.at(i + 1).position : length;
+ int end = i < scriptItems.size() - 1 ? scriptItems.at(i + 1).position : length;
for (int j = item.position; j < end; ++j)
analysis[j].script = item.script;
}
@@ -1949,7 +1953,17 @@ void QTextEngine::itemize() const
while (uc < e) {
switch (*uc) {
case QChar::ObjectReplacementCharacter:
- analysis->flags = QScriptAnalysis::Object;
+ {
+ const QTextDocumentPrivate *doc_p = QTextDocumentPrivate::get(block);
+ if (doc_p != nullptr
+ && doc_p->layout() != nullptr
+ && QAbstractTextDocumentLayoutPrivate::get(doc_p->layout()) != nullptr
+ && QAbstractTextDocumentLayoutPrivate::get(doc_p->layout())->hasHandlers()) {
+ analysis->flags = QScriptAnalysis::Object;
+ } else {
+ analysis->flags = QScriptAnalysis::None;
+ }
+ }
break;
case QChar::LineSeparator:
analysis->flags = QScriptAnalysis::LineOrParagraphSeparator;
@@ -2001,7 +2015,7 @@ void QTextEngine::itemize() const
const QTextFragmentData * const frag = it.value();
if (it == end || format != frag->format) {
if (s && position >= preeditPosition) {
- position += s->preeditText.length();
+ position += s->preeditText.size();
preeditPosition = INT_MAX;
}
Q_ASSERT(position <= length);
@@ -2010,7 +2024,7 @@ void QTextEngine::itemize() const
? formatCollection()->charFormat(format).fontCapitalization()
: formatCollection()->defaultFont().capitalization();
if (s) {
- for (const auto &range : qAsConst(s->formats)) {
+ for (const auto &range : std::as_const(s->formats)) {
if (range.start + range.length <= prevPosition || range.start >= position)
continue;
if (range.format.hasProperty(QTextFormat::FontCapitalization)) {
@@ -2098,35 +2112,30 @@ int QTextEngine::findItem(int strPos, int firstItem) const
return right;
}
-QFixed QTextEngine::width(int from, int len) const
+namespace {
+template<typename InnerFunc>
+void textIterator(const QTextEngine *textEngine, int from, int len, QFixed &width, InnerFunc &&innerFunc)
{
- itemize();
-
- QFixed w = 0;
-
-// qDebug("QTextEngine::width(from = %d, len = %d), numItems=%d, strleng=%d", from, len, items.size(), string.length());
- for (int i = 0; i < layoutData->items.size(); i++) {
- const QScriptItem *si = layoutData->items.constData() + i;
+ for (int i = 0; i < textEngine->layoutData->items.size(); i++) {
+ const QScriptItem *si = textEngine->layoutData->items.constData() + i;
int pos = si->position;
- int ilen = length(i);
+ int ilen = textEngine->length(i);
// qDebug("item %d: from %d len %d", i, pos, ilen);
if (pos >= from + len)
break;
if (pos + ilen > from) {
if (!si->num_glyphs)
- shape(i);
+ textEngine->shape(i);
if (si->analysis.flags == QScriptAnalysis::Object) {
- w += si->width;
+ width += si->width;
continue;
} else if (si->analysis.flags == QScriptAnalysis::Tab) {
- w += calculateTabWidth(i, w);
+ width += textEngine->calculateTabWidth(i, width);
continue;
}
-
- QGlyphLayout glyphs = shapedGlyphs(si);
- unsigned short *logClusters = this->logClusters(si);
+ unsigned short *logClusters = textEngine->logClusters(si);
// fprintf(stderr, " logclusters:");
// for (int k = 0; k < ilen; k++)
@@ -2151,11 +2160,24 @@ QFixed QTextEngine::width(int from, int len) const
glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd];
// qDebug("char: start=%d end=%d / glyph: start = %d, end = %d", charFrom, charEnd, glyphStart, glyphEnd);
- for (int i = glyphStart; i < glyphEnd; i++)
- w += glyphs.advances[i] * !glyphs.attributes[i].dontPrint;
+ innerFunc(glyphStart, glyphEnd, si);
}
}
}
+}
+} // namespace
+
+QFixed QTextEngine::width(int from, int len) const
+{
+ itemize();
+
+ QFixed w = 0;
+// qDebug("QTextEngine::width(from = %d, len = %d), numItems=%d, strleng=%d", from, len, items.size(), string.length());
+ textIterator(this, from, len, w, [this, &w](int glyphStart, int glyphEnd, const QScriptItem *si) {
+ QGlyphLayout glyphs = this->shapedGlyphs(si);
+ for (int j = glyphStart; j < glyphEnd; j++)
+ w += glyphs.advances[j] * !glyphs.attributes[j].dontPrint;
+ });
// qDebug(" --> w= %d ", w);
return w;
}
@@ -2166,58 +2188,20 @@ glyph_metrics_t QTextEngine::boundingBox(int from, int len) const
glyph_metrics_t gm;
- for (int i = 0; i < layoutData->items.size(); i++) {
- const QScriptItem *si = layoutData->items.constData() + i;
-
- int pos = si->position;
- int ilen = length(i);
- if (pos > from + len)
- break;
- if (pos + ilen > from) {
- if (!si->num_glyphs)
- shape(i);
-
- if (si->analysis.flags == QScriptAnalysis::Object) {
- gm.width += si->width;
- continue;
- } else if (si->analysis.flags == QScriptAnalysis::Tab) {
- gm.width += calculateTabWidth(i, gm.width);
- continue;
- }
-
- unsigned short *logClusters = this->logClusters(si);
- QGlyphLayout glyphs = shapedGlyphs(si);
-
- // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0.
- int charFrom = from - pos;
- if (charFrom < 0)
- charFrom = 0;
- int glyphStart = logClusters[charFrom];
- if (charFrom > 0 && logClusters[charFrom-1] == glyphStart)
- while (charFrom < ilen && logClusters[charFrom] == glyphStart)
- charFrom++;
- if (charFrom < ilen) {
- QFontEngine *fe = fontEngine(*si);
- glyphStart = logClusters[charFrom];
- int charEnd = from + len - 1 - pos;
- if (charEnd >= ilen)
- charEnd = ilen-1;
- int glyphEnd = logClusters[charEnd];
- while (charEnd < ilen && logClusters[charEnd] == glyphEnd)
- charEnd++;
- glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd];
- if (glyphStart <= glyphEnd ) {
- glyph_metrics_t m = fe->boundingBox(glyphs.mid(glyphStart, glyphEnd - glyphStart));
- gm.x = qMin(gm.x, m.x + gm.xoff);
- gm.y = qMin(gm.y, m.y + gm.yoff);
- gm.width = qMax(gm.width, m.width+gm.xoff);
- gm.height = qMax(gm.height, m.height+gm.yoff);
- gm.xoff += m.xoff;
- gm.yoff += m.yoff;
- }
- }
+ textIterator(this, from, len, gm.width, [this, &gm](int glyphStart, int glyphEnd, const QScriptItem *si) {
+ if (glyphStart <= glyphEnd) {
+ QGlyphLayout glyphs = this->shapedGlyphs(si);
+ QFontEngine *fe = this->fontEngine(*si);
+ glyph_metrics_t m = fe->boundingBox(glyphs.mid(glyphStart, glyphEnd - glyphStart));
+ gm.x = qMin(gm.x, m.x + gm.xoff);
+ gm.y = qMin(gm.y, m.y + gm.yoff);
+ gm.width = qMax(gm.width, m.width + gm.xoff);
+ gm.height = qMax(gm.height, m.height + gm.yoff);
+ gm.xoff += m.xoff;
+ gm.yoff += m.yoff;
}
- }
+ });
+
return gm;
}
@@ -2227,48 +2211,19 @@ glyph_metrics_t QTextEngine::tightBoundingBox(int from, int len) const
glyph_metrics_t gm;
- for (int i = 0; i < layoutData->items.size(); i++) {
- const QScriptItem *si = layoutData->items.constData() + i;
- int pos = si->position;
- int ilen = length(i);
- if (pos > from + len)
- break;
- if (pos + len > from) {
- if (!si->num_glyphs)
- shape(i);
- unsigned short *logClusters = this->logClusters(si);
- QGlyphLayout glyphs = shapedGlyphs(si);
-
- // do the simple thing for now and give the first glyph in a cluster the full width, all other ones 0.
- int charFrom = from - pos;
- if (charFrom < 0)
- charFrom = 0;
- int glyphStart = logClusters[charFrom];
- if (charFrom > 0 && logClusters[charFrom-1] == glyphStart)
- while (charFrom < ilen && logClusters[charFrom] == glyphStart)
- charFrom++;
- if (charFrom < ilen) {
- glyphStart = logClusters[charFrom];
- int charEnd = from + len - 1 - pos;
- if (charEnd >= ilen)
- charEnd = ilen-1;
- int glyphEnd = logClusters[charEnd];
- while (charEnd < ilen && logClusters[charEnd] == glyphEnd)
- charEnd++;
- glyphEnd = (charEnd == ilen) ? si->num_glyphs : logClusters[charEnd];
- if (glyphStart <= glyphEnd ) {
- QFontEngine *fe = fontEngine(*si);
- glyph_metrics_t m = fe->tightBoundingBox(glyphs.mid(glyphStart, glyphEnd - glyphStart));
- gm.x = qMin(gm.x, m.x + gm.xoff);
- gm.y = qMin(gm.y, m.y + gm.yoff);
- gm.width = qMax(gm.width, m.width+gm.xoff);
- gm.height = qMax(gm.height, m.height+gm.yoff);
- gm.xoff += m.xoff;
- gm.yoff += m.yoff;
- }
- }
- }
- }
+ textIterator(this, from, len, gm.width, [this, &gm](int glyphStart, int glyphEnd, const QScriptItem *si) {
+ if (glyphStart <= glyphEnd) {
+ QGlyphLayout glyphs = this->shapedGlyphs(si);
+ QFontEngine *fe = fontEngine(*si);
+ glyph_metrics_t m = fe->tightBoundingBox(glyphs.mid(glyphStart, glyphEnd - glyphStart));
+ gm.x = qMin(gm.x, m.x + gm.xoff);
+ gm.y = qMin(gm.y, m.y + gm.yoff);
+ gm.width = qMax(gm.width, m.width + gm.xoff);
+ gm.height = qMax(gm.height, m.height + gm.yoff);
+ gm.xoff += m.xoff;
+ gm.yoff += m.yoff;
+ }
+ });
return gm;
}
@@ -2335,6 +2290,12 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
if (feCache.prevScaledFontEngine) {
scaledEngine = feCache.prevScaledFontEngine;
} else {
+ // GCC 12 gets confused about QFontEngine::ref, for some non-obvious reason
+ // warning: ‘unsigned int __atomic_or_fetch_4(volatile void*, unsigned int, int)’ writing 4 bytes
+ // into a region of size 0 overflows the destination [-Wstringop-overflow=]
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_GCC("-Wstringop-overflow")
+
QFontEngine *scEngine = rawFont.d->fontEngine->cloneWithSize(smallCapsFraction * rawFont.pixelSize());
scEngine->ref.ref();
scaledEngine = QFontEngineMulti::createMultiFontEngine(scEngine, script);
@@ -2344,6 +2305,7 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
if (!scEngine->ref.deref())
delete scEngine;
+ QT_WARNING_POP
}
}
} else
@@ -2393,9 +2355,9 @@ QFontEngine *QTextEngine::fontEngine(const QScriptItem &si, QFixed *ascent, QFix
feCache.prevLength = length(&si);
}
} else {
- if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1)
+ if (feCache.prevFontEngine && feCache.prevScript == script && feCache.prevPosition == -1) {
engine = feCache.prevFontEngine;
- else {
+ } else {
engine = font.d->engineForScript(script);
Q_ASSERT(engine);
engine->ref.ref();
@@ -2482,7 +2444,7 @@ void QTextEngine::justify(const QScriptLine &line)
if (!forceJustification) {
int end = line.from + (int)line.length + line.trailingSpaces;
- if (end == layoutData->string.length())
+ if (end == layoutData->string.size())
return; // no justification at end of paragraph
if (end && layoutData->items.at(findItem(end - 1)).analysis.flags == QScriptAnalysis::LineOrParagraphSeparator)
return; // no justification at the end of an explicitly separated line
@@ -2688,18 +2650,20 @@ QTextEngine::LayoutData::LayoutData()
haveCharAttributes = false;
logClustersPtr = nullptr;
available_glyphs = 0;
+ currentMaxWidth = 0;
}
-QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int _allocated)
+QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, qsizetype _allocated)
: string(str)
{
allocated = _allocated;
- int space_charAttributes = int(sizeof(QCharAttributes) * string.length() / sizeof(void*) + 1);
- int space_logClusters = int(sizeof(unsigned short) * string.length() / sizeof(void*) + 1);
- available_glyphs = ((int)allocated - space_charAttributes - space_logClusters)*(int)sizeof(void*)/(int)QGlyphLayout::SpaceNeeded;
+ constexpr qsizetype voidSize = sizeof(void*);
+ qsizetype space_charAttributes = sizeof(QCharAttributes) * string.size() / voidSize + 1;
+ qsizetype space_logClusters = sizeof(unsigned short) * string.size() / voidSize + 1;
+ available_glyphs = (allocated - space_charAttributes - space_logClusters) * voidSize / QGlyphLayout::SpaceNeeded;
- if (available_glyphs < str.length()) {
+ if (available_glyphs < str.size()) {
// need to allocate on the heap
allocated = 0;
@@ -2712,7 +2676,7 @@ QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int
logClustersPtr = (unsigned short *)(memory + space_charAttributes);
void *m = memory + space_charAttributes + space_logClusters;
- glyphLayout = QGlyphLayout(reinterpret_cast<char *>(m), str.length());
+ glyphLayout = QGlyphLayout(reinterpret_cast<char *>(m), str.size());
glyphLayout.clear();
memset(memory, 0, space_charAttributes*sizeof(void *));
}
@@ -2720,6 +2684,7 @@ QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int
hasBidi = false;
layoutState = LayoutEmpty;
haveCharAttributes = false;
+ currentMaxWidth = 0;
}
QTextEngine::LayoutData::~LayoutData()
@@ -2737,15 +2702,16 @@ bool QTextEngine::LayoutData::reallocate(int totalGlyphs)
return true;
}
- int space_charAttributes = int(sizeof(QCharAttributes) * string.length() / sizeof(void*) + 1);
- int space_logClusters = int(sizeof(unsigned short) * string.length() / sizeof(void*) + 1);
- int space_glyphs = (totalGlyphs * QGlyphLayout::SpaceNeeded) / sizeof(void *) + 2;
+ const qsizetype space_charAttributes = (sizeof(QCharAttributes) * string.size() / sizeof(void*) + 1);
+ const qsizetype space_logClusters = (sizeof(unsigned short) * string.size() / sizeof(void*) + 1);
+ const qsizetype space_glyphs = qsizetype(totalGlyphs) * QGlyphLayout::SpaceNeeded / sizeof(void *) + 2;
- int newAllocated = space_charAttributes + space_glyphs + space_logClusters;
- // These values can be negative if the length of string/glyphs causes overflow,
+ const qsizetype newAllocated = space_charAttributes + space_glyphs + space_logClusters;
+ // Check if the length of string/glyphs causes int overflow,
// we can't layout such a long string all at once, so return false here to
// indicate there is a failure
- if (space_charAttributes < 0 || space_logClusters < 0 || space_glyphs < 0 || newAllocated < allocated) {
+ if (size_t(space_charAttributes) > INT_MAX || size_t(space_logClusters) > INT_MAX || totalGlyphs < 0
+ || size_t(space_glyphs) > INT_MAX || size_t(newAllocated) > INT_MAX || newAllocated < allocated) {
layoutState = LayoutFailed;
return false;
}
@@ -2765,7 +2731,7 @@ bool QTextEngine::LayoutData::reallocate(int totalGlyphs)
logClustersPtr = (unsigned short *) m;
m += space_logClusters;
- const int space_preGlyphLayout = space_charAttributes + space_logClusters;
+ const qsizetype space_preGlyphLayout = space_charAttributes + space_logClusters;
if (allocated < space_preGlyphLayout)
memset(memory + allocated, 0, (space_preGlyphLayout - allocated)*sizeof(void *));
@@ -2805,6 +2771,7 @@ void QTextEngine::freeMemory()
layoutData->hasBidi = false;
layoutData->layoutState = LayoutEmpty;
layoutData->haveCharAttributes = false;
+ layoutData->currentMaxWidth = 0;
layoutData->items.clear();
}
if (specialData)
@@ -2828,10 +2795,10 @@ int QTextEngine::formatIndex(const QScriptItem *si) const
return -1;
int pos = si->position;
if (specialData && si->position >= specialData->preeditPosition) {
- if (si->position < specialData->preeditPosition + specialData->preeditText.length())
+ if (si->position < specialData->preeditPosition + specialData->preeditText.size())
pos = qMax(qMin(block.length(), specialData->preeditPosition) - 1, 0);
else
- pos -= specialData->preeditText.length();
+ pos -= specialData->preeditText.size();
}
QTextDocumentPrivate::FragmentIterator it = p->find(block.position() + pos);
return it.value()->format;
@@ -2966,9 +2933,9 @@ void QTextEngine::indexFormats()
*/
static inline bool nextCharJoins(const QString &string, int pos)
{
- while (pos < string.length() && string.at(pos).category() == QChar::Mark_NonSpacing)
+ while (pos < string.size() && string.at(pos).category() == QChar::Mark_NonSpacing)
++pos;
- if (pos == string.length())
+ if (pos == string.size())
return false;
QChar::JoiningType joining = string.at(pos).joiningType();
return joining != QChar::Joining_None && joining != QChar::Joining_Transparent;
@@ -2984,11 +2951,11 @@ static inline bool prevCharJoins(const QString &string, int pos)
return joining == QChar::Joining_Dual || joining == QChar::Joining_Causing;
}
-static inline bool isRetainableControlCode(QChar c)
+static constexpr bool isRetainableControlCode(char16_t c) noexcept
{
- return (c.unicode() >= 0x202a && c.unicode() <= 0x202e) // LRE, RLE, PDF, LRO, RLO
- || (c.unicode() >= 0x200e && c.unicode() <= 0x200f) // LRM, RLM
- || (c.unicode() >= 0x2066 && c.unicode() <= 0x2069); // LRI, RLI, FSI, PDI
+ return (c >= 0x202a && c <= 0x202e) // LRE, RLE, PDF, LRO, RLO
+ || (c >= 0x200e && c <= 0x200f) // LRM, RLM
+ || (c >= 0x2066 && c <= 0x2069); // LRI, RLI, FSI, PDI
}
static QString stringMidRetainingBidiCC(const QString &string,
@@ -3001,14 +2968,14 @@ static QString stringMidRetainingBidiCC(const QString &string,
{
QString prefix;
for (int i=subStringFrom; i<midStart; ++i) {
- QChar c = string.at(i);
+ char16_t c = string.at(i).unicode();
if (isRetainableControlCode(c))
prefix += c;
}
QString suffix;
for (int i=midStart + midLength; i<subStringTo; ++i) {
- QChar c = string.at(i);
+ char16_t c = string.at(i).unicode();
if (isRetainableControlCode(c))
suffix += c;
}
@@ -3016,7 +2983,7 @@ static QString stringMidRetainingBidiCC(const QString &string,
return prefix + ellidePrefix + QStringView{string}.mid(midStart, midLength) + ellideSuffix + suffix;
}
-QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int flags, int from, int count) const
+QString QTextEngine::elidedText(Qt::TextElideMode mode, QFixed width, int flags, int from, int count) const
{
// qDebug() << "elidedText; available width" << width.toReal() << "text width:" << this->width(0, layoutData->string.length()).toReal();
@@ -3035,14 +3002,14 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
const int end = si.position + length(&si);
for (int i = si.position; i < end - 1; ++i) {
- if (layoutData->string.at(i) == QLatin1Char('&')
+ if (layoutData->string.at(i) == u'&'
&& !attributes[i + 1].whiteSpace && attributes[i + 1].graphemeBoundary) {
const int gp = logClusters[i - si.position];
glyphs.attributes[gp].dontPrint = true;
// emulate grapheme cluster
attributes[i] = attributes[i + 1];
memset(attributes + i + 1, 0, sizeof(QCharAttributes));
- if (layoutData->string.at(i + 1) == QLatin1Char('&'))
+ if (layoutData->string.at(i + 1) == u'&')
++i;
}
}
@@ -3051,12 +3018,12 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
validate();
- const int to = count >= 0 && count <= layoutData->string.length() - from
+ const int to = count >= 0 && count <= layoutData->string.size() - from
? from + count
- : layoutData->string.length();
+ : layoutData->string.size();
if (mode == Qt::ElideNone
- || this->width(from, layoutData->string.length()) <= width
+ || this->width(from, layoutData->string.size()) <= width
|| to - from <= 1)
return layoutData->string.mid(from, from - to);
@@ -3065,7 +3032,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
{
QFontEngine *engine = fnt.d->engineForScript(QChar::Script_Common);
- QChar ellipsisChar = u'\x2026';
+ constexpr char16_t ellipsisChar = u'\x2026';
// We only want to use the ellipsis character if it is from the main
// font (not one of the fallbacks), since using a fallback font
@@ -3077,7 +3044,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
engine = multiEngine->engine(0);
}
- glyph_t glyph = engine->glyphIndex(ellipsisChar.unicode());
+ glyph_t glyph = engine->glyphIndex(ellipsisChar);
QGlyphLayout glyphs;
glyphs.numGlyphs = 1;
@@ -3095,6 +3062,11 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
ellipsisWidth *= 3;
ellipsisText = QStringLiteral("...");
+ } else {
+ engine = fnt.d->engineForScript(QChar::Script_Common);
+ glyph = engine->glyphIndex(ellipsisChar);
+ engine->recalcAdvances(&glyphs, { });
+ ellipsisText = ellipsisChar;
}
}
}
@@ -3118,7 +3090,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
pos = nextBreak;
++nextBreak;
- while (nextBreak < layoutData->string.length() && !attributes[nextBreak].graphemeBoundary)
+ while (nextBreak < layoutData->string.size() && !attributes[nextBreak].graphemeBoundary)
++nextBreak;
currentWidth += this->width(pos, nextBreak - pos);
@@ -3170,7 +3142,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
rightPos = nextRightBreak;
++nextLeftBreak;
- while (nextLeftBreak < layoutData->string.length() && !attributes[nextLeftBreak].graphemeBoundary)
+ while (nextLeftBreak < layoutData->string.size() && !attributes[nextLeftBreak].graphemeBoundary)
++nextLeftBreak;
--nextRightBreak;
@@ -3209,7 +3181,7 @@ void QTextEngine::setBoundary(int strPos) const
QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
{
- const QScriptItem &si = layoutData->items[item];
+ const QScriptItem &si = layoutData->items.at(item);
QFixed dpiScale = 1;
if (QTextDocumentPrivate::get(block) != nullptr && QTextDocumentPrivate::get(block)->layout() != nullptr) {
@@ -3243,15 +3215,15 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
}
}
}
- for (const QTextOption::Tab &tabSpec : qAsConst(tabArray)) {
+ for (const QTextOption::Tab &tabSpec : std::as_const(tabArray)) {
QFixed tab = QFixed::fromReal(tabSpec.position) * dpiScale;
if (tab > x) { // this is the tab we need.
- int tabSectionEnd = layoutData->string.count();
+ int tabSectionEnd = layoutData->string.size();
if (tabSpec.type == QTextOption::RightTab || tabSpec.type == QTextOption::CenterTab) {
// find next tab to calculate the width required.
tab = QFixed::fromReal(tabSpec.position);
- for (int i=item + 1; i < layoutData->items.count(); i++) {
- const QScriptItem &item = layoutData->items[i];
+ for (int i=item + 1; i < layoutData->items.size(); i++) {
+ const QScriptItem &item = layoutData->items.at(i);
if (item.analysis.flags == QScriptAnalysis::TabOrObject) { // found it.
tabSectionEnd = item.position;
break;
@@ -3259,13 +3231,13 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
}
}
else if (tabSpec.type == QTextOption::DelimiterTab)
- // find delimitor character to calculate the width required
+ // find delimiter character to calculate the width required
tabSectionEnd = qMax(si.position, layoutData->string.indexOf(tabSpec.delimiter, si.position) + 1);
if (tabSectionEnd > si.position) {
QFixed length;
// Calculate the length of text between this tab and the tabSectionEnd
- for (int i=item; i < layoutData->items.count(); i++) {
+ for (int i=item; i < layoutData->items.size(); i++) {
const QScriptItem &item = layoutData->items.at(i);
if (item.position > tabSectionEnd || item.position <= si.position)
continue;
@@ -3337,7 +3309,7 @@ void QTextEngine::resolveFormats() const
QTextFormatCollection *collection = formatCollection();
- QList<QTextCharFormat> resolvedFormats(layoutData->items.count());
+ QList<QTextCharFormat> resolvedFormats(layoutData->items.size());
QVarLengthArray<int, 64> formatsSortedByStart;
formatsSortedByStart.reserve(specialData->formats.size());
@@ -3355,7 +3327,7 @@ void QTextEngine::resolveFormats() const
const int *startIt = formatsSortedByStart.constBegin();
const int *endIt = formatsSortedByEnd.constBegin();
- for (int i = 0; i < layoutData->items.count(); ++i) {
+ for (int i = 0; i < layoutData->items.size(); ++i) {
const QScriptItem *si = &layoutData->items.at(i);
int end = si->position + length(si);
@@ -3531,8 +3503,8 @@ int QTextEngine::previousLogicalPosition(int oldPos) const
{
const QCharAttributes *attrs = attributes();
int len = block.isValid() ? block.length() - 1
- : layoutData->string.length();
- Q_ASSERT(len <= layoutData->string.length());
+ : layoutData->string.size();
+ Q_ASSERT(len <= layoutData->string.size());
if (!attrs || oldPos <= 0 || oldPos > len)
return oldPos;
@@ -3546,8 +3518,8 @@ int QTextEngine::nextLogicalPosition(int oldPos) const
{
const QCharAttributes *attrs = attributes();
int len = block.isValid() ? block.length() - 1
- : layoutData->string.length();
- Q_ASSERT(len <= layoutData->string.length());
+ : layoutData->string.size();
+ Q_ASSERT(len <= layoutData->string.size());
if (!attrs || oldPos < 0 || oldPos >= len)
return oldPos;
@@ -3561,7 +3533,7 @@ int QTextEngine::lineNumberForTextPosition(int pos)
{
if (!layoutData)
itemize();
- if (pos == layoutData->string.length() && lines.size())
+ if (pos == layoutData->string.size() && lines.size())
return lines.size() - 1;
for (int i = 0; i < lines.size(); ++i) {
const QScriptLine& line = lines[i];
@@ -3885,10 +3857,12 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co
x += eng->alignLine(line);
- QVarLengthArray<uchar> levels(nItems);
- for (int i = 0; i < nItems; ++i)
- levels[i] = eng->layoutData->items.at(i + firstItem).analysis.bidiLevel;
- QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
+ if (nItems > 0) {
+ QVarLengthArray<uchar> levels(nItems);
+ for (int i = 0; i < nItems; ++i)
+ levels[i] = eng->layoutData->items.at(i + firstItem).analysis.bidiLevel;
+ QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
+ }
eng->shapeLine(line);
}
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 6ae3196963..a829265a22 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTENGINE_P_H
#define QTEXTENGINE_P_H
@@ -62,6 +26,7 @@
#include "QtCore/qlist.h"
#include "QtCore/qnamespace.h"
#include "QtCore/qset.h"
+#include <QtCore/qspan.h>
#include "QtCore/qstring.h"
#include "QtCore/qvarlengtharray.h"
@@ -194,10 +159,8 @@ Q_DECLARE_TYPEINFO(QGlyphAttributes, Q_PRIMITIVE_TYPE);
struct QGlyphLayout
{
- enum {
- SpaceNeeded = sizeof(glyph_t) + sizeof(QFixed) + sizeof(QFixedPoint)
- + sizeof(QGlyphAttributes) + sizeof(QGlyphJustification)
- };
+ static constexpr qsizetype SpaceNeeded = sizeof(glyph_t) + sizeof(QFixed) + sizeof(QFixedPoint)
+ + sizeof(QGlyphAttributes) + sizeof(QGlyphJustification);
// init to 0 not needed, done when shaping
QFixedPoint *offsets; // 8 bytes per element
@@ -213,7 +176,7 @@ struct QGlyphLayout
inline explicit QGlyphLayout(char *address, int totalGlyphs)
{
offsets = reinterpret_cast<QFixedPoint *>(address);
- int offset = totalGlyphs * sizeof(QFixedPoint);
+ qsizetype offset = totalGlyphs * sizeof(QFixedPoint);
glyphs = reinterpret_cast<glyph_t *>(address + offset);
offset += totalGlyphs * sizeof(glyph_t);
advances = reinterpret_cast<QFixed *>(address + offset);
@@ -246,7 +209,7 @@ struct QGlyphLayout
last = numGlyphs;
if (first == 0 && last == numGlyphs
&& reinterpret_cast<char *>(offsets + numGlyphs) == reinterpret_cast<char *>(glyphs)) {
- memset(static_cast<void *>(offsets), 0, (numGlyphs * SpaceNeeded));
+ memset(static_cast<void *>(offsets), 0, qsizetype(numGlyphs) * SpaceNeeded);
} else {
const int num = last - first;
memset(static_cast<void *>(offsets + first), 0, num * sizeof(QFixedPoint));
@@ -407,12 +370,12 @@ public:
LayoutFailed
};
struct Q_GUI_EXPORT LayoutData {
- LayoutData(const QString &str, void **stack_memory, int mem_size);
+ LayoutData(const QString &str, void **stack_memory, qsizetype mem_size);
LayoutData();
~LayoutData();
mutable QScriptItemArray items;
- int allocated;
- int available_glyphs;
+ qsizetype allocated;
+ qsizetype available_glyphs;
void **memory;
unsigned short *logClustersPtr;
QGlyphLayout glyphLayout;
@@ -421,6 +384,7 @@ public:
uint layoutState : 2;
uint memory_on_stack : 1;
uint haveCharAttributes : 1;
+ QFixed currentMaxWidth;
QString string;
bool reallocate(int totalGlyphs);
};
@@ -470,14 +434,14 @@ public:
const QScriptItem &si = layoutData->items[item];
int from = si.position;
item++;
- return (item < layoutData->items.size() ? layoutData->items[item].position : layoutData->string.length()) - from;
+ return (item < layoutData->items.size() ? layoutData->items[item].position : layoutData->string.size()) - from;
}
int length(const QScriptItem *si) const {
int end;
if (si + 1 < layoutData->items.constData()+ layoutData->items.size())
end = (si+1)->position;
else
- end = layoutData->string.length();
+ end = layoutData->string.size();
return end - si->position;
}
@@ -622,7 +586,7 @@ private:
public:
bool atWordSeparator(int position) const;
- QString elidedText(Qt::TextElideMode mode, const QFixed &width, int flags = 0, int from = 0, int count = -1) const;
+ QString elidedText(Qt::TextElideMode mode, QFixed width, int flags = 0, int from = 0, int count = -1) const;
void shapeLine(const QScriptLine &line);
QFixed leadingSpaceWidth(const QScriptLine &line);
@@ -656,9 +620,14 @@ private:
void addRequiredBoundaries() const;
void shapeText(int item) const;
#if QT_CONFIG(harfbuzz)
- int shapeTextWithHarfbuzzNG(const QScriptItem &si, const ushort *string, int itemLength,
- QFontEngine *fontEngine, const QList<uint> &itemBoundaries,
- bool kerningEnabled, bool hasLetterSpacing) const;
+ int shapeTextWithHarfbuzzNG(const QScriptItem &si,
+ const ushort *string,
+ int itemLength,
+ QFontEngine *fontEngine,
+ QSpan<uint> itemBoundaries,
+ bool kerningEnabled,
+ bool hasLetterSpacing,
+ const QHash<QFont::Tag, quint32> &features) const;
#endif
int endOfLine(int lineNum);
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 0166cd7ad2..3e4bacf78c 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextformat.h"
#include "qtextformat_p.h"
@@ -204,7 +168,7 @@ public:
if (key >= QTextFormat::FirstFontProperty && key <= QTextFormat::LastFontProperty)
fontDirty = true;
- for (int i = 0; i < props.count(); ++i)
+ for (int i = 0; i < props.size(); ++i)
if (props.at(i).key == key) {
props[i].value = value;
return;
@@ -214,7 +178,7 @@ public:
inline void clearProperty(qint32 key)
{
- for (int i = 0; i < props.count(); ++i)
+ for (int i = 0; i < props.size(); ++i)
if (props.at(i).key == key) {
hashDirty = true;
if (key >= QTextFormat::FirstFontProperty && key <= QTextFormat::LastFontProperty)
@@ -226,7 +190,7 @@ public:
inline int propertyIndex(qint32 key) const
{
- for (int i = 0; i < props.count(); ++i)
+ for (int i = 0; i < props.size(); ++i)
if (props.at(i).key == key)
return i;
return -1;
@@ -293,7 +257,7 @@ static inline size_t variantHash(const QVariant &variant)
case QMetaType::Bool: return 0x371818 + variant.toBool();
case QMetaType::QPen: return 0x02020202 + hash(qvariant_cast<QPen>(variant));
case QMetaType::QVariantList:
- return 0x8377U + qvariant_cast<QVariantList>(variant).count();
+ return 0x8377U + qvariant_cast<QVariantList>(variant).size();
case QMetaType::QColor: return hash(qvariant_cast<QColor>(variant));
case QMetaType::QTextLength:
return 0x377 + hash(qvariant_cast<QTextLength>(variant).rawValue());
@@ -354,7 +318,7 @@ void QTextFormatPrivate::recalcFont() const
QFont::SpacingType spacingType = QFont::PercentageSpacing;
qreal letterSpacing = 0.0;
- for (int i = 0; i < props.count(); ++i) {
+ for (int i = 0; i < props.size(); ++i) {
switch (props.at(i).key) {
case QTextFormat::FontFamilies:
f.setFamilies(props.at(i).value.toStringList());
@@ -441,27 +405,27 @@ Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextFormat &fmt
{
QMap<int, QVariant> properties = fmt.properties();
if (stream.version() < QDataStream::Qt_6_0) {
- auto it = properties.find(QTextFormat::FontLetterSpacingType);
- if (it != properties.end()) {
+ auto it = properties.constFind(QTextFormat::FontLetterSpacingType);
+ if (it != properties.cend()) {
properties[QTextFormat::OldFontLetterSpacingType] = it.value();
properties.erase(it);
}
- it = properties.find(QTextFormat::FontStretch);
- if (it != properties.end()) {
+ it = properties.constFind(QTextFormat::FontStretch);
+ if (it != properties.cend()) {
properties[QTextFormat::OldFontStretch] = it.value();
properties.erase(it);
}
- it = properties.find(QTextFormat::TextUnderlineColor);
- if (it != properties.end()) {
+ it = properties.constFind(QTextFormat::TextUnderlineColor);
+ if (it != properties.cend()) {
properties[QTextFormat::OldTextUnderlineColor] = it.value();
properties.erase(it);
}
- it = properties.find(QTextFormat::FontFamilies);
- if (it != properties.end()) {
- properties[QTextFormat::FontFamily] = QVariant(it.value().toStringList().first());
+ it = properties.constFind(QTextFormat::FontFamilies);
+ if (it != properties.cend()) {
+ properties[QTextFormat::OldFontFamily] = QVariant(it.value().toStringList().constFirst());
properties.erase(it);
}
}
@@ -489,13 +453,63 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
key = QTextFormat::FontStretch;
else if (key == QTextFormat::OldTextUnderlineColor)
key = QTextFormat::TextUnderlineColor;
- else if (key == QTextFormat::FontFamily)
+ else if (key == QTextFormat::OldFontFamily)
key = QTextFormat::FontFamilies;
fmt.d->insertProperty(key, it.value());
}
return stream;
}
+
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextCharFormat &fmt)
+{
+ return stream << static_cast<const QTextFormat &>(fmt);
+}
+
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextCharFormat &fmt)
+{
+ return stream >> static_cast<QTextFormat &>(fmt);
+}
+
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextBlockFormat &fmt)
+{
+ return stream << static_cast<const QTextFormat &>(fmt);
+}
+
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextBlockFormat &fmt)
+{
+ return stream >> static_cast<QTextFormat &>(fmt);
+}
+
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextListFormat &fmt)
+{
+ return stream << static_cast<const QTextFormat &>(fmt);
+}
+
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextListFormat &fmt)
+{
+ return stream >> static_cast<QTextFormat &>(fmt);
+}
+
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextFrameFormat &fmt)
+{
+ return stream << static_cast<const QTextFormat &>(fmt);
+}
+
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFrameFormat &fmt)
+{
+ return stream >> static_cast<QTextFormat &>(fmt);
+}
+
+Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextTableCellFormat &fmt)
+{
+ return stream << static_cast<const QTextFormat &>(fmt);
+}
+
+Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextTableCellFormat &fmt)
+{
+ return stream >> static_cast<QTextFormat &>(fmt);
+}
#endif // QT_NO_DATASTREAM
/*!
@@ -611,6 +625,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
Character properties
\value FontFamily e{This property has been deprecated.} Use QTextFormat::FontFamilies instead.
+ \omitvalue OldFontFamily
\value FontFamilies
\value FontStyleName
\value FontPointSize
@@ -669,6 +684,8 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
numeric lists.
\value ListNumberSuffix Defines the text which is appended to item numbers in
numeric lists.
+ \value [since 6.6] ListStart
+ Defines the first value of a list.
Table and frame properties
@@ -936,9 +953,13 @@ void QTextFormat::merge(const QTextFormat &other)
const QList<QT_PREPEND_NAMESPACE(Property)> &otherProps = other.d.constData()->props;
p->props.reserve(p->props.size() + otherProps.size());
- for (int i = 0; i < otherProps.count(); ++i) {
+ for (int i = 0; i < otherProps.size(); ++i) {
const QT_PREPEND_NAMESPACE(Property) &prop = otherProps.at(i);
- p->insertProperty(prop.key, prop.value);
+ if (prop.value.isValid()) {
+ p->insertProperty(prop.key, prop.value);
+ } else {
+ p->clearProperty(prop.key);
+ }
}
}
@@ -1195,10 +1216,8 @@ void QTextFormat::setProperty(int propertyId, const QVariant &value)
{
if (!d)
d = new QTextFormatPrivate;
- if (!value.isValid())
- clearProperty(propertyId);
- else
- d->insertProperty(propertyId, value);
+
+ d->insertProperty(propertyId, value);
}
/*!
@@ -1308,7 +1327,7 @@ QMap<int, QVariant> QTextFormat::properties() const
{
QMap<int, QVariant> map;
if (d) {
- for (int i = 0; i < d->props.count(); ++i)
+ for (int i = 0; i < d->props.size(); ++i)
map.insert(d->props.at(i).key, d->props.at(i).value);
}
return map;
@@ -1320,7 +1339,7 @@ QMap<int, QVariant> QTextFormat::properties() const
*/
int QTextFormat::propertyCount() const
{
- return d ? d->props.count() : 0;
+ return d ? d->props.size() : 0;
}
/*!
@@ -1373,7 +1392,7 @@ bool QTextFormat::operator==(const QTextFormat &rhs) const
The font used can be set by supplying a font to the setFont() function, and
each aspect of its appearance can be adjusted to give the desired effect.
- setFontFamily() and setFontPointSize() define the font's family (e.g. Times)
+ setFontFamilies() and setFontPointSize() define the font's family (e.g. Times)
and printed size; setFontWeight() and setFontItalic() provide control over
the style of the font. setFontUnderline(), setFontOverline(),
setFontStrikeOut(), and setFontFixedPitch() provide additional effects for
@@ -1418,7 +1437,7 @@ bool QTextFormat::operator==(const QTextFormat &rhs) const
\value SingleUnderline A line is drawn using Qt::SolidLine.
\value DashUnderline Dashes are drawn using Qt::DashLine.
\value DotLine Dots are drawn using Qt::DotLine;
- \value DashDotLine Dashs and dots are drawn using Qt::DashDotLine.
+ \value DashDotLine Dashes and dots are drawn using Qt::DashDotLine.
\value DashDotDotLine Underlines draw drawn using Qt::DashDotDotLine.
\value WaveUnderline The text is underlined using a wave shaped line.
\value SpellCheckUnderline The underline is drawn depending on the SpellCheckUnderlineStyle
@@ -1457,7 +1476,7 @@ QTextCharFormat::QTextCharFormat(const QTextFormat &fmt)
/*!
\fn void QTextCharFormat::setFontFamily(const QString &family)
- \deprecated Use setFontFamilies() instead.
+ \deprecated [6.1] Use setFontFamilies() instead.
Sets the text format's font \a family.
@@ -1467,7 +1486,7 @@ QTextCharFormat::QTextCharFormat(const QTextFormat &fmt)
/*!
\fn QString QTextCharFormat::fontFamily() const
- \deprecated Use fontFamilies() instead.
+ \deprecated [6.1] Use fontFamilies() instead.
Returns the text format's font family.
@@ -1497,7 +1516,7 @@ QTextCharFormat::QTextCharFormat(const QTextFormat &fmt)
\sa font()
*/
#else
-/*!
+/* // Qt 7 documents this function
\fn QStringList QTextCharFormat::fontFamilies() const
\since 5.13
@@ -1530,7 +1549,7 @@ QTextCharFormat::QTextCharFormat(const QTextFormat &fmt)
\sa font(), QFont::styleName()
*/
#else
-/*!
+/* // Qt 7 documents this function
\fn QStringList QTextCharFormat::fontStyleName() const
\since 5.13
@@ -2152,7 +2171,7 @@ QFont QTextCharFormat::font() const
associated QTextBlockFormat that specifies its characteristics.
To cater for left-to-right and right-to-left languages you can set
- a block's direction with setDirection(). Paragraph alignment is
+ a block's direction with setLayoutDirection(). Paragraph alignment is
set with setAlignment(). Margins are controlled by setTopMargin(),
setBottomMargin(), setLeftMargin(), setRightMargin(). Overall
indentation is set with setIndent(), the indentation of the first
@@ -2222,14 +2241,9 @@ QTextBlockFormat::QTextBlockFormat(const QTextFormat &fmt)
void QTextBlockFormat::setTabPositions(const QList<QTextOption::Tab> &tabs)
{
QList<QVariant> list;
- list.reserve(tabs.count());
- QList<QTextOption::Tab>::ConstIterator iter = tabs.constBegin();
- while (iter != tabs.constEnd()) {
- QVariant v;
- v.setValue(*iter);
- list.append(v);
- ++iter;
- }
+ list.reserve(tabs.size());
+ for (const auto &e : tabs)
+ list.append(QVariant::fromValue(e));
setProperty(TabPositions, list);
}
@@ -2245,13 +2259,10 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
if (variant.isNull())
return QList<QTextOption::Tab>();
QList<QTextOption::Tab> answer;
- QList<QVariant> variantsList = qvariant_cast<QList<QVariant> >(variant);
- QList<QVariant>::Iterator iter = variantsList.begin();
- answer.reserve(variantsList.count());
- while(iter != variantsList.end()) {
- answer.append( qvariant_cast<QTextOption::Tab>(*iter));
- ++iter;
- }
+ const QList<QVariant> variantsList = qvariant_cast<QList<QVariant> >(variant);
+ answer.reserve(variantsList.size());
+ for (const auto &e: variantsList)
+ answer.append(qvariant_cast<QTextOption::Tab>(e));
return answer;
}
@@ -2595,7 +2606,8 @@ QList<QTextOption::Tab> QTextBlockFormat::tabPositions() const
The style used to decorate each item is set with setStyle() and can be read
with the style() function. The style controls the type of bullet points and
numbering scheme used for items in the list. Note that lists that use the
- decimal numbering scheme begin counting at 1 rather than 0.
+ decimal numbering scheme begin counting at 1 rather than 0, unless it has
+ been overridden via setStart().
Style properties can be set to further configure the appearance of list
items; for example, the ListNumberPrefix and ListNumberSuffix properties
@@ -2632,6 +2644,7 @@ QTextListFormat::QTextListFormat()
: QTextFormat(ListFormat)
{
setIndent(1);
+ setStart(1);
}
/*!
@@ -2736,6 +2749,32 @@ QTextListFormat::QTextListFormat(const QTextFormat &fmt)
*/
/*!
+ \fn void QTextListFormat::setStart(int start)
+ \since 6.6
+
+ Sets the list format's \a start index.
+
+ This allows you to start a list with an index other than 1. This can be
+ used with all sorted list types: for example if the style() is
+ QTextListFormat::ListLowerAlpha and start() is \c 4, the first list item
+ begins with "d". It does not have any effect on unsorted list types.
+
+ The default start is \c 1.
+
+ \sa start()
+*/
+
+/*!
+ \fn int QTextListFormat::start() const
+ \since 6.6
+
+ Returns the number to be shown by the first list item, if the style() is
+ QTextListFormat::ListDecimal, or to offset other sorted list types.
+
+ \sa setStart()
+*/
+
+/*!
\class QTextFrameFormat
\reentrant
@@ -3442,7 +3481,7 @@ QTextImageFormat::QTextImageFormat(const QTextFormat &fmt)
\fn void QTextCharFormat::setFontCapitalization(QFont::Capitalization capitalization)
\since 4.4
- Sets the capitalization of the text that apppears in this font to \a capitalization.
+ Sets the capitalization of the text that appears in this font to \a capitalization.
A font's capitalization makes the text appear in the selected capitalization mode.
@@ -3954,7 +3993,7 @@ bool QTextFormatCollection::hasFormatCached(const QTextFormat &format) const
int QTextFormatCollection::objectFormatIndex(int objectIndex) const
{
- if (objectIndex == -1)
+ if (objectIndex == -1 || objectIndex >= objFormats.size())
return -1;
return objFormats.at(objectIndex);
}
@@ -3973,7 +4012,7 @@ int QTextFormatCollection::createObjectIndex(const QTextFormat &f)
QTextFormat QTextFormatCollection::format(int idx) const
{
- if (idx < 0 || idx >= formats.count())
+ if (idx < 0 || idx >= formats.size())
return QTextFormat();
return formats.at(idx);
@@ -3982,7 +4021,7 @@ QTextFormat QTextFormatCollection::format(int idx) const
void QTextFormatCollection::setDefaultFont(const QFont &f)
{
defaultFnt = f;
- for (int i = 0; i < formats.count(); ++i)
+ for (int i = 0; i < formats.size(); ++i)
if (formats.at(i).d)
formats[i].d->resolveFont(defaultFnt);
}
@@ -4005,3 +4044,5 @@ QDebug operator<<(QDebug dbg, const QTextFormat &f)
#endif
QT_END_NAMESPACE
+
+#include "moc_qtextformat.cpp"
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index 45bf458cae..c009d328cb 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTFORMAT_H
#define QTEXTFORMAT_H
@@ -73,11 +37,6 @@ class QTextCursor;
class QTextDocument;
class QTextLength;
-#ifndef QT_NO_DATASTREAM
-Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextLength &);
-Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextLength &);
-#endif
-
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QTextLength &);
#endif
@@ -123,11 +82,6 @@ Q_DECLARE_TYPEINFO(QTextLength, Q_PRIMITIVE_TYPE);
inline QTextLength::QTextLength(Type atype, qreal avalue)
: lengthType(atype), fixedValueOrPercentage(avalue) {}
-#ifndef QT_NO_DATASTREAM
-Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextFormat &);
-Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextFormat &);
-#endif
-
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QTextFormat &);
#endif
@@ -225,6 +179,7 @@ public:
OldFontLetterSpacingType = 0x2033,
OldFontStretch = 0x2034,
OldTextUnderlineColor = 0x2010,
+ OldFontFamily = 0x2000, // same as FontFamily
ObjectType = 0x2f00,
@@ -233,6 +188,7 @@ public:
ListIndent = 0x3001,
ListNumberPrefix = 0x3002,
ListNumberSuffix = 0x3003,
+ ListStart = 0x3004,
// table and frame properties
FrameBorder = 0x4000,
@@ -330,7 +286,7 @@ public:
~QTextFormat();
void swap(QTextFormat &other)
- { qSwap(d, other.d); qSwap(format_type, other.format_type); }
+ { d.swap(other.d); std::swap(format_type, other.format_type); }
void merge(const QTextFormat &other);
@@ -624,6 +580,8 @@ public:
protected:
explicit QTextCharFormat(const QTextFormat &fmt);
friend class QTextFormat;
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextCharFormat &);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextCharFormat &);
};
Q_DECLARE_SHARED(QTextCharFormat)
@@ -717,7 +675,7 @@ public:
{ return boolProperty(BlockNonBreakableLines); }
inline void setPageBreakPolicy(PageBreakFlags flags)
- { setProperty(PageBreakPolicy, int(flags)); }
+ { setProperty(PageBreakPolicy, int(flags.toInt())); }
inline PageBreakFlags pageBreakPolicy() const
{ return PageBreakFlags(intProperty(PageBreakPolicy)); }
@@ -732,12 +690,14 @@ public:
protected:
explicit QTextBlockFormat(const QTextFormat &fmt);
friend class QTextFormat;
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextBlockFormat &);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextBlockFormat &);
};
Q_DECLARE_SHARED(QTextBlockFormat)
inline void QTextBlockFormat::setAlignment(Qt::Alignment aalignment)
-{ setProperty(BlockAlignment, int(aalignment)); }
+{ setProperty(BlockAlignment, int(aalignment.toInt())); }
inline void QTextBlockFormat::setIndent(int aindent)
{ setProperty(BlockIndent, aindent); }
@@ -794,6 +754,9 @@ public:
inline QString numberSuffix() const
{ return stringProperty(ListNumberSuffix); }
+ inline void setStart(int indent);
+ inline int start() const { return intProperty(ListStart); }
+
protected:
explicit QTextListFormat(const QTextFormat &fmt);
friend class QTextFormat;
@@ -813,6 +776,11 @@ inline void QTextListFormat::setNumberPrefix(const QString &np)
inline void QTextListFormat::setNumberSuffix(const QString &ns)
{ setProperty(ListNumberSuffix, ns); }
+inline void QTextListFormat::setStart(int astart)
+{
+ setProperty(ListStart, astart);
+}
+
class Q_GUI_EXPORT QTextImageFormat : public QTextCharFormat
{
public:
@@ -832,13 +800,19 @@ public:
inline qreal height() const
{ return doubleProperty(ImageHeight); }
- inline void setQuality(int quality = 100);
+ inline void setQuality(int quality);
+#if QT_DEPRECATED_SINCE(6, 3)
+ QT_DEPRECATED_VERSION_X_6_3("Pass a quality value, the default is 100") inline void setQuality()
+ { setQuality(100); }
+#endif
inline int quality() const
{ return intProperty(ImageQuality); }
protected:
explicit QTextImageFormat(const QTextFormat &format);
friend class QTextFormat;
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextListFormat &);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextListFormat &);
};
Q_DECLARE_SHARED(QTextImageFormat)
@@ -935,13 +909,15 @@ public:
{ return lengthProperty(FrameHeight); }
inline void setPageBreakPolicy(PageBreakFlags flags)
- { setProperty(PageBreakPolicy, int(flags)); }
+ { setProperty(PageBreakPolicy, int(flags.toInt())); }
inline PageBreakFlags pageBreakPolicy() const
{ return PageBreakFlags(intProperty(PageBreakPolicy)); }
protected:
explicit QTextFrameFormat(const QTextFormat &fmt);
friend class QTextFormat;
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextFrameFormat &);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextFrameFormat &);
};
Q_DECLARE_SHARED(QTextFrameFormat)
@@ -1033,7 +1009,7 @@ inline void QTextTableFormat::setCellPadding(qreal apadding)
{ setProperty(TableCellPadding, apadding); }
inline void QTextTableFormat::setAlignment(Qt::Alignment aalignment)
-{ setProperty(BlockAlignment, int(aalignment)); }
+{ setProperty(BlockAlignment, int(aalignment.toInt())); }
class Q_GUI_EXPORT QTextTableCellFormat : public QTextCharFormat
{
@@ -1124,6 +1100,8 @@ public:
protected:
explicit QTextTableCellFormat(const QTextFormat &fmt);
+ friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextTableCellFormat &);
+ friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextTableCellFormat &);
friend class QTextFormat;
};
diff --git a/src/gui/text/qtextformat_p.h b/src/gui/text/qtextformat_p.h
index 13815d06b3..1bd9120513 100644
--- a/src/gui/text/qtextformat_p.h
+++ b/src/gui/text/qtextformat_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTFORMAT_P_H
#define QTEXTFORMAT_P_H
@@ -54,6 +18,7 @@
#include <QtGui/private/qtguiglobal_p.h>
#include "QtGui/qtextformat.h"
#include "QtCore/qlist.h"
+#include <QtCore/qhash.h> // QMultiHash
QT_BEGIN_NAMESPACE
@@ -90,7 +55,7 @@ public:
inline QTextImageFormat imageFormat(int index) const
{ return format(index).toImageFormat(); }
- inline int numFormats() const { return formats.count(); }
+ inline int numFormats() const { return formats.size(); }
typedef QList<QTextFormat> FormatVector;
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 6a9f7d3a96..ee92cece78 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtexthtmlparser_p.h"
@@ -57,6 +21,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// see also tst_qtextdocumentfragment.cpp
#define MAX_ENTITY 258
static const struct QTextHtmlEntity { const char name[9]; char16_t code; } entities[]= {
@@ -321,21 +287,21 @@ static const struct QTextHtmlEntity { const char name[9]; char16_t code; } entit
};
static_assert(MAX_ENTITY == sizeof entities / sizeof *entities);
-#if defined(Q_CC_MSVC) && _MSC_VER < 1600
+#if defined(Q_CC_MSVC_ONLY) && _MSC_VER < 1600
bool operator<(const QTextHtmlEntity &entity1, const QTextHtmlEntity &entity2)
{
- return QLatin1String(entity1.name) < QLatin1String(entity2.name);
+ return QLatin1StringView(entity1.name) < QLatin1StringView(entity2.name);
}
#endif
static bool operator<(QStringView entityStr, const QTextHtmlEntity &entity)
{
- return entityStr < QLatin1String(entity.name);
+ return entityStr < QLatin1StringView(entity.name);
}
static bool operator<(const QTextHtmlEntity &entity, QStringView entityStr)
{
- return QLatin1String(entity.name) < entityStr;
+ return QLatin1StringView(entity.name) < entityStr;
}
static QChar resolveEntity(QStringView entity)
@@ -447,17 +413,17 @@ static const QTextHtmlElement elements[Html_NumElements]= {
{ "var", Html_var, QTextHtmlElement::DisplayInline },
};
-static bool operator<(const QString &str, const QTextHtmlElement &e)
+static bool operator<(QStringView str, const QTextHtmlElement &e)
{
- return str < QLatin1String(e.name);
+ return str < QLatin1StringView(e.name);
}
-static bool operator<(const QTextHtmlElement &e, const QString &str)
+static bool operator<(const QTextHtmlElement &e, QStringView str)
{
- return QLatin1String(e.name) < str;
+ return QLatin1StringView(e.name) < str;
}
-static const QTextHtmlElement *lookupElementHelper(const QString &element)
+static const QTextHtmlElement *lookupElementHelper(QStringView element)
{
const QTextHtmlElement *start = &elements[0];
const QTextHtmlElement *end = &elements[Html_NumElements];
@@ -467,7 +433,7 @@ static const QTextHtmlElement *lookupElementHelper(const QString &element)
return e;
}
-int QTextHtmlParser::lookupElement(const QString &element)
+int QTextHtmlParser::lookupElement(QStringView element)
{
const QTextHtmlElement *e = lookupElementHelper(element);
if (!e)
@@ -479,7 +445,7 @@ int QTextHtmlParser::lookupElement(const QString &element)
static QString quoteNewline(const QString &s)
{
QString n = s;
- n.replace(QLatin1Char('\n'), QLatin1String("\\n"));
+ n.replace(u'\n', "\\n"_L1);
return n;
}
@@ -509,10 +475,9 @@ QTextHtmlParserNode::QTextHtmlParserNode()
void QTextHtmlParser::dumpHtml()
{
for (int i = 0; i < count(); ++i) {
- qDebug().nospace() << qPrintable(QString(depth(i)*4, QLatin1Char(' ')))
+ qDebug().nospace() << qPrintable(QString(depth(i) * 4, u' '))
<< qPrintable(at(i).tag) << ':'
<< quoteNewline(at(i).text);
- ;
}
}
@@ -523,7 +488,7 @@ QTextHtmlParserNode *QTextHtmlParser::newNode(int parent)
bool reuseLastNode = true;
- if (nodes.count() == 1) {
+ if (nodes.size() == 1) {
reuseLastNode = false;
} else if (lastNode->tag.isEmpty()) {
@@ -531,7 +496,7 @@ QTextHtmlParserNode *QTextHtmlParser::newNode(int parent)
reuseLastNode = true;
} else { // last node is a text node (empty tag) with some text
- if (lastNode->text.length() == 1 && lastNode->text.at(0).isSpace()) {
+ if (lastNode->text.size() == 1 && lastNode->text.at(0).isSpace()) {
int lastSibling = count() - 2;
while (lastSibling
@@ -578,7 +543,7 @@ void QTextHtmlParser::parse(const QString &text, const QTextDocument *_resourceP
nodes.append(new QTextHtmlParserNode);
txt = text;
pos = 0;
- len = txt.length();
+ len = txt.size();
textEditMode = false;
resourceProvider = _resourceProvider;
parse();
@@ -637,9 +602,9 @@ void QTextHtmlParser::parse()
{
while (pos < len) {
QChar c = txt.at(pos++);
- if (c == QLatin1Char('<')) {
+ if (c == u'<') {
parseTag();
- } else if (c == QLatin1Char('&')) {
+ } else if (c == u'&') {
nodes.last()->text += parseEntity();
} else {
nodes.last()->text += c;
@@ -653,7 +618,7 @@ void QTextHtmlParser::parseTag()
eatSpace();
// handle comments and other exclamation mark declarations
- if (hasPrefix(QLatin1Char('!'))) {
+ if (hasPrefix(u'!')) {
parseExclamationTag();
if (nodes.last()->wsm != QTextHtmlParserNode::WhiteSpacePre
&& nodes.last()->wsm != QTextHtmlParserNode::WhiteSpacePreWrap
@@ -663,7 +628,7 @@ void QTextHtmlParser::parseTag()
}
// if close tag just close
- if (hasPrefix(QLatin1Char('/'))) {
+ if (hasPrefix(u'/')) {
if (nodes.last()->id == Html_style) {
#ifndef QT_NO_CSSPARSER
QCss::Parser parser(nodes.constLast()->text);
@@ -707,15 +672,15 @@ void QTextHtmlParser::parseTag()
resolveNode();
#ifndef QT_NO_CSSPARSER
- const int nodeIndex = nodes.count() - 1; // this new node is always the last
+ const int nodeIndex = nodes.size() - 1; // this new node is always the last
node->applyCssDeclarations(declarationsForNode(nodeIndex), resourceProvider);
#endif
applyAttributes(node->attributes);
// finish tag
bool tagClosed = false;
- while (pos < len && txt.at(pos) != QLatin1Char('>')) {
- if (txt.at(pos) == QLatin1Char('/'))
+ while (pos < len && txt.at(pos) != u'>') {
+ if (txt.at(pos) == u'/')
tagClosed = true;
pos++;
@@ -728,7 +693,7 @@ void QTextHtmlParser::parseTag()
|| node->wsm == QTextHtmlParserNode::WhiteSpacePreWrap
|| node->wsm == QTextHtmlParserNode::WhiteSpacePreLine)
&& node->isBlock()) {
- if (pos < len - 1 && txt.at(pos) == QLatin1Char('\n'))
+ if (pos < len - 1 && txt.at(pos) == u'\n')
++pos;
}
@@ -745,7 +710,7 @@ void QTextHtmlParser::parseCloseTag()
QString tag = parseWord().toLower().trimmed();
while (pos < len) {
QChar c = txt.at(pos++);
- if (c == QLatin1Char('>'))
+ if (c == u'>')
break;
}
@@ -773,7 +738,7 @@ void QTextHtmlParser::parseCloseTag()
|| at(p).wsm == QTextHtmlParserNode::WhiteSpacePreWrap
|| at(p).wsm == QTextHtmlParserNode::WhiteSpacePreLine)
&& at(p).isBlock()) {
- if (at(last()).text.endsWith(QLatin1Char('\n')))
+ if (at(last()).text.endsWith(u'\n'))
nodes[last()]->text.chop(1);
}
@@ -785,16 +750,16 @@ void QTextHtmlParser::parseCloseTag()
void QTextHtmlParser::parseExclamationTag()
{
++pos;
- if (hasPrefix(QLatin1Char('-'),1) && hasPrefix(QLatin1Char('-'),2)) {
- pos += 3;
+ if (hasPrefix(u'-') && hasPrefix(u'-', 1)) {
+ pos += 2;
// eat comments
- int end = txt.indexOf(QLatin1String("-->"), pos);
+ int end = txt.indexOf("-->"_L1, pos);
pos = (end >= 0 ? end + 3 : len);
} else {
// eat internal tags
while (pos < len) {
QChar c = txt.at(pos++);
- if (c == QLatin1Char('>'))
+ if (c == u'>')
break;
}
}
@@ -806,13 +771,13 @@ QString QTextHtmlParser::parseEntity(QStringView entity)
if (!resolved.isNull())
return QString(resolved);
- if (entity.length() > 1 && entity.at(0) == QLatin1Char('#')) {
+ if (entity.size() > 1 && entity.at(0) == u'#') {
entity = entity.mid(1); // removing leading #
int base = 10;
bool ok = false;
- if (entity.at(0).toLower() == QLatin1Char('x')) { // hex entity?
+ if (entity.at(0).toLower() == u'x') { // hex entity?
entity = entity.mid(1);
base = 16;
}
@@ -837,7 +802,7 @@ QString QTextHtmlParser::parseEntity()
if (c.isSpace() || pos - recover > 9) {
goto error;
}
- if (c == QLatin1Char(';'))
+ if (c == u';')
break;
++entityLen;
}
@@ -850,30 +815,30 @@ QString QTextHtmlParser::parseEntity()
}
error:
pos = recover;
- return QLatin1String("&");
+ return "&"_L1;
}
// parses one word, possibly quoted, and returns it
QString QTextHtmlParser::parseWord()
{
QString word;
- if (hasPrefix(QLatin1Char('\"'))) { // double quotes
+ if (hasPrefix(u'\"')) { // double quotes
++pos;
while (pos < len) {
QChar c = txt.at(pos++);
- if (c == QLatin1Char('\"'))
+ if (c == u'\"')
break;
- else if (c == QLatin1Char('&'))
+ else if (c == u'&')
word += parseEntity();
else
word += c;
}
- } else if (hasPrefix(QLatin1Char('\''))) { // single quotes
+ } else if (hasPrefix(u'\'')) { // single quotes
++pos;
while (pos < len) {
QChar c = txt.at(pos++);
// Allow for escaped single quotes as they may be part of the string
- if (c == QLatin1Char('\'') && (txt.length() > 1 && txt.at(pos - 2) != QLatin1Char('\\')))
+ if (c == u'\'' && (txt.size() > 1 && txt.at(pos - 2) != u'\\'))
break;
else
word += c;
@@ -881,15 +846,12 @@ QString QTextHtmlParser::parseWord()
} else { // normal text
while (pos < len) {
QChar c = txt.at(pos++);
- if (c == QLatin1Char('>')
- || (c == QLatin1Char('/') && hasPrefix(QLatin1Char('>'), 1))
- || c == QLatin1Char('<')
- || c == QLatin1Char('=')
- || c.isSpace()) {
+ if (c == u'>' || (c == u'/' && hasPrefix(u'>'))
+ || c == u'<' || c == u'=' || c.isSpace()) {
--pos;
break;
}
- if (c == QLatin1Char('&'))
+ if (c == u'&')
word += parseEntity();
else
word += c;
@@ -914,21 +876,21 @@ QTextHtmlParserNode *QTextHtmlParser::resolveParent()
n = at(n).parent;
if (!n) {
- nodes.insert(nodes.count() - 1, new QTextHtmlParserNode);
- nodes.insert(nodes.count() - 1, new QTextHtmlParserNode);
+ nodes.insert(nodes.size() - 1, new QTextHtmlParserNode);
+ nodes.insert(nodes.size() - 1, new QTextHtmlParserNode);
- QTextHtmlParserNode *table = nodes[nodes.count() - 3];
+ QTextHtmlParserNode *table = nodes[nodes.size() - 3];
table->parent = p;
table->id = Html_table;
- table->tag = QLatin1String("table");
- table->children.append(nodes.count() - 2); // add row as child
+ table->tag = "table"_L1;
+ table->children.append(nodes.size() - 2); // add row as child
- QTextHtmlParserNode *row = nodes[nodes.count() - 2];
- row->parent = nodes.count() - 3; // table as parent
+ QTextHtmlParserNode *row = nodes[nodes.size() - 2];
+ row->parent = nodes.size() - 3; // table as parent
row->id = Html_tr;
- row->tag = QLatin1String("tr");
+ row->tag = "tr"_L1;
- p = nodes.count() - 2;
+ p = nodes.size() - 2;
node = nodes.last(); // re-initialize pointer
}
}
@@ -939,12 +901,12 @@ QTextHtmlParserNode *QTextHtmlParser::resolveParent()
n = at(n).parent;
if (!n) {
- nodes.insert(nodes.count() - 1, new QTextHtmlParserNode);
- QTextHtmlParserNode *table = nodes[nodes.count() - 2];
+ nodes.insert(nodes.size() - 1, new QTextHtmlParserNode);
+ QTextHtmlParserNode *table = nodes[nodes.size() - 2];
table->parent = p;
table->id = Html_table;
- table->tag = QLatin1String("table");
- p = nodes.count() - 2;
+ table->tag = "table"_L1;
+ p = nodes.size() - 2;
node = nodes.last(); // re-initialize pointer
}
}
@@ -992,7 +954,7 @@ QTextHtmlParserNode *QTextHtmlParser::resolveParent()
node->parent = p;
// makes it easier to traverse the tree, later
- nodes[p]->children.append(nodes.count() - 1);
+ nodes[p]->children.append(nodes.size() - 1);
return node;
}
@@ -1067,9 +1029,9 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent
// set element specific attributes
switch (id) {
case Html_a:
- for (int i = 0; i < attributes.count(); i += 2) {
+ for (int i = 0; i < attributes.size(); i += 2) {
const QString key = attributes.at(i);
- if (key.compare(QLatin1String("href"), Qt::CaseInsensitive) == 0
+ if (key.compare("href"_L1, Qt::CaseInsensitive) == 0
&& !attributes.at(i + 1).isEmpty()) {
hasHref = true;
}
@@ -1155,7 +1117,7 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent
#ifndef QT_NO_CSSPARSER
void QTextHtmlParserNode::setListStyle(const QList<QCss::Value> &cssValues)
{
- for (int i = 0; i < cssValues.count(); ++i) {
+ for (int i = 0; i < cssValues.size(); ++i) {
if (cssValues.at(i).type == QCss::Value::KnownIdentifier) {
switch (static_cast<QCss::KnownValue>(cssValues.at(i).variant.toInt())) {
case QCss::Value_None: hasOwnListStyle = true; listStyle = QTextListFormat::ListStyleUndefined; break;
@@ -1219,7 +1181,7 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
QCss::ValueExtractor extractor(declarations);
extractor.extractBox(margin, padding);
- if (id == Html_td || id == Html_th) {
+ auto getBorderValues = [&extractor](qreal *borderWidth, QBrush *borderBrush, QTextFrameFormat::BorderStyle *borderStyles) {
QCss::BorderStyle cssStyles[4];
int cssBorder[4];
QSize cssRadii[4]; // unused
@@ -1231,20 +1193,24 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
// QCss::BorderWidth parsing below which expects a single value
// will not work as expected - which in this case does not matter
// because tableBorder is not relevant for cells.
- extractor.extractBorder(cssBorder, tableCellBorderBrush, cssStyles, cssRadii);
+ bool hit = extractor.extractBorder(cssBorder, borderBrush, cssStyles, cssRadii);
for (int i = 0; i < 4; ++i) {
- tableCellBorderStyle[i] = toQTextFrameFormat(cssStyles[i]);
- tableCellBorder[i] = static_cast<qreal>(cssBorder[i]);
+ borderStyles[i] = toQTextFrameFormat(cssStyles[i]);
+ borderWidth[i] = static_cast<qreal>(cssBorder[i]);
}
- }
+ return hit;
+ };
+
+ if (id == Html_td || id == Html_th)
+ getBorderValues(tableCellBorder, tableCellBorderBrush, tableCellBorderStyle);
- for (int i = 0; i < declarations.count(); ++i) {
+ for (int i = 0; i < declarations.size(); ++i) {
const QCss::Declaration &decl = declarations.at(i);
if (decl.d->values.isEmpty()) continue;
QCss::KnownValue identifier = QCss::UnknownValue;
- if (decl.d->values.first().type == QCss::Value::KnownIdentifier)
- identifier = static_cast<QCss::KnownValue>(decl.d->values.first().variant.toInt());
+ if (decl.d->values.constFirst().type == QCss::Value::KnownIdentifier)
+ identifier = static_cast<QCss::KnownValue>(decl.d->values.constFirst().variant.toInt());
switch (decl.d->propertyId) {
case QCss::BorderColor: borderBrush = QBrush(decl.colorValue()); break;
@@ -1258,6 +1224,19 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
tableBorder = borders[0];
}
break;
+ case QCss::Border: {
+ qreal tblBorder[4];
+ QBrush tblBorderBrush[4];
+ QTextFrameFormat::BorderStyle tblBorderStyle[4];
+ if (getBorderValues(tblBorder, tblBorderBrush, tblBorderStyle)) {
+ tableBorder = tblBorder[0];
+ if (tblBorderBrush[0].color().isValid())
+ borderBrush = tblBorderBrush[0];
+ if (tblBorderStyle[0] != static_cast<QTextFrameFormat::BorderStyle>(-1))
+ borderStyle = tblBorderStyle[0];
+ }
+ }
+ break;
case QCss::BorderCollapse:
borderCollapse = decl.borderCollapseValue();
break;
@@ -1271,18 +1250,18 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
}
break;
case QCss::QtBlockIndent:
- blockFormat.setIndent(decl.d->values.first().variant.toInt());
+ blockFormat.setIndent(decl.d->values.constFirst().variant.toInt());
break;
case QCss::QtLineHeightType: {
- QString lineHeightTypeName = decl.d->values.first().variant.toString();
+ QString lineHeightTypeName = decl.d->values.constFirst().variant.toString();
QTextBlockFormat::LineHeightTypes lineHeightType;
- if (lineHeightTypeName.compare(QLatin1String("proportional"), Qt::CaseInsensitive) == 0)
+ if (lineHeightTypeName.compare("proportional"_L1, Qt::CaseInsensitive) == 0)
lineHeightType = QTextBlockFormat::ProportionalHeight;
- else if (lineHeightTypeName.compare(QLatin1String("fixed"), Qt::CaseInsensitive) == 0)
+ else if (lineHeightTypeName.compare("fixed"_L1, Qt::CaseInsensitive) == 0)
lineHeightType = QTextBlockFormat::FixedHeight;
- else if (lineHeightTypeName.compare(QLatin1String("minimum"), Qt::CaseInsensitive) == 0)
+ else if (lineHeightTypeName.compare("minimum"_L1, Qt::CaseInsensitive) == 0)
lineHeightType = QTextBlockFormat::MinimumHeight;
- else if (lineHeightTypeName.compare(QLatin1String("line-distance"), Qt::CaseInsensitive) == 0)
+ else if (lineHeightTypeName.compare("line-distance"_L1, Qt::CaseInsensitive) == 0)
lineHeightType = QTextBlockFormat::LineDistanceHeight;
else
lineHeightType = QTextBlockFormat::SingleHeight;
@@ -1303,7 +1282,7 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
lineHeightType = QTextBlockFormat::MinimumHeight;
} else {
bool ok;
- QCss::Value cssValue = decl.d->values.first();
+ QCss::Value cssValue = decl.d->values.constFirst();
QString value = cssValue.toString();
lineHeight = value.toDouble(&ok);
if (ok) {
@@ -1335,19 +1314,19 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
hasCssListIndent = true;
break;
case QCss::QtParagraphType:
- if (decl.d->values.first().variant.toString().compare(QLatin1String("empty"), Qt::CaseInsensitive) == 0)
+ if (decl.d->values.constFirst().variant.toString().compare("empty"_L1, Qt::CaseInsensitive) == 0)
isEmptyParagraph = true;
break;
case QCss::QtTableType:
- if (decl.d->values.first().variant.toString().compare(QLatin1String("frame"), Qt::CaseInsensitive) == 0)
+ if (decl.d->values.constFirst().variant.toString().compare("frame"_L1, Qt::CaseInsensitive) == 0)
isTextFrame = true;
- else if (decl.d->values.first().variant.toString().compare(QLatin1String("root"), Qt::CaseInsensitive) == 0) {
+ else if (decl.d->values.constFirst().variant.toString().compare("root"_L1, Qt::CaseInsensitive) == 0) {
isTextFrame = true;
isRootFrame = true;
}
break;
case QCss::QtUserState:
- userState = decl.d->values.first().variant.toInt();
+ userState = decl.d->values.constFirst().variant.toInt();
break;
case QCss::Whitespace:
switch (identifier) {
@@ -1401,10 +1380,10 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
setListStyle(decl.d->values);
break;
case QCss::QtListNumberPrefix:
- textListNumberPrefix = decl.d->values.first().variant.toString();
+ textListNumberPrefix = decl.d->values.constFirst().variant.toString();
break;
case QCss::QtListNumberSuffix:
- textListNumberSuffix = decl.d->values.first().variant.toString();
+ textListNumberSuffix = decl.d->values.constFirst().variant.toString();
break;
case QCss::TextAlignment:
switch (identifier) {
@@ -1419,12 +1398,36 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
{
if (resourceProvider != nullptr && QTextDocumentPrivate::get(resourceProvider) != nullptr) {
bool ok;
- qint64 searchKey = decl.d->values.first().variant.toLongLong(&ok);
+ qint64 searchKey = decl.d->values.constFirst().variant.toLongLong(&ok);
if (ok)
applyForegroundImage(searchKey, resourceProvider);
}
break;
}
+ case QCss::QtStrokeColor:
+ {
+ QPen pen = charFormat.textOutline();
+ pen.setStyle(Qt::SolidLine);
+ pen.setColor(decl.colorValue());
+ charFormat.setTextOutline(pen);
+ break;
+ }
+ case QCss::QtStrokeWidth:
+ {
+ qreal width;
+ if (decl.realValue(&width, "px")) {
+ QPen pen = charFormat.textOutline();
+ pen.setWidthF(width);
+ charFormat.setTextOutline(pen);
+ }
+ break;
+ }
+ case QCss::QtForeground:
+ {
+ QBrush brush = decl.brushValue();
+ charFormat.setForeground(brush);
+ break;
+ }
default: break;
}
}
@@ -1453,6 +1456,8 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
applyBackgroundImage(bgImage, resourceProvider);
} else if (bgBrush.style() != Qt::NoBrush) {
charFormat.setBackground(bgBrush);
+ if (id == Html_hr)
+ blockFormat.setProperty(QTextFormat::BackgroundBrush, bgBrush);
}
}
}
@@ -1523,7 +1528,7 @@ void QTextHtmlParserNode::applyBackgroundImage(const QString &url, const QTextDo
bool QTextHtmlParserNode::hasOnlyWhitespace() const
{
- for (int i = 0; i < text.count(); ++i)
+ for (int i = 0; i < text.size(); ++i)
if (!text.at(i).isSpace() || text.at(i) == QChar::LineSeparator)
return false;
return true;
@@ -1557,7 +1562,7 @@ static void setWidthAttribute(QTextLength *width, const QString &valueStr)
*width = QTextLength(QTextLength::FixedLength, realVal);
} else {
auto value = QStringView(valueStr).trimmed();
- if (!value.isEmpty() && value.endsWith(QLatin1Char('%'))) {
+ if (!value.isEmpty() && value.endsWith(u'%')) {
value.truncate(value.size() - 1);
realVal = value.toDouble(&ok);
if (ok)
@@ -1569,11 +1574,11 @@ static void setWidthAttribute(QTextLength *width, const QString &valueStr)
#ifndef QT_NO_CSSPARSER
void QTextHtmlParserNode::parseStyleAttribute(const QString &value, const QTextDocument *resourceProvider)
{
- const QString css = QLatin1String("* {") + value + QLatin1Char('}');
+ const QString css = "* {"_L1 + value + u'}';
QCss::Parser parser(css);
QCss::StyleSheet sheet;
parser.parse(&sheet, Qt::CaseInsensitive);
- if (sheet.styleRules.count() != 1) return;
+ if (sheet.styleRules.size() != 1) return;
applyCssDeclarations(sheet.styleRules.at(0).declarations, resourceProvider);
}
#endif
@@ -1584,14 +1589,14 @@ QStringList QTextHtmlParser::parseAttributes()
while (pos < len) {
eatSpace();
- if (hasPrefix(QLatin1Char('>')) || hasPrefix(QLatin1Char('/')))
+ if (hasPrefix(u'>') || hasPrefix(u'/'))
break;
QString key = parseWord().toLower();
- QString value = QLatin1String("1");
+ QString value = "1"_L1;
if (key.size() == 0)
break;
eatSpace();
- if (hasPrefix(QLatin1Char('='))){
+ if (hasPrefix(u'=')){
pos++;
eatSpace();
value = parseWord();
@@ -1611,35 +1616,34 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
QString linkHref;
QString linkType;
- if (attributes.count() % 2 == 1)
+ if (attributes.size() % 2 == 1)
return;
QTextHtmlParserNode *node = nodes.last();
- for (int i = 0; i < attributes.count(); i += 2) {
+ for (int i = 0; i < attributes.size(); i += 2) {
QString key = attributes.at(i);
QString value = attributes.at(i + 1);
switch (node->id) {
case Html_font:
// the infamous font tag
- if (key == QLatin1String("size") && value.size()) {
+ if (key == "size"_L1 && value.size()) {
int n = value.toInt();
- if (value.at(0) != QLatin1Char('+') && value.at(0) != QLatin1Char('-'))
+ if (value.at(0) != u'+' && value.at(0) != u'-')
n -= 3;
node->charFormat.setProperty(QTextFormat::FontSizeAdjustment, n);
- } else if (key == QLatin1String("face")) {
- if (value.contains(QLatin1Char(','))) {
- const QStringList values = value.split(QLatin1Char(','));
+ } else if (key == "face"_L1) {
+ if (value.contains(u',')) {
QStringList families;
- for (const QString &family : values)
- families << family.trimmed();
+ for (auto family : value.tokenize(u','))
+ families << family.trimmed().toString();
node->charFormat.setFontFamilies(families);
} else {
node->charFormat.setFontFamilies(QStringList(value));
}
- } else if (key == QLatin1String("color")) {
- QColor c; c.setNamedColor(value);
+ } else if (key == "color"_L1) {
+ QColor c = QColor::fromString(value);
if (!c.isValid())
qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
node->charFormat.setForeground(c);
@@ -1647,153 +1651,158 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
break;
case Html_ol:
case Html_ul:
- if (key == QLatin1String("type")) {
+ if (key == "type"_L1) {
node->hasOwnListStyle = true;
- if (value == QLatin1String("1")) {
+ if (value == "1"_L1) {
node->listStyle = QTextListFormat::ListDecimal;
- } else if (value == QLatin1String("a")) {
+ } else if (value == "a"_L1) {
node->listStyle = QTextListFormat::ListLowerAlpha;
- } else if (value == QLatin1String("A")) {
+ } else if (value == "A"_L1) {
node->listStyle = QTextListFormat::ListUpperAlpha;
- } else if (value == QLatin1String("i")) {
+ } else if (value == "i"_L1) {
node->listStyle = QTextListFormat::ListLowerRoman;
- } else if (value == QLatin1String("I")) {
+ } else if (value == "I"_L1) {
node->listStyle = QTextListFormat::ListUpperRoman;
} else {
value = std::move(value).toLower();
- if (value == QLatin1String("square"))
+ if (value == "square"_L1)
node->listStyle = QTextListFormat::ListSquare;
- else if (value == QLatin1String("disc"))
+ else if (value == "disc"_L1)
node->listStyle = QTextListFormat::ListDisc;
- else if (value == QLatin1String("circle"))
+ else if (value == "circle"_L1)
node->listStyle = QTextListFormat::ListCircle;
- else if (value == QLatin1String("none"))
+ else if (value == "none"_L1)
node->listStyle = QTextListFormat::ListStyleUndefined;
}
+ } else if (key == "start"_L1) {
+ setIntAttribute(&node->listStart, value);
+ }
+ break;
+ case Html_li:
+ if (key == "class"_L1) {
+ if (value == "unchecked"_L1)
+ node->blockFormat.setMarker(QTextBlockFormat::MarkerType::Unchecked);
+ else if (value == "checked"_L1)
+ node->blockFormat.setMarker(QTextBlockFormat::MarkerType::Checked);
}
break;
case Html_a:
- if (key == QLatin1String("href"))
+ if (key == "href"_L1)
node->charFormat.setAnchorHref(value);
- else if (key == QLatin1String("name"))
+ else if (key == "name"_L1)
node->charFormat.setAnchorNames({value});
break;
case Html_img:
- if (key == QLatin1String("src") || key == QLatin1String("source")) {
+ if (key == "src"_L1 || key == "source"_L1) {
node->imageName = value;
- } else if (key == QLatin1String("width")) {
+ } else if (key == "width"_L1) {
node->imageWidth = -2; // register that there is a value for it.
setFloatAttribute(&node->imageWidth, value);
- } else if (key == QLatin1String("height")) {
+ } else if (key == "height"_L1) {
node->imageHeight = -2; // register that there is a value for it.
setFloatAttribute(&node->imageHeight, value);
- } else if (key == QLatin1String("alt")) {
+ } else if (key == "alt"_L1) {
node->imageAlt = value;
- } else if (key == QLatin1String("title")) {
+ } else if (key == "title"_L1) {
node->text = value;
}
break;
case Html_tr:
case Html_body:
- if (key == QLatin1String("bgcolor")) {
- QColor c; c.setNamedColor(value);
+ if (key == "bgcolor"_L1) {
+ QColor c = QColor::fromString(value);
if (!c.isValid())
qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
node->charFormat.setBackground(c);
- } else if (key == QLatin1String("background")) {
+ } else if (key == "background"_L1) {
node->applyBackgroundImage(value, resourceProvider);
}
break;
case Html_th:
case Html_td:
- if (key == QLatin1String("width")) {
+ if (key == "width"_L1) {
setWidthAttribute(&node->width, value);
- } else if (key == QLatin1String("bgcolor")) {
- QColor c; c.setNamedColor(value);
+ } else if (key == "bgcolor"_L1) {
+ QColor c = QColor::fromString(value);
if (!c.isValid())
qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
node->charFormat.setBackground(c);
- } else if (key == QLatin1String("background")) {
+ } else if (key == "background"_L1) {
node->applyBackgroundImage(value, resourceProvider);
- } else if (key == QLatin1String("rowspan")) {
+ } else if (key == "rowspan"_L1) {
if (setIntAttribute(&node->tableCellRowSpan, value))
node->tableCellRowSpan = qMax(1, node->tableCellRowSpan);
- } else if (key == QLatin1String("colspan")) {
+ } else if (key == "colspan"_L1) {
if (setIntAttribute(&node->tableCellColSpan, value))
node->tableCellColSpan = qBound(1, node->tableCellColSpan, 20480);
}
break;
case Html_table:
- if (key == QLatin1String("border")) {
+ // If table border already set through css style, prefer that one otherwise consider this value
+ if (key == "border"_L1 && !node->tableBorder) {
setFloatAttribute(&node->tableBorder, value);
- } else if (key == QLatin1String("bgcolor")) {
- QColor c; c.setNamedColor(value);
+ } else if (key == "bgcolor"_L1) {
+ QColor c = QColor::fromString(value);
if (!c.isValid())
qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
node->charFormat.setBackground(c);
- } else if (key == QLatin1String("bordercolor")) {
- QColor c; c.setNamedColor(value);
+ } else if (key == "bordercolor"_L1) {
+ QColor c = QColor::fromString(value);
if (!c.isValid())
qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
node->borderBrush = c;
- } else if (key == QLatin1String("background")) {
+ } else if (key == "background"_L1) {
node->applyBackgroundImage(value, resourceProvider);
- } else if (key == QLatin1String("cellspacing")) {
+ } else if (key == "cellspacing"_L1) {
setFloatAttribute(&node->tableCellSpacing, value);
- } else if (key == QLatin1String("cellpadding")) {
+ } else if (key == "cellpadding"_L1) {
setFloatAttribute(&node->tableCellPadding, value);
- } else if (key == QLatin1String("width")) {
+ } else if (key == "width"_L1) {
setWidthAttribute(&node->width, value);
- } else if (key == QLatin1String("height")) {
+ } else if (key == "height"_L1) {
setWidthAttribute(&node->height, value);
}
break;
case Html_meta:
- if (key == QLatin1String("name")
- && value == QLatin1String("qrichtext")) {
+ if (key == "name"_L1 && value == "qrichtext"_L1)
seenQt3Richtext = true;
- }
-
- if (key == QLatin1String("content")
- && value == QLatin1String("1")
- && seenQt3Richtext) {
+ if (key == "content"_L1 && value == "1"_L1 && seenQt3Richtext)
textEditMode = true;
- }
break;
case Html_hr:
- if (key == QLatin1String("width"))
+ if (key == "width"_L1)
setWidthAttribute(&node->width, value);
break;
case Html_link:
- if (key == QLatin1String("href"))
+ if (key == "href"_L1)
linkHref = value;
- else if (key == QLatin1String("type"))
+ else if (key == "type"_L1)
linkType = value;
break;
case Html_pre:
- if (key == QLatin1String("class") && value.startsWith(QLatin1String("language-")))
+ if (key == "class"_L1 && value.startsWith("language-"_L1))
node->blockFormat.setProperty(QTextFormat::BlockCodeLanguage, value.mid(9));
break;
default:
break;
}
- if (key == QLatin1String("style")) {
+ if (key == "style"_L1) {
#ifndef QT_NO_CSSPARSER
node->parseStyleAttribute(value, resourceProvider);
#endif
- } else if (key == QLatin1String("align")) {
+ } else if (key == "align"_L1) {
value = std::move(value).toLower();
bool alignmentSet = true;
- if (value == QLatin1String("left"))
+ if (value == "left"_L1)
node->blockFormat.setAlignment(Qt::AlignLeft|Qt::AlignAbsolute);
- else if (value == QLatin1String("right"))
+ else if (value == "right"_L1)
node->blockFormat.setAlignment(Qt::AlignRight|Qt::AlignAbsolute);
- else if (value == QLatin1String("center"))
+ else if (value == "center"_L1)
node->blockFormat.setAlignment(Qt::AlignHCenter);
- else if (value == QLatin1String("justify"))
+ else if (value == "justify"_L1)
node->blockFormat.setAlignment(Qt::AlignJustify);
else
alignmentSet = false;
@@ -1805,36 +1814,36 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
node->cssFloat = QTextFrameFormat::FloatLeft;
else if (node->blockFormat.alignment() & Qt::AlignRight)
node->cssFloat = QTextFrameFormat::FloatRight;
- } else if (value == QLatin1String("middle")) {
+ } else if (value == "middle"_L1) {
node->charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
- } else if (value == QLatin1String("top")) {
+ } else if (value == "top"_L1) {
node->charFormat.setVerticalAlignment(QTextCharFormat::AlignTop);
}
}
- } else if (key == QLatin1String("valign")) {
+ } else if (key == "valign"_L1) {
value = std::move(value).toLower();
- if (value == QLatin1String("top"))
+ if (value == "top"_L1)
node->charFormat.setVerticalAlignment(QTextCharFormat::AlignTop);
- else if (value == QLatin1String("middle"))
+ else if (value == "middle"_L1)
node->charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle);
- else if (value == QLatin1String("bottom"))
+ else if (value == "bottom"_L1)
node->charFormat.setVerticalAlignment(QTextCharFormat::AlignBottom);
- } else if (key == QLatin1String("dir")) {
+ } else if (key == "dir"_L1) {
value = std::move(value).toLower();
- if (value == QLatin1String("ltr"))
+ if (value == "ltr"_L1)
node->blockFormat.setLayoutDirection(Qt::LeftToRight);
- else if (value == QLatin1String("rtl"))
+ else if (value == "rtl"_L1)
node->blockFormat.setLayoutDirection(Qt::RightToLeft);
- } else if (key == QLatin1String("title")) {
+ } else if (key == "title"_L1) {
node->charFormat.setToolTip(value);
- } else if (key == QLatin1String("id")) {
+ } else if (key == "id"_L1) {
node->charFormat.setAnchor(true);
node->charFormat.setAnchorNames({value});
}
}
#ifndef QT_NO_CSSPARSER
- if (resourceProvider && !linkHref.isEmpty() && linkType == QLatin1String("text/css"))
+ if (resourceProvider && !linkHref.isEmpty() && linkType == "text/css"_L1)
importStyleSheet(linkHref);
#endif
}
@@ -1846,14 +1855,14 @@ public:
inline QTextHtmlStyleSelector(const QTextHtmlParser *parser)
: parser(parser) { nameCaseSensitivity = Qt::CaseInsensitive; }
- virtual QStringList nodeNames(NodePtr node) const override;
- virtual QString attribute(NodePtr node, const QString &name) const override;
- virtual bool hasAttributes(NodePtr node) const override;
- virtual bool isNullNode(NodePtr node) const override;
- virtual NodePtr parentNode(NodePtr node) const override;
- virtual NodePtr previousSiblingNode(NodePtr node) const override;
- virtual NodePtr duplicateNode(NodePtr node) const override;
- virtual void freeNode(NodePtr node) const override;
+ QStringList nodeNames(NodePtr node) const override;
+ QString attributeValue(NodePtr node, const QCss::AttributeSelector &aSelector) const override;
+ bool hasAttributes(NodePtr node) const override;
+ bool isNullNode(NodePtr node) const override;
+ NodePtr parentNode(NodePtr node) const override;
+ NodePtr previousSiblingNode(NodePtr node) const override;
+ NodePtr duplicateNode(NodePtr node) const override;
+ void freeNode(NodePtr node) const override;
private:
const QTextHtmlParser *parser;
@@ -1877,10 +1886,10 @@ static inline int findAttribute(const QStringList &attributes, const QString &na
return idx;
}
-QString QTextHtmlStyleSelector::attribute(NodePtr node, const QString &name) const
+QString QTextHtmlStyleSelector::attributeValue(NodePtr node, const QCss::AttributeSelector &aSelector) const
{
const QStringList &attributes = parser->at(node.id).attributes;
- const int idx = findAttribute(attributes, name);
+ const int idx = findAttribute(attributes, aSelector.name);
if (idx == -1)
return QString();
return attributes.at(idx + 1);
@@ -1934,10 +1943,9 @@ void QTextHtmlStyleSelector::freeNode(NodePtr) const
void QTextHtmlParser::resolveStyleSheetImports(const QCss::StyleSheet &sheet)
{
- for (int i = 0; i < sheet.importRules.count(); ++i) {
+ for (int i = 0; i < sheet.importRules.size(); ++i) {
const QCss::ImportRule &rule = sheet.importRules.at(i);
- if (rule.media.isEmpty()
- || rule.media.contains(QLatin1String("screen"), Qt::CaseInsensitive))
+ if (rule.media.isEmpty() || rule.media.contains("screen"_L1, Qt::CaseInsensitive))
importStyleSheet(rule.href);
}
}
@@ -1946,7 +1954,7 @@ void QTextHtmlParser::importStyleSheet(const QString &href)
{
if (!resourceProvider)
return;
- for (int i = 0; i < externalStyleSheets.count(); ++i)
+ for (int i = 0; i < externalStyleSheets.size(); ++i)
if (externalStyleSheets.at(i).url == href)
return;
@@ -1977,15 +1985,15 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
case Html_u: {
bool needsUnderline = (node.id == Html_u) ? true : false;
if (node.id == Html_a) {
- for (int i = 0; i < node.attributes.count(); i += 2) {
+ for (int i = 0; i < node.attributes.size(); i += 2) {
const QString key = node.attributes.at(i);
- if (key.compare(QLatin1String("href"), Qt::CaseInsensitive) == 0
+ if (key.compare("href"_L1, Qt::CaseInsensitive) == 0
&& !node.attributes.at(i + 1).isEmpty()) {
needsUnderline = true;
- decl.d->property = QLatin1String("color");
+ decl.d->property = "color"_L1;
decl.d->propertyId = QCss::Color;
val.type = QCss::Value::Function;
- val.variant = QStringList() << QLatin1String("palette") << QLatin1String("link");
+ val.variant = QStringList() << "palette"_L1 << "link"_L1;
decl.d->values = QList<QCss::Value> { val };
decl.d->inheritable = true;
decls << decl;
@@ -1995,7 +2003,7 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
}
if (needsUnderline) {
decl = QCss::Declaration();
- decl.d->property = QLatin1String("text-decoration");
+ decl.d->property = "text-decoration"_L1;
decl.d->propertyId = QCss::TextDecoration;
val.type = QCss::Value::KnownIdentifier;
val.variant = QVariant(QCss::Value_Underline);
@@ -2014,7 +2022,7 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
case Html_h5:
case Html_th:
decl = QCss::Declaration();
- decl.d->property = QLatin1String("font-weight");
+ decl.d->property = "font-weight"_L1;
decl.d->propertyId = QCss::FontWeight;
val.type = QCss::Value::KnownIdentifier;
val.variant = QVariant(QCss::Value_Bold);
@@ -2028,7 +2036,7 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
case Html_small:
if (node.id != Html_th) {
decl = QCss::Declaration();
- decl.d->property = QLatin1String("font-size");
+ decl.d->property = "font-size"_L1;
decl.d->propertyId = QCss::FontSize;
decl.d->inheritable = false;
val.type = QCss::Value::KnownIdentifier;
@@ -2048,7 +2056,7 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
case Html_center:
case Html_td:
decl = QCss::Declaration();
- decl.d->property = QLatin1String("text-align");
+ decl.d->property = "text-align"_L1;
decl.d->propertyId = QCss::TextAlignment;
val.type = QCss::Value::KnownIdentifier;
val.variant = (node.id == Html_td) ? QVariant(QCss::Value_Left) : QVariant(QCss::Value_Center);
@@ -2058,7 +2066,7 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
break;
case Html_s:
decl = QCss::Declaration();
- decl.d->property = QLatin1String("text-decoration");
+ decl.d->property = "text-decoration"_L1;
decl.d->propertyId = QCss::TextDecoration;
val.type = QCss::Value::KnownIdentifier;
val.variant = QVariant(QCss::Value_LineThrough);
@@ -2073,7 +2081,7 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
case Html_var:
case Html_dfn:
decl = QCss::Declaration();
- decl.d->property = QLatin1String("font-style");
+ decl.d->property = "font-style"_L1;
decl.d->propertyId = QCss::FontStyle;
val.type = QCss::Value::KnownIdentifier;
val.variant = QVariant(QCss::Value_Italic);
@@ -2084,7 +2092,7 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
case Html_sub:
case Html_sup:
decl = QCss::Declaration();
- decl.d->property = QLatin1String("vertical-align");
+ decl.d->property = "vertical-align"_L1;
decl.d->propertyId = QCss::VerticalAlignment;
val.type = QCss::Value::KnownIdentifier;
val.variant = (node.id == Html_sub) ? QVariant(QCss::Value_Sub) : QVariant(QCss::Value_Super);
@@ -2095,7 +2103,7 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
case Html_ul:
case Html_ol:
decl = QCss::Declaration();
- decl.d->property = QLatin1String("list-style");
+ decl.d->property = "list-style"_L1;
decl.d->propertyId = QCss::ListStyle;
val.type = QCss::Value::KnownIdentifier;
val.variant = (node.id == Html_ul) ? QVariant(QCss::Value_Disc) : QVariant(QCss::Value_Decimal);
@@ -2109,11 +2117,11 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
case Html_samp:
case Html_pre: {
decl = QCss::Declaration();
- decl.d->property = QLatin1String("font-family");
+ decl.d->property = "font-family"_L1;
decl.d->propertyId = QCss::FontFamily;
QList<QCss::Value> values;
val.type = QCss::Value::String;
- val.variant = QFontDatabase::systemFont(QFontDatabase::FixedFont).families().first();
+ val.variant = QFontDatabase::systemFont(QFontDatabase::FixedFont).families().constFirst();
values << val;
decl.d->values = values;
decl.d->inheritable = true;
@@ -2125,7 +2133,7 @@ QList<QCss::Declaration> standardDeclarationForNode(const QTextHtmlParserNode &n
case Html_br:
case Html_nobr:
decl = QCss::Declaration();
- decl.d->property = QLatin1String("whitespace");
+ decl.d->property = "whitespace"_L1;
decl.d->propertyId = QCss::Whitespace;
val.type = QCss::Value::KnownIdentifier;
switch (node.id) {
@@ -2152,18 +2160,18 @@ QList<QCss::Declaration> QTextHtmlParser::declarationsForNode(int node) const
int idx = 0;
selector.styleSheets.resize((resourceProvider ? 1 : 0)
- + externalStyleSheets.count()
- + inlineStyleSheets.count());
+ + externalStyleSheets.size()
+ + inlineStyleSheets.size());
if (resourceProvider)
selector.styleSheets[idx++] = QTextDocumentPrivate::get(resourceProvider)->parsedDefaultStyleSheet;
- for (int i = 0; i < externalStyleSheets.count(); ++i, ++idx)
+ for (int i = 0; i < externalStyleSheets.size(); ++i, ++idx)
selector.styleSheets[idx] = externalStyleSheets.at(i).sheet;
- for (int i = 0; i < inlineStyleSheets.count(); ++i, ++idx)
+ for (int i = 0; i < inlineStyleSheets.size(); ++i, ++idx)
selector.styleSheets[idx] = inlineStyleSheets.at(i);
- selector.medium = QLatin1String("screen");
+ selector.medium = resourceProvider ? resourceProvider->metaInformation(QTextDocument::CssMedia) : "screen"_L1;
QCss::StyleSelector::NodePtr n;
n.id = node;
diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h
index 06bbc032a8..dd52baa23e 100644
--- a/src/gui/text/qtexthtmlparser_p.h
+++ b/src/gui/text/qtexthtmlparser_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTHTMLPARSER_P_H
#define QTEXTHTMLPARSER_P_H
@@ -62,7 +26,9 @@
#include "private/qtextformat_p.h"
#include "private/qtextdocument_p.h"
+#if QT_CONFIG(cssparser)
#include "private/qcssparser_p.h"
+#endif
#ifndef QT_NO_TEXTHTMLPARSER
@@ -184,6 +150,7 @@ struct QTextHtmlParserNode {
uint displayMode : 3; // QTextHtmlElement::DisplayMode
uint hasHref : 1;
QTextListFormat::Style listStyle;
+ int listStart = 1;
QString textListNumberPrefix;
QString textListNumberSuffix;
QString imageName;
@@ -288,8 +255,8 @@ public:
inline const QTextHtmlParserNode &at(int i) const { return *nodes.at(i); }
inline QTextHtmlParserNode &operator[](int i) { return *nodes[i]; }
- inline int count() const { return nodes.count(); }
- inline int last() const { return nodes.count()-1; }
+ inline int count() const { return nodes.size(); }
+ inline int last() const { return nodes.size()-1; }
int depth(int i) const;
int topMargin(int i) const;
int bottomMargin(int i) const;
@@ -309,7 +276,7 @@ public:
void parse(const QString &text, const QTextDocument *resourceProvider);
- static int lookupElement(const QString &element);
+ static int lookupElement(QStringView element);
Q_GUI_EXPORT static QString parseEntity(QStringView entity);
@@ -333,7 +300,9 @@ protected:
void applyAttributes(const QStringList &attributes);
void eatSpace();
inline bool hasPrefix(QChar c, int lookahead = 0) const
- {return pos + lookahead < len && txt.at(pos) == c; }
+ {
+ return pos + lookahead < len && txt.at(pos + lookahead) == c;
+ }
int margin(int i, int mar) const;
bool nodeIsChildOf(int i, QTextHTMLElements id) const;
diff --git a/src/gui/text/qtextimagehandler.cpp b/src/gui/text/qtextimagehandler.cpp
index 290aa256cb..5c56c30711 100644
--- a/src/gui/text/qtextimagehandler.cpp
+++ b/src/gui/text/qtextimagehandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextimagehandler_p.h"
@@ -51,142 +15,96 @@
QT_BEGIN_NAMESPACE
-extern QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio,
- qreal *sourceDevicePixelRatio);
+using namespace Qt::StringLiterals;
+
+static inline QString findAtNxFileOrResource(const QString &baseFileName,
+ qreal targetDevicePixelRatio,
+ qreal *sourceDevicePixelRatio)
+{
+ // qt_findAtNxFile expects a file name that can be tested with QFile::exists.
+ // so if the format.name() is a file:/ or qrc:/ URL, then we need to strip away the schema.
+ QString localFile;
+ const QUrl url(baseFileName);
+ if (url.isLocalFile())
+ localFile = url.toLocalFile();
+ else if (baseFileName.startsWith("qrc:/"_L1))
+ localFile = baseFileName.sliced(3);
+ else
+ localFile = baseFileName;
+ extern QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio,
+ qreal *sourceDevicePixelRatio);
+ return qt_findAtNxFile(localFile, targetDevicePixelRatio, sourceDevicePixelRatio);
+}
static inline QUrl fromLocalfileOrResources(QString path)
{
- if (path.startsWith(QLatin1String(":/"))) // auto-detect resources and convert them to url
- path.prepend(QLatin1String("qrc"));
+ if (path.startsWith(":/"_L1)) // auto-detect resources and convert them to url
+ path = path.prepend("qrc"_L1);
return QUrl(path);
}
-static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format, const qreal devicePixelRatio = 1.0)
+template<typename T>
+static T getAs(QTextDocument *doc, const QTextImageFormat &format, const qreal devicePixelRatio = 1.0)
{
qreal sourcePixelRatio = 1.0;
- const QString name = qt_findAtNxFile(format.name(), devicePixelRatio, &sourcePixelRatio);
+ const QString name = findAtNxFileOrResource(format.name(), devicePixelRatio, &sourcePixelRatio);
const QUrl url = fromLocalfileOrResources(name);
- QPixmap pm;
const QVariant data = doc->resource(QTextDocument::ImageResource, url);
- if (data.userType() == QMetaType::QPixmap || data.userType() == QMetaType::QImage) {
- pm = qvariant_cast<QPixmap>(data);
- } else if (data.userType() == QMetaType::QByteArray) {
- pm.loadFromData(data.toByteArray());
- }
-
- if (pm.isNull()) {
- QImage img;
- if (name.isEmpty() || !img.load(name))
- return QPixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"));
-
- pm = QPixmap::fromImage(img);
- doc->addResource(QTextDocument::ImageResource, url, pm);
+ T result;
+ if (data.userType() == QMetaType::QPixmap || data.userType() == QMetaType::QImage)
+ result = data.value<T>();
+ else if (data.metaType() == QMetaType::fromType<QByteArray>())
+ result.loadFromData(data.toByteArray());
+
+ if (result.isNull()) {
+ if (name.isEmpty() || !result.load(name))
+ return T(":/qt-project.org/styles/commonstyle/images/file-16.png"_L1);
+ doc->addResource(QTextDocument::ImageResource, url, result);
}
- if (name.contains(QLatin1String("@2x")))
- pm.setDevicePixelRatio(sourcePixelRatio);
-
- return pm;
+ if (sourcePixelRatio != 1.0)
+ result.setDevicePixelRatio(sourcePixelRatio);
+ return result;
}
-static QSize getPixmapSize(QTextDocument *doc, const QTextImageFormat &format)
+template<typename T>
+static QSize getSize(QTextDocument *doc, const QTextImageFormat &format)
{
- QPixmap pm;
-
const bool hasWidth = format.hasProperty(QTextFormat::ImageWidth);
const int width = qRound(format.width());
const bool hasHeight = format.hasProperty(QTextFormat::ImageHeight);
const int height = qRound(format.height());
+ T source;
QSize size(width, height);
if (!hasWidth || !hasHeight) {
- pm = getPixmap(doc, format);
- const int pmWidth = pm.width() / pm.devicePixelRatio();
- const int pmHeight = pm.height() / pm.devicePixelRatio();
+ source = getAs<T>(doc, format);
+ const QSizeF sourceSize = source.deviceIndependentSize();
if (!hasWidth) {
if (!hasHeight)
- size.setWidth(pmWidth);
+ size.setWidth(sourceSize.width());
else
- size.setWidth(qRound(height * (pmWidth / (qreal) pmHeight)));
+ size.setWidth(qRound(height * (sourceSize.width() / qreal(sourceSize.height()))));
}
if (!hasHeight) {
if (!hasWidth)
- size.setHeight(pmHeight);
+ size.setHeight(sourceSize.height());
else
- size.setHeight(qRound(width * (pmHeight / (qreal) pmWidth)));
+ size.setHeight(qRound(width * (sourceSize.height() / qreal(sourceSize.width()))));
}
}
qreal scale = 1.0;
QPaintDevice *pdev = doc->documentLayout()->paintDevice();
if (pdev) {
- if (pm.isNull())
- pm = getPixmap(doc, format);
- if (!pm.isNull())
- scale = qreal(pdev->logicalDpiY()) / qreal(qt_defaultDpi());
- }
- size *= scale;
-
- return size;
-}
-
-static QImage getImage(QTextDocument *doc, const QTextImageFormat &format, const qreal devicePixelRatio = 1.0)
-{
- qreal sourcePixelRatio = 1.0;
- const QString name = qt_findAtNxFile(format.name(), devicePixelRatio, &sourcePixelRatio);
- const QUrl url = fromLocalfileOrResources(name);
-
- QImage image;
- const QVariant data = doc->resource(QTextDocument::ImageResource, url);
- if (data.userType() == QMetaType::QImage) {
- image = qvariant_cast<QImage>(data);
- } else if (data.userType() == QMetaType::QByteArray) {
- image.loadFromData(data.toByteArray());
- }
-
- if (image.isNull()) {
- if (name.isEmpty() || !image.load(name))
- return QImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/file-16.png"));
-
- doc->addResource(QTextDocument::ImageResource, url, image);
- }
-
- if (sourcePixelRatio != 1.0)
- image.setDevicePixelRatio(sourcePixelRatio);
-
- return image;
-}
-
-static QSize getImageSize(QTextDocument *doc, const QTextImageFormat &format)
-{
- QImage image;
-
- const bool hasWidth = format.hasProperty(QTextFormat::ImageWidth);
- const int width = qRound(format.width());
- const bool hasHeight = format.hasProperty(QTextFormat::ImageHeight);
- const int height = qRound(format.height());
-
- QSize size(width, height);
- if (!hasWidth || !hasHeight) {
- image = getImage(doc, format);
- if (!hasWidth)
- size.setWidth(image.width() / image.devicePixelRatio());
- if (!hasHeight)
- size.setHeight(image.height() / image.devicePixelRatio());
- }
-
- qreal scale = 1.0;
- QPaintDevice *pdev = doc->documentLayout()->paintDevice();
- if (pdev) {
- if (image.isNull())
- image = getImage(doc, format);
- if (!image.isNull())
+ if (source.isNull())
+ source = getAs<T>(doc, format);
+ if (!source.isNull())
scale = qreal(pdev->logicalDpiY()) / qreal(qt_defaultDpi());
}
size *= scale;
-
return size;
}
@@ -201,15 +119,15 @@ QSizeF QTextImageHandler::intrinsicSize(QTextDocument *doc, int posInDocument, c
const QTextImageFormat imageFormat = format.toImageFormat();
if (QCoreApplication::instance()->thread() != QThread::currentThread())
- return getImageSize(doc, imageFormat);
- return getPixmapSize(doc, imageFormat);
+ return getSize<QImage>(doc, imageFormat);
+ return getSize<QPixmap>(doc, imageFormat);
}
QImage QTextImageHandler::image(QTextDocument *doc, const QTextImageFormat &imageFormat)
{
Q_ASSERT(doc != nullptr);
- return getImage(doc, imageFormat);
+ return getAs<QImage>(doc, imageFormat);
}
void QTextImageHandler::drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format)
@@ -218,12 +136,14 @@ void QTextImageHandler::drawObject(QPainter *p, const QRectF &rect, QTextDocumen
const QTextImageFormat imageFormat = format.toImageFormat();
if (QCoreApplication::instance()->thread() != QThread::currentThread()) {
- const QImage image = getImage(doc, imageFormat, p->device()->devicePixelRatio());
+ const QImage image = getAs<QImage>(doc, imageFormat, p->device()->devicePixelRatio());
p->drawImage(rect, image, image.rect());
} else {
- const QPixmap pixmap = getPixmap(doc, imageFormat, p->device()->devicePixelRatio());
+ const QPixmap pixmap = getAs<QPixmap>(doc, imageFormat, p->device()->devicePixelRatio());
p->drawPixmap(rect, pixmap, pixmap.rect());
}
}
QT_END_NAMESPACE
+
+#include "moc_qtextimagehandler_p.cpp"
diff --git a/src/gui/text/qtextimagehandler_p.h b/src/gui/text/qtextimagehandler_p.h
index fafd394ad3..d28f474c67 100644
--- a/src/gui/text/qtextimagehandler_p.h
+++ b/src/gui/text/qtextimagehandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTIMAGEHANDLER_P_H
#define QTEXTIMAGEHANDLER_P_H
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 70e6043231..f0c7dd24e5 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextlayout.h"
#include "qtextengine_p.h"
@@ -85,7 +49,7 @@ QT_BEGIN_NAMESPACE
/*!
\variable QTextLayout::FormatRange::length
- Specifies the numer of characters the format range spans.
+ Specifies the number of characters the format range spans.
*/
/*!
@@ -301,6 +265,10 @@ Qt::LayoutDirection QTextInlineObject::textDirection() const
The text can then be rendered by calling the layout's draw() function:
\snippet code/src_gui_text_qtextlayout.cpp 1
+ It is also possible to draw each line individually, for instance to draw
+ the last line that fits into a widget elided:
+ \snippet code/src_gui_text_qtextlayout.cpp elided
+
For a given position in the text you can find a valid cursor position with
isValidCursorPosition(), nextCursorPosition(), and previousCursorPosition().
@@ -318,6 +286,26 @@ Qt::LayoutDirection QTextInlineObject::textDirection() const
*/
/*!
+ \enum QTextLayout::GlyphRunRetrievalFlag
+ \since 6.5
+
+ GlyphRunRetrievalFlag specifies flags passed to the glyphRuns() functions to determine
+ which properties of the layout are returned in the QGlyphRun objects. Since each property
+ will consume memory and may require additional allocations, it is a good practice to only
+ request the properties you will need to access later.
+
+ \value RetrieveGlyphIndexes Retrieves the indexes in the font which correspond to the glyphs.
+ \value RetrieveGlyphPositions Retrieves the relative positions of the glyphs in the layout.
+ \value RetrieveStringIndexes Retrieves the indexes in the original string that correspond to
+ each of the glyphs.
+ \value RetrieveString Retrieves the original source string from the layout.
+ \value RetrieveAll Retrieves all available properties of the layout.
+ \omitvalue DefaultRetrievalFlags
+
+ \sa glyphRuns(), QTextLine::glyphRuns()
+*/
+
+/*!
\fn QTextEngine *QTextLayout::engine() const
\internal
@@ -663,8 +651,8 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
{
const QCharAttributes *attributes = d->attributes();
int len = d->block.isValid() ? d->block.length() - 1
- : d->layoutData->string.length();
- Q_ASSERT(len <= d->layoutData->string.length());
+ : d->layoutData->string.size();
+ Q_ASSERT(len <= d->layoutData->string.size());
if (!attributes || oldPos < 0 || oldPos >= len)
return oldPos;
@@ -699,8 +687,8 @@ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const
{
const QCharAttributes *attributes = d->attributes();
int len = d->block.isValid() ? d->block.length() - 1
- : d->layoutData->string.length();
- Q_ASSERT(len <= d->layoutData->string.length());
+ : d->layoutData->string.size();
+ Q_ASSERT(len <= d->layoutData->string.size());
if (!attributes || oldPos <= 0 || oldPos > len)
return oldPos;
@@ -753,7 +741,7 @@ int QTextLayout::leftCursorPosition(int oldPos) const
return newPos;
}
-/*!/
+/*!
Returns \c true if position \a pos is a valid cursor position.
In a Unicode context some positions in the text are not valid
@@ -763,7 +751,7 @@ int QTextLayout::leftCursorPosition(int oldPos) const
A grapheme cluster is a sequence of two or more Unicode characters
that form one indivisible entity on the screen. For example the
latin character `\unicode{0xC4}' can be represented in Unicode by two
- characters, `A' (0x41), and the combining diaresis (0x308). A text
+ characters, `A' (0x41), and the combining diaeresis (0x308). A text
cursor can only validly be positioned before or after these two
characters, never between them since that wouldn't make sense. In
indic languages every syllable forms a grapheme cluster.
@@ -771,7 +759,7 @@ int QTextLayout::leftCursorPosition(int oldPos) const
bool QTextLayout::isValidCursorPosition(int pos) const
{
const QCharAttributes *attributes = d->attributes();
- if (!attributes || pos < 0 || pos > (int)d->layoutData->string.length())
+ if (!attributes || pos < 0 || pos > (int)d->layoutData->string.size())
return false;
return attributes[pos].graphemeBoundary;
}
@@ -812,7 +800,7 @@ QTextLine QTextLayout::createLine()
}
}
int from = l > 0 ? d->lines.at(l-1).from + d->lines.at(l-1).length + d->lines.at(l-1).trailingSpaces : 0;
- int strlen = d->layoutData->string.length();
+ int strlen = d->layoutData->string.size();
if (l && from >= strlen) {
if (!d->lines.at(l-1).length || d->layoutData->string.at(strlen - 1) != QChar::LineSeparator)
return QTextLine();
@@ -997,7 +985,9 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip)
}
+#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
/*!
+ \overload
Returns the glyph indexes and positions for all glyphs corresponding to the \a length characters
starting at the position \a from in this QTextLayout. This is an expensive function, and should
not be called in a time sensitive context.
@@ -1005,27 +995,57 @@ static inline QRectF clipIfValid(const QRectF &rect, const QRectF &clip)
If \a from is less than zero, then the glyph run will begin at the first character in the
layout. If \a length is less than zero, it will span the entire string from the start position.
+ \note This is equivalent to calling
+ glyphRuns(from,
+ length,
+ QTextLayout::GlyphRunRetrievalFlag::GlyphIndexes |
+ QTextLayout::GlyphRunRetrievalFlag::GlyphPositions).
+
\since 4.8
\sa draw(), QPainter::drawGlyphRun()
*/
-#if !defined(QT_NO_RAWFONT)
+# if !defined(QT_NO_RAWFONT)
QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const
{
+ return glyphRuns(from, length, QTextLayout::GlyphRunRetrievalFlag::DefaultRetrievalFlags);
+}
+# endif
+#endif
+
+/*!
+ \overload
+ Returns the glyph indexes and positions for all glyphs corresponding to the \a length characters
+ starting at the position \a from in this QTextLayout. This is an expensive function, and should
+ not be called in a time sensitive context.
+
+ If \a from is less than zero, then the glyph run will begin at the first character in the
+ layout. If \a length is less than zero, it will span the entire string from the start position.
+
+ The \a retrievalFlags specifies which properties of the QGlyphRun will be retrieved from the
+ layout. To minimize allocations and memory consumption, this should be set to include only the
+ properties that you need to access later.
+
+ \since 6.5
+ \sa draw(), QPainter::drawGlyphRun()
+*/
+#if !defined(QT_NO_RAWFONT)
+QList<QGlyphRun> QTextLayout::glyphRuns(int from,
+ int length,
+ QTextLayout::GlyphRunRetrievalFlags retrievalFlags) const
+{
if (from < 0)
from = 0;
if (length < 0)
- length = text().length();
+ length = text().size();
QHash<QPair<QFontEngine *, int>, QGlyphRun> glyphRunHash;
for (int i=0; i<d->lines.size(); ++i) {
if (d->lines.at(i).from > from + length)
break;
- else if (d->lines.at(i).from + d->lines[i].length >= from) {
- QList<QGlyphRun> glyphRuns = QTextLine(i, d).glyphRuns(from, length);
-
- for (int j = 0; j < glyphRuns.size(); j++) {
- const QGlyphRun &glyphRun = glyphRuns.at(j);
+ else if (d->lines.at(i).from + d->lines.at(i).length >= from) {
+ const QList<QGlyphRun> glyphRuns = QTextLine(i, d).glyphRuns(from, length, retrievalFlags);
+ for (const QGlyphRun &glyphRun : glyphRuns) {
QRawFont rawFont = glyphRun.rawFont();
QFontEngine *fontEngine = rawFont.d->fontEngine;
@@ -1038,14 +1058,17 @@ QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const
} else {
QList<quint32> indexes = oldGlyphRun.glyphIndexes();
QList<QPointF> positions = oldGlyphRun.positions();
+ QList<qsizetype> stringIndexes = oldGlyphRun.stringIndexes();
QRectF boundingRect = oldGlyphRun.boundingRect();
indexes += glyphRun.glyphIndexes();
positions += glyphRun.positions();
+ stringIndexes += glyphRun.stringIndexes();
boundingRect = boundingRect.united(glyphRun.boundingRect());
oldGlyphRun.setGlyphIndexes(indexes);
oldGlyphRun.setPositions(positions);
+ oldGlyphRun.setStringIndexes(stringIndexes);
oldGlyphRun.setBoundingRect(boundingRect);
}
}
@@ -1081,7 +1104,6 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QList<FormatRange>
int firstLine = 0;
int lastLine = d->lines.size();
for (int i = 0; i < d->lines.size(); ++i) {
- QTextLine l(i, d);
const QScriptLine &sl = d->lines.at(i);
if (sl.y > clipe) {
@@ -1108,6 +1130,7 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QList<FormatRange>
QRectF lineRect(tl.naturalTextRect());
lineRect.translate(position);
lineRect.adjust(0, 0, d->leadingSpaceWidth(sl).toReal(), 0);
+ lineRect.setBottom(qCeil(lineRect.bottom()));
bool isLastLineInBlock = (line == d->lines.size()-1);
int sl_length = sl.length + (isLastLineInBlock? 1 : 0); // the infamous newline
@@ -1129,6 +1152,7 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QList<FormatRange>
QRectF fullLineRect(tl.rect());
fullLineRect.translate(position);
fullLineRect.setRight(QFIXED_MAX);
+ fullLineRect.setBottom(qCeil(fullLineRect.bottom()));
const bool rightToLeft = d->isRightToLeft();
@@ -1266,7 +1290,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
QPointF position = pos + d->position;
- cursorPosition = qBound(0, cursorPosition, d->layoutData->string.length());
+ cursorPosition = qBound(0, cursorPosition, d->layoutData->string.size());
int line = d->lineNumberForTextPosition(cursorPosition);
if (line < 0)
line = 0;
@@ -1278,27 +1302,46 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
qreal x = position.x() + l.cursorToX(cursorPosition);
- int itm;
+ QFixed base = sl.base();
+ QFixed descent = sl.descent;
+ bool rightToLeft = d->isRightToLeft();
+ const int realCursorPosition = cursorPosition;
if (d->visualCursorMovement()) {
if (cursorPosition == sl.from + sl.length)
- cursorPosition--;
- itm = d->findItem(cursorPosition);
- } else
- itm = d->findItem(cursorPosition - 1);
+ --cursorPosition;
+ } else {
+ --cursorPosition;
+ }
+ int itm = d->findItem(cursorPosition);
- QFixed base = sl.base();
- QFixed descent = sl.descent;
- bool rightToLeft = d->isRightToLeft();
if (itm >= 0) {
- const QScriptItem &si = d->layoutData->items.at(itm);
- if (si.ascent >= 0)
- base = si.ascent;
- if (si.descent >= 0)
- descent = si.descent;
- rightToLeft = si.analysis.bidiLevel % 2;
+ const QScriptItem *si = &d->layoutData->items.at(itm);
+ // Same logic as in cursorToX to handle edges between writing directions to prioritise the script item
+ // that matches the writing direction of the paragraph.
+ if (d->layoutData->hasBidi && !d->visualCursorMovement() && si->analysis.bidiLevel % 2 != rightToLeft) {
+ int neighborItem = itm;
+ if (neighborItem > 0 && si->position == realCursorPosition)
+ --neighborItem;
+ else if (neighborItem < d->layoutData->items.size() - 1 && si->position + si->num_glyphs == realCursorPosition)
+ ++neighborItem;
+ const bool onBoundary = neighborItem != itm
+ && si->analysis.bidiLevel != d->layoutData->items[neighborItem].analysis.bidiLevel;
+ if (onBoundary && rightToLeft != si->analysis.bidiLevel % 2) {
+ itm = neighborItem;
+ si = &d->layoutData->items[itm];
+ }
+ }
+ // objects need some special treatment as they can have special alignment or be floating
+ if (si->analysis.flags != QScriptAnalysis::Object) {
+ if (si->ascent > 0)
+ base = si->ascent;
+ if (si->descent > 0)
+ descent = si->descent;
+ }
+ rightToLeft = si->analysis.bidiLevel % 2;
}
- qreal y = position.y() + (sl.y + sl.base() + sl.descent - base - descent).toReal();
+ qreal y = position.y() + (sl.y + sl.base() - base).toReal();
bool toggleAntialiasing = !(p->renderHints() & QPainter::Antialiasing)
&& (p->transform().type() > QTransform::TxTranslate);
if (toggleAntialiasing)
@@ -1306,7 +1349,20 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
QPainter::CompositionMode origCompositionMode = p->compositionMode();
if (p->paintEngine()->hasFeature(QPaintEngine::RasterOpModes))
p->setCompositionMode(QPainter::RasterOp_NotDestination);
- p->fillRect(QRectF(x, y, qreal(width), (base + descent).toReal()), p->pen().brush());
+ const QTransform &deviceTransform = p->deviceTransform();
+ const qreal xScale = deviceTransform.m11();
+ if (deviceTransform.type() != QTransform::TxScale || std::trunc(xScale) == xScale) {
+ p->fillRect(QRectF(x, y, qreal(width), (base + descent).toReal()), p->pen().brush());
+ } else {
+ // Ensure consistently rendered cursor width under fractional scaling
+ const QPen origPen = p->pen();
+ QPen pen(origPen.brush(), qRound(width * xScale), Qt::SolidLine, Qt::FlatCap);
+ pen.setCosmetic(true);
+ const qreal center = x + qreal(width) / 2;
+ p->setPen(pen);
+ p->drawLine(QPointF(center, y), QPointF(center, qCeil(y + (base + descent).toReal())));
+ p->setPen(origPen);
+ }
p->setCompositionMode(origCompositionMode);
if (toggleAntialiasing)
p->setRenderHint(QPainter::Antialiasing, false);
@@ -1556,13 +1612,10 @@ void QTextLine::setLineWidth(qreal width)
return;
}
- if (width > QFIXED_MAX)
- width = QFIXED_MAX;
-
- line.width = QFixed::fromReal(width);
+ line.width = QFixed::fromReal(qBound(0.0, width, qreal(QFIXED_MAX)));
if (line.length
&& line.textWidth <= line.width
- && line.from + line.length == eng->layoutData->string.length())
+ && line.from + line.length == eng->layoutData->string.size())
// no need to do anything if the line is already layouted and the last one. This optimization helps
// when using things in a single line layout.
return;
@@ -1599,7 +1652,7 @@ void QTextLine::setNumColumns(int numColumns)
void QTextLine::setNumColumns(int numColumns, qreal alignmentWidth)
{
QScriptLine &line = eng->lines[index];
- line.width = QFixed::fromReal(alignmentWidth);
+ line.width = QFixed::fromReal(qBound(0.0, alignmentWidth, qreal(QFIXED_MAX)));
line.length = 0;
line.textWidth = 0;
layout_helper(numColumns);
@@ -1615,23 +1668,18 @@ namespace {
struct LineBreakHelper
{
- LineBreakHelper()
- : glyphCount(0), maxGlyphs(0), currentPosition(0), fontEngine(nullptr), logClusters(nullptr),
- manualWrap(false), whiteSpaceOrObject(true)
- {
- }
-
+ LineBreakHelper() = default;
QScriptLine tmpData;
QScriptLine spaceData;
QGlyphLayout glyphs;
- int glyphCount;
- int maxGlyphs;
- int currentPosition;
- glyph_t previousGlyph;
- QFontEngine *previousGlyphFontEngine;
+ int glyphCount = 0;
+ int maxGlyphs = 0;
+ int currentPosition = 0;
+ glyph_t previousGlyph = 0;
+ QExplicitlySharedDataPointer<QFontEngine> previousGlyphFontEngine;
QFixed minw;
QFixed currentSoftHyphenWidth;
@@ -1639,11 +1687,11 @@ namespace {
QFixed rightBearing;
QFixed minimumRightBearing;
- QFontEngine *fontEngine;
- const unsigned short *logClusters;
+ QExplicitlySharedDataPointer<QFontEngine> fontEngine;
+ const unsigned short *logClusters = nullptr;
- bool manualWrap;
- bool whiteSpaceOrObject;
+ bool manualWrap = false;
+ bool whiteSpaceOrObject = true;
bool checkFullOtherwiseExtend(QScriptLine &line);
@@ -1687,13 +1735,13 @@ namespace {
{
if (currentPosition <= 0)
return;
- calculateRightBearing(fontEngine, currentGlyph());
+ calculateRightBearing(fontEngine.data(), currentGlyph());
}
inline void calculateRightBearingForPreviousGlyph()
{
if (previousGlyph > 0)
- calculateRightBearing(previousGlyphFontEngine, previousGlyph);
+ calculateRightBearing(previousGlyphFontEngine.data(), previousGlyph);
}
static const QFixed RightBearingNotCalculated;
@@ -1714,7 +1762,7 @@ namespace {
}
};
-const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1);
+Q_CONSTINIT const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1);
inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
{
@@ -1778,12 +1826,12 @@ void QTextLine::layout_helper(int maxGlyphs)
line.textWidth = 0;
line.hasTrailingSpaces = false;
- if (!eng->layoutData->items.size() || line.from >= eng->layoutData->string.length()) {
+ if (!eng->layoutData->items.size() || line.from >= eng->layoutData->string.size()) {
line.setDefaultHeight(eng);
return;
}
- Q_ASSERT(line.from < eng->layoutData->string.length());
+ Q_ASSERT(line.from < eng->layoutData->string.size());
LineBreakHelper lbh;
@@ -1810,6 +1858,7 @@ void QTextLine::layout_helper(int maxGlyphs)
lbh.logClusters = eng->layoutData->logClustersPtr;
lbh.previousGlyph = 0;
+ bool manuallyWrapped = false;
bool hasInlineObject = false;
QFixed maxInlineObjectHeight = 0;
@@ -1885,6 +1934,7 @@ void QTextLine::layout_helper(int maxGlyphs)
lbh.calculateRightBearingForPreviousGlyph();
}
line += lbh.tmpData;
+ manuallyWrapped = true;
goto found;
} else if (current.analysis.flags == QScriptAnalysis::Object) {
lbh.whiteSpaceOrObject = true;
@@ -1919,12 +1969,10 @@ void QTextLine::layout_helper(int maxGlyphs)
addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount,
current, lbh.logClusters, lbh.glyphs);
}
-
- if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) {
- lbh.spaceData.textWidth = line.width; // ignore spaces that fall out of the line.
- goto found;
- }
} else {
+ if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width)
+ goto found;
+
lbh.whiteSpaceOrObject = false;
bool sb_or_ws = false;
lbh.saveCurrentGlyph();
@@ -1938,11 +1986,11 @@ void QTextLine::layout_helper(int maxGlyphs)
// spaces to behave as in previous Qt versions in the line breaking algorithm.
// The line breaks do not currently follow the Unicode specs, but fixing this would
// require refactoring the code and would cause behavioral regressions.
- bool isBreakableSpace = lbh.currentPosition < eng->layoutData->string.length()
+ const bool isBreakableSpace = lbh.currentPosition < eng->layoutData->string.size()
&& attributes[lbh.currentPosition].whiteSpace
&& eng->layoutData->string.at(lbh.currentPosition).decompositionTag() != QChar::NoBreak;
- if (lbh.currentPosition >= eng->layoutData->string.length()
+ if (lbh.currentPosition >= eng->layoutData->string.size()
|| isBreakableSpace
|| attributes[lbh.currentPosition].lineBreak
|| lbh.tmpData.textWidth >= QFIXED_MAX) {
@@ -1999,7 +2047,7 @@ void QTextLine::layout_helper(int maxGlyphs)
// and when we then end up breaking on the next glyph we compute the right bearing
// and end up with a line width that is slightly larger width than what was requested.
// Unfortunately we can't remove this optimization as it will slow down text
- // layouting significantly, so we accept the slight correctnes issue.
+ // layouting significantly, so we accept the slight correctness issue.
if ((lbh.calculateNewWidth(line) + qAbs(lbh.minimumRightBearing)) > line.width)
lbh.calculateRightBearing();
@@ -2107,12 +2155,17 @@ found:
eng->maxWidth = qMax(eng->maxWidth, line.textWidth);
} else {
eng->minWidth = qMax(eng->minWidth, lbh.minw);
- eng->maxWidth += line.textWidth;
+ if (qAddOverflow(eng->layoutData->currentMaxWidth, line.textWidth, &eng->layoutData->currentMaxWidth))
+ eng->layoutData->currentMaxWidth = QFIXED_MAX;
+ if (!manuallyWrapped) {
+ if (qAddOverflow(eng->layoutData->currentMaxWidth, lbh.spaceData.textWidth, &eng->layoutData->currentMaxWidth))
+ eng->layoutData->currentMaxWidth = QFIXED_MAX;
+ }
+ eng->maxWidth = qMax(eng->maxWidth, eng->layoutData->currentMaxWidth);
+ if (manuallyWrapped)
+ eng->layoutData->currentMaxWidth = 0;
}
- if (line.textWidth > 0 && item < eng->layoutData->items.size())
- eng->maxWidth += lbh.spaceData.textWidth;
-
line.textWidth += trailingSpace;
if (lbh.spaceData.length) {
line.trailingSpaces = lbh.spaceData.length;
@@ -2164,35 +2217,37 @@ int QTextLine::textStart() const
int QTextLine::textLength() const
{
if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators
- && eng->block.isValid() && index == eng->lines.count()-1) {
+ && eng->block.isValid() && index == eng->lines.size()-1) {
return eng->lines.at(index).length - 1;
}
return eng->lines.at(index).length + eng->lines.at(index).trailingSpaces;
}
-static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const QTextCharFormat &chf, const QRectF &r)
+static void drawBackground(QPainter *p, const QTextCharFormat &chf, const QRectF &r)
{
- QBrush c = chf.foreground();
- if (c.style() == Qt::NoBrush) {
- p->setPen(defaultPen);
- }
-
QBrush bg = chf.background();
if (bg.style() != Qt::NoBrush && !chf.property(SuppressBackground).toBool())
p->fillRect(r.toAlignedRect(), bg);
- if (c.style() != Qt::NoBrush) {
- p->setPen(QPen(c, 0));
- }
+}
+static void setPen(QPainter *p, const QPen &defaultPen, const QTextCharFormat &chf)
+{
+ QBrush c = chf.foreground();
+ if (c.style() == Qt::NoBrush)
+ p->setPen(defaultPen);
+ else
+ p->setPen(QPen(c, 0));
}
#if !defined(QT_NO_RAWFONT)
static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine,
+ const QString &text,
const QGlyphLayout &glyphLayout,
const QPointF &pos,
const QGlyphRun::GlyphRunFlags &flags,
- const QFixed &selectionX,
- const QFixed &selectionWidth,
+ QTextLayout::GlyphRunRetrievalFlags retrievalFlags,
+ QFixed selectionX,
+ QFixed selectionWidth,
int glyphsStart,
int glyphsEnd,
unsigned short *logClusters,
@@ -2206,14 +2261,15 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine,
QGlyphRunPrivate *d = QGlyphRunPrivate::get(glyphRun);
int rangeStart = textPosition;
- while (*logClusters != glyphsStart && rangeStart < textPosition + textLength) {
- ++logClusters;
+ int logClusterIndex = 0;
+ while (logClusters[logClusterIndex] != glyphsStart && rangeStart < textPosition + textLength) {
+ ++logClusterIndex;
++rangeStart;
}
int rangeEnd = rangeStart;
- while (*logClusters != glyphsEnd && rangeEnd < textPosition + textLength) {
- ++logClusters;
+ while (logClusters[logClusterIndex] != glyphsEnd && rangeEnd < textPosition + textLength) {
+ ++logClusterIndex;
++rangeEnd;
}
@@ -2246,14 +2302,43 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine,
qreal minY = 0;
qreal maxY = 0;
QList<quint32> glyphs;
- glyphs.reserve(glyphsArray.size());
+ if (retrievalFlags & QTextLayout::RetrieveGlyphIndexes)
+ glyphs.reserve(glyphsArray.size());
QList<QPointF> positions;
- positions.reserve(glyphsArray.size());
- for (int i=0; i<glyphsArray.size(); ++i) {
- glyphs.append(glyphsArray.at(i) & 0xffffff);
+ if (retrievalFlags & QTextLayout::RetrieveGlyphPositions)
+ positions.reserve(glyphsArray.size());
+ QList<qsizetype> stringIndexes;
+ if (retrievalFlags & QTextLayout::RetrieveStringIndexes)
+ stringIndexes.reserve(glyphsArray.size());
+
+ int nextClusterIndex = 0;
+ int currentClusterIndex = 0;
+ for (int i = 0; i < glyphsArray.size(); ++i) {
+ const int glyphArrayIndex = i + glyphsStart;
+ // Search for the next cluster in the string (or the end of string if there are no
+ // more clusters)
+ if (retrievalFlags & QTextLayout::RetrieveStringIndexes) {
+ if (nextClusterIndex < textLength && logClusters[nextClusterIndex] == glyphArrayIndex) {
+ currentClusterIndex = nextClusterIndex; // Store current cluster
+ while (logClusters[nextClusterIndex] == glyphArrayIndex && nextClusterIndex < textLength)
+ ++nextClusterIndex;
+ }
+
+ // We are now either at end of string (no more clusters) or we are not yet at the
+ // next cluster in glyph array. We fill in current cluster so that there is always one
+ // entry in stringIndexes for each glyph.
+ Q_ASSERT(nextClusterIndex == textLength || logClusters[nextClusterIndex] != glyphArrayIndex);
+ stringIndexes.append(textPosition + currentClusterIndex);
+ }
+
+ if (retrievalFlags & QTextLayout::RetrieveGlyphIndexes) {
+ glyph_t glyphIndex = glyphsArray.at(i) & 0xffffff;
+ glyphs.append(glyphIndex);
+ }
QPointF position = positionsArray.at(i).toPointF() + pos;
- positions.append(position);
+ if (retrievalFlags & QTextLayout::RetrieveGlyphPositions)
+ positions.append(position);
if (i == 0) {
maxY = minY = position.y();
@@ -2265,8 +2350,14 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine,
qreal height = maxY + fontHeight - minY;
- glyphRun.setGlyphIndexes(glyphs);
- glyphRun.setPositions(positions);
+ if (retrievalFlags & QTextLayout::RetrieveGlyphIndexes)
+ glyphRun.setGlyphIndexes(glyphs);
+ if (retrievalFlags & QTextLayout::RetrieveGlyphPositions)
+ glyphRun.setPositions(positions);
+ if (retrievalFlags & QTextLayout::RetrieveStringIndexes)
+ glyphRun.setStringIndexes(stringIndexes);
+ if (retrievalFlags & QTextLayout::RetrieveString)
+ glyphRun.setSourceString(text);
glyphRun.setFlags(flags);
glyphRun.setRawFont(font);
@@ -2276,7 +2367,9 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine,
return glyphRun;
}
+# if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
/*!
+ \overload
Returns the glyph indexes and positions for all glyphs in this QTextLine for characters
in the range defined by \a from and \a length. The \a from index is relative to the beginning
of the text in the containing QTextLayout, and the range must be within the range of QTextLine
@@ -2285,12 +2378,43 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine,
If \a from is negative, it will default to textStart(), and if \a length is negative it will
default to the return value of textLength().
+ \note This is equivalent to calling
+ glyphRuns(from,
+ length,
+ QTextLayout::GlyphRunRetrievalFlag::GlyphIndexes |
+ QTextLayout::GlyphRunRetrievalFlag::GlyphPositions).
+
\since 5.0
\sa QTextLayout::glyphRuns()
*/
QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
{
+ return glyphRuns(from, length, QTextLayout::GlyphRunRetrievalFlag::DefaultRetrievalFlags);
+}
+# endif
+
+/*!
+ Returns the glyph indexes and positions for all glyphs in this QTextLine for characters
+ in the range defined by \a from and \a length. The \a from index is relative to the beginning
+ of the text in the containing QTextLayout, and the range must be within the range of QTextLine
+ as given by functions textStart() and textLength().
+
+ The \a retrievalFlags specifies which properties of the QGlyphRun will be retrieved from the
+ layout. To minimize allocations and memory consumption, this should be set to include only the
+ properties that you need to access later.
+
+ If \a from is negative, it will default to textStart(), and if \a length is negative it will
+ default to the return value of textLength().
+
+ \since 6.5
+
+ \sa QTextLayout::glyphRuns()
+*/
+QList<QGlyphRun> QTextLine::glyphRuns(int from,
+ int length,
+ QTextLayout::GlyphRunRetrievalFlags retrievalFlags) const
+{
const QScriptLine &line = eng->lines.at(index);
if (line.length == 0)
@@ -2362,14 +2486,18 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
// when we're breaking a RTL script item, since the expected position passed into
// getGlyphPositions() is the left-most edge of the left-most glyph in an RTL run.
if (relativeFrom != (iterator.itemStart - si.position) && !rtl) {
- for (int i=itemGlyphsStart; i<glyphsStart; ++i) {
- QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);
- pos.rx() += (glyphLayout.advances[i] + justification).toReal();
+ for (int i = itemGlyphsStart; i < glyphsStart; ++i) {
+ if (!glyphLayout.attributes[i].dontPrint) {
+ QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);
+ pos.rx() += (glyphLayout.advances[i] + justification).toReal();
+ }
}
} else if (relativeTo != (iterator.itemEnd - si.position - 1) && rtl) {
- for (int i=itemGlyphsEnd; i>glyphsEnd; --i) {
- QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);
- pos.rx() += (glyphLayout.advances[i] + justification).toReal();
+ for (int i = itemGlyphsEnd; i > glyphsEnd; --i) {
+ if (!glyphLayout.attributes[i].dontPrint) {
+ QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);
+ pos.rx() += (glyphLayout.advances[i] + justification).toReal();
+ }
}
}
@@ -2406,20 +2534,28 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
if (start == 0 && startsInsideLigature)
subFlags |= QGlyphRun::SplitLigature;
- glyphRuns.append(glyphRunWithInfo(multiFontEngine->engine(which),
- subLayout,
- pos,
- subFlags,
- x,
- width,
- glyphsStart + start,
- glyphsStart + end,
- logClusters + relativeFrom,
- relativeFrom + si.position,
- relativeTo - relativeFrom + 1));
+ {
+ QGlyphRun glyphRun = glyphRunWithInfo(multiFontEngine->engine(which),
+ eng->text,
+ subLayout,
+ pos,
+ subFlags,
+ retrievalFlags,
+ x,
+ width,
+ glyphsStart + start,
+ glyphsStart + end,
+ logClusters + relativeFrom,
+ relativeFrom + si.position,
+ relativeTo - relativeFrom + 1);
+ if (!glyphRun.isEmpty())
+ glyphRuns.append(glyphRun);
+ }
for (int i = 0; i < subLayout.numGlyphs; ++i) {
- QFixed justification = QFixed::fromFixed(subLayout.justifications[i].space_18d6);
- pos.rx() += (subLayout.advances[i] + justification).toReal();
+ if (!subLayout.attributes[i].dontPrint) {
+ QFixed justification = QFixed::fromFixed(subLayout.justifications[i].space_18d6);
+ pos.rx() += (subLayout.advances[i] + justification).toReal();
+ }
}
if (rtl)
@@ -2437,9 +2573,11 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
subFlags |= QGlyphRun::SplitLigature;
QGlyphRun glyphRun = glyphRunWithInfo(multiFontEngine->engine(which),
+ eng->text,
subLayout,
pos,
subFlags,
+ retrievalFlags,
x,
width,
glyphsStart + start,
@@ -2453,9 +2591,11 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
if (startsInsideLigature || endsInsideLigature)
flags |= QGlyphRun::SplitLigature;
QGlyphRun glyphRun = glyphRunWithInfo(mainFontEngine,
+ eng->text,
glyphLayout,
pos,
flags,
+ retrievalFlags,
x,
width,
glyphsStart,
@@ -2483,7 +2623,7 @@ void QTextLine::draw(QPainter *painter, const QPointF &position) const
draw_internal(painter, position, nullptr);
}
-void QTextLine::draw_internal(QPainter *p, const QPointF &pos,
+void QTextLine::draw_internal(QPainter *p, const QPointF &origPos,
const QTextLayout::FormatRange *selection) const
{
#ifndef QT_NO_RAWFONT
@@ -2491,7 +2631,6 @@ void QTextLine::draw_internal(QPainter *p, const QPointF &pos,
Q_ASSERT(!eng->useRawFont);
#endif
const QScriptLine &line = eng->lines[index];
- QPen pen = p->pen();
bool noText = (selection && selection->format.property(SuppressText).toBool());
@@ -2501,19 +2640,22 @@ void QTextLine::draw_internal(QPainter *p, const QPointF &pos,
&& selection->start + selection->length > line.from) {
const qreal lineHeight = line.height().toReal();
- QRectF r(pos.x() + line.x.toReal(), pos.y() + line.y.toReal(),
- lineHeight / 2, QFontMetrics(eng->font()).horizontalAdvance(QLatin1Char(' ')));
- setPenAndDrawBackground(p, QPen(), selection->format, r);
- p->setPen(pen);
+ QRectF r(origPos.x() + line.x.toReal(), origPos.y() + line.y.toReal(),
+ lineHeight / 2, QFontMetrics(eng->font()).horizontalAdvance(u' '));
+ drawBackground(p, selection->format, r);
}
return;
}
- static QRectF maxFixedRect(QPointF(-QFIXED_MAX, -QFIXED_MAX), QPointF(QFIXED_MAX, QFIXED_MAX));
- if (!maxFixedRect.contains(pos))
- return;
+ Q_CONSTINIT static QRectF maxFixedRect(-QFIXED_MAX / 2, -QFIXED_MAX / 2, QFIXED_MAX, QFIXED_MAX);
+ const bool xlateToFixedRange = !maxFixedRect.contains(origPos);
+ QPointF pos;
+ if (Q_LIKELY(!xlateToFixedRange))
+ pos = origPos;
+ else
+ p->translate(origPos);
+
- QTextLineItemIterator iterator(eng, index, pos, selection);
QFixed lineBase = line.base();
eng->clearDecorations();
eng->enableDelayDecorations();
@@ -2523,187 +2665,214 @@ void QTextLine::draw_internal(QPainter *p, const QPointF &pos,
const QTextFormatCollection *formatCollection = eng->formatCollection();
bool suppressColors = (eng->option.flags() & QTextOption::SuppressColors);
- while (!iterator.atEnd()) {
- QScriptItem &si = iterator.next();
- if (selection && selection->start >= 0 && iterator.isOutsideSelection())
- continue;
-
- if (si.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator
- && !(eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators))
- continue;
+ auto prepareFormat = [suppressColors, selection, this](QTextCharFormat &format,
+ QScriptItem *si) {
+ format.merge(eng->format(si));
- QFixed itemBaseLine = y;
- QFont f = eng->font(si);
- QTextCharFormat format;
- if (formatCollection != nullptr)
- format = formatCollection->defaultTextFormat();
-
- if (eng->hasFormats() || selection || formatCollection) {
- format.merge(eng->format(&si));
+ if (suppressColors) {
+ format.clearForeground();
+ format.clearBackground();
+ format.clearProperty(QTextFormat::TextUnderlineColor);
+ }
+ if (selection)
+ format.merge(selection->format);
+ };
- if (suppressColors) {
- format.clearForeground();
- format.clearBackground();
- format.clearProperty(QTextFormat::TextUnderlineColor);
- }
- if (selection)
- format.merge(selection->format);
-
- setPenAndDrawBackground(p, pen, format, QRectF(iterator.x.toReal(), (y - lineBase).toReal(),
- iterator.itemWidth.toReal(), line.height().toReal()));
-
- const qreal baseLineOffset = format.baselineOffset() / 100.0;
- QTextCharFormat::VerticalAlignment valign = format.verticalAlignment();
- if (valign == QTextCharFormat::AlignSuperScript
- || valign == QTextCharFormat::AlignSubScript
- || !qFuzzyIsNull(baseLineOffset))
- {
- QFontEngine *fe = f.d->engineForScript(si.analysis.script);
- QFixed height = fe->ascent() + fe->descent();
- itemBaseLine -= height * QFixed::fromReal(baseLineOffset);
-
- if (valign == QTextCharFormat::AlignSubScript)
- itemBaseLine += height * QFixed::fromReal(format.subScriptBaseline() / 100.0);
- else if (valign == QTextCharFormat::AlignSuperScript)
- itemBaseLine -= height * QFixed::fromReal(format.superScriptBaseline() / 100.0);
+ {
+ QTextLineItemIterator iterator(eng, index, pos, selection);
+ while (!iterator.atEnd()) {
+ QScriptItem &si = iterator.next();
+
+ if (eng->hasFormats() || selection || formatCollection) {
+ QTextCharFormat format;
+ if (formatCollection != nullptr)
+ format = formatCollection->defaultTextFormat();
+ prepareFormat(format, &si);
+ drawBackground(p, format, QRectF(iterator.x.toReal(), (y - lineBase).toReal(),
+ iterator.itemWidth.toReal(), line.height().toReal()));
}
}
+ }
- if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
+ QPen pen = p->pen();
+ {
+ QTextLineItemIterator iterator(eng, index, pos, selection);
+ while (!iterator.atEnd()) {
+ QScriptItem &si = iterator.next();
- if (eng->hasFormats()) {
- p->save();
- if (si.analysis.flags == QScriptAnalysis::Object && QTextDocumentPrivate::get(eng->block)) {
- QFixed itemY = y - si.ascent;
- switch (format.verticalAlignment()) {
- case QTextCharFormat::AlignTop:
- itemY = y - lineBase;
- break;
- case QTextCharFormat::AlignMiddle:
- itemY = y - lineBase + (line.height() - si.height()) / 2;
- break;
- case QTextCharFormat::AlignBottom:
- itemY = y - lineBase + line.height() - si.height();
- break;
- default:
- break;
- }
+ if (selection && selection->start >= 0 && iterator.isOutsideSelection())
+ continue;
- QRectF itemRect(iterator.x.toReal(), itemY.toReal(), iterator.itemWidth.toReal(), si.height().toReal());
-
- eng->docLayout()->drawInlineObject(p, itemRect,
- QTextInlineObject(iterator.item, eng),
- si.position + eng->block.position(),
- format);
- if (selection) {
- QBrush bg = format.brushProperty(ObjectSelectionBrush);
- if (bg.style() != Qt::NoBrush) {
- QColor c = bg.color();
- c.setAlpha(128);
- p->fillRect(itemRect, c);
- }
- }
- } else { // si.isTab
- QFont f = eng->font(si);
- QTextItemInt gf(si, &f, format);
- gf.chars = nullptr;
- gf.num_chars = 0;
- gf.width = iterator.itemWidth;
- QPainterPrivate::get(p)->drawTextItem(QPointF(iterator.x.toReal(), y.toReal()), gf, eng);
- if (eng->option.flags() & QTextOption::ShowTabsAndSpaces) {
- const QChar visualTab = QChar(QChar::VisualTabCharacter);
- int w = QFontMetrics(f).horizontalAdvance(visualTab);
- qreal x = iterator.itemWidth.toReal() - w; // Right-aligned
- if (x < 0)
- p->setClipRect(QRectF(iterator.x.toReal(), line.y.toReal(),
- iterator.itemWidth.toReal(), line.height().toReal()),
- Qt::IntersectClip);
- else
- x /= 2; // Centered
- p->setFont(f);
- p->drawText(QPointF(iterator.x.toReal() + x,
- y.toReal()), visualTab);
- }
+ if (si.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator
+ && !(eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators))
+ continue;
+ QFixed itemBaseLine = y;
+ QFont f = eng->font(si);
+ QTextCharFormat format;
+ if (formatCollection != nullptr)
+ format = formatCollection->defaultTextFormat();
+
+ if (eng->hasFormats() || selection || formatCollection) {
+ prepareFormat(format, &si);
+ setPen(p, pen, format);
+
+ const qreal baseLineOffset = format.baselineOffset() / 100.0;
+ QTextCharFormat::VerticalAlignment valign = format.verticalAlignment();
+ if (valign == QTextCharFormat::AlignSuperScript
+ || valign == QTextCharFormat::AlignSubScript
+ || !qFuzzyIsNull(baseLineOffset))
+ {
+ QFontEngine *fe = f.d->engineForScript(si.analysis.script);
+ QFixed height = fe->ascent() + fe->descent();
+ itemBaseLine -= height * QFixed::fromReal(baseLineOffset);
+
+ if (valign == QTextCharFormat::AlignSubScript)
+ itemBaseLine += height * QFixed::fromReal(format.subScriptBaseline() / 100.0);
+ else if (valign == QTextCharFormat::AlignSuperScript)
+ itemBaseLine -= height * QFixed::fromReal(format.superScriptBaseline() / 100.0);
}
- p->restore();
}
- continue;
- }
+ if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
- unsigned short *logClusters = eng->logClusters(&si);
- QGlyphLayout glyphs = eng->shapedGlyphs(&si);
+ if (eng->hasFormats()) {
+ p->save();
+ if (si.analysis.flags == QScriptAnalysis::Object && QTextDocumentPrivate::get(eng->block)) {
+ QFixed itemY = y - si.ascent;
+ switch (format.verticalAlignment()) {
+ case QTextCharFormat::AlignTop:
+ itemY = y - lineBase;
+ break;
+ case QTextCharFormat::AlignMiddle:
+ itemY = y - lineBase + (line.height() - si.height()) / 2;
+ break;
+ case QTextCharFormat::AlignBottom:
+ itemY = y - lineBase + line.height() - si.height();
+ break;
+ default:
+ break;
+ }
- QTextItemInt gf(glyphs.mid(iterator.glyphsStart, iterator.glyphsEnd - iterator.glyphsStart),
- &f, eng->layoutData->string.unicode() + iterator.itemStart,
- iterator.itemEnd - iterator.itemStart, eng->fontEngine(si), format);
- gf.logClusters = logClusters + iterator.itemStart - si.position;
- gf.width = iterator.itemWidth;
- gf.justified = line.justified;
- gf.initWithScriptItem(si);
-
- Q_ASSERT(gf.fontEngine);
-
- QPointF pos(iterator.x.toReal(), itemBaseLine.toReal());
- if (format.penProperty(QTextFormat::TextOutline).style() != Qt::NoPen) {
- QPainterPath path;
- path.setFillRule(Qt::WindingFill);
-
- if (gf.glyphs.numGlyphs)
- gf.fontEngine->addOutlineToPath(pos.x(), pos.y(), gf.glyphs, &path, gf.flags);
- if (gf.flags) {
- const QFontEngine *fe = gf.fontEngine;
- const qreal lw = fe->lineThickness().toReal();
- if (gf.flags & QTextItem::Underline) {
- qreal offs = fe->underlinePosition().toReal();
- path.addRect(pos.x(), pos.y() + offs, gf.width.toReal(), lw);
- }
- if (gf.flags & QTextItem::Overline) {
- qreal offs = fe->ascent().toReal() + 1;
- path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
- }
- if (gf.flags & QTextItem::StrikeOut) {
- qreal offs = fe->ascent().toReal() / 3;
- path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
+ QRectF itemRect(iterator.x.toReal(), itemY.toReal(), iterator.itemWidth.toReal(), si.height().toReal());
+
+ eng->docLayout()->drawInlineObject(p, itemRect,
+ QTextInlineObject(iterator.item, eng),
+ si.position + eng->block.position(),
+ format);
+ if (selection) {
+ QBrush bg = format.brushProperty(ObjectSelectionBrush);
+ if (bg.style() != Qt::NoBrush) {
+ QColor c = bg.color();
+ c.setAlpha(128);
+ p->fillRect(itemRect, c);
+ }
+ }
+ } else { // si.isTab
+ QFont f = eng->font(si);
+ QTextItemInt gf(si, &f, format);
+ gf.chars = nullptr;
+ gf.num_chars = 0;
+ gf.width = iterator.itemWidth;
+ QPainterPrivate::get(p)->drawTextItem(QPointF(iterator.x.toReal(), y.toReal()), gf, eng);
+ if (eng->option.flags() & QTextOption::ShowTabsAndSpaces) {
+ const QChar visualTab = QChar(QChar::VisualTabCharacter);
+ int w = QFontMetrics(f).horizontalAdvance(visualTab);
+ qreal x = iterator.itemWidth.toReal() - w; // Right-aligned
+ if (x < 0)
+ p->setClipRect(QRectF(iterator.x.toReal(), line.y.toReal(),
+ iterator.itemWidth.toReal(), line.height().toReal()),
+ Qt::IntersectClip);
+ else
+ x /= 2; // Centered
+ p->setFont(f);
+ p->drawText(QPointF(iterator.x.toReal() + x,
+ y.toReal()), visualTab);
+ }
+
+ }
+ p->restore();
}
+
+ continue;
}
- p->save();
- p->setRenderHint(QPainter::Antialiasing);
- //Currently QPen with a Qt::NoPen style still returns a default
- //QBrush which != Qt::NoBrush so we need this specialcase to reset it
- if (p->pen().style() == Qt::NoPen)
- p->setBrush(Qt::NoBrush);
- else
- p->setBrush(p->pen().brush());
+ unsigned short *logClusters = eng->logClusters(&si);
+ QGlyphLayout glyphs = eng->shapedGlyphs(&si);
- p->setPen(format.textOutline());
- p->drawPath(path);
- p->restore();
- } else {
- if (noText)
- gf.glyphs.numGlyphs = 0; // slightly less elegant than it should be
- QPainterPrivate::get(p)->drawTextItem(pos, gf, eng);
- }
+ QTextItemInt gf(glyphs.mid(iterator.glyphsStart, iterator.glyphsEnd - iterator.glyphsStart),
+ &f, eng->layoutData->string.unicode() + iterator.itemStart,
+ iterator.itemEnd - iterator.itemStart, eng->fontEngine(si), format);
+ gf.logClusters = logClusters + iterator.itemStart - si.position;
+ gf.width = iterator.itemWidth;
+ gf.justified = line.justified;
+ gf.initWithScriptItem(si);
+
+ Q_ASSERT(gf.fontEngine);
+
+ QPointF pos(iterator.x.toReal(), itemBaseLine.toReal());
+ if (format.penProperty(QTextFormat::TextOutline).style() != Qt::NoPen) {
+ QPainterPath path;
+ path.setFillRule(Qt::WindingFill);
+
+ if (gf.glyphs.numGlyphs)
+ gf.fontEngine->addOutlineToPath(pos.x(), pos.y(), gf.glyphs, &path, gf.flags);
+ if (gf.flags) {
+ const QFontEngine *fe = gf.fontEngine;
+ const qreal lw = fe->lineThickness().toReal();
+ if (gf.flags & QTextItem::Underline) {
+ qreal offs = fe->underlinePosition().toReal();
+ path.addRect(pos.x(), pos.y() + offs, gf.width.toReal(), lw);
+ }
+ if (gf.flags & QTextItem::Overline) {
+ qreal offs = fe->ascent().toReal() + 1;
+ path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
+ }
+ if (gf.flags & QTextItem::StrikeOut) {
+ qreal offs = fe->ascent().toReal() / 3;
+ path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
+ }
+ }
- if ((si.analysis.flags == QScriptAnalysis::Space
- || si.analysis.flags == QScriptAnalysis::Nbsp)
- && (eng->option.flags() & QTextOption::ShowTabsAndSpaces)) {
- QBrush c = format.foreground();
- if (c.style() != Qt::NoBrush)
- p->setPen(c.color());
- const QChar visualSpace = si.analysis.flags == QScriptAnalysis::Space ? u'\xb7' : u'\xb0';
- QFont oldFont = p->font();
- p->setFont(eng->font(si));
- p->drawText(QPointF(iterator.x.toReal(), itemBaseLine.toReal()), visualSpace);
- p->setPen(pen);
- p->setFont(oldFont);
+ p->save();
+ p->setRenderHint(QPainter::Antialiasing);
+ //Currently QPen with a Qt::NoPen style still returns a default
+ //QBrush which != Qt::NoBrush so we need this specialcase to reset it
+ if (p->pen().style() == Qt::NoPen)
+ p->setBrush(Qt::NoBrush);
+ else
+ p->setBrush(p->pen().brush());
+
+ p->setPen(format.textOutline());
+ p->drawPath(path);
+ p->restore();
+ } else {
+ if (noText)
+ gf.glyphs.numGlyphs = 0; // slightly less elegant than it should be
+ QPainterPrivate::get(p)->drawTextItem(pos, gf, eng);
+ }
+
+ if ((si.analysis.flags == QScriptAnalysis::Space
+ || si.analysis.flags == QScriptAnalysis::Nbsp)
+ && (eng->option.flags() & QTextOption::ShowTabsAndSpaces)) {
+ QBrush c = format.foreground();
+ if (c.style() != Qt::NoBrush)
+ p->setPen(c.color());
+ const QChar visualSpace = si.analysis.flags == QScriptAnalysis::Space ? u'\xb7' : u'\xb0';
+ QFont oldFont = p->font();
+ p->setFont(eng->font(si));
+ p->drawText(QPointF(iterator.x.toReal(), itemBaseLine.toReal()), visualSpace);
+ p->setPen(pen);
+ p->setFont(oldFont);
+ }
}
}
eng->drawDecorations(p);
+ if (xlateToFixedRange)
+ p->translate(-origPos);
+
if (eng->hasFormats())
p->setPen(pen);
}
@@ -2740,7 +2909,6 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
int lineEnd = line.from + line.length + line.trailingSpaces;
int pos = qBound(line.from, *cursorPos, lineEnd);
- int itm;
const QCharAttributes *attributes = eng->attributes();
if (!attributes) {
*cursorPos = line.from;
@@ -2748,38 +2916,54 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
}
while (pos < lineEnd && !attributes[pos].graphemeBoundary)
pos++;
- if (pos == lineEnd) {
- // end of line ensure we have the last item on the line
- itm = eng->findItem(pos-1);
- }
- else
- itm = eng->findItem(pos);
+ // end of line ensure we have the last item on the line
+ int itm = pos == lineEnd ? eng->findItem(pos-1) : eng->findItem(pos);
if (itm < 0) {
*cursorPos = line.from;
return x.toReal();
}
eng->shapeLine(line);
- const QScriptItem *si = &eng->layoutData->items[itm];
- if (!si->num_glyphs)
+ const QScriptItem *scriptItem = &eng->layoutData->items[itm];
+ if (!scriptItem->num_glyphs)
eng->shape(itm);
+ if ((scriptItem->analysis.bidiLevel % 2 != eng->isRightToLeft()) && !eng->visualCursorMovement()) {
+ // If the item we found has a different writing direction than the engine,
+ // check if the cursor is between two items with different writing direction
+ int neighborItem = itm;
+ if (neighborItem > 0 && scriptItem->position == pos)
+ --neighborItem;
+ else if (neighborItem < eng->layoutData->items.size() - 1 && scriptItem->position + scriptItem->num_glyphs == pos)
+ ++neighborItem;
+ const bool onBoundary = neighborItem != itm && scriptItem->analysis.bidiLevel != eng->layoutData->items[neighborItem].analysis.bidiLevel;
+ // If we are, prioritise the neighbor item that has the same direction as the engine
+ if (onBoundary) {
+ if (eng->isRightToLeft() != scriptItem->analysis.bidiLevel % 2) {
+ itm = neighborItem;
+ scriptItem = &eng->layoutData->items[itm];
+ if (!scriptItem->num_glyphs)
+ eng->shape(itm);
+ }
+ }
+ }
+
const int l = eng->length(itm);
- pos = qBound(0, pos - si->position, l);
+ pos = qBound(0, pos - scriptItem->position, l);
- QGlyphLayout glyphs = eng->shapedGlyphs(si);
- unsigned short *logClusters = eng->logClusters(si);
+ QGlyphLayout glyphs = eng->shapedGlyphs(scriptItem);
+ unsigned short *logClusters = eng->logClusters(scriptItem);
Q_ASSERT(logClusters);
- int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos];
- if (edge == Trailing && glyph_pos < si->num_glyphs) {
+ int glyph_pos = pos == l ? scriptItem->num_glyphs : logClusters[pos];
+ if (edge == Trailing && glyph_pos < scriptItem->num_glyphs) {
// trailing edge is leading edge of next cluster
glyph_pos++;
- while (glyph_pos < si->num_glyphs && !glyphs.attributes[glyph_pos].clusterStart)
+ while (glyph_pos < scriptItem->num_glyphs && !glyphs.attributes[glyph_pos].clusterStart)
glyph_pos++;
}
- bool reverse = si->analysis.bidiLevel % 2;
+ bool reverse = scriptItem->analysis.bidiLevel % 2;
// add the items left of the cursor
@@ -2824,32 +3008,32 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
}
}
- logClusters = eng->logClusters(si);
- glyphs = eng->shapedGlyphs(si);
- if (si->analysis.flags >= QScriptAnalysis::TabOrObject) {
+ logClusters = eng->logClusters(scriptItem);
+ glyphs = eng->shapedGlyphs(scriptItem);
+ if (scriptItem->analysis.flags >= QScriptAnalysis::TabOrObject) {
if (pos == (reverse ? 0 : l))
- x += si->width;
+ x += scriptItem->width;
} else {
bool rtl = eng->isRightToLeft();
bool visual = eng->visualCursorMovement();
- int end = qMin(lineEnd, si->position + l) - si->position;
+ int end = qMin(lineEnd, scriptItem->position + l) - scriptItem->position;
if (reverse) {
- int glyph_end = end == l ? si->num_glyphs : logClusters[end];
+ int glyph_end = end == l ? scriptItem->num_glyphs : logClusters[end];
int glyph_start = glyph_pos;
if (visual && !rtl && !(lastLine && itm == (visualOrder[nItems - 1] + firstItem)))
glyph_start++;
for (int i = glyph_end - 1; i >= glyph_start; i--)
x += glyphs.effectiveAdvance(i);
- x -= eng->offsetInLigature(si, pos, end, glyph_pos);
+ x -= eng->offsetInLigature(scriptItem, pos, end, glyph_pos);
} else {
- int start = qMax(line.from - si->position, 0);
+ int start = qMax(line.from - scriptItem->position, 0);
int glyph_start = logClusters[start];
int glyph_end = glyph_pos;
if (!visual || !rtl || (lastLine && itm == visualOrder[0] + firstItem))
glyph_end--;
for (int i = glyph_start; i <= glyph_end; i++)
x += glyphs.effectiveAdvance(i);
- x += eng->offsetInLigature(si, pos, end, glyph_pos);
+ x += eng->offsetInLigature(scriptItem, pos, end, glyph_pos);
}
}
@@ -2858,7 +3042,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
if (eng->option.wrapMode() != QTextOption::NoWrap && x < 0)
x = 0;
- *cursorPos = pos + si->position;
+ *cursorPos = pos + scriptItem->position;
return x.toReal();
}
@@ -2906,18 +3090,10 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
bool visual = eng->visualCursorMovement();
if (x <= 0) {
// left of first item
- int item = visualOrder[0]+firstItem;
- QScriptItem &si = eng->layoutData->items[item];
- if (!si.num_glyphs)
- eng->shape(item);
- int pos = si.position;
- if (si.analysis.bidiLevel % 2)
- pos += eng->length(item);
- pos = qMax(line.from, pos);
- pos = qMin(line.from + line_length, pos);
- return pos;
- } else if (x < line.textWidth
- || (line.justified && x < line.width)) {
+ if (eng->isRightToLeft())
+ return line.from + line_length;
+ return line.from;
+ } else if (x < line.textWidth || (line.justified && x < line.width)) {
// has to be in one of the runs
QFixed pos;
bool rtl = eng->isRightToLeft();
@@ -3067,26 +3243,17 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const
}
}
// right of last item
-// qDebug("right of last");
- int item = visualOrder[nItems-1]+firstItem;
- QScriptItem &si = eng->layoutData->items[item];
- if (!si.num_glyphs)
- eng->shape(item);
- int pos = si.position;
- if (!(si.analysis.bidiLevel % 2))
- pos += eng->length(item);
- pos = qMax(line.from, pos);
-
- int maxPos = line.from + line_length;
+ int pos = line.from;
+ if (!eng->isRightToLeft())
+ pos += line_length;
// except for the last line we assume that the
// character between lines is a space and we want
// to position the cursor to the left of that
// character.
- if (this->index < eng->lines.count() - 1)
- maxPos = eng->previousLogicalPosition(maxPos);
+ if (index < eng->lines.size() - 1)
+ pos = qMin(eng->previousLogicalPosition(pos), pos);
- pos = qMin(pos, maxPos);
return pos;
}
diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h
index 5c6dead276..5b1b64d7ee 100644
--- a/src/gui/text/qtextlayout.h
+++ b/src/gui/text/qtextlayout.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTLAYOUT_H
#define QTEXTLAYOUT_H
@@ -105,6 +69,17 @@ class QTextOption;
class Q_GUI_EXPORT QTextLayout
{
public:
+ enum GlyphRunRetrievalFlag : quint16 {
+ RetrieveGlyphIndexes = 0x1,
+ RetrieveGlyphPositions = 0x2,
+ RetrieveStringIndexes = 0x4,
+ RetrieveString = 0x8,
+
+ DefaultRetrievalFlags = RetrieveGlyphIndexes | RetrieveGlyphPositions,
+ RetrieveAll = 0xffff
+ };
+ Q_DECLARE_FLAGS(GlyphRunRetrievalFlags, GlyphRunRetrievalFlag)
+
// does itemization
QTextLayout();
QTextLayout(const QString& text);
@@ -184,7 +159,15 @@ public:
qreal maximumWidth() const;
#if !defined(QT_NO_RAWFONT)
+
+# if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ QList<QGlyphRun> glyphRuns(int from, int length, GlyphRunRetrievalFlags flags) const;
QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const;
+# else
+ QList<QGlyphRun> glyphRuns(int from = -1,
+ int length = -1,
+ GlyphRunRetrievalFlags flags = DefaultRetrievalFlags) const;
+# endif
#endif
QTextEngine *engine() const { return d; }
@@ -202,7 +185,7 @@ private:
QTextEngine *d;
};
Q_DECLARE_TYPEINFO(QTextLayout::FormatRange, Q_RELOCATABLE_TYPE);
-
+Q_DECLARE_OPERATORS_FOR_FLAGS(QTextLayout::GlyphRunRetrievalFlags)
class Q_GUI_EXPORT QTextLine
{
@@ -255,7 +238,14 @@ public:
void draw(QPainter *painter, const QPointF &position) const;
#if !defined(QT_NO_RAWFONT)
+# if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
+ QList<QGlyphRun> glyphRuns(int from, int length, QTextLayout::GlyphRunRetrievalFlags flags) const;
QList<QGlyphRun> glyphRuns(int from = -1, int length = -1) const;
+# else
+ QList<QGlyphRun> glyphRuns(int from = -1,
+ int length = -1,
+ QTextLayout::GlyphRunRetrievalFlags flags = QTextLayout::DefaultRetrievalFlags) const;
+# endif
#endif
private:
diff --git a/src/gui/text/qtextlist.cpp b/src/gui/text/qtextlist.cpp
index c9bbe687b2..7ec8b6215e 100644
--- a/src/gui/text/qtextlist.cpp
+++ b/src/gui/text/qtextlist.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextlist.h"
@@ -46,6 +10,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
class QTextListPrivate : public QTextBlockGroupPrivate
{
public:
@@ -120,7 +86,7 @@ QTextList::~QTextList()
int QTextList::count() const
{
Q_D(const QTextList);
- return d->blocks.count();
+ return d->blocks.size();
}
/*!
@@ -179,7 +145,10 @@ QString QTextList::itemText(const QTextBlock &blockIt) const
const int style = format().style();
QString numberPrefix;
- QString numberSuffix = QLatin1String(".");
+ QString numberSuffix = u"."_s;
+
+ // the number of the item might be offset by start, which defaults to 1
+ const int itemNumber = item + format().start() - 1;
if (format().hasProperty(QTextFormat::ListNumberPrefix))
numberPrefix = format().numberPrefix();
@@ -188,15 +157,21 @@ QString QTextList::itemText(const QTextBlock &blockIt) const
switch (style) {
case QTextListFormat::ListDecimal:
- result = QString::number(item);
+ result = QString::number(itemNumber);
break;
// from the old richtext
case QTextListFormat::ListLowerAlpha:
case QTextListFormat::ListUpperAlpha:
{
+ // match the html default behavior of falling back to decimal numbers
+ if (itemNumber < 1) {
+ result = QString::number(itemNumber);
+ break;
+ }
+
const char baseChar = style == QTextListFormat::ListUpperAlpha ? 'A' : 'a';
- int c = item;
+ int c = itemNumber;
while (c > 0) {
c--;
result.prepend(QChar::fromUcs2(baseChar + (c % 26)));
@@ -207,20 +182,21 @@ QString QTextList::itemText(const QTextBlock &blockIt) const
case QTextListFormat::ListLowerRoman:
case QTextListFormat::ListUpperRoman:
{
- if (item < 5000) {
- QByteArray romanNumeral;
+ // match the html default behavior of falling back to decimal numbers
+ if (itemNumber < 1) {
+ result = QString::number(itemNumber);
+ } else if (itemNumber < 5000) {
+ QString romanNumeral;
// works for up to 4999 items
- static const char romanSymbolsLower[] = "iiivixxxlxcccdcmmmm";
- static const char romanSymbolsUpper[] = "IIIVIXXXLXCCCDCMMMM";
- QByteArray romanSymbols; // wrap to have "mid"
+ QLatin1StringView romanSymbols;
if (style == QTextListFormat::ListLowerRoman)
- romanSymbols = QByteArray::fromRawData(romanSymbolsLower, sizeof(romanSymbolsLower));
+ romanSymbols = "iiivixxxlxcccdcmmmm"_L1;
else
- romanSymbols = QByteArray::fromRawData(romanSymbolsUpper, sizeof(romanSymbolsUpper));
+ romanSymbols = "IIIVIXXXLXCCCDCMMMM"_L1;
int c[] = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };
- int n = item;
+ int n = itemNumber;
for (int i = 12; i >= 0; n %= c[i], i--) {
int q = n / c[i];
if (q > 0) {
@@ -242,13 +218,12 @@ QString QTextList::itemText(const QTextBlock &blockIt) const
numDigits = q;
}
- romanNumeral.append(romanSymbols.mid(startDigit, numDigits));
+ romanNumeral.append(romanSymbols.sliced(startDigit, numDigits));
}
}
- result = QString::fromLatin1(romanNumeral);
- }
- else {
- result = QLatin1String("?");
+ result = std::move(romanNumeral);
+ } else {
+ result = u"?"_s;
}
}
@@ -306,3 +281,5 @@ void QTextList::add(const QTextBlock &block)
}
QT_END_NAMESPACE
+
+#include "moc_qtextlist.cpp"
diff --git a/src/gui/text/qtextlist.h b/src/gui/text/qtextlist.h
index fa945c31fd..025213c2f9 100644
--- a/src/gui/text/qtextlist.h
+++ b/src/gui/text/qtextlist.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTLIST_H
#define QTEXTLIST_H
diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp
index 75b5a324c8..e7fcad67b5 100644
--- a/src/gui/text/qtextmarkdownimporter.cpp
+++ b/src/gui/text/qtextmarkdownimporter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextmarkdownimporter_p.h"
#include "qtextdocumentfragment_p.h"
@@ -56,13 +20,18 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcMD, "qt.text.markdown")
-static const QChar Newline = QLatin1Char('\n');
-static const QChar Space = QLatin1Char(' ');
+static const QChar qtmi_Newline = u'\n';
+static const QChar qtmi_Space = u' ';
+
+static constexpr auto markerString() noexcept { return "---"_L1; }
// TODO maybe eliminate the margins after all views recognize BlockQuoteLevel, CSS can format it, etc.
-static const int BlockQuoteIndent = 40; // pixels, same as in QTextHtmlParserNode::initializeProperties
+static const int qtmi_BlockQuoteIndent =
+ 40; // pixels, same as in QTextHtmlParserNode::initializeProperties
static_assert(int(QTextMarkdownImporter::FeatureCollapseWhitespace) == MD_FLAG_COLLAPSEWHITESPACE);
static_assert(int(QTextMarkdownImporter::FeaturePermissiveATXHeaders) == MD_FLAG_PERMISSIVEATXHEADERS);
@@ -79,7 +48,8 @@ static_assert(int(QTextMarkdownImporter::FeaturePermissiveAutoLinks) == MD_FLAG_
static_assert(int(QTextMarkdownImporter::FeatureTasklists) == MD_FLAG_TASKLISTS);
static_assert(int(QTextMarkdownImporter::FeatureNoHTML) == MD_FLAG_NOHTML);
static_assert(int(QTextMarkdownImporter::DialectCommonMark) == MD_DIALECT_COMMONMARK);
-static_assert(int(QTextMarkdownImporter::DialectGitHub) == (MD_DIALECT_GITHUB | MD_FLAG_UNDERLINE));
+static_assert(int(QTextMarkdownImporter::DialectGitHub) ==
+ (MD_DIALECT_GITHUB | MD_FLAG_UNDERLINE | QTextMarkdownImporter::FeatureFrontMatter));
// --------------------------------------------------------
// MD4C callback function wrappers
@@ -137,18 +107,19 @@ static Qt::Alignment MdAlignment(MD_ALIGN a, Qt::Alignment defaultAlignment = Qt
}
}
-QTextMarkdownImporter::QTextMarkdownImporter(QTextMarkdownImporter::Features features)
- : m_monoFont(QFontDatabase::systemFont(QFontDatabase::FixedFont))
+QTextMarkdownImporter::QTextMarkdownImporter(QTextDocument *doc, QTextMarkdownImporter::Features features)
+ : m_cursor(doc)
+ , m_monoFont(QFontDatabase::systemFont(QFontDatabase::FixedFont))
, m_features(features)
{
}
-QTextMarkdownImporter::QTextMarkdownImporter(QTextDocument::MarkdownFeatures features)
- : QTextMarkdownImporter(static_cast<QTextMarkdownImporter::Features>(int(features)))
+QTextMarkdownImporter::QTextMarkdownImporter(QTextDocument *doc, QTextDocument::MarkdownFeatures features)
+ : QTextMarkdownImporter(doc, static_cast<QTextMarkdownImporter::Features>(int(features)))
{
}
-void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown)
+void QTextMarkdownImporter::import(const QString &markdown)
{
MD_PARSER callbacks = {
0, // abi_version
@@ -161,19 +132,36 @@ void QTextMarkdownImporter::import(QTextDocument *doc, const QString &markdown)
&CbDebugLog,
nullptr // syntax
};
- m_doc = doc;
- m_paragraphMargin = m_doc->defaultFont().pointSize() * 2 / 3;
- m_cursor = new QTextCursor(doc);
+ QTextDocument *doc = m_cursor.document();
+ const auto defaultFont = doc->defaultFont();
+ m_paragraphMargin = defaultFont.pointSize() * 2 / 3;
doc->clear();
- if (doc->defaultFont().pointSize() != -1)
- m_monoFont.setPointSize(doc->defaultFont().pointSize());
+ if (defaultFont.pointSize() != -1)
+ m_monoFont.setPointSize(defaultFont.pointSize());
else
- m_monoFont.setPixelSize(doc->defaultFont().pixelSize());
- qCDebug(lcMD) << "default font" << doc->defaultFont() << "mono font" << m_monoFont;
- QByteArray md = markdown.toUtf8();
- md_parse(md.constData(), MD_SIZE(md.size()), &callbacks, this);
- delete m_cursor;
- m_cursor = nullptr;
+ m_monoFont.setPixelSize(defaultFont.pixelSize());
+ qCDebug(lcMD) << "default font" << defaultFont << "mono font" << m_monoFont;
+ QStringView md = markdown;
+
+ if (m_features.testFlag(QTextMarkdownImporter::FeatureFrontMatter) && md.startsWith(markerString())) {
+ qsizetype endMarkerPos = md.indexOf(markerString(), markerString().size() + 1);
+ if (endMarkerPos > 4) {
+ qsizetype firstLinePos = 4; // first line of yaml
+ while (md.at(firstLinePos) == '\n'_L1 || md.at(firstLinePos) == '\r'_L1)
+ ++firstLinePos;
+ auto frontMatter = md.sliced(firstLinePos, endMarkerPos - firstLinePos);
+ firstLinePos = endMarkerPos + 4; // first line of markdown after yaml
+ while (md.size() > firstLinePos && (md.at(firstLinePos) == '\n'_L1 || md.at(firstLinePos) == '\r'_L1))
+ ++firstLinePos;
+ md = md.sliced(firstLinePos);
+ doc->setMetaInformation(QTextDocument::FrontMatter, frontMatter.toString());
+ qCDebug(lcMD) << "extracted FrontMatter: size" << frontMatter.size();
+ }
+ }
+ const auto mdUtf8 = md.toUtf8();
+ m_cursor.beginEditBlock();
+ md_parse(mdUtf8.constData(), MD_SIZE(mdUtf8.size()), &callbacks, this);
+ m_cursor.endEditBlock();
}
int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
@@ -182,7 +170,7 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
switch (blockType) {
case MD_BLOCK_P:
if (!m_listStack.isEmpty())
- qCDebug(lcMD, m_listItem ? "P of LI at level %d" : "P continuation inside LI at level %d", int(m_listStack.count()));
+ qCDebug(lcMD, m_listItem ? "P of LI at level %d" : "P continuation inside LI at level %d", int(m_listStack.size()));
else
qCDebug(lcMD, "P");
m_needsInsertBlock = true;
@@ -194,9 +182,9 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
case MD_BLOCK_CODE: {
MD_BLOCK_CODE_DETAIL *detail = static_cast<MD_BLOCK_CODE_DETAIL *>(det);
m_codeBlock = true;
- m_blockCodeLanguage = QLatin1String(detail->lang.text, int(detail->lang.size));
+ m_blockCodeLanguage = QLatin1StringView(detail->lang.text, int(detail->lang.size));
m_blockCodeFence = detail->fence_char;
- QString info = QLatin1String(detail->info.text, int(detail->info.size));
+ QString info = QLatin1StringView(detail->info.text, int(detail->info.size));
m_needsInsertBlock = true;
if (m_blockQuoteDepth)
qCDebug(lcMD, "CODE lang '%s' info '%s' fenced with '%c' inside QUOTE %d", qPrintable(m_blockCodeLanguage), qPrintable(info), m_blockCodeFence, m_blockQuoteDepth);
@@ -212,11 +200,11 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
charFmt.setFontWeight(QFont::Bold);
blockFmt.setHeadingLevel(int(detail->level));
m_needsInsertBlock = false;
- if (m_doc->isEmpty()) {
- m_cursor->setBlockFormat(blockFmt);
- m_cursor->setCharFormat(charFmt);
+ if (m_cursor.document()->isEmpty()) {
+ m_cursor.setBlockFormat(blockFmt);
+ m_cursor.setCharFormat(charFmt);
} else {
- m_cursor->insertBlock(blockFmt, charFmt);
+ m_cursor.insertBlock(blockFmt, charFmt);
}
qCDebug(lcMD, "H%d", detail->level);
} break;
@@ -231,12 +219,12 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
} break;
case MD_BLOCK_UL: {
if (m_needsInsertList) // list nested in an empty list
- m_listStack.push(m_cursor->insertList(m_listFormat));
+ m_listStack.push(m_cursor.insertList(m_listFormat));
else
m_needsInsertList = true;
MD_BLOCK_UL_DETAIL *detail = static_cast<MD_BLOCK_UL_DETAIL *>(det);
m_listFormat = QTextListFormat();
- m_listFormat.setIndent(m_listStack.count() + 1);
+ m_listFormat.setIndent(m_listStack.size() + 1);
switch (detail->mark) {
case '*':
m_listFormat.setStyle(QTextListFormat::ListCircle);
@@ -248,19 +236,20 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
m_listFormat.setStyle(QTextListFormat::ListDisc);
break;
}
- qCDebug(lcMD, "UL %c level %d", detail->mark, int(m_listStack.count()) + 1);
+ qCDebug(lcMD, "UL %c level %d", detail->mark, int(m_listStack.size()) + 1);
} break;
case MD_BLOCK_OL: {
if (m_needsInsertList) // list nested in an empty list
- m_listStack.push(m_cursor->insertList(m_listFormat));
+ m_listStack.push(m_cursor.insertList(m_listFormat));
else
m_needsInsertList = true;
MD_BLOCK_OL_DETAIL *detail = static_cast<MD_BLOCK_OL_DETAIL *>(det);
m_listFormat = QTextListFormat();
- m_listFormat.setIndent(m_listStack.count() + 1);
+ m_listFormat.setIndent(m_listStack.size() + 1);
m_listFormat.setNumberSuffix(QChar::fromLatin1(detail->mark_delimiter));
m_listFormat.setStyle(QTextListFormat::ListDecimal);
- qCDebug(lcMD, "OL xx%d level %d", detail->mark_delimiter, int(m_listStack.count()) + 1);
+ m_listFormat.setStart(detail->start);
+ qCDebug(lcMD, "OL xx%d level %d start %d", detail->mark_delimiter, int(m_listStack.size()) + 1, detail->start);
} break;
case MD_BLOCK_TD: {
MD_BLOCK_TD_DETAIL *detail = static_cast<MD_BLOCK_TD_DETAIL *>(det);
@@ -272,10 +261,10 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
qWarning("malformed table in Markdown input");
return 1;
}
- *m_cursor = cell.firstCursorPosition();
- QTextBlockFormat blockFmt = m_cursor->blockFormat();
+ m_cursor = cell.firstCursorPosition();
+ QTextBlockFormat blockFmt = m_cursor.blockFormat();
blockFmt.setAlignment(MdAlignment(detail->align));
- m_cursor->setBlockFormat(blockFmt);
+ m_cursor.setBlockFormat(blockFmt);
qCDebug(lcMD) << "TD; align" << detail->align << MdAlignment(detail->align) << "col" << m_tableCol;
} break;
case MD_BLOCK_TH: {
@@ -303,13 +292,13 @@ int QTextMarkdownImporter::cbEnterBlock(int blockType, void *det)
case MD_BLOCK_TABLE:
m_tableColumnCount = 0;
m_tableRowCount = 0;
- m_currentTable = m_cursor->insertTable(1, 1); // we don't know the dimensions yet
+ m_currentTable = m_cursor.insertTable(1, 1); // we don't know the dimensions yet
break;
case MD_BLOCK_HR: {
qCDebug(lcMD, "HR");
QTextBlockFormat blockFmt;
blockFmt.setProperty(QTextFormat::BlockTrailingHorizontalRulerWidth, 1);
- m_cursor->insertBlock(blockFmt, QTextCharFormat());
+ m_cursor.insertBlock(blockFmt, QTextCharFormat());
} break;
default:
break; // nothing to do for now
@@ -327,11 +316,11 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail)
case MD_BLOCK_UL:
case MD_BLOCK_OL:
if (Q_UNLIKELY(m_needsInsertList))
- m_listStack.push(m_cursor->createList(m_listFormat));
+ m_listStack.push(m_cursor.createList(m_listFormat));
if (Q_UNLIKELY(m_listStack.isEmpty())) {
qCWarning(lcMD, "list ended unexpectedly");
} else {
- qCDebug(lcMD, "list at level %d ended", int(m_listStack.count()));
+ qCDebug(lcMD, "list at level %d ended", int(m_listStack.size()));
m_listStack.pop();
}
break;
@@ -365,10 +354,10 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail)
case MD_BLOCK_TABLE:
qCDebug(lcMD) << "table ended with" << m_currentTable->columns() << "cols and" << m_currentTable->rows() << "rows";
m_currentTable = nullptr;
- m_cursor->movePosition(QTextCursor::End);
+ m_cursor.movePosition(QTextCursor::End);
break;
case MD_BLOCK_LI:
- qCDebug(lcMD, "LI at level %d ended", int(m_listStack.count()));
+ qCDebug(lcMD, "LI at level %d ended", int(m_listStack.size()));
m_listItem = false;
break;
case MD_BLOCK_CODE: {
@@ -382,7 +371,7 @@ int QTextMarkdownImporter::cbLeaveBlock(int blockType, void *detail)
m_needsInsertBlock = true;
} break;
case MD_BLOCK_H:
- m_cursor->setCharFormat(QTextCharFormat());
+ m_cursor.setCharFormat(QTextCharFormat());
break;
default:
break;
@@ -426,16 +415,17 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det)
}
case MD_SPAN_CODE:
charFmt.setFont(m_monoFont);
+ charFmt.setFontFixedPitch(true);
break;
case MD_SPAN_DEL:
charFmt.setFontStrikeOut(true);
break;
}
m_spanFormatStack.push(charFmt);
- qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().families().first()
+ qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().families().constFirst()
<< charFmt.fontWeight() << (charFmt.fontItalic() ? "italic" : "")
<< charFmt.foreground().color().name();
- m_cursor->setCharFormat(charFmt);
+ m_cursor.setCharFormat(charFmt);
return 0; // no error
}
@@ -448,8 +438,8 @@ int QTextMarkdownImporter::cbLeaveSpan(int spanType, void *detail)
if (!m_spanFormatStack.isEmpty())
charFmt = m_spanFormatStack.top();
}
- m_cursor->setCharFormat(charFmt);
- qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().families().first()
+ m_cursor.setCharFormat(charFmt);
+ qCDebug(lcMD) << spanType << "setCharFormat" << charFmt.font().families().constFirst()
<< charFmt.fontWeight() << (charFmt.fontItalic() ? "italic" : "")
<< charFmt.foreground().color().name();
if (spanType == int(MD_SPAN_IMG))
@@ -480,17 +470,20 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
s = QString(QChar(u'\xFFFD')); // CommonMark-required replacement for null
break;
case MD_TEXT_BR:
- s = QString(Newline);
+ s = QString(qtmi_Newline);
break;
case MD_TEXT_SOFTBR:
- s = QString(Space);
+ s = QString(qtmi_Space);
break;
case MD_TEXT_CODE:
// We'll see MD_SPAN_CODE too, which will set the char format, and that's enough.
break;
#if QT_CONFIG(texthtmlparser)
case MD_TEXT_ENTITY:
- m_cursor->insertHtml(s);
+ if (m_htmlTagDepth)
+ m_htmlAccumulator += s;
+ else
+ m_cursor.insertHtml(s);
s = QString();
break;
#endif
@@ -512,11 +505,11 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
m_htmlAccumulator += s;
if (!m_htmlTagDepth) { // all open tags are now closed
qCDebug(lcMD) << "HTML" << m_htmlAccumulator;
- m_cursor->insertHtml(m_htmlAccumulator);
+ m_cursor.insertHtml(m_htmlAccumulator);
if (m_spanFormatStack.isEmpty())
- m_cursor->setCharFormat(QTextCharFormat());
+ m_cursor.setCharFormat(QTextCharFormat());
else
- m_cursor->setCharFormat(m_spanFormatStack.top());
+ m_cursor.setCharFormat(m_spanFormatStack.top());
m_htmlAccumulator = QString();
}
#endif
@@ -528,6 +521,14 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
case MD_BLOCK_TD:
m_nonEmptyTableCells.append(m_tableCol);
break;
+ case MD_BLOCK_CODE:
+ if (s == qtmi_Newline) {
+ // defer a blank line until we see something else in the code block,
+ // to avoid ending every code block with a gratuitous blank line
+ m_needsInsertBlock = true;
+ s = QString();
+ }
+ break;
default:
break;
}
@@ -538,35 +539,33 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
m_imageFormat.setProperty(QTextFormat::ImageAltText, s);
qCDebug(lcMD) << "image" << m_imageFormat.name()
<< "title" << m_imageFormat.stringProperty(QTextFormat::ImageTitle)
- << "alt" << s << "relative to" << m_doc->baseUrl();
- m_cursor->insertImage(m_imageFormat);
+ << "alt" << s << "relative to" << m_cursor.document()->baseUrl();
+ m_cursor.insertImage(m_imageFormat);
return 0; // no error
}
if (!s.isEmpty())
- m_cursor->insertText(s);
- if (m_cursor->currentList()) {
+ m_cursor.insertText(s);
+ if (m_cursor.currentList()) {
// The list item will indent the list item's text, so we don't need indentation on the block.
- QTextBlockFormat bfmt = m_cursor->blockFormat();
+ QTextBlockFormat bfmt = m_cursor.blockFormat();
bfmt.setIndent(0);
- m_cursor->setBlockFormat(bfmt);
+ m_cursor.setBlockFormat(bfmt);
}
if (lcMD().isEnabled(QtDebugMsg)) {
- QTextBlockFormat bfmt = m_cursor->blockFormat();
+ QTextBlockFormat bfmt = m_cursor.blockFormat();
QString debugInfo;
- if (m_cursor->currentList())
- debugInfo = QLatin1String("in list at depth ") + QString::number(m_cursor->currentList()->format().indent());
+ if (m_cursor.currentList())
+ debugInfo = "in list at depth "_L1 + QString::number(m_cursor.currentList()->format().indent());
if (bfmt.hasProperty(QTextFormat::BlockQuoteLevel))
- debugInfo += QLatin1String("in blockquote at depth ") +
+ debugInfo += "in blockquote at depth "_L1 +
QString::number(bfmt.intProperty(QTextFormat::BlockQuoteLevel));
if (bfmt.hasProperty(QTextFormat::BlockCodeLanguage))
- debugInfo += QLatin1String("in a code block");
+ debugInfo += "in a code block"_L1;
qCDebug(lcMD) << textType << "in block" << m_blockType << s << qPrintable(debugInfo)
<< "bindent" << bfmt.indent() << "tindent" << bfmt.textIndent()
<< "margins" << bfmt.leftMargin() << bfmt.topMargin() << bfmt.bottomMargin() << bfmt.rightMargin();
}
- qCDebug(lcMD) << textType << "in block" << m_blockType << s << "in list?" << m_cursor->currentList()
- << "indent" << m_cursor->blockFormat().indent();
return 0; // no error
}
@@ -574,7 +573,7 @@ int QTextMarkdownImporter::cbText(int textType, const char *text, unsigned size)
Insert a new block based on stored state.
m_cursor cannot store the state for the _next_ block ahead of time, because
- m_cursor->setBlockFormat() controls the format of the block that the cursor
+ m_cursor.setBlockFormat() controls the format of the block that the cursor
is already in; so cbLeaveBlock() cannot call setBlockFormat() without
altering the block that was just added. Therefore cbLeaveBlock() and the
following cbEnterBlock() set variables to remember what formatting should
@@ -596,13 +595,15 @@ void QTextMarkdownImporter::insertBlock()
}
if (m_blockQuoteDepth) {
blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth);
- blockFormat.setLeftMargin(BlockQuoteIndent * m_blockQuoteDepth);
- blockFormat.setRightMargin(BlockQuoteIndent);
+ blockFormat.setLeftMargin(qtmi_BlockQuoteIndent * m_blockQuoteDepth);
+ blockFormat.setRightMargin(qtmi_BlockQuoteIndent);
}
if (m_codeBlock) {
blockFormat.setProperty(QTextFormat::BlockCodeLanguage, m_blockCodeLanguage);
- if (m_blockCodeFence)
+ if (m_blockCodeFence) {
+ blockFormat.setNonBreakableLines(true);
blockFormat.setProperty(QTextFormat::BlockCodeFence, QString(QLatin1Char(m_blockCodeFence)));
+ }
charFormat.setFont(m_monoFont);
} else {
blockFormat.setTopMargin(m_paragraphMargin);
@@ -613,17 +614,20 @@ void QTextMarkdownImporter::insertBlock()
else
blockFormat.setMarker(m_markerType);
if (!m_listStack.isEmpty())
- blockFormat.setIndent(m_listStack.count());
- if (m_doc->isEmpty()) {
- m_cursor->setBlockFormat(blockFormat);
- m_cursor->setCharFormat(charFormat);
+ blockFormat.setIndent(m_listStack.size());
+ if (m_cursor.document()->isEmpty()) {
+ m_cursor.setBlockFormat(blockFormat);
+ m_cursor.setCharFormat(charFormat);
+ } else if (m_listItem) {
+ m_cursor.insertBlock(blockFormat, QTextCharFormat());
+ m_cursor.setCharFormat(charFormat);
} else {
- m_cursor->insertBlock(blockFormat, charFormat);
+ m_cursor.insertBlock(blockFormat, charFormat);
}
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 && m_listStack.top()) {
- m_listStack.top()->add(m_cursor->block());
+ m_listStack.top()->add(m_cursor.block());
}
m_needsInsertList = false;
m_needsInsertBlock = false;
diff --git a/src/gui/text/qtextmarkdownimporter_p.h b/src/gui/text/qtextmarkdownimporter_p.h
index 12a7c5a3a6..8b8f4ec9bb 100644
--- a/src/gui/text/qtextmarkdownimporter_p.h
+++ b/src/gui/text/qtextmarkdownimporter_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTMARKDOWNIMPORTER_H
#define QTEXTMARKDOWNIMPORTER_H
@@ -58,6 +22,7 @@
#include <QtGui/qtextlist.h>
#include <QtCore/qpointer.h>
#include <QtCore/qstack.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -81,6 +46,7 @@ public:
FeaturePermissiveWWWAutoLinks = 0x0400,
FeatureTasklists = 0x0800,
FeatureUnderline = 0x4000,
+ FeatureFrontMatter = 0x100000, // Qt feature, not yet in MD4C
// composite flags
FeaturePermissiveAutoLinks = FeaturePermissiveMailAutoLinks
| FeaturePermissiveURLAutoLinks | FeaturePermissiveWWWAutoLinks,
@@ -90,10 +56,10 @@ public:
};
Q_DECLARE_FLAGS(Features, Feature)
- QTextMarkdownImporter(Features features);
- QTextMarkdownImporter(QTextDocument::MarkdownFeatures features);
+ QTextMarkdownImporter(QTextDocument *doc, Features features);
+ QTextMarkdownImporter(QTextDocument *doc, QTextDocument::MarkdownFeatures features);
- void import(QTextDocument *doc, const QString &markdown);
+ void import(const QString &markdown);
public:
// MD4C callbacks
@@ -107,8 +73,7 @@ private:
void insertBlock();
private:
- QTextDocument *m_doc = nullptr;
- QTextCursor *m_cursor = nullptr;
+ QTextCursor m_cursor;
QTextTable *m_currentTable = nullptr; // because m_cursor->currentTable() doesn't work
#if QT_CONFIG(regularexpression)
QString m_htmlAccumulator;
diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp
index 26e41149b2..361158e722 100644
--- a/src/gui/text/qtextmarkdownwriter.cpp
+++ b/src/gui/text/qtextmarkdownwriter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextmarkdownwriter_p.h"
#include "qtextdocumentlayout_p.h"
@@ -46,24 +10,28 @@
#include "qtexttable.h"
#include "qtextcursor.h"
#include "qtextimagehandler_p.h"
+#include "qtextmarkdownimporter_p.h"
#include "qloggingcategory.h"
+#include <QtCore/QRegularExpression>
#if QT_CONFIG(itemmodel)
#include "qabstractitemmodel.h"
#endif
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_LOGGING_CATEGORY(lcMDW, "qt.text.markdown.writer")
-static const QChar Space = QLatin1Char(' ');
-static const QChar Tab = QLatin1Char('\t');
-static const QChar Newline = QLatin1Char('\n');
-static const QChar CarriageReturn = QLatin1Char('\r');
-static const QChar LineBreak = u'\x2028';
-static const QChar DoubleQuote = QLatin1Char('"');
-static const QChar Backtick = QLatin1Char('`');
-static const QChar Backslash = QLatin1Char('\\');
-static const QChar Period = QLatin1Char('.');
+static const QChar qtmw_Space = u' ';
+static const QChar qtmw_Tab = u'\t';
+static const QChar qtmw_Newline = u'\n';
+static const QChar qtmw_CarriageReturn = u'\r';
+static const QChar qtmw_LineBreak = u'\x2028';
+static const QChar qtmw_DoubleQuote = u'"';
+static const QChar qtmw_Backtick = u'`';
+static const QChar qtmw_Backslash = u'\\';
+static const QChar qtmw_Period = u'.';
QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features)
: m_stream(stream), m_features(features)
@@ -72,6 +40,7 @@ QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::Mar
bool QTextMarkdownWriter::writeAll(const QTextDocument *document)
{
+ writeFrontMatter(document->metaInformation(QTextDocument::FrontMatter));
writeFrame(document->rootFrame());
return true;
}
@@ -81,28 +50,28 @@ void QTextMarkdownWriter::writeTable(const QAbstractItemModel *table)
{
QList<int> tableColumnWidths(table->columnCount());
for (int col = 0; col < table->columnCount(); ++col) {
- tableColumnWidths[col] = table->headerData(col, Qt::Horizontal).toString().length();
+ tableColumnWidths[col] = table->headerData(col, Qt::Horizontal).toString().size();
for (int row = 0; row < table->rowCount(); ++row) {
tableColumnWidths[col] = qMax(tableColumnWidths[col],
- table->data(table->index(row, col)).toString().length());
+ table->data(table->index(row, col)).toString().size());
}
}
// write the header and separator
for (int col = 0; col < table->columnCount(); ++col) {
QString s = table->headerData(col, Qt::Horizontal).toString();
- m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space);
+ m_stream << '|' << s << QString(tableColumnWidths[col] - s.size(), qtmw_Space);
}
m_stream << "|" << Qt::endl;
- for (int col = 0; col < tableColumnWidths.length(); ++col)
- m_stream << '|' << QString(tableColumnWidths[col], QLatin1Char('-'));
+ for (int col = 0; col < tableColumnWidths.size(); ++col)
+ m_stream << '|' << QString(tableColumnWidths[col], u'-');
m_stream << '|'<< Qt::endl;
// write the body
for (int row = 0; row < table->rowCount(); ++row) {
for (int col = 0; col < table->columnCount(); ++col) {
QString s = table->data(table->index(row, col)).toString();
- m_stream << "|" << s << QString(tableColumnWidths[col] - s.length(), Space);
+ m_stream << '|' << s << QString(tableColumnWidths[col] - s.size(), qtmw_Space);
}
m_stream << '|'<< Qt::endl;
}
@@ -110,6 +79,19 @@ void QTextMarkdownWriter::writeTable(const QAbstractItemModel *table)
}
#endif
+void QTextMarkdownWriter::writeFrontMatter(const QString &fm)
+{
+ const bool featureEnabled = m_features.testFlag(
+ static_cast<QTextDocument::MarkdownFeature>(QTextMarkdownImporter::FeatureFrontMatter));
+ qCDebug(lcMDW) << "writing FrontMatter?" << featureEnabled << "size" << fm.size();
+ if (fm.isEmpty() || !featureEnabled)
+ return;
+ m_stream << "---\n"_L1 << fm;
+ if (!fm.endsWith(qtmw_Newline))
+ m_stream << qtmw_Newline;
+ m_stream << "---\n"_L1;
+}
+
void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
{
Q_ASSERT(frame);
@@ -129,7 +111,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
while (it != cell.end()) {
QTextBlock block = it.currentBlock();
if (block.isValid())
- cellTextLen += block.text().length();
+ cellTextLen += block.text().size();
++it;
}
if (cell.columnSpan() == 1 && tableColumnWidths[col] < cellTextLen)
@@ -146,17 +128,22 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
// suppress needless blank lines, when there will be a big change in block format
bool nextIsDifferent = false;
bool ending = false;
+ int blockQuoteIndent = 0;
+ int nextBlockQuoteIndent = 0;
{
QTextFrame::iterator next = iterator;
++next;
+ QTextBlockFormat format = iterator.currentBlock().blockFormat();
+ QTextBlockFormat nextFormat = next.currentBlock().blockFormat();
+ blockQuoteIndent = format.intProperty(QTextFormat::BlockQuoteLevel);
+ nextBlockQuoteIndent = nextFormat.intProperty(QTextFormat::BlockQuoteLevel);
if (next.atEnd()) {
nextIsDifferent = true;
ending = true;
} else {
- QTextBlockFormat format = iterator.currentBlock().blockFormat();
- QTextBlockFormat nextFormat = next.currentBlock().blockFormat();
if (nextFormat.indent() != format.indent() ||
- nextFormat.property(QTextFormat::BlockCodeLanguage) != format.property(QTextFormat::BlockCodeLanguage))
+ nextFormat.property(QTextFormat::BlockCodeLanguage) !=
+ format.property(QTextFormat::BlockCodeLanguage))
nextIsDifferent = true;
}
}
@@ -164,17 +151,19 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
QTextTableCell cell = table->cellAt(block.position());
if (tableRow < cell.row()) {
if (tableRow == 0) {
- m_stream << Newline;
- for (int col = 0; col < tableColumnWidths.length(); ++col)
- m_stream << '|' << QString(tableColumnWidths[col], QLatin1Char('-'));
+ m_stream << qtmw_Newline;
+ for (int col = 0; col < tableColumnWidths.size(); ++col)
+ m_stream << '|' << QString(tableColumnWidths[col], u'-');
m_stream << '|';
}
- m_stream << Newline << "|";
+ m_stream << qtmw_Newline << '|';
tableRow = cell.row();
}
} else if (!block.textList()) {
- if (lastWasList)
- m_stream << Newline;
+ if (lastWasList) {
+ m_stream << qtmw_Newline;
+ m_linePrefixWritten = false;
+ }
}
int endingCol = writeBlock(block, !table, table && tableRow == 0,
nextIsDifferent && !block.textList());
@@ -186,20 +175,28 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
for (int col = cell.column(); col < spanEndCol; ++col)
paddingLen += tableColumnWidths[col];
if (paddingLen > 0)
- m_stream << QString(paddingLen, Space);
+ m_stream << QString(paddingLen, qtmw_Space);
for (int col = cell.column(); col < spanEndCol; ++col)
m_stream << "|";
} else if (m_fencedCodeBlock && ending) {
- m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space)
- << m_codeBlockFence << Newline << Newline;
+ m_stream << qtmw_Newline << m_linePrefix << QString(m_wrappedLineIndent, qtmw_Space)
+ << m_codeBlockFence << qtmw_Newline << qtmw_Newline;
m_codeBlockFence.clear();
} else if (m_indentedCodeBlock && nextIsDifferent) {
- m_stream << Newline;
+ m_stream << qtmw_Newline << qtmw_Newline;
} else if (endingCol > 0) {
if (block.textList() || block.blockFormat().hasProperty(QTextFormat::BlockCodeLanguage)) {
- m_stream << Newline;
+ m_stream << qtmw_Newline;
+ if (block.textList()) {
+ m_stream << m_linePrefix;
+ m_linePrefixWritten = true;
+ }
} else {
- m_stream << Newline << Newline;
+ m_stream << qtmw_Newline;
+ if (nextBlockQuoteIndent < blockQuoteIndent)
+ setLinePrefixForBlockQuote(nextBlockQuoteIndent);
+ m_stream << m_linePrefix;
+ m_stream << qtmw_Newline;
m_doubleNewlineWritten = true;
}
}
@@ -209,7 +206,7 @@ void QTextMarkdownWriter::writeFrame(const QTextFrame *frame)
++iterator;
}
if (table) {
- m_stream << Newline << Newline;
+ m_stream << qtmw_Newline << qtmw_Newline;
m_doubleNewlineWritten = true;
}
m_listInfo.clear();
@@ -245,18 +242,28 @@ QTextMarkdownWriter::ListInfo QTextMarkdownWriter::listInfo(QTextList *list)
return m_listInfo.value(list);
}
+void QTextMarkdownWriter::setLinePrefixForBlockQuote(int level)
+{
+ m_linePrefix.clear();
+ if (level > 0) {
+ m_linePrefix.reserve(level * 2);
+ for (int i = 0; i < level; ++i)
+ m_linePrefix += u"> ";
+ }
+}
+
static int nearestWordWrapIndex(const QString &s, int before)
{
- before = qMin(before, s.length());
+ before = qMin(before, s.size());
int fragBegin = qMax(before - 15, 0);
if (lcMDW().isDebugEnabled()) {
QString frag = s.mid(fragBegin, 30);
qCDebug(lcMDW) << frag << before;
- qCDebug(lcMDW) << QString(before - fragBegin, Period) + QLatin1Char('<');
+ qCDebug(lcMDW) << QString(before - fragBegin, qtmw_Period) + u'<';
}
for (int i = before - 1; i >= 0; --i) {
if (s.at(i).isSpace()) {
- qCDebug(lcMDW) << QString(i - fragBegin, Period) + QLatin1Char('^') << i;
+ qCDebug(lcMDW) << QString(i - fragBegin, qtmw_Period) + u'^' << i;
return i;
}
}
@@ -266,10 +273,10 @@ static int nearestWordWrapIndex(const QString &s, int before)
static int adjacentBackticksCount(const QString &s)
{
- int start = -1, len = s.length();
+ int start = -1, len = s.size();
int ret = 0;
for (int i = 0; i < len; ++i) {
- if (s.at(i) == Backtick) {
+ if (s.at(i) == qtmw_Backtick) {
if (start < 0)
start = i;
} else if (start >= 0) {
@@ -277,20 +284,58 @@ static int adjacentBackticksCount(const QString &s)
start = -1;
}
}
- if (s.at(len - 1) == Backtick)
+ if (s.at(len - 1) == qtmw_Backtick)
ret = qMax(ret, len - start);
return ret;
}
+/*! \internal
+ Escape anything at the beginning of a line of markdown that would be
+ misinterpreted by a markdown parser, including any period that follows a
+ number (to avoid misinterpretation as a numbered list item).
+ https://spec.commonmark.org/0.31.2/#backslash-escapes
+*/
static void maybeEscapeFirstChar(QString &s)
{
+ static const QRegularExpression numericListRe(uR"(\d+([\.)])\s)"_s);
+ static const QLatin1StringView specialFirstCharacters("#*+-");
+
QString sTrimmed = s.trimmed();
if (sTrimmed.isEmpty())
return;
- char firstChar = sTrimmed.at(0).toLatin1();
- if (firstChar == '*' || firstChar == '+' || firstChar == '-') {
- int i = s.indexOf(QLatin1Char(firstChar));
- s.insert(i, QLatin1Char('\\'));
+ QChar firstChar = sTrimmed.at(0);
+ if (specialFirstCharacters.contains(firstChar)) {
+ int i = s.indexOf(firstChar); // == 0 unless s got trimmed
+ s.insert(i, u'\\');
+ } else {
+ auto match = numericListRe.match(s, 0, QRegularExpression::NormalMatch,
+ QRegularExpression::AnchorAtOffsetMatchOption);
+ if (match.hasMatch())
+ s.insert(match.capturedStart(1), qtmw_Backslash);
+ }
+}
+
+/*! \internal
+ Escape all backslashes. Then escape any special character that stands
+ alone or prefixes a "word", including the \c < that starts an HTML tag.
+ https://spec.commonmark.org/0.31.2/#backslash-escapes
+*/
+static void escapeSpecialCharacters(QString &s)
+{
+ static const QRegularExpression spaceRe(uR"(\s+)"_s);
+ static const QRegularExpression specialRe(uR"([<!*[`&]+[/\w])"_s);
+
+ s.replace("\\"_L1, "\\\\"_L1);
+
+ int i = 0;
+ while (i >= 0) {
+ if (int j = s.indexOf(specialRe, i); j >= 0) {
+ s.insert(j, qtmw_Backslash);
+ i = j + 3;
+ }
+ i = s.indexOf(spaceRe, i);
+ if (i >= 0)
+ ++i; // past the whitespace, if found
}
}
@@ -304,14 +349,14 @@ static LineEndPositions findLineEnd(const QChar *begin, const QChar *end)
LineEndPositions result{ end, end };
while (begin < end) {
- if (*begin == Newline) {
+ if (*begin == qtmw_Newline) {
result.lineEnd = begin;
result.nextLineBegin = begin + 1;
break;
- } else if (*begin == CarriageReturn) {
+ } else if (*begin == qtmw_CarriageReturn) {
result.lineEnd = begin;
result.nextLineBegin = begin + 1;
- if (((begin + 1) < end) && begin[1] == Newline)
+ if (((begin + 1) < end) && begin[1] == qtmw_Newline)
++result.nextLineBegin;
break;
}
@@ -325,7 +370,7 @@ static LineEndPositions findLineEnd(const QChar *begin, const QChar *end)
static bool isBlankLine(const QChar *begin, const QChar *end)
{
while (begin < end) {
- if (*begin != Space && *begin != Tab)
+ if (*begin != qtmw_Space && *begin != qtmw_Tab)
return false;
++begin;
}
@@ -336,7 +381,7 @@ static QString createLinkTitle(const QString &title)
{
QString result;
result.reserve(title.size() + 2);
- result += DoubleQuote;
+ result += qtmw_DoubleQuote;
const QChar *data = title.data();
const QChar *end = data + title.size();
@@ -346,8 +391,8 @@ static QString createLinkTitle(const QString &title)
if (!isBlankLine(data, lineEndPositions.lineEnd)) {
while (data < lineEndPositions.nextLineBegin) {
- if (*data == DoubleQuote)
- result += Backslash;
+ if (*data == qtmw_DoubleQuote)
+ result += qtmw_Backslash;
result += *data;
++data;
}
@@ -356,7 +401,7 @@ static QString createLinkTitle(const QString &title)
data = lineEndPositions.nextLineBegin;
}
- result += DoubleQuote;
+ result += qtmw_DoubleQuote;
return result;
}
@@ -368,17 +413,29 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
QTextBlockFormat blockFmt = block.blockFormat();
bool missedBlankCodeBlockLine = false;
const bool codeBlock = blockFmt.hasProperty(QTextFormat::BlockCodeFence) ||
- blockFmt.stringProperty(QTextFormat::BlockCodeLanguage).length() > 0;
+ blockFmt.stringProperty(QTextFormat::BlockCodeLanguage).size() > 0 ||
+ blockFmt.nonBreakableLines();
+ const int blockQuoteLevel = blockFmt.intProperty(QTextFormat::BlockQuoteLevel);
if (m_fencedCodeBlock && !codeBlock) {
- m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space)
- << m_codeBlockFence << Newline;
+ m_stream << m_linePrefix << m_codeBlockFence << qtmw_Newline;
m_fencedCodeBlock = false;
m_codeBlockFence.clear();
+ m_linePrefixWritten = m_linePrefix.size() > 0;
+ }
+ m_linePrefix.clear();
+ if (!blockFmt.headingLevel() && blockQuoteLevel > 0) {
+ setLinePrefixForBlockQuote(blockQuoteLevel);
+ if (!m_linePrefixWritten) {
+ m_stream << m_linePrefix;
+ m_linePrefixWritten = true;
+ }
}
if (block.textList()) { // it's a list-item
auto fmt = block.textList()->format();
const int listLevel = fmt.indent();
- const int number = block.textList()->itemNumber(block) + 1;
+ // Negative numbers don't start a list in Markdown, so ignore them.
+ const int start = fmt.start() >= 0 ? fmt.start() : 1;
+ const int number = block.textList()->itemNumber(block) + start;
QByteArray bullet = " ";
bool numeric = false;
switch (fmt.style()) {
@@ -417,19 +474,19 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
int indentFirstLine = (listLevel - 1) * (numeric ? 4 : 2);
m_wrappedLineIndent += indentFirstLine;
if (m_lastListIndent != listLevel && !m_doubleNewlineWritten && listInfo(block.textList()).loose)
- m_stream << Newline;
+ m_stream << qtmw_Newline;
m_lastListIndent = listLevel;
- QString prefix(indentFirstLine, Space);
+ QString prefix(indentFirstLine, qtmw_Space);
if (numeric) {
QString suffix = fmt.numberSuffix();
if (suffix.isEmpty())
- suffix = QString(Period);
- QString numberStr = QString::number(number) + suffix + Space;
- if (numberStr.length() == 3)
- numberStr += Space;
+ suffix = QString(qtmw_Period);
+ QString numberStr = QString::number(number) + suffix + qtmw_Space;
+ if (numberStr.size() == 3)
+ numberStr += qtmw_Space;
prefix += numberStr;
} else {
- prefix += QLatin1String(bullet) + Space;
+ prefix += QLatin1StringView(bullet) + qtmw_Space;
}
m_stream << prefix;
} else if (blockFmt.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) {
@@ -443,136 +500,159 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
if (!m_fencedCodeBlock) {
QString fenceChar = blockFmt.stringProperty(QTextFormat::BlockCodeFence);
if (fenceChar.isEmpty())
- fenceChar = QLatin1String("`");
+ fenceChar = "`"_L1;
m_codeBlockFence = QString(3, fenceChar.at(0));
+ if (blockFmt.hasProperty(QTextFormat::BlockIndent))
+ m_codeBlockFence = QString(m_wrappedLineIndent, qtmw_Space) + m_codeBlockFence;
// A block quote can contain an indented code block, but not vice-versa.
- m_stream << m_linePrefix << QString(m_wrappedLineIndent, Space) << m_codeBlockFence
- << blockFmt.stringProperty(QTextFormat::BlockCodeLanguage) << Newline;
+ m_stream << m_codeBlockFence << blockFmt.stringProperty(QTextFormat::BlockCodeLanguage)
+ << qtmw_Newline << m_linePrefix;
m_fencedCodeBlock = true;
}
wrap = false;
} else if (!blockFmt.indent()) {
m_wrappedLineIndent = 0;
- m_linePrefix.clear();
- if (blockFmt.hasProperty(QTextFormat::BlockQuoteLevel)) {
- int level = blockFmt.intProperty(QTextFormat::BlockQuoteLevel);
- QString quoteMarker = QStringLiteral("> ");
- m_linePrefix.reserve(level * 2);
- for (int i = 0; i < level; ++i)
- m_linePrefix += quoteMarker;
- }
if (blockFmt.hasProperty(QTextFormat::BlockCodeLanguage)) {
// A block quote can contain an indented code block, but not vice-versa.
- m_linePrefix += QString(4, Space);
+ m_linePrefix += QString(4, qtmw_Space);
m_indentedCodeBlock = true;
}
+ if (!m_linePrefixWritten) {
+ m_stream << m_linePrefix;
+ m_linePrefixWritten = true;
+ }
}
- if (blockFmt.headingLevel())
+ if (blockFmt.headingLevel()) {
m_stream << QByteArray(blockFmt.headingLevel(), '#') << ' ';
- else
- m_stream << m_linePrefix;
+ wrap = false;
+ }
- QString wrapIndentString = m_linePrefix + QString(m_wrappedLineIndent, Space);
+ QString wrapIndentString = m_linePrefix + QString(m_wrappedLineIndent, qtmw_Space);
// It would be convenient if QTextStream had a lineCharPos() accessor,
// to keep track of how many characters (not bytes) have been written on the current line,
// but it doesn't. So we have to keep track with this col variable.
- int col = wrapIndentString.length();
+ int col = wrapIndentString.size();
bool mono = false;
bool startsOrEndsWithBacktick = false;
bool bold = false;
bool italic = false;
bool underline = false;
bool strikeOut = false;
- QString backticks(Backtick);
+ bool endingMarkers = false;
+ QString backticks(qtmw_Backtick);
for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) {
missedBlankCodeBlockLine = false;
QString fragmentText = frag.fragment().text();
- while (fragmentText.endsWith(Newline))
+ while (fragmentText.endsWith(qtmw_Newline))
fragmentText.chop(1);
+ if (!(m_fencedCodeBlock || m_indentedCodeBlock)) {
+ escapeSpecialCharacters(fragmentText);
+ maybeEscapeFirstChar(fragmentText);
+ }
if (block.textList()) { // <li>first line</br>continuation</li>
- QString newlineIndent = QString(Newline) + QString(m_wrappedLineIndent, Space);
- fragmentText.replace(QString(LineBreak), newlineIndent);
+ QString newlineIndent =
+ QString(qtmw_Newline) + QString(m_wrappedLineIndent, qtmw_Space);
+ fragmentText.replace(QString(qtmw_LineBreak), newlineIndent);
} else if (blockFmt.indent() > 0) { // <li>first line<p>continuation</p></li>
- m_stream << QString(m_wrappedLineIndent, Space);
+ m_stream << QString(m_wrappedLineIndent, qtmw_Space);
} else {
- fragmentText.replace(LineBreak, Newline);
+ fragmentText.replace(qtmw_LineBreak, qtmw_Newline);
}
- startsOrEndsWithBacktick |= fragmentText.startsWith(Backtick) || fragmentText.endsWith(Backtick);
+ startsOrEndsWithBacktick |=
+ fragmentText.startsWith(qtmw_Backtick) || fragmentText.endsWith(qtmw_Backtick);
QTextCharFormat fmt = frag.fragment().charFormat();
if (fmt.isImageFormat()) {
QTextImageFormat ifmt = fmt.toImageFormat();
QString desc = ifmt.stringProperty(QTextFormat::ImageAltText);
if (desc.isEmpty())
- desc = QLatin1String("image");
- QString s = QLatin1String("![") + desc + QLatin1String("](") + ifmt.name();
+ desc = "image"_L1;
+ QString s = "!["_L1 + desc + "]("_L1 + ifmt.name();
QString title = ifmt.stringProperty(QTextFormat::ImageTitle);
if (!title.isEmpty())
- s += Space + DoubleQuote + title + DoubleQuote;
- s += QLatin1Char(')');
- if (wrap && col + s.length() > ColumnLimit) {
- m_stream << Newline << wrapIndentString;
+ s += qtmw_Space + qtmw_DoubleQuote + title + qtmw_DoubleQuote;
+ s += u')';
+ if (wrap && col + s.size() > ColumnLimit) {
+ m_stream << qtmw_Newline << wrapIndentString;
col = m_wrappedLineIndent;
}
m_stream << s;
- col += s.length();
+ col += s.size();
} else if (fmt.hasProperty(QTextFormat::AnchorHref)) {
- QString s = QLatin1Char('[') + fragmentText + QLatin1String("](") +
- fmt.property(QTextFormat::AnchorHref).toString();
- if (fmt.hasProperty(QTextFormat::TextToolTip)) {
- s += Space;
- s += createLinkTitle(fmt.property(QTextFormat::TextToolTip).toString());
+ const auto href = fmt.property(QTextFormat::AnchorHref).toString();
+ const bool hasToolTip = fmt.hasProperty(QTextFormat::TextToolTip);
+ QString s;
+ if (!hasToolTip && href == fragmentText && !QUrl(href, QUrl::StrictMode).scheme().isEmpty()) {
+ s = u'<' + href + u'>';
+ } else {
+ s = u'[' + fragmentText + "]("_L1 + href;
+ if (hasToolTip) {
+ s += qtmw_Space;
+ s += createLinkTitle(fmt.property(QTextFormat::TextToolTip).toString());
+ }
+ s += u')';
}
- s += QLatin1Char(')');
- if (wrap && col + s.length() > ColumnLimit) {
- m_stream << Newline << wrapIndentString;
+ if (wrap && col + s.size() > ColumnLimit) {
+ m_stream << qtmw_Newline << wrapIndentString;
col = m_wrappedLineIndent;
}
m_stream << s;
- col += s.length();
+ col += s.size();
} else {
QFontInfo fontInfo(fmt.font());
- bool monoFrag = fontInfo.fixedPitch();
+ bool monoFrag = fontInfo.fixedPitch() || fmt.fontFixedPitch();
QString markers;
if (!ignoreFormat) {
if (monoFrag != mono && !m_indentedCodeBlock && !m_fencedCodeBlock) {
if (monoFrag)
- backticks = QString(adjacentBackticksCount(fragmentText) + 1, Backtick);
+ backticks =
+ QString(adjacentBackticksCount(fragmentText) + 1, qtmw_Backtick);
markers += backticks;
if (startsOrEndsWithBacktick)
- markers += Space;
+ markers += qtmw_Space;
mono = monoFrag;
+ if (!mono)
+ endingMarkers = true;
}
if (!blockFmt.headingLevel() && !mono) {
if (fontInfo.bold() != bold) {
- markers += QLatin1String("**");
+ markers += "**"_L1;
bold = fontInfo.bold();
+ if (!bold)
+ endingMarkers = true;
}
if (fontInfo.italic() != italic) {
- markers += QLatin1Char('*');
+ markers += u'*';
italic = fontInfo.italic();
+ if (!italic)
+ endingMarkers = true;
}
if (fontInfo.strikeOut() != strikeOut) {
- markers += QLatin1String("~~");
+ markers += "~~"_L1;
strikeOut = fontInfo.strikeOut();
+ if (!strikeOut)
+ endingMarkers = true;
}
if (fontInfo.underline() != underline) {
- // Markdown doesn't support underline, but the parser will treat a single underline
- // the same as a single asterisk, and the marked fragment will be rendered in italics.
- // That will have to do.
- markers += QLatin1Char('_');
+ // CommonMark specifies underline as another way to get emphasis (italics):
+ // https://spec.commonmark.org/0.31.2/#example-148
+ // but md4c allows us to distinguish them; so we support underlining (in GitHub dialect).
+ markers += u'_';
underline = fontInfo.underline();
+ if (!underline)
+ endingMarkers = true;
}
}
}
- if (wrap && col + markers.length() * 2 + fragmentText.length() > ColumnLimit) {
+ if (wrap && col + markers.size() * 2 + fragmentText.size() > ColumnLimit) {
int i = 0;
- int fragLen = fragmentText.length();
+ const int fragLen = fragmentText.size();
bool breakingLine = false;
while (i < fragLen) {
if (col >= ColumnLimit) {
- m_stream << Newline << wrapIndentString;
+ m_stream << markers << qtmw_Newline << wrapIndentString;
+ markers.clear();
col = m_wrappedLineIndent;
- while (fragmentText[i].isSpace())
+ while (i < fragLen && fragmentText[i].isSpace())
++i;
}
int j = i + ColumnLimit - col;
@@ -580,6 +660,13 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
int wi = nearestWordWrapIndex(fragmentText, j);
if (wi < 0) {
j = fragLen;
+ // can't break within the fragment: we need to break already _before_ it
+ if (endingMarkers) {
+ m_stream << markers;
+ markers.clear();
+ }
+ m_stream << qtmw_Newline << wrapIndentString;
+ col = m_wrappedLineIndent;
} else if (wi >= i) {
j = wi;
breakingLine = true;
@@ -591,28 +678,32 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
QString subfrag = fragmentText.mid(i, j - i);
if (!i) {
m_stream << markers;
- col += markers.length();
+ col += markers.size();
}
if (col == m_wrappedLineIndent)
maybeEscapeFirstChar(subfrag);
m_stream << subfrag;
if (breakingLine) {
- m_stream << Newline << wrapIndentString;
+ m_stream << qtmw_Newline << wrapIndentString;
col = m_wrappedLineIndent;
} else {
- col += subfrag.length();
+ col += subfrag.size();
}
i = j + 1;
- }
+ } // loop over fragment characters (we know we need to break somewhere)
} else {
+ if (!m_linePrefixWritten && col == wrapIndentString.size()) {
+ m_stream << m_linePrefix;
+ col += m_linePrefix.size();
+ }
m_stream << markers << fragmentText;
- col += markers.length() + fragmentText.length();
+ col += markers.size() + fragmentText.size();
}
}
}
if (mono) {
if (startsOrEndsWithBacktick) {
- m_stream << Space;
+ m_stream << qtmw_Space;
col += 1;
}
m_stream << backticks;
@@ -635,7 +726,8 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
col += 2;
}
if (missedBlankCodeBlockLine)
- m_stream << Newline;
+ m_stream << qtmw_Newline;
+ m_linePrefixWritten = false;
return col;
}
diff --git a/src/gui/text/qtextmarkdownwriter_p.h b/src/gui/text/qtextmarkdownwriter_p.h
index c3076155d0..c0989b8f72 100644
--- a/src/gui/text/qtextmarkdownwriter_p.h
+++ b/src/gui/text/qtextmarkdownwriter_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTMARKDOWNWRITER_P_H
#define QTEXTMARKDOWNWRITER_P_H
@@ -72,6 +36,7 @@ public:
int writeBlock(const QTextBlock &block, bool table, bool ignoreFormat, bool ignoreEmpty);
void writeFrame(const QTextFrame *frame);
+ void writeFrontMatter(const QString &fm);
private:
struct ListInfo {
@@ -79,6 +44,7 @@ private:
};
ListInfo listInfo(QTextList *list);
+ void setLinePrefixForBlockQuote(int level);
private:
QTextStream &m_stream;
@@ -89,6 +55,7 @@ private:
int m_wrappedLineIndent = 0;
int m_lastListIndent = 1;
bool m_doubleNewlineWritten = false;
+ bool m_linePrefixWritten = false;
bool m_indentedCodeBlock = false;
bool m_fencedCodeBlock = false;
};
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index 45e07ac5b5..6aafdc1a25 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextobject.h"
#include "qtextobject_p.h"
@@ -78,7 +42,7 @@ QT_BEGIN_NAMESPACE
objects, you will also need to reimplement QTextDocument::createObject()
which acts as a factory method for creating text objects.
- \sa QTextDocument, {Text Object Example}
+ \sa QTextDocument
*/
/*!
@@ -201,7 +165,7 @@ QTextDocument *QTextObject::document() const
void QTextBlockGroupPrivate::markBlocksDirty()
{
- for (int i = 0; i < blocks.count(); ++i) {
+ for (int i = 0; i < blocks.size(); ++i) {
const QTextBlock &block = blocks.at(i);
pieceTable->documentChange(block.position(), block.length());
}
@@ -210,7 +174,7 @@ void QTextBlockGroupPrivate::markBlocksDirty()
/*!
\fn QTextBlockGroup::QTextBlockGroup(QTextDocument *document)
- Creates a new new block group for the given \a document.
+ Creates a new block group for the given \a document.
\warning This function should only be called from
QTextDocument::createObject().
@@ -359,28 +323,28 @@ QTextFrameLayoutData::~QTextFrameLayoutData()
/*!
\fn bool QTextFrame::iterator::operator==(const iterator &other) const
- Retuns true if the iterator is the same as the \a other iterator;
+ Returns true if the iterator is the same as the \a other iterator;
otherwise returns \c false.
*/
/*!
\fn bool QTextFrame::iterator::operator!=(const iterator &other) const
- Retuns true if the iterator is different from the \a other iterator;
+ Returns true if the iterator is different from the \a other iterator;
otherwise returns \c false.
*/
/*!
\fn QTextFrame::iterator QTextFrame::iterator::operator++(int)
- The postfix ++ operator (\c{i++}) advances the iterator to the
+ The postfix \c{++} operator (\c{i++}) advances the iterator to the
next item in the text frame, and returns an iterator to the old item.
*/
/*!
\fn QTextFrame::iterator QTextFrame::iterator::operator--(int)
- The postfix -- operator (\c{i--}) makes the preceding item in the
+ The postfix \c{--} operator (\c{i--}) makes the preceding item in the
current frame, and returns an iterator to the old item.
*/
@@ -922,14 +886,14 @@ bool QTextBlock::isValid() const
/*!
\fn bool QTextBlock::iterator::operator==(const iterator &other) const
- Retuns true if this iterator is the same as the \a other iterator;
+ Returns true if this iterator is the same as the \a other iterator;
otherwise returns \c false.
*/
/*!
\fn bool QTextBlock::iterator::operator!=(const iterator &other) const
- Retuns true if this iterator is different from the \a other iterator;
+ Returns true if this iterator is different from the \a other iterator;
otherwise returns \c false.
*/
@@ -1792,3 +1756,5 @@ QString QTextFragment::text() const
}
QT_END_NAMESPACE
+
+#include "moc_qtextobject.cpp"
diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h
index 5402360baf..875886f825 100644
--- a/src/gui/text/qtextobject.h
+++ b/src/gui/text/qtextobject.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTOBJECT_H
#define QTEXTOBJECT_H
diff --git a/src/gui/text/qtextobject_p.h b/src/gui/text/qtextobject_p.h
index 87c83868da..8dad4d7ef4 100644
--- a/src/gui/text/qtextobject_p.h
+++ b/src/gui/text/qtextobject_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTOBJECT_P_H
#define QTEXTOBJECT_P_H
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp
index 76d316517d..b50771c12f 100644
--- a/src/gui/text/qtextodfwriter.cpp
+++ b/src/gui/text/qtextodfwriter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qglobal.h>
@@ -54,17 +18,20 @@
#include "qtexttable.h"
#include "qtextcursor.h"
#include "qtextimagehandler_p.h"
-#include "qzipwriter_p.h"
#include <QDebug>
+#include <QtCore/private/qzipwriter_p.h>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/// Convert pixels to postscript point units
static QString pixelToPoint(qreal pixels)
{
// we hardcode 96 DPI, we do the same in the ODF importer to have a perfect roundtrip.
- return QString::number(pixels * 72 / 96) + QLatin1String("pt");
+ return QString::number(pixels * 72 / 96) + "pt"_L1;
}
// strategies
@@ -296,17 +263,17 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
const int listLevel = block.textList()->format().indent();
if (m_listStack.isEmpty() || m_listStack.top() != block.textList()) {
// not the same list we were in.
- while (m_listStack.count() >= listLevel && !m_listStack.isEmpty() && m_listStack.top() != block.textList() ) { // we need to close tags
+ while (m_listStack.size() >= listLevel && !m_listStack.isEmpty() && m_listStack.top() != block.textList() ) { // we need to close tags
m_listStack.pop();
writer.writeEndElement(); // list
- if (m_listStack.count())
+ if (m_listStack.size())
writer.writeEndElement(); // list-item
}
- while (m_listStack.count() < listLevel) {
- if (m_listStack.count())
+ while (m_listStack.size() < listLevel) {
+ if (m_listStack.size())
writer.writeStartElement(textNS, QString::fromLatin1("list-item"));
writer.writeStartElement(textNS, QString::fromLatin1("list"));
- if (m_listStack.count() == listLevel - 1) {
+ if (m_listStack.size() == listLevel - 1) {
m_listStack.push(block.textList());
writer.writeAttribute(textNS, QString::fromLatin1("style-name"), QString::fromLatin1("L%1")
.arg(block.textList()->formatIndex()));
@@ -322,7 +289,7 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
while (! m_listStack.isEmpty()) {
m_listStack.pop();
writer.writeEndElement(); // list
- if (m_listStack.count())
+ if (m_listStack.size())
writer.writeEndElement(); // list-item
}
}
@@ -349,7 +316,7 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
writer.writeStartElement(textNS, QString::fromLatin1("span"));
QString fragmentText = frag.fragment().text();
- if (fragmentText.length() == 1 && fragmentText[0] == u'\xFFFC') { // its an inline character.
+ if (fragmentText.size() == 1 && fragmentText[0] == u'\xFFFC') { // its an inline character.
writeInlineCharacter(writer, frag.fragment());
writer.writeEndElement(); // span
continue;
@@ -360,8 +327,8 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
bool escapeNextSpace = true;
int precedingSpaces = 0;
int exportedIndex = 0;
- for (int i=0; i <= fragmentText.count(); ++i) {
- QChar character = (i == fragmentText.count() ? QChar() : fragmentText.at(i));
+ for (int i=0; i <= fragmentText.size(); ++i) {
+ QChar character = (i == fragmentText.size() ? QChar() : fragmentText.at(i));
bool isSpace = character.unicode() == ' ';
// find more than one space. -> <text:s text:c="2" />
@@ -377,7 +344,7 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
exportedIndex = i;
}
- if (i < fragmentText.count()) {
+ if (i < fragmentText.size()) {
if (character.unicode() == 0x2028) { // soft-return
//if (exportedIndex < i)
writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
@@ -454,11 +421,11 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
QImage image;
QString name = imageFormat.name();
- if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
- name.prepend(QLatin1String("qrc"));
+ if (name.startsWith(":/"_L1)) // auto-detect resources
+ name.prepend("qrc"_L1);
QUrl url = QUrl(name);
const QVariant variant = m_document->resource(QTextDocument::ImageResource, url);
- if (variant.userType() == QMetaType::QImage) {
+ if (variant.userType() == QMetaType::QPixmap || variant.userType() == QMetaType::QImage) {
image = qvariant_cast<QImage>(variant);
} else if (variant.userType() == QMetaType::QByteArray) {
data = variant.toByteArray();
@@ -479,7 +446,7 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
QBuffer imageBytes;
int imgQuality = imageFormat.quality();
- if (imgQuality >= 100 || imgQuality < 0 || image.hasAlphaChannel()) {
+ if (imgQuality >= 100 || imgQuality <= 0 || image.hasAlphaChannel()) {
QImageWriter imageWriter(&imageBytes, "png");
imageWriter.write(image);
@@ -678,7 +645,7 @@ void QTextOdfWriter::writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFor
value = QString::number(format.fontWeight());
writer.writeAttribute(foNS, QString::fromLatin1("font-weight"), value);
}
- if (format.hasProperty(QTextFormat::FontFamily))
+ if (format.hasProperty(QTextFormat::OldFontFamily))
writer.writeAttribute(foNS, QString::fromLatin1("font-family"), format.fontFamilies().toStringList().value(0, QString()));
else
writer.writeAttribute(foNS, QString::fromLatin1("font-family"), QString::fromLatin1("Sans")); // Qt default
@@ -867,7 +834,7 @@ void QTextOdfWriter::writeTableFormat(QXmlStreamWriter &writer, QTextTableFormat
writer.writeAttribute(tableNS, QString::fromLatin1("align"), QString::fromLatin1(align));
if (format.width().rawValue()) {
writer.writeAttribute(styleNS, QString::fromLatin1("width"),
- QString::number(format.width().rawValue()) + QLatin1String("pt"));
+ QString::number(format.width().rawValue()) + "pt"_L1);
}
writer.writeEndElement();
// start writing table-column style element
@@ -883,14 +850,14 @@ void QTextOdfWriter::writeTableFormat(QXmlStreamWriter &writer, QTextTableFormat
QString columnWidth;
if (format.columnWidthConstraints().at(colit).type() == QTextLength::PercentageLength) {
columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
- + QLatin1String("%");
+ + "%"_L1;
} else if (format.columnWidthConstraints().at(colit).type() == QTextLength::FixedLength) {
columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
- + QLatin1String("pt");
+ + "pt"_L1;
} else {
//!! HARD-CODING variableWidth Constraints to 100% / nr constraints
columnWidth = QString::number(100 / format.columnWidthConstraints().size())
- + QLatin1String("%");
+ + "%"_L1;
}
writer.writeAttribute(styleNS, QString::fromLatin1("column-width"), columnWidth);
writer.writeEndElement();
@@ -932,8 +899,8 @@ void QTextOdfWriter::tableCellStyleElement(QXmlStreamWriter &writer, const int &
writer.writeEmptyElement(styleNS, QString::fromLatin1("table-cell-properties"));
if (hasBorder) {
writer.writeAttribute(foNS, QString::fromLatin1("border"),
- pixelToPoint(tableFormatTmp.border()) + QLatin1String(" ")
- + borderStyleName(tableFormatTmp.borderStyle()) + QLatin1String(" ")
+ pixelToPoint(tableFormatTmp.border()) + " "_L1
+ + borderStyleName(tableFormatTmp.borderStyle()) + " "_L1
+ tableFormatTmp.borderBrush().color().name(QColor::HexRgb));
}
qreal topPadding = format.topPadding();
@@ -984,14 +951,14 @@ void QTextOdfWriter::tableCellStyleElement(QXmlStreamWriter &writer, const int &
///////////////////////
QTextOdfWriter::QTextOdfWriter(const QTextDocument &document, QIODevice *device)
- : officeNS (QLatin1String("urn:oasis:names:tc:opendocument:xmlns:office:1.0")),
- textNS (QLatin1String("urn:oasis:names:tc:opendocument:xmlns:text:1.0")),
- styleNS (QLatin1String("urn:oasis:names:tc:opendocument:xmlns:style:1.0")),
- foNS (QLatin1String("urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0")),
- tableNS (QLatin1String("urn:oasis:names:tc:opendocument:xmlns:table:1.0")),
- drawNS (QLatin1String("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0")),
- xlinkNS (QLatin1String("http://www.w3.org/1999/xlink")),
- svgNS (QLatin1String("urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0")),
+ : officeNS ("urn:oasis:names:tc:opendocument:xmlns:office:1.0"_L1),
+ textNS ("urn:oasis:names:tc:opendocument:xmlns:text:1.0"_L1),
+ styleNS ("urn:oasis:names:tc:opendocument:xmlns:style:1.0"_L1),
+ foNS ("urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"_L1),
+ tableNS ("urn:oasis:names:tc:opendocument:xmlns:table:1.0"_L1),
+ drawNS ("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"_L1),
+ xlinkNS ("http://www.w3.org/1999/xlink"_L1),
+ svgNS ("urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"_L1),
m_document(&document),
m_device(device),
m_strategy(nullptr),
diff --git a/src/gui/text/qtextodfwriter_p.h b/src/gui/text/qtextodfwriter_p.h
index 2c41dfba67..e02297da98 100644
--- a/src/gui/text/qtextodfwriter_p.h
+++ b/src/gui/text/qtextodfwriter_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTODFWRITER_H
#define QTEXTODFWRITER_H
diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp
index 908e0f914a..b6beadbe91 100644
--- a/src/gui/text/qtextoption.cpp
+++ b/src/gui/text/qtextoption.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtextoption.h"
#include "qguiapplication.h"
@@ -43,6 +7,8 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN_TAGGED(QTextOption::Tab, QTextOption_Tab)
+
struct QTextOptionPrivate
{
QList<QTextOption::Tab> tabStops;
@@ -143,7 +109,7 @@ void QTextOption::setTabArray(const QList<qreal> &tabStops)
d = new QTextOptionPrivate;
QList<QTextOption::Tab> tabs;
QTextOption::Tab tab;
- tabs.reserve(tabStops.count());
+ tabs.reserve(tabStops.size());
for (qreal pos : tabStops) {
tab.position = pos;
tabs.append(tab);
@@ -176,7 +142,7 @@ QList<qreal> QTextOption::tabArray() const
if (!d)
return answer;
- answer.reserve(d->tabStops.count());
+ answer.reserve(d->tabStops.size());
QList<QTextOption::Tab>::ConstIterator iter = d->tabStops.constBegin();
while(iter != d->tabStops.constEnd()) {
answer.append( (*iter).position);
@@ -363,11 +329,11 @@ QList<QTextOption::Tab> QTextOption::tabs() const
*/
/*!
- \variable Tab::position
+ \variable QTextOption::Tab::position
Distance from the start of the paragraph.
The position of a tab is from the start of the paragraph which implies that when
the alignment of the paragraph is set to centered, the tab is interpreted to be
- moved the same distance as the left ege of the paragraph does.
+ moved the same distance as the left edge of the paragraph does.
In case the paragraph is set to have a layoutDirection() RightToLeft the position
is interpreted to be from the right side of the paragraph with higher numbers moving
the tab to the left.
diff --git a/src/gui/text/qtextoption.h b/src/gui/text/qtextoption.h
index 629c1d48da..dcff41584f 100644
--- a/src/gui/text/qtextoption.h
+++ b/src/gui/text/qtextoption.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTOPTION_H
#define QTEXTOPTION_H
@@ -141,16 +105,16 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QTextOption::Flags)
inline void QTextOption::setAlignment(Qt::Alignment aalignment)
-{ align = aalignment; }
+{ align = uint(aalignment.toInt()); }
inline void QTextOption::setFlags(Flags aflags)
-{ f = aflags; }
+{ f = uint(aflags.toInt()); }
inline void QTextOption::setTabStopDistance(qreal atabStop)
{ tab = atabStop; }
QT_END_NAMESPACE
-Q_DECLARE_METATYPE( QTextOption::Tab )
+QT_DECL_METATYPE_EXTERN_TAGGED(QTextOption::Tab, QTextOption_Tab, Q_GUI_EXPORT)
#endif // QTEXTOPTION_H
diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp
index 951408052d..64b7aa6765 100644
--- a/src/gui/text/qtexttable.cpp
+++ b/src/gui/text/qtexttable.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtexttable.h"
#include "qtextcursor.h"
@@ -50,6 +14,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QTextTableCell
\reentrant
@@ -415,7 +381,7 @@ void QTextTablePrivate::fragmentRemoved(QChar type, uint fragment)
return;
if (type == QTextBeginningOfFrame) {
Q_ASSERT(cells.indexOf(int(fragment)) != -1);
- cells.removeAll(fragment);
+ cells.removeAll(int(fragment));
if (fragment_start == fragment && cells.size()) {
fragment_start = cells.at(0);
}
@@ -973,7 +939,7 @@ void QTextTable::removeColumns(int pos, int num)
QTextTableFormat tfmt = format();
tfmt.setColumns(tfmt.columns()-num);
QList<QTextLength> columnWidths = tfmt.columnWidthConstraints();
- if (columnWidths.count() > pos) {
+ if (columnWidths.size() > pos) {
columnWidths.remove(pos, num);
tfmt.setColumnWidthConstraints (columnWidths);
}
@@ -1110,7 +1076,7 @@ void QTextTable::mergeCells(int row, int column, int numRows, int numCols)
QTextCursorPrivate::fromPosition(p, insertPos++).insertBlock();
p->move(pos + 1, insertPos, nextPos - pos);
} else if (rowHasText) {
- QTextCursorPrivate::fromPosition(p, insertPos++).insertText(QLatin1String(" "));
+ QTextCursorPrivate::fromPosition(p, insertPos++).insertText(" "_L1);
p->move(pos + 1, insertPos, nextPos - pos);
} else {
p->move(pos, insertPos, nextPos - pos);
@@ -1335,3 +1301,5 @@ void QTextTable::setFormat(const QTextTableFormat &format)
*/
QT_END_NAMESPACE
+
+#include "moc_qtexttable.cpp"
diff --git a/src/gui/text/qtexttable.h b/src/gui/text/qtexttable.h
index 156b091b05..49f606d429 100644
--- a/src/gui/text/qtexttable.h
+++ b/src/gui/text/qtexttable.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTTABLE_H
#define QTEXTTABLE_H
diff --git a/src/gui/text/qtexttable_p.h b/src/gui/text/qtexttable_p.h
index 20ff67d1f9..3a652af046 100644
--- a/src/gui/text/qtexttable_p.h
+++ b/src/gui/text/qtexttable_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTTABLE_P_H
#define QTEXTTABLE_P_H
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
deleted file mode 100644
index 0f50a7508a..0000000000
--- a/src/gui/text/qzip.cpp
+++ /dev/null
@@ -1,1366 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qglobal.h>
-
-#ifndef QT_NO_TEXTODFWRITER
-
-#include "qzipreader_p.h"
-#include "qzipwriter_p.h"
-#include <qdatetime.h>
-#include <qendian.h>
-#include <qdebug.h>
-#include <qdir.h>
-
-#include <zlib.h>
-
-// Zip standard version for archives handled by this API
-// (actually, the only basic support of this version is implemented but it is enough for now)
-#define ZIP_VERSION 20
-
-#if 0
-#define ZDEBUG qDebug
-#else
-#define ZDEBUG if (0) qDebug
-#endif
-
-QT_BEGIN_NAMESPACE
-
-static inline uint readUInt(const uchar *data)
-{
- return (data[0]) + (data[1]<<8) + (data[2]<<16) + (data[3]<<24);
-}
-
-static inline ushort readUShort(const uchar *data)
-{
- return (data[0]) + (data[1]<<8);
-}
-
-static inline void writeUInt(uchar *data, uint i)
-{
- data[0] = i & 0xff;
- data[1] = (i>>8) & 0xff;
- data[2] = (i>>16) & 0xff;
- data[3] = (i>>24) & 0xff;
-}
-
-static inline void writeUShort(uchar *data, ushort i)
-{
- data[0] = i & 0xff;
- data[1] = (i>>8) & 0xff;
-}
-
-static inline void copyUInt(uchar *dest, const uchar *src)
-{
- dest[0] = src[0];
- dest[1] = src[1];
- dest[2] = src[2];
- dest[3] = src[3];
-}
-
-static inline void copyUShort(uchar *dest, const uchar *src)
-{
- dest[0] = src[0];
- dest[1] = src[1];
-}
-
-static void writeMSDosDate(uchar *dest, const QDateTime& dt)
-{
- if (dt.isValid()) {
- quint16 time =
- (dt.time().hour() << 11) // 5 bit hour
- | (dt.time().minute() << 5) // 6 bit minute
- | (dt.time().second() >> 1); // 5 bit double seconds
-
- dest[0] = time & 0xff;
- dest[1] = time >> 8;
-
- quint16 date =
- ((dt.date().year() - 1980) << 9) // 7 bit year 1980-based
- | (dt.date().month() << 5) // 4 bit month
- | (dt.date().day()); // 5 bit day
-
- dest[2] = char(date);
- dest[3] = char(date >> 8);
- } else {
- dest[0] = 0;
- dest[1] = 0;
- dest[2] = 0;
- dest[3] = 0;
- }
-}
-
-static int inflate(Bytef *dest, ulong *destLen, const Bytef *source, ulong sourceLen)
-{
- z_stream stream;
- int err;
-
- stream.next_in = const_cast<Bytef*>(source);
- stream.avail_in = (uInt)sourceLen;
- if ((uLong)stream.avail_in != sourceLen)
- return Z_BUF_ERROR;
-
- stream.next_out = dest;
- stream.avail_out = (uInt)*destLen;
- if ((uLong)stream.avail_out != *destLen)
- return Z_BUF_ERROR;
-
- stream.zalloc = (alloc_func)nullptr;
- stream.zfree = (free_func)nullptr;
-
- err = inflateInit2(&stream, -MAX_WBITS);
- if (err != Z_OK)
- return err;
-
- err = inflate(&stream, Z_FINISH);
- if (err != Z_STREAM_END) {
- inflateEnd(&stream);
- if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
- return Z_DATA_ERROR;
- return err;
- }
- *destLen = stream.total_out;
-
- err = inflateEnd(&stream);
- return err;
-}
-
-static int deflate (Bytef *dest, ulong *destLen, const Bytef *source, ulong sourceLen)
-{
- z_stream stream;
- int err;
-
- stream.next_in = const_cast<Bytef*>(source);
- stream.avail_in = (uInt)sourceLen;
- stream.next_out = dest;
- stream.avail_out = (uInt)*destLen;
- if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
-
- stream.zalloc = (alloc_func)nullptr;
- stream.zfree = (free_func)nullptr;
- stream.opaque = (voidpf)nullptr;
-
- err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
- if (err != Z_OK) return err;
-
- err = deflate(&stream, Z_FINISH);
- if (err != Z_STREAM_END) {
- deflateEnd(&stream);
- return err == Z_OK ? Z_BUF_ERROR : err;
- }
- *destLen = stream.total_out;
-
- err = deflateEnd(&stream);
- return err;
-}
-
-
-namespace WindowsFileAttributes {
-enum {
- Dir = 0x10, // FILE_ATTRIBUTE_DIRECTORY
- File = 0x80, // FILE_ATTRIBUTE_NORMAL
- TypeMask = 0x90,
-
- ReadOnly = 0x01, // FILE_ATTRIBUTE_READONLY
- PermMask = 0x01
-};
-}
-
-namespace UnixFileAttributes {
-enum {
- Dir = 0040000, // __S_IFDIR
- File = 0100000, // __S_IFREG
- SymLink = 0120000, // __S_IFLNK
- TypeMask = 0170000, // __S_IFMT
-
- ReadUser = 0400, // __S_IRUSR
- WriteUser = 0200, // __S_IWUSR
- ExeUser = 0100, // __S_IXUSR
- ReadGroup = 0040, // __S_IRGRP
- WriteGroup = 0020, // __S_IWGRP
- ExeGroup = 0010, // __S_IXGRP
- ReadOther = 0004, // __S_IROTH
- WriteOther = 0002, // __S_IWOTH
- ExeOther = 0001, // __S_IXOTH
- PermMask = 0777
-};
-}
-
-static QFile::Permissions modeToPermissions(quint32 mode)
-{
- QFile::Permissions ret;
- if (mode & UnixFileAttributes::ReadUser)
- ret |= QFile::ReadOwner | QFile::ReadUser;
- if (mode & UnixFileAttributes::WriteUser)
- ret |= QFile::WriteOwner | QFile::WriteUser;
- if (mode & UnixFileAttributes::ExeUser)
- ret |= QFile::ExeOwner | QFile::ExeUser;
- if (mode & UnixFileAttributes::ReadGroup)
- ret |= QFile::ReadGroup;
- if (mode & UnixFileAttributes::WriteGroup)
- ret |= QFile::WriteGroup;
- if (mode & UnixFileAttributes::ExeGroup)
- ret |= QFile::ExeGroup;
- if (mode & UnixFileAttributes::ReadOther)
- ret |= QFile::ReadOther;
- if (mode & UnixFileAttributes::WriteOther)
- ret |= QFile::WriteOther;
- if (mode & UnixFileAttributes::ExeOther)
- ret |= QFile::ExeOther;
- return ret;
-}
-
-static quint32 permissionsToMode(QFile::Permissions perms)
-{
- quint32 mode = 0;
- if (perms & (QFile::ReadOwner | QFile::ReadUser))
- mode |= UnixFileAttributes::ReadUser;
- if (perms & (QFile::WriteOwner | QFile::WriteUser))
- mode |= UnixFileAttributes::WriteUser;
- if (perms & (QFile::ExeOwner | QFile::ExeUser))
- mode |= UnixFileAttributes::WriteUser;
- if (perms & QFile::ReadGroup)
- mode |= UnixFileAttributes::ReadGroup;
- if (perms & QFile::WriteGroup)
- mode |= UnixFileAttributes::WriteGroup;
- if (perms & QFile::ExeGroup)
- mode |= UnixFileAttributes::ExeGroup;
- if (perms & QFile::ReadOther)
- mode |= UnixFileAttributes::ReadOther;
- if (perms & QFile::WriteOther)
- mode |= UnixFileAttributes::WriteOther;
- if (perms & QFile::ExeOther)
- mode |= UnixFileAttributes::ExeOther;
- return mode;
-}
-
-static QDateTime readMSDosDate(const uchar *src)
-{
- uint dosDate = readUInt(src);
- quint64 uDate;
- uDate = (quint64)(dosDate >> 16);
- uint tm_mday = (uDate & 0x1f);
- uint tm_mon = ((uDate & 0x1E0) >> 5);
- uint tm_year = (((uDate & 0x0FE00) >> 9) + 1980);
- uint tm_hour = ((dosDate & 0xF800) >> 11);
- uint tm_min = ((dosDate & 0x7E0) >> 5);
- uint tm_sec = ((dosDate & 0x1f) << 1);
-
- return QDateTime(QDate(tm_year, tm_mon, tm_mday), QTime(tm_hour, tm_min, tm_sec));
-}
-
-// for details, see http://www.pkware.com/documents/casestudies/APPNOTE.TXT
-
-enum HostOS {
- HostFAT = 0,
- HostAMIGA = 1,
- HostVMS = 2, // VAX/VMS
- HostUnix = 3,
- HostVM_CMS = 4,
- HostAtari = 5, // what if it's a minix filesystem? [cjh]
- HostHPFS = 6, // filesystem used by OS/2 (and NT 3.x)
- HostMac = 7,
- HostZ_System = 8,
- HostCPM = 9,
- HostTOPS20 = 10, // pkzip 2.50 NTFS
- HostNTFS = 11, // filesystem used by Windows NT
- HostQDOS = 12, // SMS/QDOS
- HostAcorn = 13, // Archimedes Acorn RISC OS
- HostVFAT = 14, // filesystem used by Windows 95, NT
- HostMVS = 15,
- HostBeOS = 16, // hybrid POSIX/database filesystem
- HostTandem = 17,
- HostOS400 = 18,
- HostOSX = 19
-};
-Q_DECLARE_TYPEINFO(HostOS, Q_PRIMITIVE_TYPE);
-
-enum GeneralPurposeFlag {
- Encrypted = 0x01,
- AlgTune1 = 0x02,
- AlgTune2 = 0x04,
- HasDataDescriptor = 0x08,
- PatchedData = 0x20,
- StrongEncrypted = 0x40,
- Utf8Names = 0x0800,
- CentralDirectoryEncrypted = 0x2000
-};
-Q_DECLARE_TYPEINFO(GeneralPurposeFlag, Q_PRIMITIVE_TYPE);
-
-enum CompressionMethod {
- CompressionMethodStored = 0,
- CompressionMethodShrunk = 1,
- CompressionMethodReduced1 = 2,
- CompressionMethodReduced2 = 3,
- CompressionMethodReduced3 = 4,
- CompressionMethodReduced4 = 5,
- CompressionMethodImploded = 6,
- CompressionMethodReservedTokenizing = 7, // reserved for tokenizing
- CompressionMethodDeflated = 8,
- CompressionMethodDeflated64 = 9,
- CompressionMethodPKImploding = 10,
-
- CompressionMethodBZip2 = 12,
-
- CompressionMethodLZMA = 14,
-
- CompressionMethodTerse = 18,
- CompressionMethodLz77 = 19,
-
- CompressionMethodJpeg = 96,
- CompressionMethodWavPack = 97,
- CompressionMethodPPMd = 98,
- CompressionMethodWzAES = 99
-};
-Q_DECLARE_TYPEINFO(CompressionMethod, Q_PRIMITIVE_TYPE);
-
-struct LocalFileHeader
-{
- uchar signature[4]; // 0x04034b50
- uchar version_needed[2];
- uchar general_purpose_bits[2];
- uchar compression_method[2];
- uchar last_mod_file[4];
- uchar crc_32[4];
- uchar compressed_size[4];
- uchar uncompressed_size[4];
- uchar file_name_length[2];
- uchar extra_field_length[2];
-};
-Q_DECLARE_TYPEINFO(LocalFileHeader, Q_PRIMITIVE_TYPE);
-
-struct DataDescriptor
-{
- uchar crc_32[4];
- uchar compressed_size[4];
- uchar uncompressed_size[4];
-};
-Q_DECLARE_TYPEINFO(DataDescriptor, Q_PRIMITIVE_TYPE);
-
-struct CentralFileHeader
-{
- uchar signature[4]; // 0x02014b50
- uchar version_made[2];
- uchar version_needed[2];
- uchar general_purpose_bits[2];
- uchar compression_method[2];
- uchar last_mod_file[4];
- uchar crc_32[4];
- uchar compressed_size[4];
- uchar uncompressed_size[4];
- uchar file_name_length[2];
- uchar extra_field_length[2];
- uchar file_comment_length[2];
- uchar disk_start[2];
- uchar internal_file_attributes[2];
- uchar external_file_attributes[4];
- uchar offset_local_header[4];
-};
-Q_DECLARE_TYPEINFO(CentralFileHeader, Q_PRIMITIVE_TYPE);
-
-struct EndOfDirectory
-{
- uchar signature[4]; // 0x06054b50
- uchar this_disk[2];
- uchar start_of_directory_disk[2];
- uchar num_dir_entries_this_disk[2];
- uchar num_dir_entries[2];
- uchar directory_size[4];
- uchar dir_start_offset[4];
- uchar comment_length[2];
-};
-Q_DECLARE_TYPEINFO(EndOfDirectory, Q_PRIMITIVE_TYPE);
-
-struct FileHeader
-{
- CentralFileHeader h;
- QByteArray file_name;
- QByteArray extra_field;
- QByteArray file_comment;
-};
-Q_DECLARE_TYPEINFO(FileHeader, Q_RELOCATABLE_TYPE);
-
-class QZipPrivate
-{
-public:
- QZipPrivate(QIODevice *device, bool ownDev)
- : device(device), ownDevice(ownDev), dirtyFileTree(true), start_of_directory(0)
- {
- }
-
- ~QZipPrivate()
- {
- if (ownDevice)
- delete device;
- }
-
- QZipReader::FileInfo fillFileInfo(int index) const;
-
- QIODevice *device;
- bool ownDevice;
- bool dirtyFileTree;
- QList<FileHeader> fileHeaders;
- QByteArray comment;
- uint start_of_directory;
-};
-
-QZipReader::FileInfo QZipPrivate::fillFileInfo(int index) const
-{
- QZipReader::FileInfo fileInfo;
- FileHeader header = fileHeaders.at(index);
- quint32 mode = readUInt(header.h.external_file_attributes);
- const HostOS hostOS = HostOS(readUShort(header.h.version_made) >> 8);
- switch (hostOS) {
- case HostUnix:
- mode = (mode >> 16) & 0xffff;
- switch (mode & UnixFileAttributes::TypeMask) {
- case UnixFileAttributes::SymLink:
- fileInfo.isSymLink = true;
- break;
- case UnixFileAttributes::Dir:
- fileInfo.isDir = true;
- break;
- case UnixFileAttributes::File:
- default: // ### just for the case; should we warn?
- fileInfo.isFile = true;
- break;
- }
- fileInfo.permissions = modeToPermissions(mode);
- break;
- case HostFAT:
- case HostNTFS:
- case HostHPFS:
- case HostVFAT:
- switch (mode & WindowsFileAttributes::TypeMask) {
- case WindowsFileAttributes::Dir:
- fileInfo.isDir = true;
- break;
- case WindowsFileAttributes::File:
- default:
- fileInfo.isFile = true;
- break;
- }
- fileInfo.permissions |= QFile::ReadOwner | QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther;
- if ((mode & WindowsFileAttributes::ReadOnly) == 0)
- fileInfo.permissions |= QFile::WriteOwner | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther;
- if (fileInfo.isDir)
- fileInfo.permissions |= QFile::ExeOwner | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther;
- break;
- default:
- qWarning("QZip: Zip entry format at %d is not supported.", index);
- return fileInfo; // we don't support anything else
- }
-
- ushort general_purpose_bits = readUShort(header.h.general_purpose_bits);
- // if bit 11 is set, the filename and comment fields must be encoded using UTF-8
- const bool inUtf8 = (general_purpose_bits & Utf8Names) != 0;
- fileInfo.filePath = inUtf8 ? QString::fromUtf8(header.file_name) : QString::fromLocal8Bit(header.file_name);
- fileInfo.crc = readUInt(header.h.crc_32);
- fileInfo.size = readUInt(header.h.uncompressed_size);
- fileInfo.lastModified = readMSDosDate(header.h.last_mod_file);
-
- // fix the file path, if broken (convert separators, eat leading and trailing ones)
- fileInfo.filePath = QDir::fromNativeSeparators(fileInfo.filePath);
- QStringView filePathRef(fileInfo.filePath);
- while (filePathRef.startsWith(QLatin1Char('.')) || filePathRef.startsWith(QLatin1Char('/')))
- filePathRef = filePathRef.mid(1);
- while (filePathRef.endsWith(QLatin1Char('/')))
- filePathRef.chop(1);
-
- fileInfo.filePath = filePathRef.toString();
- return fileInfo;
-}
-
-class QZipReaderPrivate : public QZipPrivate
-{
-public:
- QZipReaderPrivate(QIODevice *device, bool ownDev)
- : QZipPrivate(device, ownDev), status(QZipReader::NoError)
- {
- }
-
- void scanFiles();
-
- QZipReader::Status status;
-};
-
-class QZipWriterPrivate : public QZipPrivate
-{
-public:
- QZipWriterPrivate(QIODevice *device, bool ownDev)
- : QZipPrivate(device, ownDev),
- status(QZipWriter::NoError),
- permissions(QFile::ReadOwner | QFile::WriteOwner),
- compressionPolicy(QZipWriter::AlwaysCompress)
- {
- }
-
- QZipWriter::Status status;
- QFile::Permissions permissions;
- QZipWriter::CompressionPolicy compressionPolicy;
-
- enum EntryType { Directory, File, Symlink };
-
- void addEntry(EntryType type, const QString &fileName, const QByteArray &contents);
-};
-
-static LocalFileHeader toLocalHeader(const CentralFileHeader &ch)
-{
- LocalFileHeader h;
- writeUInt(h.signature, 0x04034b50);
- copyUShort(h.version_needed, ch.version_needed);
- copyUShort(h.general_purpose_bits, ch.general_purpose_bits);
- copyUShort(h.compression_method, ch.compression_method);
- copyUInt(h.last_mod_file, ch.last_mod_file);
- copyUInt(h.crc_32, ch.crc_32);
- copyUInt(h.compressed_size, ch.compressed_size);
- copyUInt(h.uncompressed_size, ch.uncompressed_size);
- copyUShort(h.file_name_length, ch.file_name_length);
- copyUShort(h.extra_field_length, ch.extra_field_length);
- return h;
-}
-
-void QZipReaderPrivate::scanFiles()
-{
- if (!dirtyFileTree)
- return;
-
- if (! (device->isOpen() || device->open(QIODevice::ReadOnly))) {
- status = QZipReader::FileOpenError;
- return;
- }
-
- if ((device->openMode() & QIODevice::ReadOnly) == 0) { // only read the index from readable files.
- status = QZipReader::FileReadError;
- return;
- }
-
- dirtyFileTree = false;
- uchar tmp[4];
- device->read((char *)tmp, 4);
- if (readUInt(tmp) != 0x04034b50) {
- qWarning("QZip: not a zip file!");
- return;
- }
-
- // find EndOfDirectory header
- int i = 0;
- int start_of_directory = -1;
- int num_dir_entries = 0;
- EndOfDirectory eod;
- while (start_of_directory == -1) {
- const int pos = device->size() - int(sizeof(EndOfDirectory)) - i;
- if (pos < 0 || i > 65535) {
- qWarning("QZip: EndOfDirectory not found");
- return;
- }
-
- device->seek(pos);
- device->read((char *)&eod, sizeof(EndOfDirectory));
- if (readUInt(eod.signature) == 0x06054b50)
- break;
- ++i;
- }
-
- // have the eod
- start_of_directory = readUInt(eod.dir_start_offset);
- num_dir_entries = readUShort(eod.num_dir_entries);
- ZDEBUG("start_of_directory at %d, num_dir_entries=%d", start_of_directory, num_dir_entries);
- int comment_length = readUShort(eod.comment_length);
- if (comment_length != i)
- qWarning("QZip: failed to parse zip file.");
- comment = device->read(qMin(comment_length, i));
-
-
- device->seek(start_of_directory);
- for (i = 0; i < num_dir_entries; ++i) {
- FileHeader header;
- int read = device->read((char *) &header.h, sizeof(CentralFileHeader));
- if (read < (int)sizeof(CentralFileHeader)) {
- qWarning("QZip: Failed to read complete header, index may be incomplete");
- break;
- }
- if (readUInt(header.h.signature) != 0x02014b50) {
- qWarning("QZip: invalid header signature, index may be incomplete");
- break;
- }
-
- int l = readUShort(header.h.file_name_length);
- header.file_name = device->read(l);
- if (header.file_name.length() != l) {
- qWarning("QZip: Failed to read filename from zip index, index may be incomplete");
- break;
- }
- l = readUShort(header.h.extra_field_length);
- header.extra_field = device->read(l);
- if (header.extra_field.length() != l) {
- qWarning("QZip: Failed to read extra field in zip file, skipping file, index may be incomplete");
- break;
- }
- l = readUShort(header.h.file_comment_length);
- header.file_comment = device->read(l);
- if (header.file_comment.length() != l) {
- qWarning("QZip: Failed to read read file comment, index may be incomplete");
- break;
- }
-
- ZDEBUG("found file '%s'", header.file_name.data());
- fileHeaders.append(header);
- }
-}
-
-void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const QByteArray &contents/*, QFile::Permissions permissions, QZip::Method m*/)
-{
-#ifndef NDEBUG
- static const char *const entryTypes[] = {
- "directory",
- "file ",
- "symlink " };
- ZDEBUG() << "adding" << entryTypes[type] <<":" << fileName.toUtf8().data() << (type == 2 ? QByteArray(" -> " + contents).constData() : "");
-#endif
-
- if (! (device->isOpen() || device->open(QIODevice::WriteOnly))) {
- status = QZipWriter::FileOpenError;
- return;
- }
- device->seek(start_of_directory);
-
- // don't compress small files
- QZipWriter::CompressionPolicy compression = compressionPolicy;
- if (compressionPolicy == QZipWriter::AutoCompress) {
- if (contents.length() < 64)
- compression = QZipWriter::NeverCompress;
- else
- compression = QZipWriter::AlwaysCompress;
- }
-
- FileHeader header;
- memset(&header.h, 0, sizeof(CentralFileHeader));
- writeUInt(header.h.signature, 0x02014b50);
-
- writeUShort(header.h.version_needed, ZIP_VERSION);
- writeUInt(header.h.uncompressed_size, contents.length());
- writeMSDosDate(header.h.last_mod_file, QDateTime::currentDateTime());
- QByteArray data = contents;
- if (compression == QZipWriter::AlwaysCompress) {
- writeUShort(header.h.compression_method, CompressionMethodDeflated);
-
- ulong len = contents.length();
- // shamelessly copied form zlib
- len += (len >> 12) + (len >> 14) + 11;
- int res;
- do {
- data.resize(len);
- res = deflate((uchar*)data.data(), &len, (const uchar*)contents.constData(), contents.length());
-
- switch (res) {
- case Z_OK:
- data.resize(len);
- break;
- case Z_MEM_ERROR:
- qWarning("QZip: Z_MEM_ERROR: Not enough memory to compress file, skipping");
- data.resize(0);
- break;
- case Z_BUF_ERROR:
- len *= 2;
- break;
- }
- } while (res == Z_BUF_ERROR);
- }
-// TODO add a check if data.length() > contents.length(). Then try to store the original and revert the compression method to be uncompressed
- writeUInt(header.h.compressed_size, data.length());
- uint crc_32 = ::crc32(0, nullptr, 0);
- crc_32 = ::crc32(crc_32, (const uchar *)contents.constData(), contents.length());
- writeUInt(header.h.crc_32, crc_32);
-
- // if bit 11 is set, the filename and comment fields must be encoded using UTF-8
- ushort general_purpose_bits = Utf8Names; // always use utf-8
- writeUShort(header.h.general_purpose_bits, general_purpose_bits);
-
- const bool inUtf8 = (general_purpose_bits & Utf8Names) != 0;
- header.file_name = inUtf8 ? fileName.toUtf8() : fileName.toLocal8Bit();
- if (header.file_name.size() > 0xffff) {
- qWarning("QZip: Filename is too long, chopping it to 65535 bytes");
- header.file_name = header.file_name.left(0xffff); // ### don't break the utf-8 sequence, if any
- }
- if (header.file_comment.size() + header.file_name.size() > 0xffff) {
- qWarning("QZip: File comment is too long, chopping it to 65535 bytes");
- header.file_comment.truncate(0xffff - header.file_name.size()); // ### don't break the utf-8 sequence, if any
- }
- writeUShort(header.h.file_name_length, header.file_name.length());
- //h.extra_field_length[2];
-
- writeUShort(header.h.version_made, HostUnix << 8);
- //uchar internal_file_attributes[2];
- //uchar external_file_attributes[4];
- quint32 mode = permissionsToMode(permissions);
- switch (type) {
- case Symlink:
- mode |= UnixFileAttributes::SymLink;
- break;
- case Directory:
- mode |= UnixFileAttributes::Dir;
- break;
- case File:
- mode |= UnixFileAttributes::File;
- break;
- default:
- Q_UNREACHABLE();
- break;
- }
- writeUInt(header.h.external_file_attributes, mode << 16);
- writeUInt(header.h.offset_local_header, start_of_directory);
-
-
- fileHeaders.append(header);
-
- LocalFileHeader h = toLocalHeader(header.h);
- device->write((const char *)&h, sizeof(LocalFileHeader));
- device->write(header.file_name);
- device->write(data);
- start_of_directory = device->pos();
- dirtyFileTree = true;
-}
-
-////////////////////////////// Reader
-
-/*!
- \class QZipReader::FileInfo
- \internal
- Represents one entry in the zip table of contents.
-*/
-
-/*!
- \variable FileInfo::filePath
- The full filepath inside the archive.
-*/
-
-/*!
- \variable FileInfo::isDir
- A boolean type indicating if the entry is a directory.
-*/
-
-/*!
- \variable FileInfo::isFile
- A boolean type, if it is one this entry is a file.
-*/
-
-/*!
- \variable FileInfo::isSymLink
- A boolean type, if it is one this entry is symbolic link.
-*/
-
-/*!
- \variable FileInfo::permissions
- A list of flags for the permissions of this entry.
-*/
-
-/*!
- \variable FileInfo::crc
- The calculated checksum as a crc type.
-*/
-
-/*!
- \variable FileInfo::size
- The total size of the unpacked content.
-*/
-
-/*!
- \class QZipReader
- \internal
- \since 4.5
-
- \brief the QZipReader class provides a way to inspect the contents of a zip
- archive and extract individual files from it.
-
- QZipReader can be used to read a zip archive either from a file or from any
- device. An in-memory QBuffer for instance. The reader can be used to read
- which files are in the archive using fileInfoList() and entryInfoAt() but
- also to extract individual files using fileData() or even to extract all
- files in the archive using extractAll()
-*/
-
-/*!
- Create a new zip archive that operates on the \a fileName. The file will be
- opened with the \a mode.
-*/
-QZipReader::QZipReader(const QString &archive, QIODevice::OpenMode mode)
-{
- QScopedPointer<QFile> f(new QFile(archive));
- const bool result = f->open(mode);
- QZipReader::Status status;
- const QFileDevice::FileError error = f->error();
- if (result && error == QFile::NoError) {
- status = NoError;
- } else {
- if (error == QFile::ReadError)
- status = FileReadError;
- else if (error == QFile::OpenError)
- status = FileOpenError;
- else if (error == QFile::PermissionsError)
- status = FilePermissionsError;
- else
- status = FileError;
- }
-
- d = new QZipReaderPrivate(f.data(), /*ownDevice=*/true);
- f.take();
- d->status = status;
-}
-
-/*!
- Create a new zip archive that operates on the archive found in \a device.
- You have to open the device previous to calling the constructor and only a
- device that is readable will be scanned for zip filecontent.
- */
-QZipReader::QZipReader(QIODevice *device)
- : d(new QZipReaderPrivate(device, /*ownDevice=*/false))
-{
- Q_ASSERT(device);
-}
-
-/*!
- Desctructor
-*/
-QZipReader::~QZipReader()
-{
- close();
- delete d;
-}
-
-/*!
- Returns device used for reading zip archive.
-*/
-QIODevice* QZipReader::device() const
-{
- return d->device;
-}
-
-/*!
- Returns \c true if the user can read the file; otherwise returns \c false.
-*/
-bool QZipReader::isReadable() const
-{
- return d->device->isReadable();
-}
-
-/*!
- Returns \c true if the file exists; otherwise returns \c false.
-*/
-bool QZipReader::exists() const
-{
- QFile *f = qobject_cast<QFile*> (d->device);
- if (f == nullptr)
- return true;
- return f->exists();
-}
-
-/*!
- Returns the list of files the archive contains.
-*/
-QList<QZipReader::FileInfo> QZipReader::fileInfoList() const
-{
- d->scanFiles();
- QList<FileInfo> files;
- const int numFileHeaders = d->fileHeaders.size();
- files.reserve(numFileHeaders);
- for (int i = 0; i < numFileHeaders; ++i)
- files.append(d->fillFileInfo(i));
- return files;
-
-}
-
-/*!
- Return the number of items in the zip archive.
-*/
-int QZipReader::count() const
-{
- d->scanFiles();
- return d->fileHeaders.count();
-}
-
-/*!
- Returns a FileInfo of an entry in the zipfile.
- The \a index is the index into the directory listing of the zipfile.
- Returns an invalid FileInfo if \a index is out of boundaries.
-
- \sa fileInfoList()
-*/
-QZipReader::FileInfo QZipReader::entryInfoAt(int index) const
-{
- d->scanFiles();
- if (index >= 0 && index < d->fileHeaders.count())
- return d->fillFileInfo(index);
- return QZipReader::FileInfo();
-}
-
-/*!
- Fetch the file contents from the zip archive and return the uncompressed bytes.
-*/
-QByteArray QZipReader::fileData(const QString &fileName) const
-{
- d->scanFiles();
- int i;
- for (i = 0; i < d->fileHeaders.size(); ++i) {
- if (QString::fromLocal8Bit(d->fileHeaders.at(i).file_name) == fileName)
- break;
- }
- if (i == d->fileHeaders.size())
- return QByteArray();
-
- FileHeader header = d->fileHeaders.at(i);
-
- ushort version_needed = readUShort(header.h.version_needed);
- if (version_needed > ZIP_VERSION) {
- qWarning("QZip: .ZIP specification version %d implementationis needed to extract the data.", version_needed);
- return QByteArray();
- }
-
- ushort general_purpose_bits = readUShort(header.h.general_purpose_bits);
- int compressed_size = readUInt(header.h.compressed_size);
- int uncompressed_size = readUInt(header.h.uncompressed_size);
- int start = readUInt(header.h.offset_local_header);
- //qDebug("uncompressing file %d: local header at %d", i, start);
-
- d->device->seek(start);
- LocalFileHeader lh;
- d->device->read((char *)&lh, sizeof(LocalFileHeader));
- uint skip = readUShort(lh.file_name_length) + readUShort(lh.extra_field_length);
- d->device->seek(d->device->pos() + skip);
-
- int compression_method = readUShort(lh.compression_method);
- //qDebug("file=%s: compressed_size=%d, uncompressed_size=%d", fileName.toLocal8Bit().data(), compressed_size, uncompressed_size);
-
- if ((general_purpose_bits & Encrypted) != 0) {
- qWarning("QZip: Unsupported encryption method is needed to extract the data.");
- return QByteArray();
- }
-
- //qDebug("file at %lld", d->device->pos());
- QByteArray compressed = d->device->read(compressed_size);
- if (compression_method == CompressionMethodStored) {
- // no compression
- compressed.truncate(uncompressed_size);
- return compressed;
- } else if (compression_method == CompressionMethodDeflated) {
- // Deflate
- //qDebug("compressed=%d", compressed.size());
- compressed.truncate(compressed_size);
- QByteArray baunzip;
- ulong len = qMax(uncompressed_size, 1);
- int res;
- do {
- baunzip.resize(len);
- res = inflate((uchar*)baunzip.data(), &len,
- (const uchar*)compressed.constData(), compressed_size);
-
- switch (res) {
- case Z_OK:
- if ((int)len != baunzip.size())
- baunzip.resize(len);
- break;
- case Z_MEM_ERROR:
- qWarning("QZip: Z_MEM_ERROR: Not enough memory");
- break;
- case Z_BUF_ERROR:
- len *= 2;
- break;
- case Z_DATA_ERROR:
- qWarning("QZip: Z_DATA_ERROR: Input data is corrupted");
- break;
- }
- } while (res == Z_BUF_ERROR);
- return baunzip;
- }
-
- qWarning("QZip: Unsupported compression method %d is needed to extract the data.", compression_method);
- return QByteArray();
-}
-
-/*!
- Extracts the full contents of the zip file into \a destinationDir on
- the local filesystem.
- In case writing or linking a file fails, the extraction will be aborted.
-*/
-bool QZipReader::extractAll(const QString &destinationDir) const
-{
- QDir baseDir(destinationDir);
-
- // create directories first
- const QList<FileInfo> allFiles = fileInfoList();
- for (const FileInfo &fi : allFiles) {
- const QString absPath = destinationDir + QDir::separator() + fi.filePath;
- if (fi.isDir) {
- if (!baseDir.mkpath(fi.filePath))
- return false;
- if (!QFile::setPermissions(absPath, fi.permissions))
- return false;
- }
- }
-
- // set up symlinks
- for (const FileInfo &fi : allFiles) {
- const QString absPath = destinationDir + QDir::separator() + fi.filePath;
- if (fi.isSymLink) {
- QString destination = QFile::decodeName(fileData(fi.filePath));
- if (destination.isEmpty())
- return false;
- QFileInfo linkFi(absPath);
- if (!QFile::exists(linkFi.absolutePath()))
- QDir::root().mkpath(linkFi.absolutePath());
- if (!QFile::link(destination, absPath))
- return false;
- /* cannot change permission of links
- if (!QFile::setPermissions(absPath, fi.permissions))
- return false;
- */
- }
- }
-
- for (const FileInfo &fi : allFiles) {
- const QString absPath = destinationDir + QDir::separator() + fi.filePath;
- if (fi.isFile) {
- QFile f(absPath);
- if (!f.open(QIODevice::WriteOnly))
- return false;
- f.write(fileData(fi.filePath));
- f.setPermissions(fi.permissions);
- f.close();
- }
- }
-
- return true;
-}
-
-/*!
- \enum QZipReader::Status
-
- The following status values are possible:
-
- \value NoError No error occurred.
- \value FileReadError An error occurred when reading from the file.
- \value FileOpenError The file could not be opened.
- \value FilePermissionsError The file could not be accessed.
- \value FileError Another file error occurred.
-*/
-
-/*!
- Returns a status code indicating the first error that was met by QZipReader,
- or QZipReader::NoError if no error occurred.
-*/
-QZipReader::Status QZipReader::status() const
-{
- return d->status;
-}
-
-/*!
- Close the zip file.
-*/
-void QZipReader::close()
-{
- d->device->close();
-}
-
-////////////////////////////// Writer
-
-/*!
- \class QZipWriter
- \internal
- \since 4.5
-
- \brief the QZipWriter class provides a way to create a new zip archive.
-
- QZipWriter can be used to create a zip archive containing any number of files
- and directories. The files in the archive will be compressed in a way that is
- compatible with common zip reader applications.
-*/
-
-
-/*!
- Create a new zip archive that operates on the \a archive filename. The file will
- be opened with the \a mode.
- \sa isValid()
-*/
-QZipWriter::QZipWriter(const QString &fileName, QIODevice::OpenMode mode)
-{
- QScopedPointer<QFile> f(new QFile(fileName));
- QZipWriter::Status status;
- if (f->open(mode) && f->error() == QFile::NoError)
- status = QZipWriter::NoError;
- else {
- if (f->error() == QFile::WriteError)
- status = QZipWriter::FileWriteError;
- else if (f->error() == QFile::OpenError)
- status = QZipWriter::FileOpenError;
- else if (f->error() == QFile::PermissionsError)
- status = QZipWriter::FilePermissionsError;
- else
- status = QZipWriter::FileError;
- }
-
- d = new QZipWriterPrivate(f.data(), /*ownDevice=*/true);
- f.take();
- d->status = status;
-}
-
-/*!
- Create a new zip archive that operates on the archive found in \a device.
- You have to open the device previous to calling the constructor and
- only a device that is readable will be scanned for zip filecontent.
- */
-QZipWriter::QZipWriter(QIODevice *device)
- : d(new QZipWriterPrivate(device, /*ownDevice=*/false))
-{
- Q_ASSERT(device);
-}
-
-QZipWriter::~QZipWriter()
-{
- close();
- delete d;
-}
-
-/*!
- Returns device used for writing zip archive.
-*/
-QIODevice* QZipWriter::device() const
-{
- return d->device;
-}
-
-/*!
- Returns \c true if the user can write to the archive; otherwise returns \c false.
-*/
-bool QZipWriter::isWritable() const
-{
- return d->device->isWritable();
-}
-
-/*!
- Returns \c true if the file exists; otherwise returns \c false.
-*/
-bool QZipWriter::exists() const
-{
- QFile *f = qobject_cast<QFile*> (d->device);
- if (f == nullptr)
- return true;
- return f->exists();
-}
-
-/*!
- \enum QZipWriter::Status
-
- The following status values are possible:
-
- \value NoError No error occurred.
- \value FileWriteError An error occurred when writing to the device.
- \value FileOpenError The file could not be opened.
- \value FilePermissionsError The file could not be accessed.
- \value FileError Another file error occurred.
-*/
-
-/*!
- Returns a status code indicating the first error that was met by QZipWriter,
- or QZipWriter::NoError if no error occurred.
-*/
-QZipWriter::Status QZipWriter::status() const
-{
- return d->status;
-}
-
-/*!
- \enum QZipWriter::CompressionPolicy
-
- \value AlwaysCompress A file that is added is compressed.
- \value NeverCompress A file that is added will be stored without changes.
- \value AutoCompress A file that is added will be compressed only if that will give a smaller file.
-*/
-
-/*!
- Sets the policy for compressing newly added files to the new \a policy.
-
- \note the default policy is AlwaysCompress
-
- \sa compressionPolicy()
- \sa addFile()
-*/
-void QZipWriter::setCompressionPolicy(CompressionPolicy policy)
-{
- d->compressionPolicy = policy;
-}
-
-/*!
- Returns the currently set compression policy.
- \sa setCompressionPolicy()
- \sa addFile()
-*/
-QZipWriter::CompressionPolicy QZipWriter::compressionPolicy() const
-{
- return d->compressionPolicy;
-}
-
-/*!
- Sets the permissions that will be used for newly added files.
-
- \note the default permissions are QFile::ReadOwner | QFile::WriteOwner.
-
- \sa creationPermissions()
- \sa addFile()
-*/
-void QZipWriter::setCreationPermissions(QFile::Permissions permissions)
-{
- d->permissions = permissions;
-}
-
-/*!
- Returns the currently set creation permissions.
-
- \sa setCreationPermissions()
- \sa addFile()
-*/
-QFile::Permissions QZipWriter::creationPermissions() const
-{
- return d->permissions;
-}
-
-/*!
- Add a file to the archive with \a data as the file contents.
- The file will be stored in the archive using the \a fileName which
- includes the full path in the archive.
-
- The new file will get the file permissions based on the current
- creationPermissions and it will be compressed using the zip compression
- based on the current compression policy.
-
- \sa setCreationPermissions()
- \sa setCompressionPolicy()
-*/
-void QZipWriter::addFile(const QString &fileName, const QByteArray &data)
-{
- d->addEntry(QZipWriterPrivate::File, QDir::fromNativeSeparators(fileName), data);
-}
-
-/*!
- Add a file to the archive with \a device as the source of the contents.
- The contents returned from QIODevice::readAll() will be used as the
- filedata.
- The file will be stored in the archive using the \a fileName which
- includes the full path in the archive.
-*/
-void QZipWriter::addFile(const QString &fileName, QIODevice *device)
-{
- Q_ASSERT(device);
- QIODevice::OpenMode mode = device->openMode();
- bool opened = false;
- if ((mode & QIODevice::ReadOnly) == 0) {
- opened = true;
- if (! device->open(QIODevice::ReadOnly)) {
- d->status = FileOpenError;
- return;
- }
- }
- d->addEntry(QZipWriterPrivate::File, QDir::fromNativeSeparators(fileName), device->readAll());
- if (opened)
- device->close();
-}
-
-/*!
- Create a new directory in the archive with the specified \a dirName and
- the \a permissions;
-*/
-void QZipWriter::addDirectory(const QString &dirName)
-{
- QString name(QDir::fromNativeSeparators(dirName));
- // separator is mandatory
- if (!name.endsWith(QLatin1Char('/')))
- name.append(QLatin1Char('/'));
- d->addEntry(QZipWriterPrivate::Directory, name, QByteArray());
-}
-
-/*!
- Create a new symbolic link in the archive with the specified \a dirName
- and the \a permissions;
- A symbolic link contains the destination (relative) path and name.
-*/
-void QZipWriter::addSymLink(const QString &fileName, const QString &destination)
-{
- d->addEntry(QZipWriterPrivate::Symlink, QDir::fromNativeSeparators(fileName), QFile::encodeName(destination));
-}
-
-/*!
- Closes the zip file.
-*/
-void QZipWriter::close()
-{
- if (!(d->device->openMode() & QIODevice::WriteOnly)) {
- d->device->close();
- return;
- }
-
- //qDebug("QZip::close writing directory, %d entries", d->fileHeaders.size());
- d->device->seek(d->start_of_directory);
- // write new directory
- for (int i = 0; i < d->fileHeaders.size(); ++i) {
- const FileHeader &header = d->fileHeaders.at(i);
- d->device->write((const char *)&header.h, sizeof(CentralFileHeader));
- d->device->write(header.file_name);
- d->device->write(header.extra_field);
- d->device->write(header.file_comment);
- }
- int dir_size = d->device->pos() - d->start_of_directory;
- // write end of directory
- EndOfDirectory eod;
- memset(&eod, 0, sizeof(EndOfDirectory));
- writeUInt(eod.signature, 0x06054b50);
- //uchar this_disk[2];
- //uchar start_of_directory_disk[2];
- writeUShort(eod.num_dir_entries_this_disk, d->fileHeaders.size());
- writeUShort(eod.num_dir_entries, d->fileHeaders.size());
- writeUInt(eod.directory_size, dir_size);
- writeUInt(eod.dir_start_offset, d->start_of_directory);
- writeUShort(eod.comment_length, d->comment.length());
-
- d->device->write((const char *)&eod, sizeof(EndOfDirectory));
- d->device->write(d->comment);
- d->device->close();
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_TEXTODFWRITER
diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h
deleted file mode 100644
index add3a40087..0000000000
--- a/src/gui/text/qzipreader_p.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QZIPREADER_H
-#define QZIPREADER_H
-
-#include <QtGui/private/qtguiglobal_p.h>
-#include <QtCore/qglobal.h>
-
-#ifndef QT_NO_TEXTODFWRITER
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of the QZipReader class. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qdatetime.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qstring.h>
-
-QT_BEGIN_NAMESPACE
-
-class QZipReaderPrivate;
-
-class Q_GUI_EXPORT QZipReader
-{
-public:
- explicit QZipReader(const QString &fileName, QIODevice::OpenMode mode = QIODevice::ReadOnly );
-
- explicit QZipReader(QIODevice *device);
- ~QZipReader();
-
- QIODevice* device() const;
-
- bool isReadable() const;
- bool exists() const;
-
- struct FileInfo
- {
- FileInfo() noexcept
- : isDir(false), isFile(false), isSymLink(false), crc(0), size(0)
- {}
-
- bool isValid() const noexcept { return isDir || isFile || isSymLink; }
-
- QString filePath;
- uint isDir : 1;
- uint isFile : 1;
- uint isSymLink : 1;
- QFile::Permissions permissions;
- uint crc;
- qint64 size;
- QDateTime lastModified;
- };
-
- QList<FileInfo> fileInfoList() const;
- int count() const;
-
- FileInfo entryInfoAt(int index) const;
- QByteArray fileData(const QString &fileName) const;
- bool extractAll(const QString &destinationDir) const;
-
- enum Status {
- NoError,
- FileReadError,
- FileOpenError,
- FilePermissionsError,
- FileError
- };
-
- Status status() const;
-
- void close();
-
-private:
- QZipReaderPrivate *d;
- Q_DISABLE_COPY_MOVE(QZipReader)
-};
-Q_DECLARE_TYPEINFO(QZipReader::FileInfo, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QZipReader::Status, Q_PRIMITIVE_TYPE);
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_TEXTODFWRITER
-#endif // QZIPREADER_H
diff --git a/src/gui/text/qzipwriter_p.h b/src/gui/text/qzipwriter_p.h
deleted file mode 100644
index b3bb5929cf..0000000000
--- a/src/gui/text/qzipwriter_p.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#ifndef QZIPWRITER_H
-#define QZIPWRITER_H
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#ifndef QT_NO_TEXTODFWRITER
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of the QZipWriter class. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qstring.h>
-#include <QtCore/qfile.h>
-
-QT_BEGIN_NAMESPACE
-
-class QZipWriterPrivate;
-
-
-class Q_GUI_EXPORT QZipWriter
-{
-public:
- explicit QZipWriter(const QString &fileName, QIODevice::OpenMode mode = (QIODevice::WriteOnly | QIODevice::Truncate) );
-
- explicit QZipWriter(QIODevice *device);
- ~QZipWriter();
-
- QIODevice* device() const;
-
- bool isWritable() const;
- bool exists() const;
-
- enum Status {
- NoError,
- FileWriteError,
- FileOpenError,
- FilePermissionsError,
- FileError
- };
-
- Status status() const;
-
- enum CompressionPolicy {
- AlwaysCompress,
- NeverCompress,
- AutoCompress
- };
-
- void setCompressionPolicy(CompressionPolicy policy);
- CompressionPolicy compressionPolicy() const;
-
- void setCreationPermissions(QFile::Permissions permissions);
- QFile::Permissions creationPermissions() const;
-
- void addFile(const QString &fileName, const QByteArray &data);
-
- void addFile(const QString &fileName, QIODevice *device);
-
- void addDirectory(const QString &dirName);
-
- void addSymLink(const QString &fileName, const QString &destination);
-
- void close();
-private:
- QZipWriterPrivate *d;
- Q_DISABLE_COPY_MOVE(QZipWriter)
-};
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_TEXTODFWRITER
-#endif // QZIPWRITER_H
diff --git a/src/gui/text/unix/qfontconfigdatabase.cpp b/src/gui/text/unix/qfontconfigdatabase.cpp
index ee9d323747..d607d38235 100644
--- a/src/gui/text/unix/qfontconfigdatabase.cpp
+++ b/src/gui/text/unix/qfontconfigdatabase.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfontconfigdatabase_p.h"
#include "qfontenginemultifontconfig_p.h"
@@ -52,7 +16,6 @@
#include <qpa/qplatformservices.h>
#include <QtGui/private/qguiapplication_p.h>
-#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/qguiapplication.h>
@@ -65,6 +28,8 @@
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcFontDb)
+
static inline int mapToQtWeightForRange(int fcweight, int fcLower, int fcUpper, int qtLower, int qtUpper)
{
return qtLower + ((fcweight - fcLower) * (qtUpper - qtLower)) / (fcUpper - fcLower);
@@ -276,7 +241,14 @@ static const char specialLanguages[][6] = {
"", // Chorasmian
"", // DivesAkuru
"", // KhitanSmallScript
- "" // Yezidi
+ "", // Yezidi
+ "", // CyproMinoan
+ "", // OldUyghur
+ "", // Tangsa
+ "", // Toto
+ "", // Vithkuqi
+ "", // Kawi
+ "", // NagMundari
};
static_assert(sizeof specialLanguages / sizeof *specialLanguages == QChar::ScriptCount);
@@ -395,7 +367,10 @@ static inline bool requiresOpenType(int writingSystem)
|| writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko);
}
-static void populateFromPattern(FcPattern *pattern, QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr)
+static void populateFromPattern(FcPattern *pattern,
+ QFontDatabasePrivate::ApplicationFont *applicationFont = nullptr,
+ FT_Face face = nullptr,
+ QFontconfigDatabase *db = nullptr)
{
QString familyName;
QString familyNameLang;
@@ -517,7 +492,21 @@ static void populateFromPattern(FcPattern *pattern, QFontDatabasePrivate::Applic
applicationFont->properties.append(properties);
}
- QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile);
+ QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1StringView((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile);
+ if (applicationFont != nullptr && face != nullptr && db != nullptr) {
+ db->addNamedInstancesForFace(face,
+ indexValue,
+ familyName,
+ styleName,
+ weight,
+ stretch,
+ style,
+ fixedPitch,
+ writingSystems,
+ QByteArray((const char*)file_value),
+ applicationFont->data);
+ }
+
// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size;
for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) {
@@ -549,7 +538,7 @@ static void populateFromPattern(FcPattern *pattern, QFontDatabasePrivate::Applic
applicationFont->properties.append(properties);
}
FontFile *altFontFile = new FontFile(*fontFile);
- QPlatformFontDatabase::registerFont(altFamilyName, altStyleName, QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,altFontFile);
+ QPlatformFontDatabase::registerFont(altFamilyName, altStyleName, QLatin1StringView((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,altFontFile);
} else {
QPlatformFontDatabase::registerAliasToFontFamily(familyName, altFamilyName);
}
@@ -557,6 +546,11 @@ static void populateFromPattern(FcPattern *pattern, QFontDatabasePrivate::Applic
}
+static bool isDprScaling()
+{
+ return !qFuzzyCompare(qApp->devicePixelRatio(), 1.0);
+}
+
QFontconfigDatabase::~QFontconfigDatabase()
{
FcConfigDestroy(FcConfigGetCurrent());
@@ -585,9 +579,17 @@ void QFontconfigDatabase::populateFontDatabase()
FcObjectSetAdd(os, *p);
++p;
}
+
+#ifdef FC_VARIABLE
+ /* Support the named instance of Variable Fonts. */
+ FcPatternAddBool(pattern, FC_VARIABLE, FcFalse);
+#endif
+
fonts = FcFontList(nullptr, pattern, os);
FcObjectSetDestroy(os);
FcPatternDestroy(pattern);
+ if (!fonts)
+ return;
}
for (int i = 0; i < fonts->nfont; i++)
@@ -640,7 +642,7 @@ QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine,
}
namespace {
-QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match, bool useXftConf)
+QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match, bool preferXftConf)
{
switch (hintingPreference) {
case QFont::PreferNoHinting:
@@ -653,9 +655,16 @@ QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintin
break;
}
- if (QHighDpiScaling::isActive())
+ if (isDprScaling())
return QFontEngine::HintNone;
+ void *hintStyleResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle",
+ QGuiApplication::primaryScreen());
+ int xftHintStyle = int(reinterpret_cast<qintptr>(hintStyleResource));
+ if (preferXftConf && xftHintStyle > 0)
+ return QFontEngine::HintStyle(xftHintStyle - 1);
+
int hint_style = 0;
if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultMatch) {
switch (hint_style) {
@@ -672,21 +681,21 @@ QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintin
break;
}
}
-
- if (useXftConf) {
- void *hintStyleResource =
- QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle",
- QGuiApplication::primaryScreen());
- int hintStyle = int(reinterpret_cast<qintptr>(hintStyleResource));
- if (hintStyle > 0)
- return QFontEngine::HintStyle(hintStyle - 1);
- }
+ if (xftHintStyle > 0)
+ return QFontEngine::HintStyle(xftHintStyle - 1);
return QFontEngine::HintFull;
}
-QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bool useXftConf)
+QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bool preferXftConf)
{
+ void *subpixelTypeResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype",
+ QGuiApplication::primaryScreen());
+ int xftSubpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource));
+ if (preferXftConf && xftSubpixelType > 0)
+ return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
+
int subpixel = FC_RGBA_UNKNOWN;
if (FcPatternGetInteger(match, FC_RGBA, 0, &subpixel) == FcResultMatch) {
switch (subpixel) {
@@ -707,14 +716,8 @@ QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bo
}
}
- if (useXftConf) {
- void *subpixelTypeResource =
- QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype",
- QGuiApplication::primaryScreen());
- int subpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource));
- if (subpixelType > 0)
- return QFontEngine::SubpixelAntialiasingType(subpixelType - 1);
- }
+ if (xftSubpixelType > 0)
+ return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
return QFontEngine::Subpixel_None;
}
@@ -729,6 +732,8 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr)
QFontEngine::FaceId fid;
fid.filename = QFile::encodeName(fontfile->fileName);
fid.index = fontfile->indexValue;
+ fid.instanceIndex = fontfile->instanceIndex;
+ fid.variableAxes = f.variableAxisValues;
// FIXME: Unify with logic in QFontEngineFT::create()
QFontEngineFT *engine = new QFontEngineFT(f);
@@ -830,26 +835,28 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont
return fallbackFamilies;
}
-static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count)
+static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count, FT_Face *face)
{
#if FC_VERSION < 20402
Q_UNUSED(data);
+ *face = nullptr;
return FcFreeTypeQuery(file, id, blanks, count);
#else
- if (data.isEmpty())
+ if (data.isEmpty()) {
+ *face = nullptr;
return FcFreeTypeQuery(file, id, blanks, count);
+ }
FT_Library lib = qt_getFreetype();
FcPattern *pattern = nullptr;
- FT_Face face;
- if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, &face)) {
- *count = face->num_faces;
-
- pattern = FcFreeTypeQueryFace(face, file, id, blanks);
+ if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, face)) {
+ *count = (*face)->num_faces;
- FT_Done_Face(face);
+ pattern = FcFreeTypeQueryFace(*face, file, id, blanks);
+ } else {
+ *face = nullptr;
}
return pattern;
@@ -877,8 +884,9 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData,
FcPattern *pattern;
do {
+ FT_Face face;
pattern = queryFont((const FcChar8 *)QFile::encodeName(fileName).constData(),
- fontData, id, blanks, &count);
+ fontData, id, blanks, &count, &face);
if (!pattern)
return families;
@@ -887,7 +895,10 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData,
QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam));
families << family;
}
- populateFromPattern(pattern, applicationFont);
+ populateFromPattern(pattern, applicationFont, face, this);
+
+ if (face)
+ FT_Done_Face(face);
FcFontSetAdd(set, pattern);
@@ -952,28 +963,20 @@ QFont QFontconfigDatabase::defaultFont() const
void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const
{
bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
- bool forcedAntialiasSetting = !antialias || QHighDpiScaling::isActive();
+ bool forcedAntialiasSetting = !antialias || isDprScaling();
const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
- bool useXftConf = false;
+ bool preferXftConf = false;
if (services) {
const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(':');
- useXftConf = desktopEnv.contains("GNOME") || desktopEnv.contains("UNITY") || desktopEnv.contains("XFCE");
- }
-
- if (useXftConf && !forcedAntialiasSetting) {
- void *antialiasResource =
- QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled",
- QGuiApplication::primaryScreen());
- int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource));
- if (antialiasingEnabled > 0)
- antialias = antialiasingEnabled - 1;
+ preferXftConf = !(desktopEnv.contains("KDE") || desktopEnv.contains("LXQT") || desktopEnv.contains("UKUI"));
}
QFontEngine::GlyphFormat format;
// try and get the pattern
FcPattern *pattern = FcPatternCreate();
+ FcPattern *match = nullptr;
FcValue value;
value.type = FcTypeString;
@@ -992,7 +995,7 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
FcPatternAdd(pattern,FC_INDEX,value,true);
}
- if (fontDef.pixelSize > 0.1)
+ if (!qFuzzyIsNull(fontDef.pixelSize))
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize);
FcResult result;
@@ -1000,9 +1003,68 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
- FcPattern *match = FcFontMatch(nullptr, pattern, &result);
+#ifdef FC_VARIABLE
+ if (!fid.filename.isEmpty()) {
+ // FC_INDEX is ignored during processing in FcFontMatch.
+ // So iterate FcPatterns directly and find it out.
+ FcFontSet *fcsets[2], *fcfs;
+
+ fcsets[0] = FcConfigGetFonts(nullptr, FcSetSystem);
+ fcsets[1] = FcConfigGetFonts(nullptr, FcSetApplication);
+ for (int nset = 0; nset < 2; nset++) {
+ fcfs = fcsets[nset];
+ if (fcfs == nullptr)
+ continue;
+ for (int fnum = 0; fnum < fcfs->nfont; fnum++) {
+ FcPattern *fcpat = fcfs->fonts[fnum];
+ FcChar8 *fcfile;
+ FcBool variable;
+ double fcpixelsize;
+ int fcindex;
+
+ // Skip the variable font itself, only to use the named instances and normal fonts here
+ if (FcPatternGetBool(fcpat, FC_VARIABLE, 0, &variable) == FcResultMatch &&
+ variable == FcTrue)
+ continue;
+
+ if (!qFuzzyIsNull(fontDef.pixelSize)) {
+ if (FcPatternGetDouble(fcpat, FC_PIXEL_SIZE, 0, &fcpixelsize) == FcResultMatch &&
+ fontDef.pixelSize != fcpixelsize)
+ continue;
+ }
+
+ if (FcPatternGetString(fcpat, FC_FILE, 0, &fcfile) == FcResultMatch &&
+ FcPatternGetInteger(fcpat, FC_INDEX, 0, &fcindex) == FcResultMatch) {
+ QByteArray f = QByteArray::fromRawData((const char *)fcfile,
+ qstrlen((const char *)fcfile));
+ if (f == fid.filename && fcindex == fid.index) {
+ // We found it.
+ match = FcFontRenderPrepare(nullptr, pattern, fcpat);
+ goto bail;
+ }
+ }
+ }
+ }
+ }
+bail:
+#endif
+
+ if (!match)
+ match = FcFontMatch(nullptr, pattern, &result);
+
+ int xftAntialias = 0;
+ if (!forcedAntialiasSetting) {
+ void *antialiasResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled",
+ QGuiApplication::primaryScreen());
+ xftAntialias = int(reinterpret_cast<qintptr>(antialiasResource));
+ if ((preferXftConf || !match) && xftAntialias > 0) {
+ antialias = xftAntialias - 1;
+ forcedAntialiasSetting = true;
+ }
+ }
if (match) {
- engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf));
+ engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, preferXftConf));
FcBool fc_autohint;
if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch)
@@ -1023,18 +1085,37 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
if (antialias) {
QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None;
if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias))
- subpixelType = subpixelTypeFromMatch(match, useXftConf);
+ subpixelType = subpixelTypeFromMatch(match, preferXftConf);
engine->subpixelType = subpixelType;
-
- format = (subpixelType == QFontEngine::Subpixel_None)
- ? QFontEngine::Format_A8
- : QFontEngine::Format_A32;
- } else
- format = QFontEngine::Format_Mono;
+ }
FcPatternDestroy(match);
- } else
- format = antialias ? QFontEngine::Format_A8 : QFontEngine::Format_Mono;
+ } else {
+ void *hintStyleResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle",
+ QGuiApplication::primaryScreen());
+ int xftHintStyle = int(reinterpret_cast<qintptr>(hintStyleResource));
+ if (xftHintStyle > 0)
+ engine->setDefaultHintStyle(QFontEngine::HintStyle(xftHintStyle - 1));
+ if (antialias) {
+ engine->subpixelType = QFontEngine::Subpixel_None;
+ if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) {
+ void *subpixelTypeResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype",
+ QGuiApplication::primaryScreen());
+ int xftSubpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource));
+ if (xftSubpixelType > 1)
+ engine->subpixelType = QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
+ }
+ }
+ }
+ if (antialias) {
+ format = (engine->subpixelType == QFontEngine::Subpixel_None)
+ ? QFontEngine::Format_A8
+ : QFontEngine::Format_A32;
+ } else {
+ format = QFontEngine::Format_Mono;
+ }
FcPatternDestroy(pattern);
@@ -1043,4 +1124,13 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
engine->glyphFormat = format;
}
+bool QFontconfigDatabase::supportsVariableApplicationFonts() const
+{
+#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 20900
+ return true;
+#else
+ return false;
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/text/unix/qfontconfigdatabase_p.h b/src/gui/text/unix/qfontconfigdatabase_p.h
index 856a11fde4..dd7a70a375 100644
--- a/src/gui/text/unix/qfontconfigdatabase_p.h
+++ b/src/gui/text/unix/qfontconfigdatabase_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTCONFIGDATABASE_H
#define QFONTCONFIGDATABASE_H
@@ -64,6 +28,7 @@ public:
~QFontconfigDatabase() override;
void populateFontDatabase() override;
void invalidate() override;
+ bool supportsVariableApplicationFonts() const override;
QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) override;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
diff --git a/src/gui/text/unix/qfontenginemultifontconfig.cpp b/src/gui/text/unix/qfontenginemultifontconfig.cpp
index 01d58022f2..6419a764f7 100644
--- a/src/gui/text/unix/qfontenginemultifontconfig.cpp
+++ b/src/gui/text/unix/qfontenginemultifontconfig.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qfontenginemultifontconfig_p.h"
@@ -50,7 +14,7 @@ QFontEngineMultiFontConfig::QFontEngineMultiFontConfig(QFontEngine *fe, int scri
QFontEngineMultiFontConfig::~QFontEngineMultiFontConfig()
{
- for (FcPattern *pattern : qAsConst(cachedMatchPatterns)) {
+ for (FcPattern *pattern : std::as_const(cachedMatchPatterns)) {
if (pattern)
FcPatternDestroy(pattern);
}
diff --git a/src/gui/text/unix/qfontenginemultifontconfig_p.h b/src/gui/text/unix/qfontenginemultifontconfig_p.h
index daaa8baecf..9ab96123ae 100644
--- a/src/gui/text/unix/qfontenginemultifontconfig_p.h
+++ b/src/gui/text/unix/qfontenginemultifontconfig_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFONTENGINEMULTIFONTCONFIG_H
#define QFONTENGINEMULTIFONTCONFIG_H
diff --git a/src/gui/text/unix/qgenericunixfontdatabase_p.h b/src/gui/text/unix/qgenericunixfontdatabase_p.h
index 21c57c303e..96124d025b 100644
--- a/src/gui/text/unix/qgenericunixfontdatabase_p.h
+++ b/src/gui/text/unix/qgenericunixfontdatabase_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGENERICUNIXFONTDATABASE_H
#define QGENERICUNIXFONTDATABASE_H
@@ -56,9 +20,12 @@
#if QT_CONFIG(fontconfig)
#include <QtGui/private/qfontconfigdatabase_p.h>
using QGenericUnixFontDatabase = QFontconfigDatabase;
-#else
+#elif QT_CONFIG(freetype)
#include <QtGui/private/qfreetypefontdatabase_p.h>
using QGenericUnixFontDatabase = QFreeTypeFontDatabase;
-#endif //Q_FONTCONFIGDATABASE
+#else
+#include <qpa/qplatformfontdatabase.h>
+using QGenericUnixFontDatabase = QPlatformFontDatabase;
+#endif
#endif // QGENERICUNIXFONTDATABASE_H
diff --git a/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp b/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp
index 1779872f7d..2e15fbb1ac 100644
--- a/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp
+++ b/src/gui/text/windows/qwindowsdirectwritefontdatabase.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsdirectwritefontdatabase_p.h"
#include "qwindowsfontenginedirectwrite_p.h"
@@ -54,6 +18,32 @@ QT_BEGIN_NAMESPACE
// Defined in gui/text/qfontdatabase.cpp
Q_GUI_EXPORT QFontDatabase::WritingSystem qt_writing_system_for_script(int script);
+template<typename T>
+struct DirectWriteScope {
+ DirectWriteScope(T *res = nullptr) : m_res(res) {}
+ ~DirectWriteScope() {
+ if (m_res != nullptr)
+ m_res->Release();
+ }
+
+ T **operator&()
+ {
+ return &m_res;
+ }
+
+ T *operator->()
+ {
+ return m_res;
+ }
+
+ T *operator*() {
+ return m_res;
+ }
+
+private:
+ T *m_res;
+};
+
QWindowsDirectWriteFontDatabase::QWindowsDirectWriteFontDatabase()
{
qCDebug(lcQpaFonts) << "Creating DirectWrite database";
@@ -116,6 +106,12 @@ static QFont::Style fromDirectWriteStyle(DWRITE_FONT_STYLE style)
void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName)
{
auto it = m_populatedFonts.find(familyName);
+ if (it == m_populatedFonts.end() && m_populatedBitmapFonts.contains(familyName)) {
+ qCDebug(lcQpaFonts) << "Populating bitmap font" << familyName;
+ QWindowsFontDatabase::populateFamily(familyName);
+ return;
+ }
+
IDWriteFontFamily *fontFamily = it != m_populatedFonts.end() ? it.value() : nullptr;
if (fontFamily == nullptr) {
qCWarning(lcQpaFonts) << "Cannot find" << familyName << "in list of fonts";
@@ -134,7 +130,7 @@ void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName)
const bool antialias = false;
const int size = SMOOTH_SCALABLE;
- IDWriteFontList *matchingFonts;
+ DirectWriteScope<IDWriteFontList> matchingFonts;
if (SUCCEEDED(fontFamily->GetMatchingFonts(DWRITE_FONT_WEIGHT_REGULAR,
DWRITE_FONT_STRETCH_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
@@ -142,7 +138,7 @@ void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName)
for (uint j = 0; j < matchingFonts->GetFontCount(); ++j) {
IDWriteFont *font;
if (SUCCEEDED(matchingFonts->GetFont(j, &font))) {
- IDWriteFont1 *font1 = nullptr;
+ DirectWriteScope<IDWriteFont1> font1;
if (!SUCCEEDED(font->QueryInterface(__uuidof(IDWriteFont1),
reinterpret_cast<void **>(&font1)))) {
qCWarning(lcQpaFonts) << "COM object does not support IDWriteFont1";
@@ -152,27 +148,23 @@ void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName)
QString defaultLocaleFamilyName;
QString englishLocaleFamilyName;
- IDWriteFontFamily *fontFamily2;
+ DirectWriteScope<IDWriteFontFamily> fontFamily2;
if (SUCCEEDED(font1->GetFontFamily(&fontFamily2))) {
- IDWriteLocalizedStrings *names;
+ DirectWriteScope<IDWriteLocalizedStrings> names;
if (SUCCEEDED(fontFamily2->GetFamilyNames(&names))) {
- defaultLocaleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
- englishLocaleFamilyName = localeString(names, englishLocale);
-
- names->Release();
+ defaultLocaleFamilyName = hasDefaultLocale ? localeString(*names, defaultLocale) : QString();
+ englishLocaleFamilyName = localeString(*names, englishLocale);
}
-
- fontFamily2->Release();
}
if (defaultLocaleFamilyName.isEmpty() && englishLocaleFamilyName.isEmpty())
englishLocaleFamilyName = familyName;
{
- IDWriteLocalizedStrings *names;
+ DirectWriteScope<IDWriteLocalizedStrings> names;
if (SUCCEEDED(font1->GetFaceNames(&names))) {
- QString defaultLocaleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
- QString englishLocaleStyleName = localeString(names, englishLocale);
+ QString defaultLocaleStyleName = hasDefaultLocale ? localeString(*names, defaultLocale) : QString();
+ QString englishLocaleStyleName = localeString(*names, englishLocale);
QFont::Stretch stretch = fromDirectWriteStretch(font1->GetStretch());
QFont::Style style = fromDirectWriteStyle(font1->GetStyle());
@@ -181,77 +173,233 @@ void QWindowsDirectWriteFontDatabase::populateFamily(const QString &familyName)
qCDebug(lcQpaFonts) << "Family" << familyName << "has english variant" << englishLocaleStyleName << ", in default locale:" << defaultLocaleStyleName << stretch << style << weight << fixed;
- IDWriteFontFace *face = nullptr;
+ DirectWriteScope<IDWriteFontFace> face;
if (SUCCEEDED(font->CreateFontFace(&face))) {
- QSupportedWritingSystems writingSystems;
-
- const void *tableData = nullptr;
- UINT32 tableSize;
- void *tableContext = nullptr;
- BOOL exists;
- HRESULT hr = face->TryGetFontTable(qbswap<quint32>(MAKE_TAG('O','S','/','2')),
- &tableData,
- &tableSize,
- &tableContext,
- &exists);
- if (SUCCEEDED(hr) && exists) {
- writingSystems = QPlatformFontDatabase::writingSystemsFromOS2Table(reinterpret_cast<const char *>(tableData), tableSize);
- } else { // Fall back to checking first character of each Unicode range in font (may include too many writing systems)
- quint32 rangeCount;
- hr = font1->GetUnicodeRanges(0, nullptr, &rangeCount);
-
- if (rangeCount > 0) {
- QVarLengthArray<DWRITE_UNICODE_RANGE, QChar::ScriptCount> ranges(rangeCount);
-
- hr = font1->GetUnicodeRanges(rangeCount, ranges.data(), &rangeCount);
- if (SUCCEEDED(hr)) {
- for (uint i = 0; i < rangeCount; ++i) {
- QChar::Script script = QChar::script(ranges.at(i).first);
-
- QFontDatabase::WritingSystem writingSystem = qt_writing_system_for_script(script);
-
- if (writingSystem > QFontDatabase::Any && writingSystem < QFontDatabase::WritingSystemsCount)
- writingSystems.setSupported(writingSystem);
- }
- } else {
- const QString errorString = qt_error_string(int(hr));
- qCWarning(lcQpaFonts) << "Failed to get unicode ranges for font" << englishLocaleFamilyName << englishLocaleStyleName << ":" << errorString;
- }
- }
- }
+ QSupportedWritingSystems writingSystems = supportedWritingSystems(*face);
if (!englishLocaleStyleName.isEmpty() || defaultLocaleStyleName.isEmpty()) {
qCDebug(lcQpaFonts) << "Font" << englishLocaleFamilyName << englishLocaleStyleName << "supports writing systems:" << writingSystems;
- QPlatformFontDatabase::registerFont(englishLocaleFamilyName, englishLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face);
- face->AddRef();
+ QPlatformFontDatabase::registerFont(englishLocaleFamilyName,
+ englishLocaleStyleName,
+ QString(),
+ weight,
+ style,
+ stretch,
+ antialias,
+ scalable,
+ size,
+ fixed,
+ writingSystems,
+ new FontHandle(*face, englishLocaleFamilyName));
}
if (!defaultLocaleFamilyName.isEmpty() && defaultLocaleFamilyName != englishLocaleFamilyName) {
- QPlatformFontDatabase::registerFont(defaultLocaleFamilyName, defaultLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face);
- face->AddRef();
+ QPlatformFontDatabase::registerFont(defaultLocaleFamilyName,
+ defaultLocaleStyleName,
+ QString(),
+ weight,
+ style,
+ stretch,
+ antialias,
+ scalable,
+ size,
+ fixed,
+ writingSystems,
+ new FontHandle(*face, defaultLocaleFamilyName));
}
-
- face->Release();
}
-
- names->Release();
}
}
+ }
+ }
+ }
+}
- font1->Release();
- font->Release();
+QSupportedWritingSystems QWindowsDirectWriteFontDatabase::supportedWritingSystems(IDWriteFontFace *face) const
+{
+ QSupportedWritingSystems writingSystems;
+ writingSystems.setSupported(QFontDatabase::Any);
+
+ DirectWriteScope<IDWriteFontFace1> face1;
+ if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace1),
+ reinterpret_cast<void **>(&face1)))) {
+ const void *tableData = nullptr;
+ UINT32 tableSize;
+ void *tableContext = nullptr;
+ BOOL exists;
+ HRESULT hr = face->TryGetFontTable(qFromBigEndian(QFont::Tag("OS/2").value()),
+ &tableData,
+ &tableSize,
+ &tableContext,
+ &exists);
+ if (SUCCEEDED(hr) && exists) {
+ writingSystems = QPlatformFontDatabase::writingSystemsFromOS2Table(reinterpret_cast<const char *>(tableData), tableSize);
+ } else { // Fall back to checking first character of each Unicode range in font (may include too many writing systems)
+ quint32 rangeCount;
+ hr = face1->GetUnicodeRanges(0, nullptr, &rangeCount);
+
+ if (rangeCount > 0) {
+ QVarLengthArray<DWRITE_UNICODE_RANGE, QChar::ScriptCount> ranges(rangeCount);
+
+ hr = face1->GetUnicodeRanges(rangeCount, ranges.data(), &rangeCount);
+ if (SUCCEEDED(hr)) {
+ for (uint i = 0; i < rangeCount; ++i) {
+ QChar::Script script = QChar::script(ranges.at(i).first);
+
+ QFontDatabase::WritingSystem writingSystem = qt_writing_system_for_script(script);
+
+ if (writingSystem > QFontDatabase::Any && writingSystem < QFontDatabase::WritingSystemsCount)
+ writingSystems.setSupported(writingSystem);
+ }
+ } else {
+ const QString errorString = qt_error_string(int(hr));
+ qCWarning(lcQpaFonts) << "Failed to get unicode ranges for font:" << errorString;
+ }
}
}
+ }
+
+ return writingSystems;
+}
+
+bool QWindowsDirectWriteFontDatabase::populateFamilyAliases(const QString &missingFamily)
+{
+ // If the font has not been populated, it is possible this is a legacy font family supported
+ // by GDI. We make an attempt at loading it via GDI and then add this face directly to the
+ // database.
+ if (!missingFamily.isEmpty()
+ && missingFamily.size() < LF_FACESIZE
+ && !m_populatedFonts.contains(missingFamily)
+ && !m_populatedBitmapFonts.contains(missingFamily)) {
+ qCDebug(lcQpaFonts) << "Loading unpopulated" << missingFamily << ". Trying GDI.";
+
+ LOGFONT lf;
+ memset(&lf, 0, sizeof(LOGFONT));
+ memcpy(lf.lfFaceName, missingFamily.utf16(), missingFamily.size() * sizeof(wchar_t));
+
+ HFONT hfont = CreateFontIndirect(&lf);
+ if (hfont) {
+ HDC dummy = GetDC(0);
+ HGDIOBJ oldFont = SelectObject(dummy, hfont);
+
+ DirectWriteScope<IDWriteFontFace> directWriteFontFace;
+ if (SUCCEEDED(data()->directWriteGdiInterop->CreateFontFaceFromHdc(dummy, &directWriteFontFace))) {
+ DirectWriteScope<IDWriteFontCollection> fontCollection;
+ if (SUCCEEDED(data()->directWriteFactory->GetSystemFontCollection(&fontCollection))) {
+ DirectWriteScope<IDWriteFont> font;
+ if (SUCCEEDED(fontCollection->GetFontFromFontFace(*directWriteFontFace, &font))) {
+
+ DirectWriteScope<IDWriteFont1> font1;
+ if (SUCCEEDED(font->QueryInterface(__uuidof(IDWriteFont1),
+ reinterpret_cast<void **>(&font1)))) {
+ DirectWriteScope<IDWriteLocalizedStrings> names;
+ if (SUCCEEDED(font1->GetFaceNames(&names))) {
+ wchar_t englishLocale[] = L"en-us";
+ QString englishLocaleStyleName = localeString(*names, englishLocale);
+
+ QFont::Stretch stretch = fromDirectWriteStretch(font1->GetStretch());
+ QFont::Style style = fromDirectWriteStyle(font1->GetStyle());
+ QFont::Weight weight = fromDirectWriteWeight(font1->GetWeight());
+ bool fixed = font1->IsMonospacedFont();
+
+ QSupportedWritingSystems writingSystems = supportedWritingSystems(*directWriteFontFace);
+
+ qCDebug(lcQpaFonts) << "Registering legacy font family" << missingFamily;
+ QPlatformFontDatabase::registerFont(missingFamily,
+ englishLocaleStyleName,
+ QString(),
+ weight,
+ style,
+ stretch,
+ false,
+ true,
+ 0xffff,
+ fixed,
+ writingSystems,
+ new FontHandle(*directWriteFontFace, missingFamily));
+
+ SelectObject(dummy, oldFont);
+ DeleteObject(hfont);
+
+ return true;
+ }
+ }
+ }
+ }
+ }
- matchingFonts->Release();
+ SelectObject(dummy, oldFont);
+ DeleteObject(hfont);
+ }
}
+
+ // Skip over implementation in QWindowsFontDatabase
+ return QWindowsFontDatabaseBase::populateFamilyAliases(missingFamily);
+}
+
+QFontEngine *QWindowsDirectWriteFontDatabase::fontEngine(const QByteArray &fontData,
+ qreal pixelSize,
+ QFont::HintingPreference hintingPreference)
+{
+ // Skip over implementation in QWindowsFontDatabase
+ return QWindowsFontDatabaseBase::fontEngine(fontData, pixelSize, hintingPreference);
}
QFontEngine *QWindowsDirectWriteFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{
- IDWriteFontFace *face = reinterpret_cast<IDWriteFontFace *>(handle);
- Q_ASSERT(face != nullptr);
+ const FontHandle *fontHandle = static_cast<const FontHandle *>(handle);
+ IDWriteFontFace *face = fontHandle->fontFace;
+ if (face == nullptr) {
+ qCDebug(lcQpaFonts) << "Falling back to GDI";
+ return QWindowsFontDatabase::fontEngine(fontDef, handle);
+ }
+
+ DWRITE_FONT_SIMULATIONS simulations = DWRITE_FONT_SIMULATIONS_NONE;
+ if (fontDef.weight >= QFont::DemiBold || fontDef.style != QFont::StyleNormal) {
+ DirectWriteScope<IDWriteFontFace3> face3;
+ if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace3),
+ reinterpret_cast<void **>(&face3)))) {
+ if (fontDef.weight >= QFont::DemiBold && face3->GetWeight() < DWRITE_FONT_WEIGHT_DEMI_BOLD)
+ simulations |= DWRITE_FONT_SIMULATIONS_BOLD;
+
+ if (fontDef.style != QFont::StyleNormal && face3->GetStyle() == DWRITE_FONT_STYLE_NORMAL)
+ simulations |= DWRITE_FONT_SIMULATIONS_OBLIQUE;
+ }
+ }
+
+ DirectWriteScope<IDWriteFontFace5> newFace;
+ if (!fontDef.variableAxisValues.isEmpty() || simulations != DWRITE_FONT_SIMULATIONS_NONE) {
+ DirectWriteScope<IDWriteFontFace5> face5;
+ if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace5),
+ reinterpret_cast<void **>(&face5)))) {
+ DirectWriteScope<IDWriteFontResource> font;
+ if (SUCCEEDED(face5->GetFontResource(&font))) {
+ UINT32 fontAxisCount = font->GetFontAxisCount();
+ QVarLengthArray<DWRITE_FONT_AXIS_VALUE, 8> fontAxisValues(fontAxisCount);
+
+ if (!fontDef.variableAxisValues.isEmpty()) {
+ if (SUCCEEDED(face5->GetFontAxisValues(fontAxisValues.data(), fontAxisCount))) {
+ for (UINT32 i = 0; i < fontAxisCount; ++i) {
+ if (auto maybeTag = QFont::Tag::fromValue(qToBigEndian<UINT32>(fontAxisValues[i].axisTag))) {
+ if (fontDef.variableAxisValues.contains(*maybeTag))
+ fontAxisValues[i].value = fontDef.variableAxisValues.value(*maybeTag);
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(font->CreateFontFace(simulations,
+ !fontDef.variableAxisValues.isEmpty() ? fontAxisValues.data() : nullptr,
+ !fontDef.variableAxisValues.isEmpty() ? fontAxisCount : 0,
+ &newFace))) {
+ face = *newFace;
+ } else {
+ qCWarning(lcQpaFonts) << "DirectWrite: Can't create font face for variable axis values";
+ }
+ }
+ }
+ }
QWindowsFontEngineDirectWrite *fontEngine = new QWindowsFontEngineDirectWrite(face, fontDef.pixelSize, data());
fontEngine->initFontInfo(fontDef, defaultVerticalDPI());
@@ -285,111 +433,255 @@ QStringList QWindowsDirectWriteFontDatabase::addApplicationFont(const QByteArray
loadedData = file.readAll();
}
- IDWriteFontFace *face = createDirectWriteFace(loadedData);
- if (face == nullptr) {
+ QList<IDWriteFontFace *> faces = createDirectWriteFaces(loadedData);
+ if (faces.isEmpty()) {
qCWarning(lcQpaFonts) << "Failed to create DirectWrite face from font data. Font may be unsupported.";
return QStringList();
}
- wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH];
- bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0;
- wchar_t englishLocale[] = L"en-us";
+ QSet<QString> ret;
+ for (int i = 0; i < faces.size(); ++i) {
+ IDWriteFontFace *face = faces.at(i);
+ wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH];
+ bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0;
+ wchar_t englishLocale[] = L"en-us";
+
+ static const int SMOOTH_SCALABLE = 0xffff;
+ const bool scalable = true;
+ const bool antialias = false;
+ const int size = SMOOTH_SCALABLE;
+
+ QSupportedWritingSystems writingSystems = supportedWritingSystems(face);
+ DirectWriteScope<IDWriteFontFace3> face3;
+ if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace3),
+ reinterpret_cast<void **>(&face3)))) {
+ QString defaultLocaleFamilyName;
+ QString englishLocaleFamilyName;
+
+ IDWriteLocalizedStrings *names = nullptr;
+ if (SUCCEEDED(face3->GetFamilyNames(&names))) {
+ defaultLocaleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
+ englishLocaleFamilyName = localeString(names, englishLocale);
+
+ names->Release();
+ }
- static const int SMOOTH_SCALABLE = 0xffff;
- const QString foundryName; // No such concept.
- const bool scalable = true;
- const bool antialias = false;
- const int size = SMOOTH_SCALABLE;
+ QString defaultLocaleStyleName;
+ QString englishLocaleStyleName;
+ if (SUCCEEDED(face3->GetFaceNames(&names))) {
+ defaultLocaleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
+ englishLocaleStyleName = localeString(names, englishLocale);
- QSupportedWritingSystems writingSystems;
- writingSystems.setSupported(QFontDatabase::Any);
- writingSystems.setSupported(QFontDatabase::Latin);
+ names->Release();
+ }
- QStringList ret;
- IDWriteFontFace3 *face3 = nullptr;
- if (SUCCEEDED(face->QueryInterface(__uuidof(IDWriteFontFace3),
- reinterpret_cast<void **>(&face3)))) {
- QString defaultLocaleFamilyName;
- QString englishLocaleFamilyName;
+ BOOL ok;
+ QString defaultLocaleGdiCompatibleFamilyName;
+ QString englishLocaleGdiCompatibleFamilyName;
+ if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, &names, &ok)) && ok) {
+ defaultLocaleGdiCompatibleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
+ englishLocaleGdiCompatibleFamilyName = localeString(names, englishLocale);
- IDWriteLocalizedStrings *names;
- if (SUCCEEDED(face3->GetFamilyNames(&names))) {
- defaultLocaleFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
- englishLocaleFamilyName = localeString(names, englishLocale);
+ names->Release();
+ }
- names->Release();
- }
+ QString defaultLocaleGdiCompatibleStyleName;
+ QString englishLocaleGdiCompatibleStyleName;
+ if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_WIN32_SUBFAMILY_NAMES, &names, &ok)) && ok) {
+ defaultLocaleGdiCompatibleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
+ englishLocaleGdiCompatibleStyleName = localeString(names, englishLocale);
- QString defaultLocaleStyleName;
- QString englishLocaleStyleName;
- if (SUCCEEDED(face3->GetFaceNames(&names))) {
- defaultLocaleStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
- englishLocaleStyleName = localeString(names, englishLocale);
+ names->Release();
+ }
- names->Release();
- }
+ QString defaultLocaleTypographicFamilyName;
+ QString englishLocaleTypographicFamilyName;
+ if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_FAMILY_NAMES, &names, &ok)) && ok) {
+ defaultLocaleTypographicFamilyName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
+ englishLocaleTypographicFamilyName = localeString(names, englishLocale);
- QFont::Stretch stretch = fromDirectWriteStretch(face3->GetStretch());
- QFont::Style style = fromDirectWriteStyle(face3->GetStyle());
- QFont::Weight weight = fromDirectWriteWeight(face3->GetWeight());
- bool fixed = face3->IsMonospacedFont();
-
- qCDebug(lcQpaFonts) << "\tFont names:" << englishLocaleFamilyName << ", " << defaultLocaleFamilyName
- << ", style names:" << englishLocaleStyleName << ", " << defaultLocaleStyleName
- << ", stretch:" << stretch
- << ", style:" << style
- << ", weight:" << weight
- << ", fixed:" << fixed;
-
- if (!englishLocaleFamilyName.isEmpty()) {
- if (applicationFont != nullptr) {
- QFontDatabasePrivate::ApplicationFont::Properties properties;
- properties.style = style;
- properties.weight = weight;
- properties.familyName = englishLocaleFamilyName;
- properties.styleName = englishLocaleStyleName;
- applicationFont->properties.append(properties);
+ names->Release();
}
- ret.append(englishLocaleFamilyName);
- QPlatformFontDatabase::registerFont(englishLocaleFamilyName, englishLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face);
- face->AddRef();
- }
+ QString defaultLocaleTypographicStyleName;
+ QString englishLocaleTypographicStyleName;
+ if (SUCCEEDED(face3->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_TYPOGRAPHIC_SUBFAMILY_NAMES, &names, &ok)) && ok) {
+ defaultLocaleTypographicStyleName = hasDefaultLocale ? localeString(names, defaultLocale) : QString();
+ englishLocaleTypographicStyleName = localeString(names, englishLocale);
- if (!defaultLocaleFamilyName.isEmpty() && defaultLocaleFamilyName != englishLocaleFamilyName) {
- if (applicationFont != nullptr) {
- QFontDatabasePrivate::ApplicationFont::Properties properties;
- properties.style = style;
- properties.weight = weight;
- properties.familyName = englishLocaleFamilyName;
- properties.styleName = englishLocaleStyleName;
- applicationFont->properties.append(properties);
+ names->Release();
}
- ret.append(defaultLocaleFamilyName);
- QPlatformFontDatabase::registerFont(defaultLocaleFamilyName, defaultLocaleStyleName, QString(), weight, style, stretch, antialias, scalable, size, fixed, writingSystems, face);
- face->AddRef();
- }
+ QFont::Stretch stretch = fromDirectWriteStretch(face3->GetStretch());
+ QFont::Style style = fromDirectWriteStyle(face3->GetStyle());
+ QFont::Weight weight = fromDirectWriteWeight(face3->GetWeight());
+ bool fixed = face3->IsMonospacedFont();
+
+ qCDebug(lcQpaFonts) << "\tFont names:" << englishLocaleFamilyName << ", " << defaultLocaleFamilyName
+ << ", style names:" << englishLocaleStyleName << ", " << defaultLocaleStyleName
+ << ", stretch:" << stretch
+ << ", style:" << style
+ << ", weight:" << weight
+ << ", fixed:" << fixed;
+
+ if (!englishLocaleFamilyName.isEmpty()) {
+ if (applicationFont != nullptr) {
+ QFontDatabasePrivate::ApplicationFont::Properties properties;
+ properties.style = style;
+ properties.weight = weight;
+ properties.familyName = englishLocaleFamilyName;
+ properties.styleName = englishLocaleStyleName;
+ applicationFont->properties.append(properties);
+ }
- face3->Release();
- } else {
- qCWarning(lcQpaFonts) << "Unable to query IDWriteFontFace3 interface from font face.";
- }
+ ret.insert(englishLocaleFamilyName);
+ QPlatformFontDatabase::registerFont(englishLocaleFamilyName,
+ englishLocaleStyleName,
+ QString(),
+ weight,
+ style,
+ stretch,
+ antialias,
+ scalable,
+ size,
+ fixed,
+ writingSystems,
+ new FontHandle(face, englishLocaleFamilyName));
+ }
- face->Release();
+ if (!defaultLocaleFamilyName.isEmpty() && !ret.contains(defaultLocaleFamilyName)) {
+ if (applicationFont != nullptr) {
+ QFontDatabasePrivate::ApplicationFont::Properties properties;
+ properties.style = style;
+ properties.weight = weight;
+ properties.familyName = englishLocaleFamilyName;
+ properties.styleName = englishLocaleStyleName;
+ applicationFont->properties.append(properties);
+ }
- return ret;
-}
+ ret.insert(defaultLocaleFamilyName);
+ QPlatformFontDatabase::registerFont(defaultLocaleFamilyName,
+ defaultLocaleStyleName,
+ QString(),
+ weight,
+ style,
+ stretch,
+ antialias,
+ scalable,
+ size,
+ fixed,
+ writingSystems,
+ new FontHandle(face, defaultLocaleFamilyName));
+ }
-void QWindowsDirectWriteFontDatabase::releaseHandle(void *handle)
-{
- IDWriteFontFace *face = reinterpret_cast<IDWriteFontFace *>(handle);
- face->Release();
-}
+ if (!englishLocaleGdiCompatibleFamilyName.isEmpty() &&
+ !ret.contains(englishLocaleGdiCompatibleFamilyName)) {
+ if (applicationFont != nullptr) {
+ QFontDatabasePrivate::ApplicationFont::Properties properties;
+ properties.style = style;
+ properties.weight = weight;
+ properties.familyName = englishLocaleGdiCompatibleFamilyName;
+ applicationFont->properties.append(properties);
+ }
-bool QWindowsDirectWriteFontDatabase::fontsAlwaysScalable() const
-{
- return true;
+ ret.insert(englishLocaleGdiCompatibleFamilyName);
+ QPlatformFontDatabase::registerFont(englishLocaleGdiCompatibleFamilyName,
+ englishLocaleGdiCompatibleStyleName,
+ QString(),
+ weight,
+ style,
+ stretch,
+ antialias,
+ scalable,
+ size,
+ fixed,
+ writingSystems,
+ new FontHandle(face, englishLocaleGdiCompatibleFamilyName));
+ }
+
+ if (!defaultLocaleGdiCompatibleFamilyName.isEmpty()
+ && !ret.contains(defaultLocaleGdiCompatibleFamilyName)) {
+ if (applicationFont != nullptr) {
+ QFontDatabasePrivate::ApplicationFont::Properties properties;
+ properties.style = style;
+ properties.weight = weight;
+ properties.familyName = defaultLocaleGdiCompatibleFamilyName;
+ applicationFont->properties.append(properties);
+ }
+
+ ret.insert(defaultLocaleGdiCompatibleFamilyName);
+ QPlatformFontDatabase::registerFont(defaultLocaleGdiCompatibleFamilyName,
+ defaultLocaleGdiCompatibleStyleName,
+ QString(),
+ weight,
+ style,
+ stretch,
+ antialias,
+ scalable,
+ size,
+ fixed,
+ writingSystems,
+ new FontHandle(face, defaultLocaleGdiCompatibleFamilyName));
+ }
+
+ if (!englishLocaleTypographicFamilyName.isEmpty()
+ && !ret.contains(englishLocaleTypographicFamilyName)) {
+ if (applicationFont != nullptr) {
+ QFontDatabasePrivate::ApplicationFont::Properties properties;
+ properties.style = style;
+ properties.weight = weight;
+ properties.familyName = englishLocaleTypographicFamilyName;
+ applicationFont->properties.append(properties);
+ }
+
+ ret.insert(englishLocaleTypographicFamilyName);
+ QPlatformFontDatabase::registerFont(englishLocaleTypographicFamilyName,
+ englishLocaleTypographicStyleName,
+ QString(),
+ weight,
+ style,
+ stretch,
+ antialias,
+ scalable,
+ size,
+ fixed,
+ writingSystems,
+ new FontHandle(face, englishLocaleTypographicFamilyName));
+ }
+
+ if (!defaultLocaleTypographicFamilyName.isEmpty()
+ && !ret.contains(defaultLocaleTypographicFamilyName)) {
+ if (applicationFont != nullptr) {
+ QFontDatabasePrivate::ApplicationFont::Properties properties;
+ properties.style = style;
+ properties.weight = weight;
+ properties.familyName = defaultLocaleTypographicFamilyName;
+ applicationFont->properties.append(properties);
+ }
+
+ ret.insert(defaultLocaleTypographicFamilyName);
+ QPlatformFontDatabase::registerFont(defaultLocaleTypographicFamilyName,
+ defaultLocaleTypographicStyleName,
+ QString(),
+ weight,
+ style,
+ stretch,
+ antialias,
+ scalable,
+ size,
+ fixed,
+ writingSystems,
+ new FontHandle(face, defaultLocaleTypographicFamilyName));
+ }
+
+ } else {
+ qCWarning(lcQpaFonts) << "Unable to query IDWriteFontFace3 interface from font face.";
+ }
+
+ face->Release();
+ }
+
+ return ret.values();
}
bool QWindowsDirectWriteFontDatabase::isPrivateFontFamily(const QString &family) const
@@ -398,62 +690,103 @@ bool QWindowsDirectWriteFontDatabase::isPrivateFontFamily(const QString &family)
return false;
}
+static int QT_WIN_CALLBACK populateBitmapFonts(const LOGFONT *logFont,
+ const TEXTMETRIC *textmetric,
+ DWORD type,
+ LPARAM lparam)
+{
+ Q_UNUSED(textmetric);
+
+ // the "@family" fonts are just the same as "family". Ignore them.
+ const ENUMLOGFONTEX *f = reinterpret_cast<const ENUMLOGFONTEX *>(logFont);
+ const wchar_t *faceNameW = f->elfLogFont.lfFaceName;
+ if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) {
+ const QString faceName = QString::fromWCharArray(faceNameW);
+ if (type & RASTER_FONTTYPE || type == 0) {
+ QWindowsDirectWriteFontDatabase *db = reinterpret_cast<QWindowsDirectWriteFontDatabase *>(lparam);
+ if (!db->hasPopulatedFont(faceName)) {
+ db->registerFontFamily(faceName);
+ db->registerBitmapFont(faceName);
+ }
+ }
+ }
+ return 1; // continue
+}
+
void QWindowsDirectWriteFontDatabase::populateFontDatabase()
{
wchar_t defaultLocale[LOCALE_NAME_MAX_LENGTH];
bool hasDefaultLocale = GetUserDefaultLocaleName(defaultLocale, LOCALE_NAME_MAX_LENGTH) != 0;
wchar_t englishLocale[] = L"en-us";
- const QString defaultFontName = defaultFont().families().first();
- const QString systemDefaultFontName = systemDefaultFont().families().first();
+ const QString defaultFontName = defaultFont().families().constFirst();
+ const QString systemDefaultFontName = systemDefaultFont().families().constFirst();
+
+ DirectWriteScope<IDWriteFontCollection2> fontCollection;
+ DirectWriteScope<IDWriteFactory6> factory6;
+ if (FAILED(data()->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory6),
+ reinterpret_cast<void **>(&factory6)))) {
+ qCWarning(lcQpaFonts) << "Can't initialize IDWriteFactory6. Use GDI font engine instead.";
+ return;
+ }
- IDWriteFontCollection *fontCollection;
- if (SUCCEEDED(data()->directWriteFactory->GetSystemFontCollection(&fontCollection))) {
+ if (SUCCEEDED(factory6->GetSystemFontCollection(false,
+ DWRITE_FONT_FAMILY_MODEL_TYPOGRAPHIC,
+ &fontCollection))) {
for (uint i = 0; i < fontCollection->GetFontFamilyCount(); ++i) {
- IDWriteFontFamily *fontFamily;
+ DirectWriteScope<IDWriteFontFamily2> fontFamily;
if (SUCCEEDED(fontCollection->GetFontFamily(i, &fontFamily))) {
QString defaultLocaleName;
QString englishLocaleName;
- IDWriteLocalizedStrings *names;
+ DirectWriteScope<IDWriteLocalizedStrings> names;
if (SUCCEEDED(fontFamily->GetFamilyNames(&names))) {
if (hasDefaultLocale)
- defaultLocaleName = localeString(names, defaultLocale);
+ defaultLocaleName = localeString(*names, defaultLocale);
- englishLocaleName = localeString(names, englishLocale);
+ englishLocaleName = localeString(*names, englishLocale);
}
qCDebug(lcQpaFonts) << "Registering font, english name = " << englishLocaleName << ", name in current locale = " << defaultLocaleName;
if (!defaultLocaleName.isEmpty()) {
registerFontFamily(defaultLocaleName);
- m_populatedFonts.insert(defaultLocaleName, fontFamily);
+ m_populatedFonts.insert(defaultLocaleName, *fontFamily);
fontFamily->AddRef();
if (defaultLocaleName == defaultFontName && defaultFontName != systemDefaultFontName) {
qDebug(lcQpaFonts) << "Adding default font" << systemDefaultFontName << "as alternative to" << defaultLocaleName;
- m_populatedFonts.insert(systemDefaultFontName, fontFamily);
+ m_populatedFonts.insert(systemDefaultFontName, *fontFamily);
fontFamily->AddRef();
}
}
if (!englishLocaleName.isEmpty() && englishLocaleName != defaultLocaleName) {
registerFontFamily(englishLocaleName);
- m_populatedFonts.insert(englishLocaleName, fontFamily);
+ m_populatedFonts.insert(englishLocaleName, *fontFamily);
fontFamily->AddRef();
if (englishLocaleName == defaultFontName && defaultFontName != systemDefaultFontName) {
qDebug(lcQpaFonts) << "Adding default font" << systemDefaultFontName << "as alternative to" << englishLocaleName;
- m_populatedFonts.insert(systemDefaultFontName, fontFamily);
+ m_populatedFonts.insert(systemDefaultFontName, *fontFamily);
fontFamily->AddRef();
}
}
-
- fontFamily->Release();
}
}
}
+
+ // Since bitmap fonts are not supported by DirectWrite, we need to populate these as well
+ {
+ HDC dummy = GetDC(0);
+ LOGFONT lf;
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfFaceName[0] = 0;
+ lf.lfPitchAndFamily = 0;
+ EnumFontFamiliesEx(dummy, &lf, populateBitmapFonts, reinterpret_cast<intptr_t>(this), 0);
+ ReleaseDC(0, dummy);
+ }
}
QFont QWindowsDirectWriteFontDatabase::defaultFont() const
@@ -461,4 +794,16 @@ QFont QWindowsDirectWriteFontDatabase::defaultFont() const
return QFont(QStringLiteral("Segoe UI"));
}
+bool QWindowsDirectWriteFontDatabase::supportsVariableApplicationFonts() const
+{
+ QSharedPointer<QWindowsFontEngineData> fontEngineData = data();
+ DirectWriteScope<IDWriteFactory5> factory5;
+ if (SUCCEEDED(fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory5),
+ reinterpret_cast<void **>(&factory5)))) {
+ return true;
+ }
+
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/text/windows/qwindowsdirectwritefontdatabase_p.h b/src/gui/text/windows/qwindowsdirectwritefontdatabase_p.h
index 91b432f74b..093c629a16 100644
--- a/src/gui/text/windows/qwindowsdirectwritefontdatabase_p.h
+++ b/src/gui/text/windows/qwindowsdirectwritefontdatabase_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSDIRECTWRITEFONTDATABASE_P_H
#define QWINDOWSDIRECTWRITEFONTDATABASE_P_H
@@ -56,17 +20,18 @@
QT_REQUIRE_CONFIG(directwrite3);
-#include "qwindowsfontdatabasebase_p.h"
+#include "qwindowsfontdatabase_p.h"
#include <QtCore/qloggingcategory.h>
struct IDWriteFactory;
struct IDWriteFont;
+struct IDWriteFont1;
struct IDWriteFontFamily;
struct IDWriteLocalizedStrings;
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QWindowsDirectWriteFontDatabase : public QWindowsFontDatabaseBase
+class Q_GUI_EXPORT QWindowsDirectWriteFontDatabase : public QWindowsFontDatabase
{
Q_DISABLE_COPY_MOVE(QWindowsDirectWriteFontDatabase)
public:
@@ -75,19 +40,34 @@ public:
void populateFontDatabase() override;
void populateFamily(const QString &familyName) override;
+ bool populateFamilyAliases(const QString &missingFamily) override;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
+ QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const override;
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName, QFontDatabasePrivate::ApplicationFont *font = nullptr) override;
- void releaseHandle(void *handle) override;
QFont defaultFont() const override;
- bool fontsAlwaysScalable() const override;
bool isPrivateFontFamily(const QString &family) const override;
+ bool supportsVariableApplicationFonts() const override;
+
+ void registerBitmapFont(const QString &bitmapFont)
+ {
+ m_populatedBitmapFonts.insert(bitmapFont);
+ }
+
+ bool hasPopulatedFont(const QString &fontFamily) const
+ {
+ return m_populatedFonts.contains(fontFamily);
+ }
private:
+ friend class QWindowsFontEngineDirectWrite;
static QString localeString(IDWriteLocalizedStrings *names, wchar_t localeName[]);
+ QSupportedWritingSystems supportedWritingSystems(IDWriteFontFace *face) const;
+
QHash<QString, IDWriteFontFamily *> m_populatedFonts;
+ QSet<QString> m_populatedBitmapFonts;
};
QT_END_NAMESPACE
diff --git a/src/gui/text/windows/qwindowsfontdatabase.cpp b/src/gui/text/windows/qwindowsfontdatabase.cpp
index 58ff99e3a8..adc06a6c2a 100644
--- a/src/gui/text/windows/qwindowsfontdatabase.cpp
+++ b/src/gui/text/windows/qwindowsfontdatabase.cpp
@@ -1,57 +1,23 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsfontdatabase_p.h"
-#include "qwindowsfontdatabase_ft_p.h" // for default font
+#ifndef QT_NO_FREETYPE
+# include "qwindowsfontdatabase_ft_p.h" // for default font
+#endif
#include "qwindowsfontengine_p.h"
#include <QtCore/qt_windows.h>
#include <QtGui/QFont>
#include <QtGui/QGuiApplication>
-#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/private/qtgui-config_p.h>
#include <QtCore/qmath.h>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QtEndian>
-#include <QtCore/private/qsystemlibrary_p.h>
+#include <QtCore/QStandardPaths>
+#include <QtCore/private/qduplicatetracker_p.h>
#include <QtCore/private/qwinregistry_p.h>
#include <wchar.h>
@@ -65,13 +31,13 @@
# include "qwindowsfontenginedirectwrite_p.h"
#endif
-QT_BEGIN_NAMESPACE
+#include <mutex>
-#if QT_CONFIG(directwrite)
-// ### fixme: Consider direct linking of dwrite.dll once Windows Vista pre SP2 is dropped (QTBUG-49711)
+QT_BEGIN_NAMESPACE
-typedef HRESULT (WINAPI *DWriteCreateFactoryType)(DWRITE_FACTORY_TYPE, const IID &, IUnknown **);
+using namespace Qt::StringLiterals;
+#if QT_CONFIG(directwrite)
static inline bool useDirectWrite(QFont::HintingPreference hintingPreference,
const QString &familyName = QString(),
bool isColorFont = false)
@@ -82,7 +48,7 @@ static inline bool useDirectWrite(QFont::HintingPreference hintingPreference,
// At some scales, GDI will misrender the MingLiU font, so we force use of
// DirectWrite to work around the issue.
- if (Q_UNLIKELY(familyName.startsWith(QLatin1String("MingLiU"))))
+ if (Q_UNLIKELY(familyName.startsWith("MingLiU"_L1)))
return true;
if (isColorFont)
@@ -90,7 +56,7 @@ static inline bool useDirectWrite(QFont::HintingPreference hintingPreference,
return hintingPreference == QFont::PreferNoHinting
|| hintingPreference == QFont::PreferVerticalHinting
- || (QHighDpiScaling::isActive() && hintingPreference == QFont::PreferDefaultHinting);
+ || (!qFuzzyCompare(qApp->devicePixelRatio(), 1.0) && hintingPreference == QFont::PreferDefaultHinting);
}
#endif // !QT_NO_DIRECTWRITE
@@ -225,17 +191,6 @@ static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSe
return QFontDatabase::Any;
}
-#ifdef MAKE_TAG
-#undef MAKE_TAG
-#endif
-// GetFontData expects the tags in little endian ;(
-#define MAKE_TAG(ch1, ch2, ch3, ch4) (\
- (((quint32)(ch4)) << 24) | \
- (((quint32)(ch3)) << 16) | \
- (((quint32)(ch2)) << 8) | \
- ((quint32)(ch1)) \
- )
-
bool qt_localizedName(const QString &name)
{
const QChar *c = name.unicode();
@@ -413,7 +368,7 @@ QString qt_getEnglishName(const QString &familyName, bool includeStyle)
HGDIOBJ oldobj = SelectObject( hdc, hfont );
- const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' );
+ const DWORD name_tag = qFromBigEndian(QFont::Tag("name").value());
// get the name table
unsigned char *table = 0;
@@ -434,7 +389,7 @@ QString qt_getEnglishName(const QString &familyName, bool includeStyle)
const QFontNames names = qt_getCanonicalFontNames(table, bytes);
i18n_name = names.name;
if (includeStyle)
- i18n_name += QLatin1Char(' ') + names.style;
+ i18n_name += u' ' + names.style;
}
error:
delete [] table;
@@ -462,7 +417,7 @@ QFontNames qt_getCanonicalFontNames(const LOGFONT &lf)
// get the name table
QByteArray table;
- const DWORD name_tag = MAKE_TAG('n', 'a', 'm', 'e');
+ const DWORD name_tag = qFromBigEndian(QFont::Tag("name").value());
DWORD bytes = GetFontData(hdc, name_tag, 0, 0, 0);
if (bytes != GDI_ERROR) {
table.resize(bytes);
@@ -478,18 +433,6 @@ QFontNames qt_getCanonicalFontNames(const LOGFONT &lf)
return fontNames;
}
-static QChar *createFontFile(const QString &faceName)
-{
- QChar *faceNamePtr = nullptr;
- if (!faceName.isEmpty()) {
- const int nameLength = qMin(faceName.length(), LF_FACESIZE - 1);
- faceNamePtr = new QChar[nameLength + 1];
- memcpy(static_cast<void *>(faceNamePtr), faceName.utf16(), sizeof(wchar_t) * nameLength);
- faceNamePtr[nameLength] = u'\0';
- }
- return faceNamePtr;
-}
-
namespace {
struct StoreFontPayload {
StoreFontPayload(const QString &family,
@@ -499,7 +442,7 @@ namespace {
{}
QString populatedFontFamily;
- QSet<FontAndStyle> foundFontAndStyles;
+ QDuplicateTracker<FontAndStyle> foundFontAndStyles;
QWindowsFontDatabase *windowsFontDatabase;
};
}
@@ -513,7 +456,7 @@ static bool addFontToDatabase(QString familyName,
StoreFontPayload *sfp)
{
// the "@family" fonts are just the same as "family". Ignore them.
- if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_")))
+ if (familyName.isEmpty() || familyName.at(0) == u'@' || familyName.startsWith("WST_"_L1))
return false;
uchar charSet = logFont.lfCharSet;
@@ -544,7 +487,7 @@ static bool addFontToDatabase(QString familyName,
str << " TRUETYPE";
str << " scalable=" << scalable << " Size=" << size
<< " Style=" << style << " Weight=" << weight
- << " stretch=" << stretch;
+ << " stretch=" << stretch << " styleName=" << styleName;
qCDebug(lcQpaFonts) << message;
}
#endif
@@ -562,7 +505,13 @@ static bool addFontToDatabase(QString familyName,
subFamilyStyle = styleName;
faceName = familyName; // Remember the original name for later lookups
familyName = canonicalNames.preferredName;
- styleName = canonicalNames.preferredStyle;
+ // Preferred style / typographic subfamily name:
+ // "If it is absent, then name ID 2 is considered to be the typographic subfamily name."
+ // From: https://docs.microsoft.com/en-us/windows/win32/directwrite/opentype-variable-fonts
+ // Name ID 2 is already stored in the styleName variable. Furthermore, for variable fonts,
+ // styleName holds the variation instance name, which should be used over name ID 2.
+ if (!canonicalNames.preferredStyle.isEmpty())
+ styleName = canonicalNames.preferredStyle;
}
QSupportedWritingSystems writingSystems;
@@ -582,7 +531,7 @@ static bool addFontToDatabase(QString familyName,
// display Thai text by default. As a temporary work around, we special case Segoe UI
// and remove the Thai script from its list of supported writing systems.
if (writingSystems.supported(QFontDatabase::Thai) &&
- familyName == QLatin1String("Segoe UI"))
+ familyName == "Segoe UI"_L1)
writingSystems.setSupported(QFontDatabase::Thai, false);
} else {
const QFontDatabase::WritingSystem ws = writingSystemFromCharSet(charSet);
@@ -590,33 +539,35 @@ static bool addFontToDatabase(QString familyName,
writingSystems.setSupported(ws);
}
- // We came here from populating a different font family, so we have
- // to ensure the entire typographic family is populated before we
- // mark it as such inside registerFont()
- if (!subFamilyName.isEmpty()
- && familyName != subFamilyName
- && sfp->populatedFontFamily != familyName
- && !QPlatformFontDatabase::isFamilyPopulated(familyName)) {
- sfp->windowsFontDatabase->populateFamily(familyName);
- }
-
+ const bool wasPopulated = QPlatformFontDatabase::isFamilyPopulated(familyName);
QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight,
- style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
+ style, stretch, antialias, scalable, size, fixed, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
+
// add fonts windows can generate for us:
if (weight <= QFont::DemiBold && styleName.isEmpty())
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
- style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
+ style, stretch, antialias, scalable, size, fixed, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
if (style != QFont::StyleItalic && styleName.isEmpty())
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, weight,
- QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
+ QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
if (weight <= QFont::DemiBold && style != QFont::StyleItalic && styleName.isEmpty())
QPlatformFontDatabase::registerFont(familyName, QString(), foundryName, QFont::Bold,
- QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
+ QFont::StyleItalic, stretch, antialias, scalable, size, fixed, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
+
+ // We came here from populating a different font family, so we have
+ // to ensure the entire typographic family is populated before we
+ // mark it as such inside registerFont()
+ if (!subFamilyName.isEmpty()
+ && familyName != subFamilyName
+ && sfp->populatedFontFamily != familyName
+ && !wasPopulated) {
+ sfp->windowsFontDatabase->populateFamily(familyName);
+ }
if (!subFamilyName.isEmpty() && familyName != subFamilyName) {
QPlatformFontDatabase::registerFont(subFamilyName, subFamilyStyle, foundryName, weight,
- style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
+ style, stretch, antialias, scalable, size, fixed, writingSystems, new QWindowsFontDatabase::FontHandle(faceName));
}
if (!englishName.isEmpty() && englishName != familyName)
@@ -642,10 +593,8 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t
signature = &reinterpret_cast<const NEWTEXTMETRICEX *>(textmetric)->ntmFontSig;
// We get a callback for each script-type supported, but we register them all
// at once using the signature, so we only need one call to addFontToDatabase().
- FontAndStyle fontAndStyle = {familyName, styleName};
- if (sfp->foundFontAndStyles.contains(fontAndStyle))
+ if (sfp->foundFontAndStyles.hasSeen({familyName, styleName}))
return 1;
- sfp->foundFontAndStyles.insert(fontAndStyle);
}
addFontToDatabase(familyName, styleName, *logFont, textmetric, signature, type, sfp);
@@ -706,24 +655,48 @@ static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TE
return 1; // continue
}
+namespace {
+
+QString resolveFontPath(const QString &fontPath)
+{
+ if (fontPath.isEmpty())
+ return QString();
+
+ if (QFile::exists(fontPath))
+ return fontPath;
+
+ // resolve the path relatively to Windows Fonts directory
+ return QStandardPaths::locate(QStandardPaths::FontsLocation, fontPath);
+}
+
+}
+
void QWindowsFontDatabase::addDefaultEUDCFont()
{
const QString path = QWinRegistryKey(HKEY_CURRENT_USER, LR"(EUDC\1252)")
.stringValue(L"SystemDefaultEUDCFont");
- if (!path.isEmpty()) {
- QFile file(path);
- if (!file.open(QIODevice::ReadOnly)) {
- qCWarning(lcQpaFonts) << "Unable to open default EUDC font:" << path;
- return;
- }
+ if (path.isEmpty()) {
+ qCDebug(lcQpaFonts) << "There's no default EUDC font specified";
+ return;
+ }
+
+ const QString absolutePath = resolveFontPath(path);
+ if (absolutePath.isEmpty()) {
+ qCDebug(lcQpaFonts) << "Unable to locate default EUDC font:" << path;
+ return;
+ }
- m_eudcFonts = addApplicationFont(file.readAll(), path);
+ QFile file(absolutePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qCWarning(lcQpaFonts) << "Unable to open default EUDC font:" << absolutePath;
+ return;
}
+
+ m_eudcFonts = addApplicationFont(file.readAll(), absolutePath);
}
void QWindowsFontDatabase::populateFontDatabase()
{
- removeApplicationFonts();
HDC dummy = GetDC(0);
LOGFONT lf;
lf.lfCharSet = DEFAULT_CHARSET;
@@ -732,12 +705,18 @@ void QWindowsFontDatabase::populateFontDatabase()
EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, 0, 0);
ReleaseDC(0, dummy);
// Work around EnumFontFamiliesEx() not listing the system font.
- const QString systemDefaultFamily = QWindowsFontDatabase::systemDefaultFont().families().first();
+ const QString systemDefaultFamily = QWindowsFontDatabase::systemDefaultFont().families().constFirst();
if (QPlatformFontDatabase::resolveFontFamilyAlias(systemDefaultFamily) == systemDefaultFamily)
QPlatformFontDatabase::registerFontFamily(systemDefaultFamily);
addDefaultEUDCFont();
}
+void QWindowsFontDatabase::invalidate()
+{
+ QWindowsFontDatabaseBase::invalidate();
+ removeApplicationFonts();
+}
+
QWindowsFontDatabase::QWindowsFontDatabase()
{
// Properties accessed by QWin32PrintEngine (Qt Print Support)
@@ -760,7 +739,8 @@ QWindowsFontDatabase::~QWindowsFontDatabase()
QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
{
- const QString faceName(static_cast<const QChar*>(handle));
+ FontHandle *fontHandle = static_cast<FontHandle *>(handle);
+ const QString faceName = fontHandle->faceName.left(LF_FACESIZE - 1);
QFontEngine *fe = QWindowsFontDatabase::createEngine(fontDef, faceName,
defaultVerticalDPI(),
data());
@@ -782,10 +762,10 @@ QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wstrict-aliasing")
- QString uniqueFamilyName = QLatin1Char('f')
- + QString::number(guid.Data1, 36) + QLatin1Char('-')
- + QString::number(guid.Data2, 36) + QLatin1Char('-')
- + QString::number(guid.Data3, 36) + QLatin1Char('-')
+ QString uniqueFamilyName = u'f'
+ + QString::number(guid.Data1, 36) + u'-'
+ + QString::number(guid.Data2, 36) + u'-'
+ + QString::number(guid.Data3, 36) + u'-'
+ QString::number(*reinterpret_cast<quint64 *>(guid.Data4), 36);
QT_WARNING_POP
@@ -822,7 +802,7 @@ QT_WARNING_POP
if (fontEngine) {
if (request.families != fontEngine->fontDef.families) {
qWarning("%s: Failed to load font. Got fallback instead: %s", __FUNCTION__,
- qPrintable(fontEngine->fontDef.families.first()));
+ qPrintable(fontEngine->fontDef.families.constFirst()));
if (fontEngine->ref.loadRelaxed() == 0)
delete fontEngine;
fontEngine = 0;
@@ -846,10 +826,13 @@ QT_WARNING_POP
Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled font engine.");
}
- UniqueFontData uniqueData;
+ UniqueFontData uniqueData{};
uniqueData.handle = fontHandle;
- uniqueData.refCount.ref();
- m_uniqueFontData[uniqueFamilyName] = uniqueData;
+ ++uniqueData.refCount;
+ {
+ const std::scoped_lock lock(m_uniqueFontDataMutex);
+ m_uniqueFontData[uniqueFamilyName] = uniqueData;
+ }
}
} else {
RemoveFontMemResourceEx(fontHandle);
@@ -870,36 +853,70 @@ QT_WARNING_POP
return fontEngine;
}
-static QList<quint32> getTrueTypeFontOffsets(const uchar *fontData)
+static QList<quint32> getTrueTypeFontOffsets(const uchar *fontData, const uchar *fileEndSentinel)
{
QList<quint32> offsets;
- const quint32 headerTag = *reinterpret_cast<const quint32 *>(fontData);
- if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) {
- if (headerTag != MAKE_TAG(0, 1, 0, 0)
- && headerTag != MAKE_TAG('O', 'T', 'T', 'O')
- && headerTag != MAKE_TAG('t', 'r', 'u', 'e')
- && headerTag != MAKE_TAG('t', 'y', 'p', '1'))
+ if (fileEndSentinel - fontData < 12) {
+ qCWarning(lcQpaFonts) << "Corrupted font data detected";
+ return offsets;
+ }
+
+ const quint32 headerTag = qFromUnaligned<quint32>(fontData);
+ if (headerTag != qFromBigEndian(QFont::Tag("ttcf").value())) {
+ if (headerTag != qFromBigEndian(QFont::Tag("\0\1\0\0").value())
+ && headerTag != qFromBigEndian(QFont::Tag("OTTO").value())
+ && headerTag != qFromBigEndian(QFont::Tag("true").value())
+ && headerTag != qFromBigEndian(QFont::Tag("typ1").value())) {
return offsets;
+ }
offsets << 0;
return offsets;
}
+
+ const quint32 maximumNumFonts = 0xffff;
const quint32 numFonts = qFromBigEndian<quint32>(fontData + 8);
- for (uint i = 0; i < numFonts; ++i) {
- offsets << qFromBigEndian<quint32>(fontData + 12 + i * 4);
+ if (numFonts > maximumNumFonts) {
+ qCWarning(lcQpaFonts) << "Font collection of" << numFonts << "fonts is too large. Aborting.";
+ return offsets;
}
+
+ if (quintptr(fileEndSentinel - fontData) > 12 + (numFonts - 1) * 4) {
+ for (quint32 i = 0; i < numFonts; ++i)
+ offsets << qFromBigEndian<quint32>(fontData + 12 + i * 4);
+ } else {
+ qCWarning(lcQpaFonts) << "Corrupted font data detected";
+ }
+
return offsets;
}
-static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length)
+static void getFontTable(const uchar *fileBegin, const uchar *fileEndSentinel, const uchar *data, quint32 tag, const uchar **table, quint32 *length)
{
- const quint16 numTables = qFromBigEndian<quint16>(data + 4);
- for (uint i = 0; i < numTables; ++i) {
- const quint32 offset = 12 + 16 * i;
- if (*reinterpret_cast<const quint32 *>(data + offset) == tag) {
- *table = fileBegin + qFromBigEndian<quint32>(data + offset + 8);
- *length = qFromBigEndian<quint32>(data + offset + 12);
- return;
+ if (fileEndSentinel - data >= 6) {
+ const quint16 numTables = qFromBigEndian<quint16>(data + 4);
+ if (fileEndSentinel - data >= 28 + 16 * (numTables - 1)) {
+ for (quint32 i = 0; i < numTables; ++i) {
+ const quint32 offset = 12 + 16 * i;
+ if (qFromUnaligned<quint32>(data + offset) == tag) {
+ const quint32 tableOffset = qFromBigEndian<quint32>(data + offset + 8);
+ if (quintptr(fileEndSentinel - fileBegin) <= tableOffset) {
+ qCWarning(lcQpaFonts) << "Corrupted font data detected";
+ break;
+ }
+ *table = fileBegin + tableOffset;
+ *length = qFromBigEndian<quint32>(data + offset + 12);
+ if (quintptr(fileEndSentinel - *table) < *length) {
+ qCWarning(lcQpaFonts) << "Corrupted font data detected";
+ break;
+ }
+ return;
+ }
+ }
+ } else {
+ qCWarning(lcQpaFonts) << "Corrupted font data detected";
}
+ } else {
+ qCWarning(lcQpaFonts) << "Corrupted font data detected";
}
*table = 0;
*length = 0;
@@ -912,8 +929,9 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
QList<QFontValues> *values)
{
const uchar *data = reinterpret_cast<const uchar *>(fontData.constData());
+ const uchar *dataEndSentinel = data + fontData.size();
- QList<quint32> offsets = getTrueTypeFontOffsets(data);
+ QList<quint32> offsets = getTrueTypeFontOffsets(data, dataEndSentinel);
if (offsets.isEmpty())
return;
@@ -921,7 +939,9 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
const uchar *font = data + offsets.at(i);
const uchar *table;
quint32 length;
- getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length);
+ getFontTable(data, dataEndSentinel, font,
+ qFromBigEndian(QFont::Tag("name").value()),
+ &table, &length);
if (!table)
continue;
QFontNames names = qt_getCanonicalFontNames(table, length);
@@ -930,8 +950,11 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
families->append(std::move(names));
- if (values || signatures)
- getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
+ if (values || signatures) {
+ getFontTable(data, dataEndSentinel, font,
+ qFromBigEndian(QFont::Tag("OS/2").value()),
+ &table, &length);
+ }
if (values) {
QFontValues fontValues;
@@ -996,7 +1019,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
HDC hdc = GetDC(0);
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
- memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE - 1, familyName.size()));
+ memcpy(lf.lfFaceName, familyName.data(), sizeof(wchar_t) * qMin(LF_FACESIZE - 1, familyName.size()));
lf.lfCharSet = DEFAULT_CHARSET;
const QFontValues &values = fontValues.at(j);
lf.lfWeight = values.weight;
@@ -1077,7 +1100,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
void QWindowsFontDatabase::removeApplicationFonts()
{
- for (const WinApplicationFont &font : qAsConst(m_applicationFonts)) {
+ for (const WinApplicationFont &font : std::as_const(m_applicationFonts)) {
if (font.handle) {
RemoveFontMemResourceEx(font.handle);
} else {
@@ -1089,10 +1112,22 @@ void QWindowsFontDatabase::removeApplicationFonts()
m_eudcFonts.clear();
}
+QWindowsFontDatabase::FontHandle::FontHandle(IDWriteFontFace *face, const QString &name)
+ : fontFace(face), faceName(name)
+{
+ fontFace->AddRef();
+}
+
+
+QWindowsFontDatabase::FontHandle::~FontHandle()
+{
+ if (fontFace != nullptr)
+ fontFace->Release();
+}
+
void QWindowsFontDatabase::releaseHandle(void *handle)
{
- const QChar *faceName = reinterpret_cast<const QChar *>(handle);
- delete[] faceName;
+ delete static_cast<FontHandle *>(handle);
}
QString QWindowsFontDatabase::fontDir() const
@@ -1109,18 +1144,22 @@ bool QWindowsFontDatabase::fontsAlwaysScalable() const
void QWindowsFontDatabase::derefUniqueFont(const QString &uniqueFont)
{
- if (m_uniqueFontData.contains(uniqueFont)) {
- if (!m_uniqueFontData[uniqueFont].refCount.deref()) {
- RemoveFontMemResourceEx(m_uniqueFontData[uniqueFont].handle);
- m_uniqueFontData.remove(uniqueFont);
+ const std::scoped_lock lock(m_uniqueFontDataMutex);
+ const auto it = m_uniqueFontData.find(uniqueFont);
+ if (it != m_uniqueFontData.end()) {
+ if (--it->refCount == 0) {
+ RemoveFontMemResourceEx(it->handle);
+ m_uniqueFontData.erase(it);
}
}
}
void QWindowsFontDatabase::refUniqueFont(const QString &uniqueFont)
{
- if (m_uniqueFontData.contains(uniqueFont))
- m_uniqueFontData[uniqueFont].refCount.ref();
+ const std::scoped_lock lock(m_uniqueFontDataMutex);
+ const auto it = m_uniqueFontData.find(uniqueFont);
+ if (it != m_uniqueFontData.end())
+ ++it->refCount;
}
QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
@@ -1170,7 +1209,7 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q
const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam);
if (nameSubstitute != fam) {
const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1);
- memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t));
+ memcpy(lf.lfFaceName, nameSubstitute.data(), nameSubstituteLength * sizeof(wchar_t));
lf.lfFaceName[nameSubstituteLength] = 0;
}
@@ -1188,6 +1227,7 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q
HRESULT hr = data->directWriteGdiInterop->CreateFontFaceFromHdc(data->hdc, &directWriteFontFace);
if (SUCCEEDED(hr)) {
bool isColorFont = false;
+ bool needsSimulation = false;
#if QT_CONFIG(direct2d)
IDWriteFontFace2 *directWriteFontFace2 = nullptr;
if (SUCCEEDED(directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace2),
@@ -1195,10 +1235,12 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q
if (directWriteFontFace2->IsColorFont())
isColorFont = directWriteFontFace2->GetPaletteEntryCount() > 0;
+ needsSimulation = directWriteFontFace2->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE;
+
directWriteFontFace2->Release();
}
#endif // direct2d
- useDw = useDw || useDirectWrite(hintingPreference, fam, isColorFont);
+ useDw = useDw || useDirectWrite(hintingPreference, fam, isColorFont) || needsSimulation;
qCDebug(lcQpaFonts)
<< __FUNCTION__ << request.families.first() << request.pointSize << "pt"
<< "hintingPreference=" << hintingPreference << "color=" << isColorFont
@@ -1214,9 +1256,6 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, const Q
QFontDef fontDef = request;
fontDef.families = QStringList(QString::fromWCharArray(n));
-
- if (isColorFont)
- fedw->glyphFormat = QFontEngine::Format_ARGB;
fedw->initFontInfo(fontDef, dpi);
fe = fedw;
}
diff --git a/src/gui/text/windows/qwindowsfontdatabase_ft.cpp b/src/gui/text/windows/qwindowsfontdatabase_ft.cpp
index e2c8d3455d..0604a85e35 100644
--- a/src/gui/text/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/gui/text/windows/qwindowsfontdatabase_ft.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsfontdatabase_ft_p.h"
#include "qwindowsfontdatabase_p.h"
@@ -51,6 +15,8 @@
#if QT_CONFIG(regularexpression)
#include <QtCore/QRegularExpression>
#endif
+#include <QtCore/private/qduplicatetracker_p.h>
+
#include <QtGui/QGuiApplication>
#include <QtGui/QFontDatabase>
@@ -58,6 +24,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSet)
{
switch (charSet) {
@@ -138,7 +106,7 @@ static FontKeys &fontKeys()
#if QT_CONFIG(regularexpression)
realKey.remove(sizeListMatch);
#endif
- const auto fontNames = QStringView(realKey).trimmed().split(QLatin1Char('&'));
+ const auto fontNames = QStringView(realKey).trimmed().split(u'&');
fontKey.fontNames.reserve(fontNames.size());
for (const auto &fontName : fontNames)
fontKey.fontNames.append(fontName.trimmed().toString());
@@ -174,7 +142,7 @@ static bool addFontToDatabase(QString familyName,
int type)
{
// the "@family" fonts are just the same as "family". Ignore them.
- if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_")))
+ if (familyName.isEmpty() || familyName.at(0) == u'@' || familyName.startsWith("WST_"_L1))
return false;
uchar charSet = logFont.lfCharSet;
@@ -240,8 +208,7 @@ static bool addFontToDatabase(QString familyName,
// Since it's the default UI font on this platform, most widgets will be unable to
// display Thai text by default. As a temporary work around, we special case Segoe UI
// and remove the Thai script from its list of supported writing systems.
- if (writingSystems.supported(QFontDatabase::Thai) &&
- faceName == QLatin1String("Segoe UI"))
+ if (writingSystems.supported(QFontDatabase::Thai) && faceName == "Segoe UI"_L1)
writingSystems.setSupported(QFontDatabase::Thai, false);
} else {
const QFontDatabase::WritingSystem ws = writingSystemFromCharSet(charSet);
@@ -257,8 +224,8 @@ static bool addFontToDatabase(QString familyName,
QLocale systemLocale = QLocale::system();
if (systemLocale.language() != QLocale::C
&& systemLocale.language() != QLocale::English
- && styleName != QLatin1String("Italic")
- && styleName != QLatin1String("Bold")) {
+ && styleName != "Italic"_L1
+ && styleName != "Bold"_L1) {
key = findFontKey(qt_getEnglishName(fullName, true), &index);
}
if (!key)
@@ -318,11 +285,9 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t
signature = &reinterpret_cast<const NEWTEXTMETRICEX *>(textmetric)->ntmFontSig;
// We get a callback for each script-type supported, but we register them all
// at once using the signature, so we only need one call to addFontToDatabase().
- QSet<FontAndStyle> *foundFontAndStyles = reinterpret_cast<QSet<FontAndStyle> *>(lparam);
- FontAndStyle fontAndStyle = {faceName, styleName};
- if (foundFontAndStyles->contains(fontAndStyle))
+ auto foundFontAndStyles = reinterpret_cast<QDuplicateTracker<FontAndStyle> *>(lparam);
+ if (foundFontAndStyles->hasSeen({faceName, styleName}))
return 1;
- foundFontAndStyles->insert(fontAndStyle);
}
addFontToDatabase(faceName, styleName, fullName, *logFont, textmetric, signature, type);
@@ -330,6 +295,21 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t
return 1;
}
+bool QWindowsFontDatabaseFT::populateFamilyAliases(const QString &missingFamily)
+{
+ Q_UNUSED(missingFamily);
+
+ if (m_hasPopulatedAliases)
+ return false;
+
+ QStringList families = QFontDatabase::families();
+ for (const QString &family : families)
+ populateFamily(family);
+ m_hasPopulatedAliases = true;
+
+ return true;
+}
+
/*
\brief Populates the font database using EnumFontFamiliesEx().
@@ -352,7 +332,7 @@ void QWindowsFontDatabaseFT::populateFamily(const QString &familyName)
lf.lfFaceName[familyName.size()] = 0;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfPitchAndFamily = 0;
- QSet<FontAndStyle> foundFontAndStyles;
+ QDuplicateTracker<FontAndStyle> foundFontAndStyles;
EnumFontFamiliesEx(dummy, &lf, storeFont, reinterpret_cast<intptr_t>(&foundFontAndStyles), 0);
ReleaseDC(0, dummy);
}
@@ -398,7 +378,7 @@ void QWindowsFontDatabaseFT::populateFontDatabase()
EnumFontFamiliesEx(dummy, &lf, populateFontFamilies, 0, 0);
ReleaseDC(0, dummy);
// Work around EnumFontFamiliesEx() not listing the system font
- const QString systemDefaultFamily = QWindowsFontDatabase::systemDefaultFont().families().first();
+ const QString systemDefaultFamily = QWindowsFontDatabase::systemDefaultFont().families().constFirst();
if (QPlatformFontDatabase::resolveFontFamilyAlias(systemDefaultFamily) == systemDefaultFamily)
QPlatformFontDatabase::registerFontFamily(systemDefaultFamily);
}
@@ -406,7 +386,7 @@ void QWindowsFontDatabaseFT::populateFontDatabase()
QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, void *handle)
{
QFontEngine *fe = QFreeTypeFontDatabase::fontEngine(fontDef, handle);
- qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef.families.first() << fe << handle;
+ qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef.families.constFirst() << fe << handle;
return fe;
}
@@ -431,7 +411,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
}
QString QWindowsFontDatabaseFT::fontDir() const
{
- const QString result = QLatin1String(qgetenv("windir")) + QLatin1String("/Fonts");//QPlatformFontDatabase::fontDir();
+ const QString result = QLatin1StringView(qgetenv("windir")) + "/Fonts"_L1;//QPlatformFontDatabase::fontDir();
qCDebug(lcQpaFonts) << __FUNCTION__ << result;
return result;
}
diff --git a/src/gui/text/windows/qwindowsfontdatabase_ft_p.h b/src/gui/text/windows/qwindowsfontdatabase_ft_p.h
index af0b1d7077..381a7be4e7 100644
--- a/src/gui/text/windows/qwindowsfontdatabase_ft_p.h
+++ b/src/gui/text/windows/qwindowsfontdatabase_ft_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSFONTDATABASEFT_H
#define QWINDOWSFONTDATABASEFT_H
@@ -61,6 +25,7 @@ class Q_GUI_EXPORT QWindowsFontDatabaseFT : public QFreeTypeFontDatabase
{
public:
void populateFontDatabase() override;
+ bool populateFamilyAliases(const QString &familyName) override;
void populateFamily(const QString &familyName) override;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize,
@@ -72,6 +37,8 @@ public:
QString fontDir() const override;
QFont defaultFont() const override;
+
+ bool m_hasPopulatedAliases = false;
};
QT_END_NAMESPACE
diff --git a/src/gui/text/windows/qwindowsfontdatabase_p.h b/src/gui/text/windows/qwindowsfontdatabase_p.h
index b4b367b1e7..0c99c91fde 100644
--- a/src/gui/text/windows/qwindowsfontdatabase_p.h
+++ b/src/gui/text/windows/qwindowsfontdatabase_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSFONTDATABASE_H
#define QWINDOWSFONTDATABASE_H
@@ -57,6 +21,7 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QLoggingCategory>
#include <QtCore/qhashfunctions.h>
+#include <QtCore/qmutex.h>
#include <QtCore/qt_windows.h>
QT_BEGIN_NAMESPACE
@@ -79,6 +44,9 @@ public:
void ensureFamilyPopulated(const QString &familyName);
void populateFontDatabase() override;
+ void invalidate() override;
+ void removeApplicationFonts();
+
void populateFamily(const QString &familyName) override;
bool populateFamilyAliases(const QString &missingFamily) override;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
@@ -107,8 +75,16 @@ public:
static void debugFormat(QDebug &d, const LOGFONT &lf);
#endif // !QT_NO_DEBUG_STREAM
+ struct FontHandle {
+ FontHandle(const QString &name) : faceName(name) {}
+ FontHandle(IDWriteFontFace *face, const QString &name);
+ ~FontHandle();
+
+ IDWriteFontFace *fontFace = nullptr;
+ QString faceName;
+ };
+
private:
- void removeApplicationFonts();
void addDefaultEUDCFont();
struct WinApplicationFont {
@@ -120,9 +96,10 @@ private:
struct UniqueFontData {
HANDLE handle;
- QAtomicInt refCount;
+ int refCount;
};
+ QMutex m_uniqueFontDataMutex; // protects m_uniqueFontData
QMap<QString, UniqueFontData> m_uniqueFontData;
static unsigned m_fontOptions;
diff --git a/src/gui/text/windows/qwindowsfontdatabasebase.cpp b/src/gui/text/windows/qwindowsfontdatabasebase.cpp
index 81042c1284..84e619b0d9 100644
--- a/src/gui/text/windows/qwindowsfontdatabasebase.cpp
+++ b/src/gui/text/windows/qwindowsfontdatabasebase.cpp
@@ -1,46 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsfontdatabasebase_p.h"
#include "qwindowsfontdatabase_p.h"
-#include <QtCore/private/qsystemlibrary_p.h>
#include <QtCore/QThreadStorage>
#include <QtCore/QtEndian>
@@ -56,6 +19,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
// Helper classes for creating font engines directly from font data
namespace {
@@ -275,14 +240,11 @@ QString QWindowsFontDatabaseBase::EmbeddedFont::changeFamilyName(const QString &
// nameRecord now points to string data
quint16 *stringStorage = reinterpret_cast<quint16 *>(nameRecord);
- const quint16 *sourceString = newFamilyName.utf16();
- for (int i = 0; i < newFamilyName.size(); ++i)
- stringStorage[i] = qbswap<quint16>(sourceString[i]);
- stringStorage += newFamilyName.size();
+ for (QChar ch : newFamilyName)
+ *stringStorage++ = qbswap<quint16>(quint16(ch.unicode()));
- sourceString = regularString.utf16();
- for (int i = 0; i < regularString.size(); ++i)
- stringStorage[i] = qbswap<quint16>(sourceString[i]);
+ for (QChar ch : regularString)
+ *stringStorage++ = qbswap<quint16>(quint16(ch.unicode()));
}
quint32 *p = reinterpret_cast<quint32 *>(newNameTable.data());
@@ -397,10 +359,10 @@ namespace {
{
}
- inline void addKey(const void *key, const QByteArray &fontData)
+ inline void addKey(const QByteArray &fontData)
{
- Q_ASSERT(!m_fontDatas.contains(key));
- m_fontDatas.insert(key, fontData);
+ if (!m_fontDatas.contains(fontData.data()))
+ m_fontDatas.insert(fontData.data(), fontData);
}
inline void removeKey(const void *key)
@@ -416,6 +378,11 @@ namespace {
UINT32 fontFileReferenceKeySize,
OUT IDWriteFontFileStream **fontFileStream) override;
+ void clear()
+ {
+ m_fontDatas.clear();
+ }
+
private:
ULONG m_referenceCount;
QHash<const void *, QByteArray> m_fontDatas;
@@ -473,52 +440,62 @@ namespace {
return S_OK;
}
- class CustomFontFileLoader
+} // Anonymous namespace
+
+class QCustomFontFileLoader
+{
+public:
+ QCustomFontFileLoader(IDWriteFactory *factory)
{
- public:
- CustomFontFileLoader(IDWriteFactory *factory)
- {
- m_directWriteFactory = factory;
+ m_directWriteFactory = factory;
- if (m_directWriteFactory) {
- m_directWriteFactory->AddRef();
+ if (m_directWriteFactory) {
+ m_directWriteFactory->AddRef();
- m_directWriteFontFileLoader = new DirectWriteFontFileLoader();
- m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
- }
+ m_directWriteFontFileLoader = new DirectWriteFontFileLoader();
+ m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
}
+ }
- ~CustomFontFileLoader()
- {
- if (m_directWriteFactory != nullptr && m_directWriteFontFileLoader != nullptr)
- m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
+ ~QCustomFontFileLoader()
+ {
+ clear();
- if (m_directWriteFactory != nullptr)
- m_directWriteFactory->Release();
- }
+ if (m_directWriteFactory != nullptr && m_directWriteFontFileLoader != nullptr)
+ m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
- void addKey(const void *key, const QByteArray &fontData)
- {
- if (m_directWriteFontFileLoader != nullptr)
- m_directWriteFontFileLoader->addKey(key, fontData);
- }
+ if (m_directWriteFactory != nullptr)
+ m_directWriteFactory->Release();
+ }
- void removeKey(const void *key)
- {
- if (m_directWriteFontFileLoader != nullptr)
- m_directWriteFontFileLoader->removeKey(key);
- }
+ void addKey(const QByteArray &fontData)
+ {
+ if (m_directWriteFontFileLoader != nullptr)
+ m_directWriteFontFileLoader->addKey(fontData);
+ }
- IDWriteFontFileLoader *loader() const
- {
- return m_directWriteFontFileLoader;
- }
+ void removeKey(const void *key)
+ {
+ if (m_directWriteFontFileLoader != nullptr)
+ m_directWriteFontFileLoader->removeKey(key);
+ }
+
+ IDWriteFontFileLoader *loader() const
+ {
+ return m_directWriteFontFileLoader;
+ }
+
+ void clear()
+ {
+ if (m_directWriteFontFileLoader != nullptr)
+ m_directWriteFontFileLoader->clear();
+ }
+
+private:
+ IDWriteFactory *m_directWriteFactory = nullptr;
+ DirectWriteFontFileLoader *m_directWriteFontFileLoader = nullptr;
+};
- private:
- IDWriteFactory *m_directWriteFactory = nullptr;
- DirectWriteFontFileLoader *m_directWriteFontFileLoader = nullptr;
- };
-} // Anonymous namespace
#endif // directwrite && direct2d
@@ -582,36 +559,34 @@ bool QWindowsFontDatabaseBase::init(QSharedPointer<QWindowsFontEngineData> d)
}
#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
-// ### Qt 6: Link directly to dwrite instead
-typedef HRESULT (WINAPI *DWriteCreateFactoryType)(DWRITE_FACTORY_TYPE, const IID &, IUnknown **);
-static inline DWriteCreateFactoryType resolveDWriteCreateFactory()
-{
- QSystemLibrary library(QStringLiteral("dwrite"));
- QFunctionPointer result = library.resolve("DWriteCreateFactory");
- if (Q_UNLIKELY(!result)) {
- qWarning("Unable to load dwrite.dll");
- return nullptr;
- }
- return reinterpret_cast<DWriteCreateFactoryType>(result);
-}
-
void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **factory)
{
*factory = nullptr;
-
- static const DWriteCreateFactoryType dWriteCreateFactory = resolveDWriteCreateFactory();
- if (!dWriteCreateFactory)
- return;
-
IUnknown *result = nullptr;
+
# if QT_CONFIG(directwrite3)
- dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &result);
+ qCDebug(lcQpaFonts) << "Trying to create IDWriteFactory6";
+ DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory6), &result);
+
+ if (result == nullptr) {
+ qCDebug(lcQpaFonts) << "Trying to create IDWriteFactory5";
+ DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory5), &result);
+ }
+
+ if (result == nullptr) {
+ qCDebug(lcQpaFonts) << "Trying to create IDWriteFactory3";
+ DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &result);
+ }
# endif
- if (result == nullptr)
- dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result);
if (result == nullptr) {
- if (FAILED(dWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) {
+ qCDebug(lcQpaFonts) << "Trying to create IDWriteFactory2";
+ DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result);
+ }
+
+ if (result == nullptr) {
+ qCDebug(lcQpaFonts) << "Trying to create plain IDWriteFactory";
+ if (FAILED(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), &result))) {
qErrnoWarning("DWriteCreateFactory failed");
return;
}
@@ -621,16 +596,9 @@ void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **factory
}
#endif // directwrite && direct2d
-static int s_defaultVerticalDPI = 96; // Native Pixels
-
int QWindowsFontDatabaseBase::defaultVerticalDPI()
{
- return s_defaultVerticalDPI;
-}
-
-void QWindowsFontDatabaseBase::setDefaultVerticalDPI(int d)
-{
- s_defaultVerticalDPI = d;
+ return 96;
}
LOGFONT QWindowsFontDatabaseBase::fontDefToLOGFONT(const QFontDef &request, const QString &faceName)
@@ -713,16 +681,6 @@ LOGFONT QWindowsFontDatabaseBase::fontDefToLOGFONT(const QFontDef &request, cons
fam.truncate(LF_FACESIZE - 1);
}
- if (fam.isEmpty())
- fam = QStringLiteral("MS Sans Serif");
-
- if (fam == QLatin1String("MS Sans Serif")
- && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) {
- fam = QStringLiteral("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale
- }
- if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap))
- fam = QStringLiteral("Courier New");
-
memcpy(lf.lfFaceName, fam.utf16(), fam.size() * sizeof(wchar_t));
return lf;
@@ -755,36 +713,55 @@ HFONT QWindowsFontDatabaseBase::systemFont()
QFont QWindowsFontDatabaseBase::systemDefaultFont()
{
// Qt 6: Obtain default GUI font (typically "Segoe UI, 9pt", see QTBUG-58610)
- NONCLIENTMETRICS ncm;
- ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
+ NONCLIENTMETRICS ncm = {};
+ ncm.cbSize = sizeof(ncm);
+ SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, defaultVerticalDPI());
const QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont;
return systemFont;
}
+void QWindowsFontDatabaseBase::invalidate()
+{
+#if QT_CONFIG(directwrite)
+ m_fontFileLoader.reset(nullptr);
+#endif
+}
+
#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
-IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArray &fontData) const
+IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArray &fontData)
+{
+ QList<IDWriteFontFace *> faces = createDirectWriteFaces(fontData, false);
+ Q_ASSERT(faces.size() <= 1);
+
+ return faces.isEmpty() ? nullptr : faces.first();
+}
+
+QList<IDWriteFontFace *> QWindowsFontDatabaseBase::createDirectWriteFaces(const QByteArray &fontData,
+ bool queryVariations) const
{
+ QList<IDWriteFontFace *> ret;
QSharedPointer<QWindowsFontEngineData> fontEngineData = data();
if (fontEngineData->directWriteFactory == nullptr) {
qCWarning(lcQpaFonts) << "DirectWrite factory not created in QWindowsFontDatabaseBase::createDirectWriteFace()";
- return nullptr;
+ return ret;
}
- CustomFontFileLoader fontFileLoader(fontEngineData->directWriteFactory);
- fontFileLoader.addKey(this, fontData);
+ if (m_fontFileLoader == nullptr)
+ m_fontFileLoader.reset(new QCustomFontFileLoader(fontEngineData->directWriteFactory));
+
+ m_fontFileLoader->addKey(fontData);
IDWriteFontFile *fontFile = nullptr;
- const void *key = this;
+ const void *key = fontData.data();
HRESULT hres = fontEngineData->directWriteFactory->CreateCustomFontFileReference(&key,
sizeof(void *),
- fontFileLoader.loader(),
+ m_fontFileLoader->loader(),
&fontFile);
if (FAILED(hres)) {
qErrnoWarning(hres, "%s: CreateCustomFontFileReference failed", __FUNCTION__);
- return nullptr;
+ return ret;
}
BOOL isSupportedFontType;
@@ -794,28 +771,75 @@ IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArra
fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
if (!isSupportedFontType) {
fontFile->Release();
- return nullptr;
+ return ret;
+ }
+
+#if QT_CONFIG(directwrite3)
+ IDWriteFactory5 *factory5 = nullptr;
+ if (queryVariations && SUCCEEDED(fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory5),
+ reinterpret_cast<void **>(&factory5)))) {
+
+ IDWriteFontSetBuilder1 *builder;
+ if (SUCCEEDED(factory5->CreateFontSetBuilder(&builder))) {
+ if (SUCCEEDED(builder->AddFontFile(fontFile))) {
+ IDWriteFontSet *fontSet;
+ if (SUCCEEDED(builder->CreateFontSet(&fontSet))) {
+ int count = fontSet->GetFontCount();
+ qCDebug(lcQpaFonts) << "Found" << count << "variations in font file";
+ for (int i = 0; i < count; ++i) {
+ IDWriteFontFaceReference *ref;
+ if (SUCCEEDED(fontSet->GetFontFaceReference(i, &ref))) {
+ IDWriteFontFace3 *face;
+ if (SUCCEEDED(ref->CreateFontFace(&face))) {
+ ret.append(face);
+ }
+ ref->Release();
+ }
+ }
+ fontSet->Release();
+ }
+ }
+
+ builder->Release();
+ }
+
+ factory5->Release();
}
+#else
+ Q_UNUSED(queryVariations);
+#endif
// ### Currently no support for .ttc, but we could easily return a list here.
- IDWriteFontFace *directWriteFontFace = nullptr;
- hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType,
- 1,
- &fontFile,
- 0,
- DWRITE_FONT_SIMULATIONS_NONE,
- &directWriteFontFace);
- if (FAILED(hres)) {
- qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__);
- fontFile->Release();
- return nullptr;
+ if (ret.isEmpty()) {
+ IDWriteFontFace *directWriteFontFace = nullptr;
+ hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType,
+ 1,
+ &fontFile,
+ 0,
+ DWRITE_FONT_SIMULATIONS_NONE,
+ &directWriteFontFace);
+ if (FAILED(hres)) {
+ qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__);
+ fontFile->Release();
+ return ret;
+ } else {
+ ret.append(directWriteFontFace);
+ }
}
fontFile->Release();
- return directWriteFontFace;
+
+ return ret;
}
#endif // directwrite && direct2d
+QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QFontDef &fontDef, void *handle)
+{
+ // This function was apparently not used before, and probably isn't now either,
+ // call the base implementation which just prints that it's not supported.
+ return QPlatformFontDatabase::fontEngine(fontDef, handle);
+}
+
QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference)
{
QFontEngine *fontEngine = nullptr;
@@ -825,7 +849,10 @@ QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qr
if (fontEngineData->directWriteFactory == nullptr)
return nullptr;
- IDWriteFontFace *directWriteFontFace = createDirectWriteFace(fontData);
+ IDWriteFontFace * directWriteFontFace = createDirectWriteFace(fontData);
+ if (directWriteFontFace == nullptr)
+ return nullptr;
+
fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace,
pixelSize,
fontEngineData);
@@ -867,7 +894,7 @@ QString QWindowsFontDatabaseBase::familyForStyleHint(QFont::StyleHint styleHint)
default:
break;
}
- return QStringLiteral("MS Shell Dlg 2");
+ return QStringLiteral("Tahoma");
}
// Creation functions
@@ -883,6 +910,7 @@ static const char *other_tryFonts[] = {
};
static const char *jp_tryFonts [] = {
+ "Yu Gothic UI",
"MS UI Gothic",
"Arial",
"Gulim",
@@ -963,4 +991,23 @@ QStringList QWindowsFontDatabaseBase::extraTryFontsForFamily(const QString &fami
return result;
}
+QFontDef QWindowsFontDatabaseBase::sanitizeRequest(QFontDef request) const
+{
+ QFontDef req = request;
+ const QString fam = request.families.front();
+ if (fam.isEmpty())
+ req.families[0] = QStringLiteral("MS Sans Serif");
+
+ if (fam == "MS Sans Serif"_L1) {
+ int height = -qRound(request.pixelSize);
+ // MS Sans Serif has bearing problems in italic, and does not scale
+ if (request.style == QFont::StyleItalic || (height > 18 && height != 24))
+ req.families[0] = QStringLiteral("Arial");
+ }
+
+ if (!(request.styleStrategy & QFont::StyleStrategy::PreferBitmap) && fam == u"Courier")
+ req.families[0] = QStringLiteral("Courier New");
+ return req;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/text/windows/qwindowsfontdatabasebase_p.h b/src/gui/text/windows/qwindowsfontdatabasebase_p.h
index 873912f8ef..55a3363551 100644
--- a/src/gui/text/windows/qwindowsfontdatabasebase_p.h
+++ b/src/gui/text/windows/qwindowsfontdatabasebase_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSFONTDATABASEBASE_P_H
#define QWINDOWSFONTDATABASEBASE_P_H
@@ -65,6 +29,10 @@
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(directwrite)
+ class QCustomFontFileLoader;
+#endif
+
class QWindowsFontEngineData
{
Q_DISABLE_COPY_MOVE(QWindowsFontEngineData)
@@ -89,10 +57,12 @@ public:
QWindowsFontDatabaseBase();
~QWindowsFontDatabaseBase() override;
+ QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) override;
+ void invalidate() override;
+
static int defaultVerticalDPI();
- static void setDefaultVerticalDPI(int d);
static QSharedPointer<QWindowsFontEngineData> data();
#if QT_CONFIG(directwrite)
@@ -122,14 +92,22 @@ public:
QByteArray m_fontData;
};
+ QFontDef sanitizeRequest(QFontDef request) const;
+
protected:
#if QT_CONFIG(directwrite)
- IDWriteFontFace *createDirectWriteFace(const QByteArray &fontData) const;
+ QList<IDWriteFontFace *> createDirectWriteFaces(const QByteArray &fontData,
+ bool queryVariations = true) const;
+ IDWriteFontFace *createDirectWriteFace(const QByteArray &fontData);
#endif
private:
static bool init(QSharedPointer<QWindowsFontEngineData> data);
+
+#if QT_CONFIG(directwrite)
+ mutable std::unique_ptr<QCustomFontFileLoader> m_fontFileLoader;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/gui/text/windows/qwindowsfontengine.cpp b/src/gui/text/windows/qwindowsfontengine.cpp
index f4ef9f8a23..fe07897369 100644
--- a/src/gui/text/windows/qwindowsfontengine.cpp
+++ b/src/gui/text/windows/qwindowsfontengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsfontengine_p.h"
#include "qwindowsnativeimage_p.h"
@@ -74,6 +38,9 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(HFONT)
+QT_IMPL_METATYPE_EXTERN(LOGFONT)
+
//### mingw needed define
#ifndef TT_PRIM_CSPLINE
#define TT_PRIM_CSPLINE 3
@@ -89,18 +56,6 @@ QT_BEGIN_NAMESPACE
// common DC for all fonts
-typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT);
-static PtrGetCharWidthI ptrGetCharWidthI = 0;
-static bool resolvedGetCharWidthI = false;
-
-static void resolveGetCharWidthI()
-{
- if (resolvedGetCharWidthI)
- return;
- resolvedGetCharWidthI = true;
- ptrGetCharWidthI = (PtrGetCharWidthI)QSystemLibrary::resolve(QStringLiteral("gdi32"), "GetCharWidthI");
-}
-
// general font engine
QFixed QWindowsFontEngine::lineThickness() const
@@ -149,7 +104,7 @@ void QWindowsFontEngine::getCMap()
SelectObject(hdc, hfont);
bool symb = false;
if (ttf) {
- cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
+ cmapTable = getSfntTable(QFont::Tag("cmap").value());
cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()),
cmapTable.size(), &symb, &cmapSize);
}
@@ -252,9 +207,6 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
cache_cost = tm.tmHeight * tm.tmAveCharWidth * 2000;
getCMap();
- if (!resolvedGetCharWidthI)
- resolveGetCharWidthI();
-
hasUnreliableOutline = (tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) == 0;
}
@@ -326,8 +278,7 @@ bool QWindowsFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *g
inline void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width)
{
- if (ptrGetCharWidthI)
- ptrGetCharWidthI(hdc, glyph, 1, 0, &width);
+ GetCharWidthI(hdc, glyph, 1, 0, &width);
}
void QWindowsFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags flags) const
@@ -401,18 +352,6 @@ void QWindowsFontEngine::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::Shape
}
}
-glyph_metrics_t QWindowsFontEngine::boundingBox(const QGlyphLayout &glyphs)
-{
- if (glyphs.numGlyphs == 0)
- return glyph_metrics_t();
-
- QFixed w = 0;
- for (int i = 0; i < glyphs.numGlyphs; ++i)
- w += glyphs.effectiveAdvance(i);
-
- return glyph_metrics_t(0, -tm.tmAscent, w - lastRightBearing(glyphs), tm.tmHeight, w, 0);
-}
-
bool QWindowsFontEngine::getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const
{
Q_ASSERT(metrics != 0);
@@ -532,7 +471,7 @@ namespace {
QFixed QWindowsFontEngine::capHeight() const
{
- const QByteArray tableData = getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
+ const QByteArray tableData = getSfntTable(QFont::Tag("OS/2").value());
if (size_t(tableData.size()) >= sizeof(OS2Table)) {
const OS2Table *table = reinterpret_cast<const OS2Table *>(tableData.constData());
if (qFromBigEndian<quint16>(table->version) >= 2) {
@@ -675,8 +614,8 @@ qreal QWindowsFontEngine::minRightBearing() const
fmr = qMin(fmr,abc[i].abcfC);
}
}
- ml = int(fml - 0.9999);
- mr = int(fmr - 0.9999);
+ ml = qFloor(fml);
+ mr = qFloor(fmr);
delete [] abc;
}
lbearing = ml;
@@ -1150,7 +1089,7 @@ QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph,
QFontEngine *QWindowsFontEngine::cloneWithSize(qreal pixelSize) const
{
QFontDef request = fontDef;
- QString actualFontName = request.families.first();
+ QString actualFontName = request.families.constFirst();
if (!uniqueFamilyName.isEmpty())
request.families = QStringList(uniqueFamilyName);
request.pixelSize = pixelSize;
diff --git a/src/gui/text/windows/qwindowsfontengine_p.h b/src/gui/text/windows/qwindowsfontengine_p.h
index 57b619bc1c..afe8ee4ca5 100644
--- a/src/gui/text/windows/qwindowsfontengine_p.h
+++ b/src/gui/text/windows/qwindowsfontengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSFONTENGINE_H
#define QWINDOWSFONTENGINE_H
@@ -93,7 +57,6 @@ public:
HGDIOBJ selectDesignFont() const;
- glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
glyph_metrics_t boundingBox(glyph_t g) override { return boundingBox(g, QTransform()); }
glyph_metrics_t boundingBox(glyph_t g, const QTransform &t) override;
@@ -174,7 +137,7 @@ private:
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(HFONT)
-Q_DECLARE_METATYPE(LOGFONT)
+QT_DECL_METATYPE_EXTERN(HFONT, Q_GUI_EXPORT)
+QT_DECL_METATYPE_EXTERN(LOGFONT, Q_GUI_EXPORT)
#endif // QWINDOWSFONTENGINE_H
diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
index 0dac9769ef..2070deb296 100644
--- a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsfontenginedirectwrite_p.h"
#include "qwindowsfontdatabase_p.h"
@@ -48,10 +12,14 @@
#include <QtCore/private/qwinregistry_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
-#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/qpainterpath.h>
-#include <dwrite_2.h>
+#if QT_CONFIG(directwrite3)
+# include "qwindowsdirectwritefontdatabase_p.h"
+# include <dwrite_3.h>
+#else
+# include <dwrite_2.h>
+#endif
#include <d2d1.h>
@@ -101,7 +69,7 @@ namespace {
};
void GeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers,
- UINT bezierCount)
+ UINT bezierCount) noexcept
{
for (uint i=0; i<bezierCount; ++i) {
QPointF c1 = fromD2D1_POINT_2F(beziers[i].point1);
@@ -112,48 +80,48 @@ namespace {
}
}
- void GeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount)
+ void GeometrySink::AddLines(const D2D1_POINT_2F *points, UINT pointsCount) noexcept
{
for (uint i=0; i<pointsCount; ++i)
m_path->lineTo(fromD2D1_POINT_2F(points[i]));
}
void GeometrySink::BeginFigure(D2D1_POINT_2F startPoint,
- D2D1_FIGURE_BEGIN /*figureBegin*/)
+ D2D1_FIGURE_BEGIN /*figureBegin*/) noexcept
{
m_startPoint = fromD2D1_POINT_2F(startPoint);
m_path->moveTo(m_startPoint);
}
- IFACEMETHODIMP GeometrySink::Close()
+ IFACEMETHODIMP GeometrySink::Close() noexcept
{
return E_NOTIMPL;
}
- void GeometrySink::EndFigure(D2D1_FIGURE_END figureEnd)
+ void GeometrySink::EndFigure(D2D1_FIGURE_END figureEnd) noexcept
{
if (figureEnd == D2D1_FIGURE_END_CLOSED)
m_path->closeSubpath();
}
- void GeometrySink::SetFillMode(D2D1_FILL_MODE fillMode)
+ void GeometrySink::SetFillMode(D2D1_FILL_MODE fillMode) noexcept
{
m_path->setFillRule(fillMode == D2D1_FILL_MODE_ALTERNATE
? Qt::OddEvenFill
: Qt::WindingFill);
}
- void GeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT /*vertexFlags*/)
+ void GeometrySink::SetSegmentFlags(D2D1_PATH_SEGMENT /*vertexFlags*/) noexcept
{
/* Not implemented */
}
- IFACEMETHODIMP_(unsigned long) GeometrySink::AddRef()
+ IFACEMETHODIMP_(unsigned long) GeometrySink::AddRef() noexcept
{
return InterlockedIncrement(&m_refCount);
}
- IFACEMETHODIMP_(unsigned long) GeometrySink::Release()
+ IFACEMETHODIMP_(unsigned long) GeometrySink::Release() noexcept
{
unsigned long newCount = InterlockedDecrement(&m_refCount);
if (newCount == 0)
@@ -165,7 +133,7 @@ namespace {
return newCount;
}
- IFACEMETHODIMP GeometrySink::QueryInterface(IID const &riid, void **ppvObject)
+ IFACEMETHODIMP GeometrySink::QueryInterface(IID const &riid, void **ppvObject) noexcept
{
if (__uuidof(IDWriteGeometrySink) == riid) {
*ppvObject = this;
@@ -194,10 +162,19 @@ static DWRITE_MEASURING_MODE renderModeToMeasureMode(DWRITE_RENDERING_MODE rende
}
}
-static DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(QFont::HintingPreference hintingPreference)
+DWRITE_RENDERING_MODE QWindowsFontEngineDirectWrite::hintingPreferenceToRenderingMode(const QFontDef &fontDef) const
{
- if (QHighDpiScaling::isActive() && hintingPreference == QFont::PreferDefaultHinting)
- hintingPreference = QFont::PreferVerticalHinting;
+ if ((fontDef.styleStrategy & QFont::NoAntialias) && glyphFormat != QFontEngine::Format_ARGB)
+ return DWRITE_RENDERING_MODE_ALIASED;
+
+ QFont::HintingPreference hintingPreference = QFont::HintingPreference(fontDef.hintingPreference);
+ if (!qFuzzyCompare(qApp->devicePixelRatio(), 1.0) && hintingPreference == QFont::PreferDefaultHinting) {
+ // Microsoft documentation recommends using asymmetric rendering for small fonts
+ // at pixel size 16 and less, and symmetric for larger fonts.
+ hintingPreference = fontDef.pixelSize > 16.0
+ ? QFont::PreferNoHinting
+ : QFont::PreferVerticalHinting;
+ }
switch (hintingPreference) {
case QFont::PreferNoHinting:
@@ -242,7 +219,7 @@ QWindowsFontEngineDirectWrite::QWindowsFontEngineDirectWrite(IDWriteFontFace *di
fontDef.pixelSize = pixelSize;
collectMetrics();
- cache_cost = (m_ascent.toInt() + m_descent.toInt()) * m_xHeight.toInt() * 2000;
+ cache_cost = m_xHeight.toInt() * m_xHeight.toInt() * 2000;
}
QWindowsFontEngineDirectWrite::~QWindowsFontEngineDirectWrite()
@@ -337,6 +314,22 @@ QString QWindowsFontEngineDirectWrite::filenameFromFontFile(IDWriteFontFile *fon
return ret;
}
+HFONT QWindowsFontEngineDirectWrite::createHFONT() const
+{
+ if (m_fontEngineData == nullptr || m_directWriteFontFace == nullptr)
+ return NULL;
+
+ LOGFONT lf;
+ HRESULT hr = m_fontEngineData->directWriteGdiInterop->ConvertFontFaceToLOGFONT(m_directWriteFontFace,
+ &lf);
+ if (SUCCEEDED(hr)) {
+ lf.lfHeight = -qRound(fontDef.pixelSize);
+ return CreateFontIndirect(&lf);
+ } else {
+ return NULL;
+ }
+}
+
void QWindowsFontEngineDirectWrite::initializeHeightMetrics() const
{
DWRITE_FONT_METRICS metrics;
@@ -368,12 +361,14 @@ void QWindowsFontEngineDirectWrite::collectMetrics()
fontFile->Release();
}
- QByteArray table = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a'));
+ QByteArray table = getSfntTable(QFont::Tag("hhea").value());
const int advanceWidthMaxLocation = 10;
if (table.size() >= advanceWidthMaxLocation + int(sizeof(quint16))) {
quint16 advanceWidthMax = qFromBigEndian<quint16>(table.constData() + advanceWidthMaxLocation);
m_maxAdvanceWidth = DESIGN_TO_LOGICAL(advanceWidthMax);
}
+
+ loadKerningPairs(emSquareSize() / QFixed::fromReal(fontDef.pixelSize));
}
QFixed QWindowsFontEngineDirectWrite::underlinePosition() const
@@ -480,7 +475,7 @@ QFontEngine::FaceId QWindowsFontEngineDirectWrite::faceId() const
return m_faceId;
}
-void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
+void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags shaperFlags) const
{
QVarLengthArray<UINT16> glyphIndices(glyphs->numGlyphs);
@@ -491,12 +486,15 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn
QVarLengthArray<DWRITE_GLYPH_METRICS> glyphMetrics(glyphIndices.size());
HRESULT hr;
- DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(QFont::HintingPreference(fontDef.hintingPreference));
- if (renderMode == DWRITE_RENDERING_MODE_GDI_CLASSIC || renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL) {
+ DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
+ bool needsDesignMetrics = shaperFlags & QFontEngine::DesignMetrics;
+ if (!needsDesignMetrics && (renderMode == DWRITE_RENDERING_MODE_GDI_CLASSIC
+ || renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL
+ || renderMode == DWRITE_RENDERING_MODE_ALIASED)) {
hr = m_directWriteFontFace->GetGdiCompatibleGlyphMetrics(float(fontDef.pixelSize),
1.0f,
NULL,
- TRUE,
+ renderMode == DWRITE_RENDERING_MODE_GDI_NATURAL,
glyphIndices.data(),
glyphIndices.size(),
glyphMetrics.data());
@@ -514,6 +512,53 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn
}
}
+void QWindowsFontEngineDirectWrite::getUnscaledGlyph(glyph_t glyph,
+ QPainterPath *path,
+ glyph_metrics_t *metric)
+{
+ float advance = 0.0f;
+ UINT16 g = glyph;
+ DWRITE_GLYPH_OFFSET offset;
+ offset.advanceOffset = 0;
+ offset.ascenderOffset = 0;
+ GeometrySink geometrySink(path);
+ HRESULT hr = m_directWriteFontFace->GetGlyphRunOutline(m_unitsPerEm,
+ &g,
+ &advance,
+ &offset,
+ 1,
+ false,
+ false,
+ &geometrySink);
+ if (FAILED(hr)) {
+ qErrnoWarning("%s: GetGlyphRunOutline failed", __FUNCTION__);
+ return;
+ }
+
+ DWRITE_GLYPH_METRICS glyphMetrics;
+ hr = m_directWriteFontFace->GetDesignGlyphMetrics(&g, 1, &glyphMetrics);
+ if (FAILED(hr)) {
+ qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__);
+ return;
+ }
+
+ QFixed advanceWidth = QFixed(int(glyphMetrics.advanceWidth));
+ QFixed leftSideBearing = QFixed(glyphMetrics.leftSideBearing);
+ QFixed rightSideBearing = QFixed(glyphMetrics.rightSideBearing);
+ QFixed advanceHeight = QFixed(int(glyphMetrics.advanceHeight));
+ QFixed verticalOriginY = QFixed(glyphMetrics.verticalOriginY);
+ QFixed topSideBearing = QFixed(glyphMetrics.topSideBearing);
+ QFixed bottomSideBearing = QFixed(glyphMetrics.bottomSideBearing);
+ QFixed width = advanceWidth - leftSideBearing - rightSideBearing;
+ QFixed height = advanceHeight - topSideBearing - bottomSideBearing;
+ *metric = glyph_metrics_t(leftSideBearing,
+ -verticalOriginY + topSideBearing,
+ width,
+ height,
+ advanceWidth,
+ 0);
+}
+
void QWindowsFontEngineDirectWrite::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
QPainterPath *path, QTextItem::RenderFlags flags)
{
@@ -553,7 +598,9 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(const QGlyphLayout &g
for (int i = 0; i < glyphs.numGlyphs; ++i)
w += glyphs.effectiveAdvance(i);
- return glyph_metrics_t(0, -ascent(), w - lastRightBearing(glyphs), ascent() + descent(), w, 0);
+ const QFixed leftBearing = firstLeftBearing(glyphs);
+ return glyph_metrics_t(leftBearing, -ascent(), w - leftBearing - lastRightBearing(glyphs),
+ ascent() + descent(), w, 0);
}
glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(glyph_t g)
@@ -632,7 +679,37 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph,
bool QWindowsFontEngineDirectWrite::supportsHorizontalSubPixelPositions() const
{
- return true;
+ DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
+ return (renderMode != DWRITE_RENDERING_MODE_GDI_CLASSIC
+ && renderMode != DWRITE_RENDERING_MODE_GDI_NATURAL
+ && renderMode != DWRITE_RENDERING_MODE_ALIASED);
+}
+
+QFontEngine::Properties QWindowsFontEngineDirectWrite::properties() const
+{
+ IDWriteFontFace2 *directWriteFontFace2;
+ if (SUCCEEDED(m_directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace2),
+ reinterpret_cast<void **>(&directWriteFontFace2)))) {
+ DWRITE_FONT_METRICS1 metrics;
+ directWriteFontFace2->GetMetrics(&metrics);
+
+ Properties p = QFontEngine::properties();
+ p.emSquare = metrics.designUnitsPerEm;
+ p.boundingBox = QRectF(metrics.glyphBoxLeft,
+ -metrics.glyphBoxTop,
+ metrics.glyphBoxRight - metrics.glyphBoxLeft,
+ metrics.glyphBoxTop - metrics.glyphBoxBottom);
+ p.ascent = metrics.ascent;
+ p.descent = metrics.descent;
+ p.leading = metrics.lineGap;
+ p.capHeight = metrics.capHeight;
+ p.lineWidth = metrics.underlineThickness;
+
+ directWriteFontFace2->Release();
+ return p;
+ } else {
+ return QFontEngine::properties();
+ }
}
QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
@@ -670,25 +747,48 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
transform.m21 = xform.m21();
transform.m22 = xform.m22();
- DWRITE_RENDERING_MODE renderMode =
- hintingPreferenceToRenderingMode(QFont::HintingPreference(fontDef.hintingPreference));
+ DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
DWRITE_MEASURING_MODE measureMode =
renderModeToMeasureMode(renderMode);
+ DWRITE_GRID_FIT_MODE gridFitMode = fontDef.hintingPreference == QFont::PreferNoHinting
+ ? DWRITE_GRID_FIT_MODE_DISABLED
+ : DWRITE_GRID_FIT_MODE_DEFAULT;
+
+ IDWriteFactory2 *factory2 = nullptr;
+ HRESULT hr = m_fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory2),
+ reinterpret_cast<void **>(&factory2));
IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
- HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
- &glyphRun,
- 1.0f,
- &transform,
- renderMode,
- measureMode,
- 0.0, 0.0,
- &glyphAnalysis
- );
+ if (!SUCCEEDED(hr)) {
+ qErrnoWarning(hr, "%s: Failed to query IDWriteFactory2 interface.", __FUNCTION__);
+ hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
+ &glyphRun,
+ 1.0f,
+ &transform,
+ renderMode,
+ measureMode,
+ 0.0, 0.0,
+ &glyphAnalysis
+ );
+ } else {
+ hr = factory2->CreateGlyphRunAnalysis(
+ &glyphRun,
+ &transform,
+ renderMode,
+ measureMode,
+ gridFitMode,
+ DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
+ 0.0, 0.0,
+ &glyphAnalysis
+ );
+ }
if (SUCCEEDED(hr)) {
RECT rect;
- glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
+ glyphAnalysis->GetAlphaTextureBounds(renderMode == DWRITE_RENDERING_MODE_ALIASED
+ ? DWRITE_TEXTURE_ALIASED_1x1
+ : DWRITE_TEXTURE_CLEARTYPE_3x1,
+ &rect);
if (rect.top == rect.bottom || rect.left == rect.right)
return QImage();
@@ -705,10 +805,7 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
QImage image;
HRESULT hr = DWRITE_E_NOCOLOR;
IDWriteColorGlyphRunEnumerator *enumerator = 0;
- IDWriteFactory2 *factory2 = nullptr;
- if (glyphFormat == QFontEngine::Format_ARGB
- && SUCCEEDED(m_fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory2),
- reinterpret_cast<void **>(&factory2)))) {
+ if (glyphFormat == QFontEngine::Format_ARGB && factory2 != nullptr) {
hr = factory2->TranslateColorGlyphRun(0.0f,
0.0f,
&glyphRun,
@@ -736,15 +833,17 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
}
IDWriteGlyphRunAnalysis *colorGlyphsAnalysis = NULL;
- hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
+ hr = factory2->CreateGlyphRunAnalysis(
&colorGlyphRun->glyphRun,
- 1.0f,
&transform,
renderMode,
measureMode,
+ gridFitMode,
+ DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
0.0, 0.0,
&colorGlyphsAnalysis
);
+
if (FAILED(hr)) {
qErrnoWarning(hr, "%s: CreateGlyphRunAnalysis failed for color run", __FUNCTION__);
break;
@@ -770,7 +869,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
b,
a,
colorGlyphsAnalysis,
- boundingRect);
+ boundingRect,
+ renderMode);
}
colorGlyphsAnalysis->Release();
@@ -797,7 +897,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
b,
a,
glyphAnalysis,
- boundingRect);
+ boundingRect,
+ renderMode);
}
glyphAnalysis->Release();
@@ -815,7 +916,8 @@ void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
float b,
float a,
IDWriteGlyphRunAnalysis *glyphAnalysis,
- const QRect &boundingRect)
+ const QRect &boundingRect,
+ DWRITE_RENDERING_MODE renderMode)
{
const int width = destination->width();
const int height = destination->height();
@@ -836,12 +938,14 @@ void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
BYTE *alphaValues = alphaValueArray.data();
memset(alphaValues, 0, size);
- HRESULT hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1,
+ HRESULT hr = glyphAnalysis->CreateAlphaTexture(renderMode == DWRITE_RENDERING_MODE_ALIASED
+ ? DWRITE_TEXTURE_ALIASED_1x1
+ : DWRITE_TEXTURE_CLEARTYPE_3x1,
&rect,
alphaValues,
size);
if (SUCCEEDED(hr)) {
- if (destination->hasAlphaChannel()) {
+ if (destination->hasAlphaChannel()) { // Color glyphs
for (int y = 0; y < height; ++y) {
uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
BYTE *src = alphaValues + width * 3 * y;
@@ -859,7 +963,16 @@ void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
qRound(qAlpha(currentRgb) * (1.0 - averageAlpha) + averageAlpha * 255));
}
}
+ } else if (renderMode == DWRITE_RENDERING_MODE_ALIASED) {
+ for (int y = 0; y < height; ++y) {
+ uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
+ BYTE *src = alphaValues + width * y;
+ for (int x = 0; x < width; ++x) {
+ int alpha = *(src++);
+ dest[x] = (alpha << 16) + (alpha << 8) + alpha;
+ }
+ }
} else {
for (int y = 0; y < height; ++y) {
uint *dest = reinterpret_cast<uint *>(destination->scanLine(y));
@@ -928,6 +1041,27 @@ void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request,
fontDef.pointSize = fontDef.pixelSize * 72. / dpi;
else if (fontDef.pixelSize == -1)
fontDef.pixelSize = qRound(fontDef.pointSize * dpi / 72.);
+
+ m_faceId.variableAxes = request.variableAxisValues;
+
+#if QT_CONFIG(directwrite3)
+ IDWriteFontFace3 *face3 = nullptr;
+ if (SUCCEEDED(m_directWriteFontFace->QueryInterface(__uuidof(IDWriteFontFace3),
+ reinterpret_cast<void **>(&face3)))) {
+ IDWriteLocalizedStrings *names;
+ if (SUCCEEDED(face3->GetFaceNames(&names))) {
+ wchar_t englishLocale[] = L"en-us";
+ fontDef.styleName = QWindowsDirectWriteFontDatabase::localeString(names, englishLocale);
+ names->Release();
+ }
+
+ // Color font
+ if (face3->GetPaletteEntryCount() > 0)
+ glyphFormat = QFontEngine::Format_ARGB;
+
+ face3->Release();
+ }
+#endif
}
QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyName)
@@ -977,24 +1111,43 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
transform.m21 = matrix.m21();
transform.m22 = matrix.m22();
- DWRITE_RENDERING_MODE renderMode =
- hintingPreferenceToRenderingMode(QFont::HintingPreference(fontDef.hintingPreference));
+ DWRITE_RENDERING_MODE renderMode = hintingPreferenceToRenderingMode(fontDef);
DWRITE_MEASURING_MODE measureMode = renderModeToMeasureMode(renderMode);
+ DWRITE_GRID_FIT_MODE gridFitMode = fontDef.hintingPreference == QFont::PreferNoHinting
+ ? DWRITE_GRID_FIT_MODE_DISABLED
+ : DWRITE_GRID_FIT_MODE_DEFAULT;
+
+ IDWriteFactory2 *factory2 = nullptr;
+ HRESULT hr = m_fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory2),
+ reinterpret_cast<void **>(&factory2));
IDWriteGlyphRunAnalysis *glyphAnalysis = NULL;
- HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
- &glyphRun,
- 1.0f,
- &transform,
- renderMode,
- measureMode,
- 0.0, 0.0,
- &glyphAnalysis
- );
+ if (SUCCEEDED(hr)) {
+ hr = factory2->CreateGlyphRunAnalysis(
+ &glyphRun,
+ &transform,
+ renderMode,
+ measureMode,
+ gridFitMode,
+ DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
+ 0.0, 0.0,
+ &glyphAnalysis
+ );
+ } else {
+ hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis(
+ &glyphRun,
+ 1.0f,
+ &transform,
+ renderMode,
+ measureMode,
+ 0.0, 0.0,
+ &glyphAnalysis
+ );
+ }
if (SUCCEEDED(hr)) {
RECT rect;
- glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
+ glyphAnalysis->GetAlphaTextureBounds(renderMode == DWRITE_RENDERING_MODE_ALIASED ? DWRITE_TEXTURE_ALIASED_1x1 : DWRITE_TEXTURE_CLEARTYPE_3x1, &rect);
glyphAnalysis->Release();
int margin = glyphMargin(format);
diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h b/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
index 4d19c3908a..44e466789c 100644
--- a/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
+++ b/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSFONTENGINEDIRECTWRITE_H
#define QWINDOWSFONTENGINEDIRECTWRITE_H
@@ -58,6 +22,7 @@ QT_REQUIRE_CONFIG(directwrite);
#include <QtGui/private/qfontengine_p.h>
#include <QtCore/QSharedPointer>
+#include <dwrite.h>
struct IDWriteFont;
struct IDWriteFontFace;
@@ -71,7 +36,7 @@ QT_BEGIN_NAMESPACE
class QWindowsFontEngineData;
-class QWindowsFontEngineDirectWrite : public QFontEngine
+class Q_GUI_EXPORT QWindowsFontEngineDirectWrite : public QFontEngine
{
Q_DISABLE_COPY_MOVE(QWindowsFontEngineDirectWrite)
public:
@@ -107,6 +72,8 @@ public:
bool supportsHorizontalSubPixelPositions() const override;
+ HFONT createHFONT() const;
+
QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition) override;
QImage alphaMapForGlyph(glyph_t glyph,
const QFixedPoint &subPixelPosition,
@@ -132,6 +99,9 @@ public:
void initializeHeightMetrics() const override;
+ Properties properties() const override;
+ void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override;
+
private:
QImage imageForGlyph(glyph_t t,
const QFixedPoint &subPixelPosition,
@@ -139,8 +109,16 @@ private:
const QTransform &xform,
const QColor &color = QColor());
void collectMetrics();
- void renderGlyphRun(QImage *destination, float r, float g, float b, float a, IDWriteGlyphRunAnalysis *glyphAnalysis, const QRect &boundingRect);
+ void renderGlyphRun(QImage *destination,
+ float r,
+ float g,
+ float b,
+ float a,
+ IDWriteGlyphRunAnalysis *glyphAnalysis,
+ const QRect &boundingRect,
+ DWRITE_RENDERING_MODE renderMode);
static QString filenameFromFontFile(IDWriteFontFile *fontFile);
+ DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(const QFontDef &fontDef) const;
const QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
diff --git a/src/gui/text/windows/qwindowsnativeimage.cpp b/src/gui/text/windows/qwindowsnativeimage.cpp
index ad277ea7cd..eca51ccfd4 100644
--- a/src/gui/text/windows/qwindowsnativeimage.cpp
+++ b/src/gui/text/windows/qwindowsnativeimage.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsnativeimage_p.h"
diff --git a/src/gui/text/windows/qwindowsnativeimage_p.h b/src/gui/text/windows/qwindowsnativeimage_p.h
index 050ecbf03c..d223aabf45 100644
--- a/src/gui/text/windows/qwindowsnativeimage_p.h
+++ b/src/gui/text/windows/qwindowsnativeimage_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QWINDOWSNATIVEIMAGE_H
#define QWINDOWSNATIVEIMAGE_H
@@ -54,6 +18,7 @@
#include <QtCore/QtGlobal>
#include <QtCore/qt_windows.h>
#include <QtGui/QImage>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/util/qabstractlayoutstyleinfo.cpp b/src/gui/util/qabstractlayoutstyleinfo.cpp
index 40ad51452a..51d569f814 100644
--- a/src/gui/util/qabstractlayoutstyleinfo.cpp
+++ b/src/gui/util/qabstractlayoutstyleinfo.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractlayoutstyleinfo_p.h"
diff --git a/src/gui/util/qabstractlayoutstyleinfo_p.h b/src/gui/util/qabstractlayoutstyleinfo_p.h
index bf1e1fc852..42578c58ca 100644
--- a/src/gui/util/qabstractlayoutstyleinfo_p.h
+++ b/src/gui/util/qabstractlayoutstyleinfo_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTLAYOUTSTYLEINFO_P_H
#define QABSTRACTLAYOUTSTYLEINFO_P_H
diff --git a/src/gui/util/qastchandler.cpp b/src/gui/util/qastchandler.cpp
index 94cb42e29b..ec8b92f557 100644
--- a/src/gui/util/qastchandler.cpp
+++ b/src/gui/util/qastchandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qastchandler_p.h"
#include "qtexturefiledata_p.h"
@@ -59,6 +23,8 @@ struct AstcHeader
quint8 zSize[3];
};
+QAstcHandler::~QAstcHandler() = default;
+
bool QAstcHandler::canRead(const QByteArray &suffix, const QByteArray &block)
{
Q_UNUSED(suffix);
@@ -71,7 +37,7 @@ quint32 QAstcHandler::astcGLFormat(quint8 xBlockDim, quint8 yBlockDim) const
static const quint32 glFormatRGBABase = 0x93B0; // GL_COMPRESSED_RGBA_ASTC_4x4_KHR
static const quint32 glFormatSRGBBase = 0x93D0; // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
- static QSize dims[14] = {
+ Q_CONSTINIT static QSize dims[14] = {
{ 4, 4 }, // GL_COMPRESSED_xxx_ASTC_4x4_KHR
{ 5, 4 }, // GL_COMPRESSED_xxx_ASTC_5x4_KHR
{ 5, 5 }, // GL_COMPRESSED_xxx_ASTC_5x5_KHR
@@ -143,9 +109,9 @@ QTextureFileData QAstcHandler::read()
int zBlocks = (zSz + header->blockDimZ - 1) / header->blockDimZ;
int byteCount = 0;
- bool oob = mul_overflow(xBlocks, yBlocks, &byteCount)
- || mul_overflow(byteCount, zBlocks, &byteCount)
- || mul_overflow(byteCount, 16, &byteCount);
+ bool oob = qMulOverflow(xBlocks, yBlocks, &byteCount)
+ || qMulOverflow(byteCount, zBlocks, &byteCount)
+ || qMulOverflow(byteCount, 16, &byteCount);
res.setDataOffset(sizeof(AstcHeader));
diff --git a/src/gui/util/qastchandler_p.h b/src/gui/util/qastchandler_p.h
index 398f1833b6..5dd7f7a524 100644
--- a/src/gui/util/qastchandler_p.h
+++ b/src/gui/util/qastchandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QASTCHANDLER_H
#define QASTCHANDLER_H
@@ -59,6 +23,7 @@ class QAstcHandler : public QTextureFileHandler
{
public:
using QTextureFileHandler::QTextureFileHandler;
+ ~QAstcHandler() override;
static bool canRead(const QByteArray &suffix, const QByteArray &block);
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 0550cb6f75..4a12f6db6f 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qdesktopservices.h"
@@ -54,11 +18,12 @@
#include <qpa/qplatformintegration.h>
#include <qdir.h>
+#include <QtCore/private/qlocking_p.h>
+
QT_BEGIN_NAMESPACE
-class QOpenUrlHandlerRegistry : public QObject
+class QOpenUrlHandlerRegistry
{
- Q_OBJECT
public:
QOpenUrlHandlerRegistry() = default;
@@ -72,24 +37,34 @@ public:
typedef QHash<QString, Handler> HandlerHash;
HandlerHash handlers;
-public Q_SLOTS:
+#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
+ QObject context;
+
void handlerDestroyed(QObject *handler);
+#endif
};
Q_GLOBAL_STATIC(QOpenUrlHandlerRegistry, handlerRegistry)
+#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
{
+ const auto lock = qt_scoped_lock(mutex);
HandlerHash::Iterator it = handlers.begin();
while (it != handlers.end()) {
if (it->receiver == handler) {
it = handlers.erase(it);
+ qWarning("Please call QDesktopServices::unsetUrlHandler() before destroying a "
+ "registered URL handler object.\n"
+ "Support for destroying a registered URL handler object is deprecated, "
+ "and will be removed in Qt 6.6.");
} else {
++it;
}
}
}
+#endif
/*!
\class QDesktopServices
@@ -182,11 +157,18 @@ void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
\warning URLs passed to this function on iOS will not load unless their schemes are
listed in the \c LSApplicationQueriesSchemes key of the application's Info.plist file.
For more information, see the Apple Developer Documentation for
- \l{https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl}{canOpenURL(_:)}.
+ \l {iOS: canOpenURL:}{canOpenURL:}.
For example, the following lines enable URLs with the HTTPS scheme:
\snippet code/src_gui_util_qdesktopservices.cpp 3
+ \note For Android Nougat (SDK 24) and above, URLs with a \c file scheme
+ are opened using \l {Android: FileProvider}{FileProvider} which tries to obtain
+ a shareable \c content scheme URI first. For that reason, Qt for Android defines
+ a file provider with the authority \c ${applicationId}.qtprovider, with \c applicationId
+ being the app's package name to avoid name conflicts. For more information, also see
+ \l {Android: Setting up file sharing}{Setting up file sharing}.
+
\sa setUrlHandler()
*/
bool QDesktopServices::openUrl(const QUrl &url)
@@ -244,14 +226,29 @@ bool QDesktopServices::openUrl(const QUrl &url)
\snippet code/src_gui_util_qdesktopservices.cpp 0
+ If setUrlHandler() is used to set a new handler for a scheme which already
+ has a handler, the existing handler is simply replaced with the new one.
+ Since QDesktopServices does not take ownership of handlers, no objects are
+ deleted when a handler is replaced.
+
+ Note that the handler will always be called from within the same thread that
+ calls QDesktopServices::openUrl().
+
+ You must call unsetUrlHandler() before destroying the handler object, so
+ the destruction of the handler object does not overlap with concurrent
+ invocations of openUrl() using it.
+
+ \section1 iOS
+
To use this function for receiving data from other apps on iOS you also need to
add the custom scheme to the \c CFBundleURLSchemes list in your Info.plist file:
\snippet code/src_gui_util_qdesktopservices.cpp 4
For more information, see the Apple Developer Documentation for
- \l{https://developer.apple.com/documentation/uikit/core_app/allowing_apps_and_websites_to_link_to_your_content/communicating_with_other_apps_using_custom_urls?language=objc}{Communicating with Other Apps Using Custom URLs}.
- \warning It is not possible to claim support for some well known URL schemes, including http and https. This is only allowed for Universal Links.
+ \l {iOS: Defining a Custom URL Scheme for Your App}{Defining a Custom URL Scheme for Your App}.
+ \warning It is not possible to claim support for some well known URL schemes, including http and
+ https. This is only allowed for Universal Links.
To claim support for http and https the above entry in the Info.plist file
is not allowed. This is only possible when you add your domain to the
@@ -261,21 +258,39 @@ bool QDesktopServices::openUrl(const QUrl &url)
iOS will search for /.well-known/apple-app-site-association on your domain,
when the application is installed. If you want to listen to
- https://your.domain.com/help?topic=ABCDEF you need to provide the following
+ \c{https://your.domain.com/help?topic=ABCDEF} you need to provide the following
content there:
\snippet code/src_gui_util_qdesktopservices.cpp 8
For more information, see the Apple Developer Documentation for
- \l{https://developer.apple.com/documentation/safariservices/supporting_associated_domains_in_your_app}[Supporting Associated Domains}.
+ \l {iOS: Supporting Associated Domains}{Supporting Associated Domains}.
- If setUrlHandler() is used to set a new handler for a scheme which already
- has a handler, the existing handler is simply replaced with the new one.
- Since QDesktopServices does not take ownership of handlers, no objects are
- deleted when a handler is replaced.
+ \section1 Android
- Note that the handler will always be called from within the same thread that
- calls QDesktopServices::openUrl().
+ To use this function for receiving data from other apps on Android, you
+ need to add one or more intent filter to the \c activity in your app manifest:
+
+ \snippet code/src_gui_util_qdesktopservices.cpp 9
+
+ For more information, see the Android Developer Documentation for
+ \l {Android: Create Deep Links to App Content}{Create Deep Links to App Content}.
+
+ To immediately open the corresponding content in your Android app, without
+ requiring the user to select the app, you need to verify your link. To
+ enable the verification, add an additional parameter to your intent filter:
+
+ \snippet code/src_gui_util_qdesktopservices.cpp 10
+
+ Android will look for \c{https://your.domain.com/.well-known/assetlinks.json},
+ when the application is installed. If you want to listen to
+ \c{https://your.domain.com:1337/help}, you need to provide the following
+ content there:
+
+ \snippet code/src_gui_util_qdesktopservices.cpp 11
+
+ For more information, see the Android Developer Documentation for
+ \l {Android: Verify Android App Links}{Verify Android App Links}.
\sa openUrl(), unsetUrlHandler()
*/
@@ -291,13 +306,20 @@ void QDesktopServices::setUrlHandler(const QString &scheme, QObject *receiver, c
h.receiver = receiver;
h.name = method;
registry->handlers.insert(scheme.toLower(), h);
- QObject::connect(receiver, SIGNAL(destroyed(QObject*)),
- registry, SLOT(handlerDestroyed(QObject*)));
+#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
+ QObject::connect(receiver, &QObject::destroyed, &registry->context,
+ [registry](QObject *obj) { registry->handlerDestroyed(obj); },
+ Qt::DirectConnection);
+#endif
}
/*!
Removes a previously set URL handler for the specified \a scheme.
+ Call this function before the handler object that was registered for \a scheme
+ is destroyed, to prevent concurrent openUrl() calls from continuing to call
+ the destroyed handler object.
+
\sa setUrlHandler()
*/
void QDesktopServices::unsetUrlHandler(const QString &scheme)
@@ -307,6 +329,4 @@ void QDesktopServices::unsetUrlHandler(const QString &scheme)
QT_END_NAMESPACE
-#include "qdesktopservices.moc"
-
#endif // QT_NO_DESKTOPSERVICES
diff --git a/src/gui/util/qdesktopservices.h b/src/gui/util/qdesktopservices.h
index 658b601532..476b84691e 100644
--- a/src/gui/util/qdesktopservices.h
+++ b/src/gui/util/qdesktopservices.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QDESKTOPSERVICES_H
#define QDESKTOPSERVICES_H
diff --git a/src/gui/util/qedidparser.cpp b/src/gui/util/qedidparser.cpp
index db5ccf1772..4dae151e6a 100644
--- a/src/gui/util/qedidparser.cpp
+++ b/src/gui/util/qedidparser.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
-** Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/QFile>
#include <QtCore/QByteArrayView>
@@ -48,6 +12,7 @@
#define EDID_DESCRIPTOR_PRODUCT_NAME 0xfc
#define EDID_DESCRIPTOR_SERIAL_NUMBER 0xff
+#define EDID_DATA_BLOCK_COUNT 4
#define EDID_OFFSET_DATA_BLOCKS 0x36
#define EDID_OFFSET_LAST_BLOCK 0x6c
#define EDID_OFFSET_PNP_ID 0x08
@@ -60,11 +25,13 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static QString lookupVendorIdInSystemDatabase(QByteArrayView id)
{
QString result;
- const QString fileName = QLatin1String("/usr/share/hwdata/pnp.ids");
+ const QString fileName = "/usr/share/hwdata/pnp.ids"_L1;
QFile file(fileName);
if (!file.open(QFile::ReadOnly))
return result;
@@ -105,7 +72,7 @@ static QString lookupVendorIdInSystemDatabase(QByteArrayView id)
bool QEdidParser::parse(const QByteArray &blob)
{
const quint8 *data = reinterpret_cast<const quint8 *>(blob.constData());
- const size_t length = blob.length();
+ const size_t length = blob.size();
// Verify header
if (length < 128)
@@ -138,7 +105,7 @@ bool QEdidParser::parse(const QByteArray &blob)
serialNumber = QString();
// Parse EDID data
- for (int i = 0; i < 5; ++i) {
+ for (int i = 0; i < EDID_DATA_BLOCK_COUNT; ++i) {
const uint offset = EDID_OFFSET_DATA_BLOCKS + i * 18;
if (data[offset] != 0 || data[offset + 1] != 0 || data[offset + 2] != 0)
@@ -268,16 +235,22 @@ QString QEdidParser::parseEdidString(const quint8 *data)
{
QByteArray buffer(reinterpret_cast<const char *>(data), 13);
- // Erase carriage return and line feed
- buffer = buffer.replace('\r', '\0').replace('\n', '\0');
+ for (int i = 0; i < buffer.size(); ++i) {
+ // If there are less than 13 characters in the string, the string
+ // is terminated with the ASCII code ‘0Ah’ (line feed) and padded
+ // with ASCII code ‘20h’ (space). See EDID 1.4, sections 3.10.3.1,
+ // 3.10.3.2, and 3.10.3.4.
+ if (buffer[i] == '\n') {
+ buffer.truncate(i);
+ break;
+ }
- // Replace non-printable characters with dash
- for (int i = 0; i < buffer.count(); ++i) {
+ // Replace non-printable characters with dash
if (buffer[i] < '\040' || buffer[i] > '\176')
buffer[i] = '-';
}
- return QString::fromLatin1(buffer.trimmed());
+ return QString::fromLatin1(buffer);
}
QT_END_NAMESPACE
diff --git a/src/gui/util/qedidparser_p.h b/src/gui/util/qedidparser_p.h
index f18c2f1ad1..99352b03b0 100644
--- a/src/gui/util/qedidparser_p.h
+++ b/src/gui/util/qedidparser_p.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
-** Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QEDIDPARSER_P_H
#define QEDIDPARSER_P_H
@@ -61,6 +25,7 @@
#include <QtCore/qpoint.h>
#include <QtCore/qsize.h>
#include <QtCore/qstring.h>
+#include <QtCore/private/qglobal_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/util/qedidvendortable_p.h b/src/gui/util/qedidvendortable_p.h
index e6bbb8f87e..0a6132e4d7 100644
--- a/src/gui/util/qedidvendortable_p.h
+++ b/src/gui/util/qedidvendortable_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
* This lookup table was generated from https://github.com/vcrhonek/hwdata/raw/master/pnp.ids
@@ -58,6 +22,8 @@
// We mean it.
//
+#include <QtCore/private/qglobal_p.h>
+
QT_BEGIN_NAMESPACE
struct VendorTable {
diff --git a/src/gui/util/qgraphicsframecapture.cpp b/src/gui/util/qgraphicsframecapture.cpp
new file mode 100644
index 0000000000..e49fb83008
--- /dev/null
+++ b/src/gui/util/qgraphicsframecapture.cpp
@@ -0,0 +1,123 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qgraphicsframecapture_p.h"
+#if (defined (Q_OS_WIN) || defined(Q_OS_LINUX)) && QT_CONFIG(library)
+#include "qgraphicsframecapturerenderdoc_p_p.h"
+#elif QT_CONFIG(metal)
+#include "qgraphicsframecapturemetal_p_p.h"
+#else
+#include "qgraphicsframecapture_p_p.h"
+#endif
+
+#include <QtCore/qstandardpaths.h>
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+QGraphicsFrameCapturePrivate::QGraphicsFrameCapturePrivate()
+ : m_capturePath(QStandardPaths::writableLocation(QStandardPaths::TempLocation) +
+ QStringLiteral("/") + QCoreApplication::applicationName() +
+ QStringLiteral("/captures")),
+ m_capturePrefix(QCoreApplication::applicationName())
+{
+
+}
+
+QGraphicsFrameCapture::QGraphicsFrameCapture()
+{
+#if (defined (Q_OS_WIN) || defined(Q_OS_LINUX)) && QT_CONFIG(library)
+ d.reset(new QGraphicsFrameCaptureRenderDoc);
+#elif QT_CONFIG(metal)
+ d.reset(new QGraphicsFrameCaptureMetal);
+#endif
+}
+
+QGraphicsFrameCapture::~QGraphicsFrameCapture()
+{
+
+}
+
+void QGraphicsFrameCapture::setRhi(QRhi *rhi)
+{
+ if (!d.isNull())
+ d->setRhi(rhi);
+}
+
+void QGraphicsFrameCapture::startCaptureFrame()
+{
+ if (!d.isNull())
+ d->startCaptureFrame();
+}
+
+void QGraphicsFrameCapture::endCaptureFrame()
+{
+ if (!d.isNull())
+ d->endCaptureFrame();
+}
+
+QString QGraphicsFrameCapture::capturePath() const
+{
+ if (!d.isNull())
+ return d->capturePath();
+ return QString();
+}
+
+void QGraphicsFrameCapture::setCapturePath(const QString &path)
+{
+ if (!d.isNull())
+ d->setCapturePath(path);
+}
+
+QString QGraphicsFrameCapture::capturePrefix() const
+{
+ if (!d.isNull())
+ return d->capturePrefix();
+ return QString();
+}
+
+void QGraphicsFrameCapture::setCapturePrefix(const QString &prefix)
+{
+ if (!d.isNull())
+ d->setCapturePrefix(prefix);
+}
+
+QString QGraphicsFrameCapture::capturedFileName()
+{
+ if (!d.isNull())
+ return d->capturedFileName();
+
+ return QString();
+}
+
+QStringList QGraphicsFrameCapture::capturedFilesNames()
+{
+ if (!d.isNull())
+ return d->capturedFilesNames();
+
+ return QStringList();
+}
+
+bool QGraphicsFrameCapture::isLoaded() const
+{
+ if (!d.isNull())
+ return d->initialized();
+
+ return false;
+}
+
+bool QGraphicsFrameCapture::isCapturing() const
+{
+ if (!d.isNull())
+ return d->isCapturing();
+
+ return false;
+}
+
+void QGraphicsFrameCapture::openCapture() const
+{
+ if (!d.isNull())
+ d->openCapture();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qgraphicsframecapture_p.h b/src/gui/util/qgraphicsframecapture_p.h
new file mode 100644
index 0000000000..fef37d2869
--- /dev/null
+++ b/src/gui/util/qgraphicsframecapture_p.h
@@ -0,0 +1,55 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QGRAPHICSFRAMECAPTURE_P_H
+#define QGRAPHICSFRAMECAPTURE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qscopedpointer.h>
+#include <QtGui/qtguiglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsFrameCapturePrivate;
+class QRhi;
+
+class Q_GUI_EXPORT QGraphicsFrameCapture
+{
+public:
+ QGraphicsFrameCapture();
+ ~QGraphicsFrameCapture();
+
+ void setRhi(QRhi *rhi);
+ void startCaptureFrame();
+ void endCaptureFrame();
+
+ QString capturePath() const;
+ void setCapturePath(const QString &path);
+
+ QString capturePrefix() const;
+ void setCapturePrefix(const QString &prefix);
+
+ QString capturedFileName();
+ QStringList capturedFilesNames();
+
+ bool isLoaded() const;
+ bool isCapturing() const;
+ void openCapture() const;
+
+private:
+ QScopedPointer<QGraphicsFrameCapturePrivate> d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGRAPHICSFRAMECAPTURE_P_H
diff --git a/src/gui/util/qgraphicsframecapture_p_p.h b/src/gui/util/qgraphicsframecapture_p_p.h
new file mode 100644
index 0000000000..f8dbd2ca1d
--- /dev/null
+++ b/src/gui/util/qgraphicsframecapture_p_p.h
@@ -0,0 +1,67 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QGRAPHICSFRAMECAPTURE_P_P_H
+#define QGRAPHICSFRAMECAPTURE_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcGraphicsFrameCapture)
+
+class QRhi;
+struct QRhiNativeHandles;
+
+class QGraphicsFrameCapturePrivate
+{
+public:
+ QGraphicsFrameCapturePrivate() ;
+ virtual ~QGraphicsFrameCapturePrivate() = default;
+
+ virtual void setRhi(QRhi *rhi) = 0;
+ virtual void startCaptureFrame() = 0;
+ virtual void endCaptureFrame() = 0;
+
+ QString capturePath() const { return m_capturePath; };
+ virtual void setCapturePath(const QString &path) { m_capturePath = path; }
+
+ QString capturePrefix() const { return m_capturePrefix; }
+ virtual void setCapturePrefix(const QString &prefix) { m_capturePrefix = prefix; }
+
+ virtual QString capturedFileName() const
+ {
+ return !m_capturedFilesNames.isEmpty() ? m_capturedFilesNames.last() : QString();
+ }
+ virtual QStringList capturedFilesNames() const { return m_capturedFilesNames; }
+
+ virtual bool initialized() const = 0;
+ virtual bool isCapturing() const = 0;
+ virtual void openCapture() = 0;
+
+protected:
+ QRhi *m_rhi = nullptr;
+ QRhiNativeHandles *m_rhiHandles = nullptr;
+ void *m_nativeHandle = nullptr;
+ QString m_capturePath;
+ QString m_capturePrefix;
+ QStringList m_capturedFilesNames;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGRAPHICSFRAMECAPTURE_P_P_H
diff --git a/src/gui/util/qgraphicsframecapturemetal.mm b/src/gui/util/qgraphicsframecapturemetal.mm
new file mode 100644
index 0000000000..b0ff0bab2b
--- /dev/null
+++ b/src/gui/util/qgraphicsframecapturemetal.mm
@@ -0,0 +1,169 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qgraphicsframecapturemetal_p_p.h"
+#include <QtCore/qurl.h>
+#include "Metal/Metal.h"
+#include "qglobal.h"
+#include <QtGui/rhi/qrhi.h>
+#include <QtGui/rhi/qrhi_platform.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcGraphicsFrameCapture, "qt.gui.graphicsframecapture")
+
+#if __has_feature(objc_arc)
+#error ARC not supported
+#endif
+
+uint QGraphicsFrameCaptureMetal::frameNumber = 0;
+
+QGraphicsFrameCaptureMetal::QGraphicsFrameCaptureMetal()
+{
+ qputenv("METAL_CAPTURE_ENABLED", QByteArrayLiteral("1"));
+
+ m_captureDescriptor = [MTLCaptureDescriptor new];
+}
+
+QGraphicsFrameCaptureMetal::~QGraphicsFrameCaptureMetal()
+{
+#if defined(Q_OS_MACOS) && QT_CONFIG(process)
+ if (m_process) {
+ m_process->terminate();
+ delete m_process;
+ }
+#endif
+ [m_captureDescriptor release];
+}
+
+void QGraphicsFrameCaptureMetal::setRhi(QRhi *rhi)
+{
+ if (!rhi)
+ return;
+
+ QRhi::Implementation backend = rhi->backend();
+ const QRhiNativeHandles *nh = rhi->nativeHandles();
+
+ switch (backend) {
+ case QRhi::Implementation::Metal: {
+ const QRhiMetalNativeHandles *mtlnh = static_cast<const QRhiMetalNativeHandles *>(nh);
+ if (mtlnh->cmdQueue) {
+ m_captureDescriptor.captureObject = mtlnh->cmdQueue;
+ } else if (mtlnh->dev) {
+ m_captureDescriptor.captureObject = mtlnh->dev;
+ } else {
+ qCWarning(lcGraphicsFrameCapture) << "No valid Metal Device or Metal Command Queue found";
+ m_initialized = false;
+ return;
+ }
+ break;
+ }
+ default: {
+ qCWarning(lcGraphicsFrameCapture) << "Invalid handles were provided. MTLCaptureManager works only with Metal API";
+ m_initialized = false;
+ return;
+ break;
+ }
+ }
+
+ if (!m_captureManager) {
+ m_captureManager = MTLCaptureManager.sharedCaptureManager;
+ bool supportDocs = [m_captureManager supportsDestination:MTLCaptureDestinationGPUTraceDocument];
+ if (supportDocs) {
+ m_captureDescriptor.destination = MTLCaptureDestinationGPUTraceDocument;
+ m_initialized = true;
+ }
+ }
+}
+
+void QGraphicsFrameCaptureMetal::startCaptureFrame()
+{
+ if (!initialized()) {
+ qCWarning(lcGraphicsFrameCapture) << "Capturing on Metal was not initialized. Starting capturing can not be done.";
+ return;
+ }
+
+ if (isCapturing()) {
+ qCWarning(lcGraphicsFrameCapture) << "A frame capture is already in progress,"
+ "will not initiate another one until QGraphicsFrameCapture::endCaptureFrame is called.";
+ return;
+ }
+
+ updateCaptureFileName();
+ NSError *error;
+ if (![m_captureManager startCaptureWithDescriptor:m_captureDescriptor error:&error]) {
+ QString errorMsg = QString::fromNSString(error.localizedDescription);
+ qCWarning(lcGraphicsFrameCapture, "Failed to start capture : %s", qPrintable(errorMsg));
+ }
+}
+
+void QGraphicsFrameCaptureMetal::endCaptureFrame()
+{
+ if (!initialized()) {
+ qCWarning(lcGraphicsFrameCapture) << "Capturing on Metal was not initialized. End capturing can not be done.";
+ return;
+ }
+
+ if (!isCapturing()) {
+ qCWarning(lcGraphicsFrameCapture) << "A call to QGraphicsFrameCapture::endCaptureFrame can not be done"
+ " without a call to QGraphicsFrameCapture::startCaptureFrame";
+ return;
+ }
+
+ [m_captureManager stopCapture];
+ m_capturedFilesNames.append(QString::fromNSString(m_traceURL.path));
+ frameNumber++;
+}
+
+bool QGraphicsFrameCaptureMetal::initialized() const
+{
+ return m_initialized;
+}
+
+bool QGraphicsFrameCaptureMetal::isCapturing() const
+{
+ if (!initialized()) {
+ qCWarning(lcGraphicsFrameCapture) << "Capturing on Metal was not initialized. Can not query if capturing is in progress or not.";
+ return false;
+ }
+
+ return [m_captureManager isCapturing];
+}
+
+void QGraphicsFrameCaptureMetal::openCapture()
+{
+#if defined(Q_OS_MACOS)
+#if !QT_CONFIG(process)
+ qFatal("QGraphicsFrameCapture requires QProcess on macOS");
+#else
+ if (!initialized()) {
+ qCWarning(lcGraphicsFrameCapture) << "Capturing on Metal was not initialized. Can not open XCode with a valid capture.";
+ return;
+ }
+
+ if (!m_process) {
+ m_process = new QProcess();
+ m_process->setProgram(QStringLiteral("xed"));
+ QStringList args;
+ args.append(QUrl::fromNSURL(m_traceURL).toLocalFile());
+ m_process->setArguments(args);
+ }
+
+ m_process->kill();
+ m_process->start();
+#endif
+#endif
+}
+
+void QGraphicsFrameCaptureMetal::updateCaptureFileName()
+{
+ m_traceURL = QUrl::fromLocalFile(m_capturePath + "/" + m_capturePrefix + "_" + QString::number(frameNumber) + ".gputrace").toNSURL();
+ // We need to remove the trace file if it already existed else MTLCaptureManager
+ // will fail to.
+ if ([NSFileManager.defaultManager fileExistsAtPath:m_traceURL.path])
+ [NSFileManager.defaultManager removeItemAtURL:m_traceURL error:nil];
+
+ m_captureDescriptor.outputURL = m_traceURL;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qgraphicsframecapturemetal_p_p.h b/src/gui/util/qgraphicsframecapturemetal_p_p.h
new file mode 100644
index 0000000000..d703949de2
--- /dev/null
+++ b/src/gui/util/qgraphicsframecapturemetal_p_p.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QGRAPHICSFRAMEDECAPTUREMETAL_P_P_H
+#define QGRAPHICSFRAMEDECAPTUREMETAL_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qgraphicsframecapture_p_p.h"
+#include <QtCore/qmutex.h>
+#ifdef Q_OS_MACOS
+#include <QtCore/qprocess.h>
+#endif
+
+Q_FORWARD_DECLARE_OBJC_CLASS(MTLCaptureManager);
+Q_FORWARD_DECLARE_OBJC_CLASS(MTLCaptureDescriptor);
+Q_FORWARD_DECLARE_OBJC_CLASS(NSURL);
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsFrameCaptureMetal : public QGraphicsFrameCapturePrivate
+{
+public:
+ QGraphicsFrameCaptureMetal();
+ ~QGraphicsFrameCaptureMetal();
+
+ void setRhi(QRhi *rhi) override;
+ void startCaptureFrame() override;
+ void endCaptureFrame() override;
+ bool initialized() const override;
+ bool isCapturing() const override;
+ void openCapture() override;
+
+private:
+ void updateCaptureFileName();
+#if defined(Q_OS_MACOS) && QT_CONFIG(process)
+ QProcess *m_process = nullptr;
+#endif
+ MTLCaptureManager *m_captureManager = nullptr;
+ MTLCaptureDescriptor *m_captureDescriptor = nullptr;
+ NSURL *m_traceURL = nullptr;
+ bool m_initialized = false;
+ static uint frameNumber;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGRAPHICSFRAMEDECAPTUREMETAL_P_P_H
diff --git a/src/gui/util/qgraphicsframecapturerenderdoc.cpp b/src/gui/util/qgraphicsframecapturerenderdoc.cpp
new file mode 100644
index 0000000000..88ba9d839f
--- /dev/null
+++ b/src/gui/util/qgraphicsframecapturerenderdoc.cpp
@@ -0,0 +1,310 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qgraphicsframecapturerenderdoc_p_p.h"
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qlibrary.h>
+#include <QtCore/qmutex.h>
+#include "QtGui/rhi/qrhi.h"
+#include "QtGui/rhi/qrhi_platform.h"
+#include "QtGui/qopenglcontext.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcGraphicsFrameCapture, "qt.gui.graphicsframecapture")
+
+RENDERDOC_API_1_6_0 *QGraphicsFrameCaptureRenderDoc::s_rdocApi = nullptr;
+#if QT_CONFIG(thread)
+QBasicMutex QGraphicsFrameCaptureRenderDoc::s_frameCaptureMutex;
+#endif
+
+#if QT_CONFIG(opengl)
+static void *glNativeContext(QOpenGLContext *context) {
+ void *nctx = nullptr;
+ if (context != nullptr && context->isValid()) {
+#ifdef Q_OS_WIN
+ nctx = context->nativeInterface<QNativeInterface::QWGLContext>()->nativeContext();
+#endif
+
+#ifdef Q_OS_LINUX
+#if QT_CONFIG(egl)
+ QNativeInterface::QEGLContext *eglItf = context->nativeInterface<QNativeInterface::QEGLContext>();
+ if (eglItf)
+ nctx = eglItf->nativeContext();
+#endif
+
+#if QT_CONFIG(xcb_glx_plugin)
+ QNativeInterface::QGLXContext *glxItf = context->nativeInterface<QNativeInterface::QGLXContext>();
+ if (glxItf)
+ nctx = glxItf->nativeContext();
+#endif
+#endif
+
+#if QT_CONFIG(metal)
+ nctx = context->nativeInterface<QNativeInterface::QCocoaGLContext>()->nativeContext();
+#endif
+ }
+ return nctx;
+}
+#endif // QT_CONFIG(opengl)
+
+/*!
+ \class QGraphicsFrameCaptureRenderDoc
+ \internal
+ \brief The QGraphicsFrameCaptureRenderDoc class provides a way to capture a record of draw calls
+ for different graphics APIs.
+ \since 6.6
+ \inmodule QtGui
+
+ For applications that render using graphics APIs like Vulkan or OpenGL, it would be
+ convenient to have a way to check the draw calls done by the application. Specially
+ for applications that make a large amount of draw calls and the output is different
+ from what is expected.
+
+ This class acts as a wrapper over \l {https://renderdoc.org/}{RenderDoc} that allows
+ applications to capture a rendered frame either programmatically, by clicking a key
+ on the keyboard or both. The captured frame could be viewed later using RenderDoc GUI.
+
+ Read the \l {https://renderdoc.org/docs/index.html} {RenderDoc Documentation}
+ for more information.
+
+ \section1 API device handle
+
+ The functions that capture a frame like QGraphicsFrameCaptureRenderDoc::startCaptureFrame takes a device
+ pointer as argument. This pointer is unique for each graphics API and is associated
+ with the window that will be captured. This pointer has a default value of \c nullptr.
+ If no value is passed to the function the underlying API will try to find the device to
+ use, but it is not guaranteed specially in a multi-window applications.
+
+ For OpenGL, the pointer should be the OpenGL context on the platform OpenGL is being
+ used. For example, on Windows it should be \c HGLRC.
+
+ For Vulkan, the pointer should point to the dispatch table within the \c VkInstance.
+*/
+
+
+
+/*!
+ Creates a new object of this class. The constructor will load RenderDoc library
+ from the default path.
+
+ Only one instance of RenderDoc library is loaded at runtime which means creating
+ several instances of this class will not affect the RenderDoc initialization.
+*/
+
+QGraphicsFrameCaptureRenderDoc::QGraphicsFrameCaptureRenderDoc()
+ : m_nativeHandlesSet(false)
+{
+ if (!s_rdocApi)
+ init();
+}
+
+void QGraphicsFrameCaptureRenderDoc::setRhi(QRhi *rhi)
+{
+ if (!rhi)
+ return;
+
+ QRhi::Implementation backend = rhi->backend();
+ const QRhiNativeHandles *nh = rhi->nativeHandles();
+
+ switch (backend) {
+ case QRhi::Implementation::D3D11: {
+#ifdef Q_OS_WIN
+ const QRhiD3D11NativeHandles *d3d11nh = static_cast<const QRhiD3D11NativeHandles *>(nh);
+ m_nativeHandle = d3d11nh->dev;
+ break;
+#endif
+ qCWarning(lcGraphicsFrameCapture) << "Could not find valid handles for D3D11. Check platform support";
+ break;
+ }
+ case QRhi::Implementation::D3D12: {
+#ifdef Q_OS_WIN
+ const QRhiD3D12NativeHandles *d3d12nh = static_cast<const QRhiD3D12NativeHandles *>(nh);
+ m_nativeHandle = d3d12nh->dev;
+ break;
+#endif
+ qCWarning(lcGraphicsFrameCapture) << "Could not find valid handles for D3D12. Check platform support";
+ break;
+ }
+ case QRhi::Implementation::Vulkan: {
+#if QT_CONFIG(vulkan)
+ const QRhiVulkanNativeHandles *vknh = static_cast<const QRhiVulkanNativeHandles *>(nh);
+ m_nativeHandle = RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(vknh->inst->vkInstance());
+ break;
+#endif
+ qCWarning(lcGraphicsFrameCapture) << "Could not find valid handles for Vulkan. Check platform support";
+ break;
+ }
+ case QRhi::Implementation::OpenGLES2: {
+#ifndef QT_NO_OPENGL
+ const QRhiGles2NativeHandles *glnh = static_cast<const QRhiGles2NativeHandles *>(nh);
+ m_nativeHandle = glNativeContext(glnh->context);
+ if (m_nativeHandle)
+ break;
+#endif
+ qCWarning(lcGraphicsFrameCapture) << "Could not find valid handles for OpenGL. Check platform support";
+ break;
+ }
+ case QRhi::Implementation::Metal:
+ case QRhi::Implementation::Null:
+ qCWarning(lcGraphicsFrameCapture) << "Invalid handles were provided."
+ " Metal and Null backends are not supported with RenderDoc";
+ break;
+ }
+
+ if (m_nativeHandle)
+ m_nativeHandlesSet = true;
+}
+
+/*!
+ Starts a frame capture using the set native handles provided through QGraphicsFrameCaptureRenderDoc::setRhi
+ \a device. This function must be called before QGraphicsFrameCaptureRenderDoc::endCaptureFrame.
+ \sa {API device handle}
+*/
+void QGraphicsFrameCaptureRenderDoc::startCaptureFrame()
+{
+
+ if (!initialized()) {
+ qCWarning(lcGraphicsFrameCapture) << "RenderDoc was not initialized."
+ " Starting capturing can not be done.";
+ return;
+ }
+
+#if QT_CONFIG(thread)
+ // There is a single instance of RenderDoc library and it needs mutex for multithreading access.
+ QMutexLocker locker(&s_frameCaptureMutex);
+#endif
+ if (s_rdocApi->IsFrameCapturing()) {
+ qCWarning(lcGraphicsFrameCapture) << "A frame capture is already in progress, "
+ "will not initiate another one until"
+ " QGraphicsFrameCapture::endCaptureFrame is called.";
+ return;
+ }
+
+ qCInfo(lcGraphicsFrameCapture) << "A frame capture is going to start.";
+ updateCapturePathAndTemplate();
+ s_rdocApi->StartFrameCapture(m_nativeHandle, nullptr);
+}
+
+/*!
+ Ends a frame capture started by a call to QGraphicsFrameCaptureRenderDoc::startCaptureFrame
+ using the set native handles provided through QGraphicsFrameCaptureRenderDoc::setRhi.
+ This function must be called after QGraphicsFrameCaptureRenderDoc::startCaptureFrame.
+ Otherwise, a warning message will be printend and nothing will happen.
+ \sa {API device handle}
+*/
+void QGraphicsFrameCaptureRenderDoc::endCaptureFrame()
+{
+ if (!initialized()) {
+ qCWarning(lcGraphicsFrameCapture) << "RenderDoc was not initialized."
+ " End capturing can not be done.";
+ return;
+ }
+
+#if QT_CONFIG(thread)
+ // There is a single instance of RenderDoc library and it needs mutex for multithreading access.
+ QMutexLocker locker(&s_frameCaptureMutex);
+#endif
+ if (!s_rdocApi->IsFrameCapturing()) {
+ qCWarning(lcGraphicsFrameCapture) << "A call to QGraphicsFrameCapture::endCaptureFrame can not be done"
+ " without a call to QGraphicsFrameCapture::startCaptureFrame";
+ return;
+ }
+
+ qCInfo(lcGraphicsFrameCapture) << "A frame capture is going to end.";
+ uint32_t result = s_rdocApi->EndFrameCapture(m_nativeHandle, nullptr);
+
+ if (result) {
+ uint32_t count = s_rdocApi->GetNumCaptures();
+ uint32_t pathLength = 0;
+ s_rdocApi->GetCapture(count - 1, nullptr, &pathLength, nullptr);
+ if (pathLength > 0) {
+ QVarLengthArray<char> name(pathLength, 0);
+ s_rdocApi->GetCapture(count - 1, name.data(), &pathLength, nullptr);
+ m_capturedFilesNames.append(QString::fromUtf8(name.data(), -1));
+ }
+ }
+}
+
+void QGraphicsFrameCaptureRenderDoc::updateCapturePathAndTemplate()
+{
+ if (!initialized()) {
+ qCWarning(lcGraphicsFrameCapture) << "RenderDoc was not initialized."
+ " Updating save location can not be done.";
+ return;
+ }
+
+
+ QString rdocFilePathTemplate = m_capturePath + QStringLiteral("/") + m_capturePrefix;
+ s_rdocApi->SetCaptureFilePathTemplate(rdocFilePathTemplate.toUtf8().constData());
+}
+
+/*!
+ Returns true if the API is loaded and can capture frames or not.
+*/
+bool QGraphicsFrameCaptureRenderDoc::initialized() const
+{
+ return s_rdocApi && m_nativeHandlesSet;
+}
+
+bool QGraphicsFrameCaptureRenderDoc::isCapturing() const
+{
+ if (!initialized()) {
+ qCWarning(lcGraphicsFrameCapture) << "RenderDoc was not initialized."
+ " Can not query if capturing is in progress or not.";
+ return false;
+ }
+
+ return s_rdocApi->IsFrameCapturing();
+}
+
+void QGraphicsFrameCaptureRenderDoc::openCapture()
+{
+ if (!initialized()) {
+ qCWarning(lcGraphicsFrameCapture) << "RenderDoc was not initialized."
+ " Can not open RenderDoc UI tool.";
+ return;
+ }
+
+#if QT_CONFIG(thread)
+ // There is a single instance of RenderDoc library and it needs mutex for multithreading access.
+ QMutexLocker locker(&s_frameCaptureMutex);
+#endif
+ if (s_rdocApi->IsTargetControlConnected())
+ s_rdocApi->ShowReplayUI();
+ else
+ s_rdocApi->LaunchReplayUI(1, nullptr);
+}
+
+void QGraphicsFrameCaptureRenderDoc::init()
+{
+#if QT_CONFIG(thread)
+ // There is a single instance of RenderDoc library and it needs mutex for multithreading access.
+ QMutexLocker locker(&s_frameCaptureMutex);
+#endif
+
+ QLibrary renderDocLib(QStringLiteral("renderdoc"));
+ pRENDERDOC_GetAPI RENDERDOC_GetAPI = (pRENDERDOC_GetAPI) renderDocLib.resolve("RENDERDOC_GetAPI");
+ if (!renderDocLib.isLoaded() || (RENDERDOC_GetAPI == nullptr)) {
+ qCWarning(lcGraphicsFrameCapture) << renderDocLib.errorString().toLatin1();
+ return;
+ }
+
+ int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_6_0, static_cast<void **>(static_cast<void *>(&s_rdocApi)));
+
+ if (ret == 0) {
+ qCWarning(lcGraphicsFrameCapture) << "The requested RenderDoc API is invalid or not supported";
+ return;
+ }
+
+ s_rdocApi->MaskOverlayBits(RENDERDOC_OverlayBits::eRENDERDOC_Overlay_None,
+ RENDERDOC_OverlayBits::eRENDERDOC_Overlay_None);
+ s_rdocApi->SetCaptureKeys(nullptr, 0);
+ s_rdocApi->SetFocusToggleKeys(nullptr, 0);
+
+ QString rdocFilePathTemplate = m_capturePath + QStringLiteral("/") + m_capturePrefix;
+ s_rdocApi->SetCaptureFilePathTemplate(rdocFilePathTemplate.toUtf8().constData());
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qgraphicsframecapturerenderdoc_p_p.h b/src/gui/util/qgraphicsframecapturerenderdoc_p_p.h
new file mode 100644
index 0000000000..c0d92ea733
--- /dev/null
+++ b/src/gui/util/qgraphicsframecapturerenderdoc_p_p.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QGRAPHICSFRAMECAPTURERENDERDOC_P_P_H
+#define QGRAPHICSFRAMECAPTURERENDERDOC_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#include <renderdoc_app.h>
+#include "qgraphicsframecapture_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(thread)
+class QBasicMutex;
+#endif
+
+class QGraphicsFrameCaptureRenderDoc : public QGraphicsFrameCapturePrivate
+{
+public:
+ QGraphicsFrameCaptureRenderDoc();
+ ~QGraphicsFrameCaptureRenderDoc() = default;
+
+ void setRhi(QRhi *rhi) override;
+ void startCaptureFrame() override;
+ void endCaptureFrame() override;
+ bool initialized() const override;
+ bool isCapturing() const override;
+ void openCapture() override;
+
+private:
+ void init();
+ void updateCapturePathAndTemplate();
+ static RENDERDOC_API_1_5_0 *s_rdocApi;
+#if QT_CONFIG(thread)
+ static QBasicMutex s_frameCaptureMutex;
+#endif
+ bool m_nativeHandlesSet;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGRAPHICSFRAMECAPTURERENDERDOC_P_P_H
diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp
index d875db0da6..e8648eb91d 100644
--- a/src/gui/util/qgridlayoutengine.cpp
+++ b/src/gui/util/qgridlayoutengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qglobal.h"
@@ -47,10 +11,14 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+#define LAYOUTITEMSIZE_MAX (1 << 24)
+
template<typename T>
static void insertOrRemoveItems(QList<T> &items, int index, int delta)
{
- int count = items.count();
+ int count = items.size();
if (index < count) {
if (delta > 0) {
items.insert(index, delta, T());
@@ -228,7 +196,8 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz
sumAvailable = targetSize - totalBox.q_minimumSize;
if (sumAvailable > 0.0) {
- qreal sumDesired = totalBox.q_preferredSize - totalBox.q_minimumSize;
+ const qreal totalBox_preferredSize = qMin(totalBox.q_preferredSize, qreal(LAYOUTITEMSIZE_MAX));
+ qreal sumDesired = totalBox_preferredSize - totalBox.q_minimumSize;
for (int i = 0; i < n; ++i) {
if (ignore.testBit(start + i)) {
@@ -237,7 +206,8 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz
}
const QGridLayoutBox &box = boxes.at(start + i);
- qreal desired = box.q_preferredSize - box.q_minimumSize;
+ const qreal box_preferredSize = qMin(box.q_preferredSize, qreal(LAYOUTITEMSIZE_MAX));
+ qreal desired = box_preferredSize - box.q_minimumSize;
factors[i] = growthFactorBelowPreferredSize(desired, sumAvailable, sumDesired);
sumFactors += factors[i];
}
@@ -792,6 +762,8 @@ QGridLayoutEngine::QGridLayoutEngine(Qt::Alignment defaultAlignment, bool snapTo
m_visualDirection = Qt::LeftToRight;
m_defaultAlignment = defaultAlignment;
m_snapToPixelGrid = snapToPixelGrid;
+ m_uniformCellWidths = false;
+ m_uniformCellHeights = false;
invalidate();
}
@@ -807,7 +779,7 @@ int QGridLayoutEngine::columnCount(Qt::Orientation orientation) const
int QGridLayoutEngine::itemCount() const
{
- return q_items.count();
+ return q_items.size();
}
QGridLayoutItem *QGridLayoutEngine::itemAt(int index) const
@@ -852,7 +824,7 @@ void QGridLayoutEngine::setRowSpacing(int row, qreal spacing, Qt::Orientation or
Q_ASSERT(row >= 0);
QGridLayoutRowInfo &rowInfo = q_infos[orientation];
- if (row >= rowInfo.spacings.count())
+ if (row >= rowInfo.spacings.size())
rowInfo.spacings.resize(row + 1);
if (spacing >= 0)
rowInfo.spacings[row].setUserValue(spacing);
@@ -877,7 +849,7 @@ void QGridLayoutEngine::setRowStretchFactor(int row, int stretch, Qt::Orientatio
maybeExpandGrid(row, -1, orientation);
QGridLayoutRowInfo &rowInfo = q_infos[orientation];
- if (row >= rowInfo.stretches.count())
+ if (row >= rowInfo.stretches.size())
rowInfo.stretches.resize(row + 1);
rowInfo.stretches[row].setUserValue(stretch);
}
@@ -899,7 +871,7 @@ void QGridLayoutEngine::setRowSizeHint(Qt::SizeHint which, int row, qreal size,
maybeExpandGrid(row, -1, orientation);
QGridLayoutRowInfo &rowInfo = q_infos[orientation];
- if (row >= rowInfo.boxes.count())
+ if (row >= rowInfo.boxes.size())
rowInfo.boxes.resize(row + 1);
rowInfo.boxes[row].q_sizes(which) = size;
}
@@ -909,6 +881,34 @@ qreal QGridLayoutEngine::rowSizeHint(Qt::SizeHint which, int row, Qt::Orientatio
return q_infos[orientation].boxes.value(row).q_sizes(which);
}
+bool QGridLayoutEngine::uniformCellWidths() const
+{
+ return m_uniformCellWidths;
+}
+
+void QGridLayoutEngine::setUniformCellWidths(bool uniformCellWidths)
+{
+ if (m_uniformCellWidths == uniformCellWidths)
+ return;
+
+ m_uniformCellWidths = uniformCellWidths;
+ invalidate();
+}
+
+bool QGridLayoutEngine::uniformCellHeights() const
+{
+ return m_uniformCellHeights;
+}
+
+void QGridLayoutEngine::setUniformCellHeights(bool uniformCellHeights)
+{
+ if (m_uniformCellHeights == uniformCellHeights)
+ return;
+
+ m_uniformCellHeights = uniformCellHeights;
+ invalidate();
+}
+
void QGridLayoutEngine::setRowAlignment(int row, Qt::Alignment alignment,
Qt::Orientation orientation)
{
@@ -917,7 +917,7 @@ void QGridLayoutEngine::setRowAlignment(int row, Qt::Alignment alignment,
maybeExpandGrid(row, -1, orientation);
QGridLayoutRowInfo &rowInfo = q_infos[orientation];
- if (row >= rowInfo.alignments.count())
+ if (row >= rowInfo.alignments.size())
rowInfo.alignments.resize(row + 1);
rowInfo.alignments[row] = alignment;
}
@@ -964,8 +964,11 @@ void QGridLayoutEngine::insertItem(QGridLayoutItem *item, int index)
for (int i = item->firstRow(); i <= item->lastRow(); ++i) {
for (int j = item->firstColumn(); j <= item->lastColumn(); ++j) {
- if (itemAt(i, j))
- qWarning("QGridLayoutEngine::addItem: Cell (%d, %d) already taken", i, j);
+ const auto existingItem = itemAt(i, j);
+ if (existingItem) {
+ qWarning("QGridLayoutEngine::addItem: Can't add %s at cell (%d, %d) because it's already taken by %s",
+ qPrintable(item->toString()), i, j, qPrintable(existingItem->toString()));
+ }
setItemAt(i, j, item);
}
}
@@ -1026,7 +1029,7 @@ void QGridLayoutEngine::setGeometries(const QRectF &contentsGeometry, const QAbs
ensureGeometries(contentsGeometry.size(), styleInfo);
- for (int i = q_items.count() - 1; i >= 0; --i) {
+ for (int i = q_items.size() - 1; i >= 0; --i) {
QGridLayoutItem *item = q_items.at(i);
qreal x = q_xx.at(item->firstColumn());
@@ -1155,7 +1158,7 @@ void QGridLayoutEngine::transpose()
{
invalidate();
- for (int i = q_items.count() - 1; i >= 0; --i)
+ for (int i = q_items.size() - 1; i >= 0; --i)
q_items.at(i)->transpose();
q_defaultSpacings.transpose();
@@ -1187,12 +1190,12 @@ void QGridLayoutEngine::dump(int indent) const
qDebug("%*s Grid (%d x %d)", indent, "", internalGridRowCount(),
internalGridColumnCount());
for (int row = 0; row < internalGridRowCount(); ++row) {
- QString message = QLatin1String("[ ");
+ QString message = "[ "_L1;
for (int column = 0; column < internalGridColumnCount(); ++column) {
message += QString::number(q_items.indexOf(itemAt(row, column))).rightJustified(3);
- message += QLatin1Char(' ');
+ message += u' ';
}
- message += QLatin1Char(']');
+ message += u']';
qDebug("%*s %s", indent, "", qPrintable(message));
}
@@ -1214,10 +1217,10 @@ void QGridLayoutEngine::dump(int indent) const
for (int pass = 0; pass < 2; ++pass) {
QString message;
for (i = 0; i < cellPos->count(); ++i) {
- message += QLatin1String((message.isEmpty() ? "[" : ", "));
+ message += (message.isEmpty() ? "["_L1 : ", "_L1);
message += QString::number(cellPos->at(i));
}
- message += QLatin1Char(']');
+ message += u']';
qDebug("%*s %s %s", indent, "", (pass == 0 ? "rows:" : "columns:"), qPrintable(message));
cellPos = &q_xx;
}
@@ -1244,7 +1247,7 @@ void QGridLayoutEngine::maybeExpandGrid(int row, int column, Qt::Orientation ori
int newGridColumnCount = internalGridColumnCount();
int newGridSize = newGridRowCount * newGridColumnCount;
- if (newGridSize != q_grid.count()) {
+ if (newGridSize != q_grid.size()) {
q_grid.resize(newGridSize);
if (newGridColumnCount != oldGridColumnCount) {
@@ -1266,7 +1269,7 @@ void QGridLayoutEngine::regenerateGrid()
{
q_grid.fill(nullptr);
- for (int i = q_items.count() - 1; i >= 0; --i) {
+ for (int i = q_items.size() - 1; i >= 0; --i) {
QGridLayoutItem *item = q_items.at(i);
for (int j = item->firstRow(); j <= item->lastRow(); ++j) {
@@ -1299,7 +1302,7 @@ void QGridLayoutEngine::insertOrRemoveRows(int row, int delta, Qt::Orientation o
q_infos[orientation].insertOrRemoveRows(row, delta);
- for (int i = q_items.count() - 1; i >= 0; --i)
+ for (int i = q_items.size() - 1; i >= 0; --i)
q_items.at(i)->insertOrRemoveRows(row, delta, orientation);
q_grid.resize(internalGridRowCount() * internalGridColumnCount());
@@ -1440,7 +1443,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData,
}
}
}
- if (row < rowInfo.boxes.count()) {
+ if (row < rowInfo.boxes.size()) {
QGridLayoutBox rowBoxInfo = rowInfo.boxes.at(row);
rowBoxInfo.normalize();
rowBox.q_minimumSize = qMax(rowBox.q_minimumSize, rowBoxInfo.q_minimumSize);
@@ -1533,6 +1536,27 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData,
rowSpacing = qMax(windowMargin, rowSpacing);
}
}
+
+ if (rowData->boxes.size() > 1 &&
+ ((orientation == Qt::Horizontal && m_uniformCellWidths) ||
+ (orientation == Qt::Vertical && m_uniformCellHeights))) {
+ qreal averagePreferredSize = 0.;
+ qreal minimumMaximumSize = std::numeric_limits<qreal>::max();
+ qreal maximumMinimumSize = 0.;
+ for (const auto &box : rowData->boxes) {
+ averagePreferredSize += box.q_preferredSize;
+ minimumMaximumSize = qMin(minimumMaximumSize, box.q_maximumSize);
+ maximumMinimumSize = qMax(maximumMinimumSize, box.q_minimumSize);
+ }
+ averagePreferredSize /= rowData->boxes.size();
+ minimumMaximumSize = qMax(minimumMaximumSize, maximumMinimumSize);
+ averagePreferredSize = qBound(maximumMinimumSize, averagePreferredSize, minimumMaximumSize);
+ for (auto &box : rowData->boxes) {
+ box.q_preferredSize = averagePreferredSize;
+ box.q_minimumSize = maximumMinimumSize;
+ box.q_maximumSize = minimumMaximumSize;
+ }
+ }
}
void QGridLayoutEngine::ensureEffectiveFirstAndLastRows() const
@@ -1544,7 +1568,7 @@ void QGridLayoutEngine::ensureEffectiveFirstAndLastRows() const
q_cachedEffectiveFirstRows = {columnCount, rowCount};
q_cachedEffectiveLastRows = {-1, -1};
- for (int i = q_items.count() - 1; i >= 0; --i) {
+ for (int i = q_items.size() - 1; i >= 0; --i) {
const QGridLayoutItem *item = q_items.at(i);
for (Qt::Orientation o : {Qt::Horizontal, Qt::Vertical}) {
@@ -1590,7 +1614,7 @@ void QGridLayoutEngine::ensureColumnAndRowData(QGridLayoutRowData *rowData, QGri
bool QGridLayoutEngine::ensureDynamicConstraint() const
{
if (q_cachedConstraintOrientation == UnknownConstraint) {
- for (int i = q_items.count() - 1; i >= 0; --i) {
+ for (int i = q_items.size() - 1; i >= 0; --i) {
QGridLayoutItem *item = q_items.at(i);
if (item->hasDynamicConstraint()) {
Qt::Orientation itemConstraintOrientation = item->dynamicConstraintOrientation();
diff --git a/src/gui/util/qgridlayoutengine_p.h b/src/gui/util/qgridlayoutengine_p.h
index 341d159fb1..2f60cb99fd 100644
--- a/src/gui/util/qgridlayoutengine_p.h
+++ b/src/gui/util/qgridlayoutengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QGRIDLAYOUTENGINE_P_H
#define QGRIDLAYOUTENGINE_P_H
@@ -60,6 +24,7 @@
#include <QtCore/qpair.h>
#include <QtCore/qsize.h>
#include <QtCore/qrect.h>
+#include <QtCore/qdebug.h>
#include <float.h>
#include "qlayoutpolicy_p.h"
@@ -100,7 +65,7 @@ enum {
Minimal container to store Qt::Orientation-discriminated values.
The salient feature is the indexing operator, which takes
- Qt::Orientation (and assumes it's passed only Qt::Horizonal or Qt::Vertical).
+ Qt::Orientation (and assumes it's passed only Qt::Horizontal or Qt::Vertical).
*/
template <typename T>
class QHVContainer {
@@ -319,6 +284,8 @@ public:
virtual QLayoutPolicy::ControlTypes controlTypes(LayoutSide side) const;
+ inline virtual QString toString() const { return QDebug::toString(this); }
+
QRectF geometryWithin(qreal x, qreal y, qreal width, qreal height, qreal rowDescent, Qt::Alignment align, bool snapToPixelGrid) const;
QGridLayoutBox box(Qt::Orientation orientation, bool snapToPixelGrid, qreal constraint = -1.0) const;
@@ -370,6 +337,12 @@ public:
qreal rowSizeHint(Qt::SizeHint which, int row,
Qt::Orientation orientation = Qt::Vertical) const;
+ bool uniformCellWidths() const;
+ void setUniformCellWidths(bool uniformCellWidths);
+
+ bool uniformCellHeights() const;
+ void setUniformCellHeights(bool uniformCellHeights);
+
void setRowAlignment(int row, Qt::Alignment alignment, Qt::Orientation orientation);
Qt::Alignment rowAlignment(int row, Qt::Orientation orientation) const;
@@ -451,6 +424,8 @@ private:
// Configuration
Qt::Alignment m_defaultAlignment;
unsigned m_snapToPixelGrid : 1;
+ unsigned m_uniformCellWidths : 1;
+ unsigned m_uniformCellHeights : 1;
// Lazily computed from the above user input
mutable QHVContainer<int> q_cachedEffectiveFirstRows;
diff --git a/src/gui/util/qhexstring_p.h b/src/gui/util/qhexstring_p.h
index 2afbf3a42b..2b42e6c43e 100644
--- a/src/gui/util/qhexstring_p.h
+++ b/src/gui/util/qhexstring_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtGui/private/qtguiglobal_p.h>
#include <QtCore/qpoint.h>
diff --git a/src/gui/util/qktxhandler.cpp b/src/gui/util/qktxhandler.cpp
index 9f4545f3af..35f1df1185 100644
--- a/src/gui/util/qktxhandler.cpp
+++ b/src/gui/util/qktxhandler.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qktxhandler_p.h"
#include "qtexturefiledata_p.h"
#include <QtEndian>
#include <QSize>
+#include <QMap>
#include <QtCore/qiodevice.h>
//#define KTX_DEBUG
@@ -52,6 +17,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
#define KTX_IDENTIFIER_LENGTH 12
static const char ktxIdentifier[KTX_IDENTIFIER_LENGTH] = { '\xAB', 'K', 'T', 'X', ' ', '1', '1', '\xBB', '\r', '\n', '\x1A', '\n' };
static const quint32 platformEndianIdentifier = 0x04030201;
@@ -74,7 +41,7 @@ struct KTXHeader {
quint32 bytesOfKeyValueData;
};
-static const quint32 headerSize = sizeof(KTXHeader);
+static constexpr quint32 qktxh_headerSize = sizeof(KTXHeader);
// Currently unused, declared for future reference
struct KTXKeyValuePairItem {
@@ -104,18 +71,32 @@ struct KTXMipmapLevel {
*/
};
-// Returns the nearest multiple of 'rounding' greater than or equal to 'value'
-constexpr quint32 withPadding(quint32 value, quint32 rounding)
+// Returns the nearest multiple of 4 greater than or equal to 'value'
+static const std::optional<quint32> nearestMultipleOf4(quint32 value)
+{
+ constexpr quint32 rounding = 4;
+ quint32 result = 0;
+ if (qAddOverflow(value, rounding - 1, &result))
+ return std::nullopt;
+ result &= ~(rounding - 1);
+ return result;
+}
+
+// Returns a view with prechecked bounds
+static QByteArrayView safeView(QByteArrayView view, quint32 start, quint32 length)
{
- Q_ASSERT(rounding > 1);
- return value + (rounding - 1) - ((value + (rounding - 1)) % rounding);
+ quint32 end = 0;
+ if (qAddOverflow(start, length, &end) || end > quint32(view.length()))
+ return {};
+ return view.sliced(start, length);
}
+QKtxHandler::~QKtxHandler() = default;
+
bool QKtxHandler::canRead(const QByteArray &suffix, const QByteArray &block)
{
Q_UNUSED(suffix);
-
- return (qstrncmp(block.constData(), ktxIdentifier, KTX_IDENTIFIER_LENGTH) == 0);
+ return block.startsWith(ktxIdentifier);
}
QTextureFileData QKtxHandler::read()
@@ -123,56 +104,123 @@ QTextureFileData QKtxHandler::read()
if (!device())
return QTextureFileData();
- QByteArray buf = device()->readAll();
- const quint32 dataSize = quint32(buf.size());
- if (dataSize < headerSize || !canRead(QByteArray(), buf)) {
- qCDebug(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData());
+ const QByteArray buf = device()->readAll();
+ if (static_cast<size_t>(buf.size()) > std::numeric_limits<quint32>::max()) {
+ qWarning(lcQtGuiTextureIO, "Too big KTX file %s", logName().constData());
return QTextureFileData();
}
- const KTXHeader *header = reinterpret_cast<const KTXHeader *>(buf.constData());
- if (!checkHeader(*header)) {
- qCDebug(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData());
+ if (!canRead(QByteArray(), buf)) {
+ qWarning(lcQtGuiTextureIO, "Invalid KTX file %s", logName().constData());
+ return QTextureFileData();
+ }
+
+ if (buf.size() < qsizetype(qktxh_headerSize)) {
+ qWarning(lcQtGuiTextureIO, "Invalid KTX header size in %s", logName().constData());
+ return QTextureFileData();
+ }
+
+ KTXHeader header;
+ memcpy(&header, buf.data(), qktxh_headerSize);
+ if (!checkHeader(header)) {
+ qWarning(lcQtGuiTextureIO, "Unsupported KTX file format in %s", logName().constData());
return QTextureFileData();
}
QTextureFileData texData;
texData.setData(buf);
- texData.setSize(QSize(decode(header->pixelWidth), decode(header->pixelHeight)));
- texData.setGLFormat(decode(header->glFormat));
- texData.setGLInternalFormat(decode(header->glInternalFormat));
- texData.setGLBaseInternalFormat(decode(header->glBaseInternalFormat));
+ texData.setSize(QSize(decode(header.pixelWidth), decode(header.pixelHeight)));
+ texData.setGLFormat(decode(header.glFormat));
+ texData.setGLInternalFormat(decode(header.glInternalFormat));
+ texData.setGLBaseInternalFormat(decode(header.glBaseInternalFormat));
+
+ texData.setNumLevels(decode(header.numberOfMipmapLevels));
+ texData.setNumFaces(decode(header.numberOfFaces));
- texData.setNumLevels(decode(header->numberOfMipmapLevels));
- texData.setNumFaces(decode(header->numberOfFaces));
+ const quint32 bytesOfKeyValueData = decode(header.bytesOfKeyValueData);
+ quint32 headerKeyValueSize;
+ if (qAddOverflow(qktxh_headerSize, bytesOfKeyValueData, &headerKeyValueSize)) {
+ qWarning(lcQtGuiTextureIO, "Overflow in size of key value data in header of KTX file %s",
+ logName().constData());
+ return QTextureFileData();
+ }
+
+ if (headerKeyValueSize >= quint32(buf.size())) {
+ qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData());
+ return QTextureFileData();
+ }
+
+ // File contains key/values
+ if (bytesOfKeyValueData > 0) {
+ auto keyValueDataView = safeView(buf, qktxh_headerSize, bytesOfKeyValueData);
+ if (keyValueDataView.isEmpty()) {
+ qWarning(lcQtGuiTextureIO, "Invalid view in KTX file %s", logName().constData());
+ return QTextureFileData();
+ }
- const quint32 bytesOfKeyValueData = decode(header->bytesOfKeyValueData);
- if (headerSize + bytesOfKeyValueData < quint64(buf.length())) // oob check
- texData.setKeyValueMetadata(
- decodeKeyValues(QByteArrayView(buf.data() + headerSize, bytesOfKeyValueData)));
- quint32 offset = headerSize + bytesOfKeyValueData;
+ auto keyValues = decodeKeyValues(keyValueDataView);
+ if (!keyValues) {
+ qWarning(lcQtGuiTextureIO, "Could not parse key values in KTX file %s",
+ logName().constData());
+ return QTextureFileData();
+ }
+
+ texData.setKeyValueMetadata(*keyValues);
+ }
+
+ // Technically, any number of levels is allowed but if the value is bigger than
+ // what is possible in KTX V2 (and what makes sense) we return an error.
+ // maxLevels = log2(max(width, height, depth))
+ const int maxLevels = (sizeof(quint32) * 8)
+ - qCountLeadingZeroBits(std::max(
+ { header.pixelWidth, header.pixelHeight, header.pixelDepth }));
+
+ if (texData.numLevels() > maxLevels) {
+ qWarning(lcQtGuiTextureIO, "Too many levels in KTX file %s", logName().constData());
+ return QTextureFileData();
+ }
- constexpr int MAX_ITERATIONS = 32; // cap iterations in case of corrupt data
+ if (texData.numFaces() != 1 && texData.numFaces() != 6) {
+ qWarning(lcQtGuiTextureIO, "Invalid number of faces in KTX file %s", logName().constData());
+ return QTextureFileData();
+ }
- for (int level = 0; level < qMin(texData.numLevels(), MAX_ITERATIONS); level++) {
- if (offset + sizeof(quint32) > dataSize) // Corrupt file; avoid oob read
- break;
+ quint32 offset = headerKeyValueSize;
+ for (int level = 0; level < texData.numLevels(); level++) {
+ const auto imageSizeView = safeView(buf, offset, sizeof(quint32));
+ if (imageSizeView.isEmpty()) {
+ qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData());
+ return QTextureFileData();
+ }
- const quint32 imageSize = decode(qFromUnaligned<quint32>(buf.constData() + offset));
- offset += sizeof(quint32);
+ const quint32 imageSize = decode(qFromUnaligned<quint32>(imageSizeView.data()));
+ offset += sizeof(quint32); // overflow checked indirectly above
- for (int face = 0; face < qMin(texData.numFaces(), MAX_ITERATIONS); face++) {
+ for (int face = 0; face < texData.numFaces(); face++) {
texData.setDataOffset(offset, level, face);
texData.setDataLength(imageSize, level, face);
// Add image data and padding to offset
- offset += withPadding(imageSize, 4);
+ const auto padded = nearestMultipleOf4(imageSize);
+ if (!padded) {
+ qWarning(lcQtGuiTextureIO, "Overflow in KTX file %s", logName().constData());
+ return QTextureFileData();
+ }
+
+ quint32 offsetNext;
+ if (qAddOverflow(offset, *padded, &offsetNext)) {
+ qWarning(lcQtGuiTextureIO, "OOB request in KTX file %s", logName().constData());
+ return QTextureFileData();
+ }
+
+ offset = offsetNext;
}
}
if (!texData.isValid()) {
- qCDebug(lcQtGuiTextureIO, "Invalid values in header of KTX file %s", logName().constData());
+ qWarning(lcQtGuiTextureIO, "Invalid values in header of KTX file %s",
+ logName().constData());
return QTextureFileData();
}
@@ -218,33 +266,83 @@ bool QKtxHandler::checkHeader(const KTXHeader &header)
return is2D && (isCubeMap || isCompressedImage);
}
-QMap<QByteArray, QByteArray> QKtxHandler::decodeKeyValues(QByteArrayView view) const
+std::optional<QMap<QByteArray, QByteArray>> QKtxHandler::decodeKeyValues(QByteArrayView view) const
{
QMap<QByteArray, QByteArray> output;
quint32 offset = 0;
- while (offset < view.size() + sizeof(quint32)) {
+ while (offset < quint32(view.size())) {
+ const auto keyAndValueByteSizeView = safeView(view, offset, sizeof(quint32));
+ if (keyAndValueByteSizeView.isEmpty()) {
+ qWarning(lcQtGuiTextureIO, "Invalid view in KTX key-value");
+ return std::nullopt;
+ }
+
const quint32 keyAndValueByteSize =
- decode(qFromUnaligned<quint32>(view.constData() + offset));
- offset += sizeof(quint32);
+ decode(qFromUnaligned<quint32>(keyAndValueByteSizeView.data()));
- if (offset + keyAndValueByteSize > quint64(view.size()))
- break; // oob read
+ quint32 offsetKeyAndValueStart;
+ if (qAddOverflow(offset, quint32(sizeof(quint32)), &offsetKeyAndValueStart)) {
+ qWarning(lcQtGuiTextureIO, "Overflow in KTX key-value");
+ return std::nullopt;
+ }
+
+ quint32 offsetKeyAndValueEnd;
+ if (qAddOverflow(offsetKeyAndValueStart, keyAndValueByteSize, &offsetKeyAndValueEnd)) {
+ qWarning(lcQtGuiTextureIO, "Overflow in KTX key-value");
+ return std::nullopt;
+ }
+
+ const auto keyValueView = safeView(view, offsetKeyAndValueStart, keyAndValueByteSize);
+ if (keyValueView.isEmpty()) {
+ qWarning(lcQtGuiTextureIO, "Invalid view in KTX key-value");
+ return std::nullopt;
+ }
// 'key' is a UTF-8 string ending with a null terminator, 'value' is the rest.
// To separate the key and value we convert the complete data to utf-8 and find the first
// null terminator from the left, here we split the data into two.
- const auto str = QString::fromUtf8(view.constData() + offset, keyAndValueByteSize);
- const int idx = str.indexOf(QLatin1Char('\0'));
- if (idx == -1)
- continue;
-
- const QByteArray key = str.left(idx).toUtf8();
- const size_t keySize = key.size() + 1; // Actual data size
- const QByteArray value = QByteArray::fromRawData(view.constData() + offset + keySize,
- keyAndValueByteSize - keySize);
-
- offset = withPadding(offset + keyAndValueByteSize, 4);
- output.insert(key, value);
+
+ const int idx = keyValueView.indexOf('\0');
+ if (idx == -1) {
+ qWarning(lcQtGuiTextureIO, "Invalid key in KTX key-value");
+ return std::nullopt;
+ }
+
+ const QByteArrayView keyView = safeView(view, offsetKeyAndValueStart, idx);
+ if (keyView.isEmpty()) {
+ qWarning(lcQtGuiTextureIO, "Overflow in KTX key-value");
+ return std::nullopt;
+ }
+
+ const quint32 keySize = idx + 1; // Actual data size
+
+ quint32 offsetValueStart;
+ if (qAddOverflow(offsetKeyAndValueStart, keySize, &offsetValueStart)) {
+ qWarning(lcQtGuiTextureIO, "Overflow in KTX key-value");
+ return std::nullopt;
+ }
+
+ quint32 valueSize;
+ if (qSubOverflow(keyAndValueByteSize, keySize, &valueSize)) {
+ qWarning(lcQtGuiTextureIO, "Underflow in KTX key-value");
+ return std::nullopt;
+ }
+
+ const QByteArrayView valueView = safeView(view, offsetValueStart, valueSize);
+ if (valueView.isEmpty()) {
+ qWarning(lcQtGuiTextureIO, "Invalid view in KTX key-value");
+ return std::nullopt;
+ }
+
+ output.insert(keyView.toByteArray(), valueView.toByteArray());
+
+ const auto offsetNext = nearestMultipleOf4(offsetKeyAndValueEnd);
+ if (!offsetNext) {
+ qWarning(lcQtGuiTextureIO, "Overflow in KTX key-value");
+ return std::nullopt;
+ }
+
+ offset = *offsetNext;
}
return output;
diff --git a/src/gui/util/qktxhandler_p.h b/src/gui/util/qktxhandler_p.h
index 4298433f36..3a0b8fcf7e 100644
--- a/src/gui/util/qktxhandler_p.h
+++ b/src/gui/util/qktxhandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QKTXHANDLER_H
#define QKTXHANDLER_H
@@ -53,6 +17,8 @@
#include "qtexturefilehandler_p.h"
+#include <optional>
+
QT_BEGIN_NAMESPACE
struct KTXHeader;
@@ -61,6 +27,7 @@ class QKtxHandler : public QTextureFileHandler
{
public:
using QTextureFileHandler::QTextureFileHandler;
+ ~QKtxHandler() override;
static bool canRead(const QByteArray &suffix, const QByteArray &block);
@@ -68,7 +35,7 @@ public:
private:
bool checkHeader(const KTXHeader &header);
- QMap<QByteArray, QByteArray> decodeKeyValues(QByteArrayView view) const;
+ std::optional<QMap<QByteArray, QByteArray>> decodeKeyValues(QByteArrayView view) const;
quint32 decode(quint32 val) const;
bool inverseEndian = false;
diff --git a/src/gui/util/qlayoutpolicy.cpp b/src/gui/util/qlayoutpolicy.cpp
index 507df44a45..2e3a0b32cb 100644
--- a/src/gui/util/qlayoutpolicy.cpp
+++ b/src/gui/util/qlayoutpolicy.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qlayoutpolicy_p.h"
#include <QtCore/qdebug.h>
@@ -133,3 +97,5 @@ QDebug operator<<(QDebug dbg, const QLayoutPolicy &p)
#endif
QT_END_NAMESPACE
+
+#include "moc_qlayoutpolicy_p.cpp"
diff --git a/src/gui/util/qlayoutpolicy_p.h b/src/gui/util/qlayoutpolicy_p.h
index 6457aeb653..bbdabd0c7b 100644
--- a/src/gui/util/qlayoutpolicy_p.h
+++ b/src/gui/util/qlayoutpolicy_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QLAYOUTPOLICY_H
#define QLAYOUTPOLICY_H
@@ -64,10 +28,9 @@ QT_BEGIN_NAMESPACE
class QVariant;
-class Q_GUI_EXPORT QLayoutPolicy
+class QLayoutPolicy
{
- Q_GADGET
- Q_ENUMS(Policy)
+ Q_GADGET_EXPORT(Q_GUI_EXPORT)
public:
enum PolicyFlag {
@@ -76,16 +39,16 @@ public:
ShrinkFlag = 4,
IgnoreFlag = 8
};
+ Q_DECLARE_FLAGS(Policy, PolicyFlag)
+ Q_FLAG(Policy)
- enum Policy {
- Fixed = 0,
- Minimum = GrowFlag,
- Maximum = ShrinkFlag,
- Preferred = GrowFlag | ShrinkFlag,
- MinimumExpanding = GrowFlag | ExpandFlag,
- Expanding = GrowFlag | ShrinkFlag | ExpandFlag,
- Ignored = ShrinkFlag | GrowFlag | IgnoreFlag
- };
+ static constexpr inline Policy Fixed = {};
+ static constexpr inline Policy Minimum = GrowFlag;
+ static constexpr inline Policy Maximum = ShrinkFlag;
+ static constexpr inline Policy Preferred = Minimum | Maximum;
+ static constexpr inline Policy MinimumExpanding = Minimum | ExpandFlag;
+ static constexpr inline Policy Expanding = Preferred | ExpandFlag;
+ static constexpr inline Policy Ignored = Preferred | IgnoreFlag;
enum ControlType {
DefaultType = 0x00000001,
@@ -116,11 +79,11 @@ public:
}
Policy horizontalPolicy() const { return static_cast<Policy>(bits.horPolicy); }
Policy verticalPolicy() const { return static_cast<Policy>(bits.verPolicy); }
- ControlType controlType() const;
+ Q_GUI_EXPORT ControlType controlType() const;
void setHorizontalPolicy(Policy d) { bits.horPolicy = d; }
void setVerticalPolicy(Policy d) { bits.verPolicy = d; }
- void setControlType(ControlType type);
+ Q_GUI_EXPORT void setControlType(ControlType type);
Qt::Orientations expandingDirections() const {
Qt::Orientations result;
@@ -144,7 +107,7 @@ public:
void setHorizontalStretch(int stretchFactor) { bits.horStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); }
void setVerticalStretch(int stretchFactor) { bits.verStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); }
- void transpose();
+ inline void transpose();
private:
@@ -169,6 +132,7 @@ private:
};
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QLayoutPolicy::Policy)
Q_DECLARE_OPERATORS_FOR_FLAGS(QLayoutPolicy::ControlTypes)
#ifndef QT_NO_DATASTREAM
diff --git a/src/gui/util/qpkmhandler.cpp b/src/gui/util/qpkmhandler.cpp
index 0ad0a54a79..d84ce2ce7f 100644
--- a/src/gui/util/qpkmhandler.cpp
+++ b/src/gui/util/qpkmhandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpkmhandler_p.h"
#include "qtexturefiledata_p.h"
@@ -49,7 +13,7 @@
QT_BEGIN_NAMESPACE
-static const int headerSize = 16;
+static const int qpkmh_headerSize = 16;
struct PkmType
{
@@ -57,7 +21,7 @@ struct PkmType
quint32 bytesPerBlock;
};
-static PkmType typeMap[5] = {
+static constexpr PkmType typeMap[5] = {
{ 0x8D64, 8 }, // GL_ETC1_RGB8_OES
{ 0x9274, 8 }, // GL_COMPRESSED_RGB8_ETC2
{ 0, 0 }, // unused (obsolete)
@@ -65,6 +29,8 @@ static PkmType typeMap[5] = {
{ 0x9276, 8 } // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
};
+QPkmHandler::~QPkmHandler() = default;
+
bool QPkmHandler::canRead(const QByteArray &suffix, const QByteArray &block)
{
Q_UNUSED(suffix);
@@ -80,7 +46,7 @@ QTextureFileData QPkmHandler::read()
return texData;
QByteArray fileData = device()->readAll();
- if (fileData.size() < headerSize || !canRead(QByteArray(), fileData)) {
+ if (fileData.size() < qpkmh_headerSize || !canRead(QByteArray(), fileData)) {
qCDebug(lcQtGuiTextureIO, "Invalid PKM file %s", logName().constData());
return QTextureFileData();
}
@@ -109,7 +75,7 @@ QTextureFileData QPkmHandler::read()
QSize texSize(qFromBigEndian<quint16>(rawData + 12), qFromBigEndian<quint16>(rawData + 14));
texData.setSize(texSize);
- texData.setDataOffset(headerSize);
+ texData.setDataOffset(qpkmh_headerSize);
if (!texData.isValid()) {
qCDebug(lcQtGuiTextureIO, "Invalid values in header of PKM file %s", logName().constData());
diff --git a/src/gui/util/qpkmhandler_p.h b/src/gui/util/qpkmhandler_p.h
index 2f7618bc53..a773b44fb2 100644
--- a/src/gui/util/qpkmhandler_p.h
+++ b/src/gui/util/qpkmhandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPKMHANDLER_H
#define QPKMHANDLER_H
@@ -59,6 +23,7 @@ class QPkmHandler : public QTextureFileHandler
{
public:
using QTextureFileHandler::QTextureFileHandler;
+ ~QPkmHandler() override;
static bool canRead(const QByteArray &suffix, const QByteArray &block);
diff --git a/src/gui/util/qshaderformat.cpp b/src/gui/util/qshaderformat.cpp
deleted file mode 100644
index d56dfc413e..0000000000
--- a/src/gui/util/qshaderformat.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qshaderformat_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QShaderFormat::QShaderFormat() noexcept
- : m_api(NoApi)
- , m_shaderType(Fragment)
-{
-}
-
-QShaderFormat::Api QShaderFormat::api() const noexcept
-{
- return m_api;
-}
-
-void QShaderFormat::setApi(QShaderFormat::Api api) noexcept
-{
- m_api = api;
-}
-
-QVersionNumber QShaderFormat::version() const noexcept
-{
- return m_version;
-}
-
-void QShaderFormat::setVersion(const QVersionNumber &version) noexcept
-{
- m_version = version;
-}
-
-QStringList QShaderFormat::extensions() const noexcept
-{
- return m_extensions;
-}
-
-void QShaderFormat::setExtensions(const QStringList &extensions) noexcept
-{
- m_extensions = extensions;
- m_extensions.sort();
-}
-
-QString QShaderFormat::vendor() const noexcept
-{
- return m_vendor;
-}
-
-void QShaderFormat::setVendor(const QString &vendor) noexcept
-{
- m_vendor = vendor;
-}
-
-bool QShaderFormat::isValid() const noexcept
-{
- return m_api != NoApi && m_version.majorVersion() > 0;
-}
-
-bool QShaderFormat::supports(const QShaderFormat &other) const noexcept
-{
- if (!isValid() || !other.isValid())
- return false;
-
- if (m_api == OpenGLES && m_api != other.m_api)
- return false;
-
- if (m_api == OpenGLCoreProfile && m_api != other.m_api)
- return false;
-
- if (m_version < other.m_version)
- return false;
-
- if (m_shaderType != other.m_shaderType)
- return false;
-
- const auto containsAllExtensionsFromOther = std::includes(m_extensions.constBegin(),
- m_extensions.constEnd(),
- other.m_extensions.constBegin(),
- other.m_extensions.constEnd());
- if (!containsAllExtensionsFromOther)
- return false;
-
- if (!other.m_vendor.isEmpty() && m_vendor != other.m_vendor)
- return false;
-
- return true;
-}
-
-QShaderFormat::ShaderType QShaderFormat::shaderType() const noexcept
-{
- return m_shaderType;
-}
-
-void QShaderFormat::setShaderType(QShaderFormat::ShaderType shaderType) noexcept
-{
- m_shaderType = shaderType;
-}
-
-bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept
-{
- return lhs.api() == rhs.api()
- && lhs.version() == rhs.version()
- && lhs.extensions() == rhs.extensions()
- && lhs.vendor() == rhs.vendor()
- && lhs.shaderType() == rhs.shaderType();
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderformat_p.h b/src/gui/util/qshaderformat_p.h
deleted file mode 100644
index e47fbb8a03..0000000000
--- a/src/gui/util/qshaderformat_p.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHADERFORMAT_P_H
-#define QSHADERFORMAT_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#include <QtCore/qstringlist.h>
-#include <QtCore/qversionnumber.h>
-
-QT_BEGIN_NAMESPACE
-
-class QShaderFormat
-{
-public:
- enum Api : int {
- NoApi,
- OpenGLNoProfile,
- OpenGLCoreProfile,
- OpenGLCompatibilityProfile,
- OpenGLES,
- VulkanFlavoredGLSL
- };
-
- enum ShaderType : int {
- Vertex = 0,
- TessellationControl,
- TessellationEvaluation,
- Geometry,
- Fragment,
- Compute
- };
-
- Q_GUI_EXPORT QShaderFormat() noexcept;
-
- Q_GUI_EXPORT Api api() const noexcept;
- Q_GUI_EXPORT void setApi(Api api) noexcept;
-
- Q_GUI_EXPORT QVersionNumber version() const noexcept;
- Q_GUI_EXPORT void setVersion(const QVersionNumber &version) noexcept;
-
- Q_GUI_EXPORT QStringList extensions() const noexcept;
- Q_GUI_EXPORT void setExtensions(const QStringList &extensions) noexcept;
-
- Q_GUI_EXPORT QString vendor() const noexcept;
- Q_GUI_EXPORT void setVendor(const QString &vendor) noexcept;
-
- Q_GUI_EXPORT bool isValid() const noexcept;
- Q_GUI_EXPORT bool supports(const QShaderFormat &other) const noexcept;
-
- Q_GUI_EXPORT ShaderType shaderType() const noexcept;
- Q_GUI_EXPORT void setShaderType(ShaderType shaderType) noexcept;
-
-private:
- Api m_api;
- QVersionNumber m_version;
- QStringList m_extensions;
- QString m_vendor;
- ShaderType m_shaderType;
-};
-
-Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept;
-
-inline bool operator!=(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-Q_DECLARE_TYPEINFO(QShaderFormat, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QShaderFormat)
-
-#endif // QSHADERFORMAT_P_H
diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp
deleted file mode 100644
index 4933e913a3..0000000000
--- a/src/gui/util/qshadergenerator.cpp
+++ /dev/null
@@ -1,638 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qshadergenerator_p.h"
-
-#include "qshaderlanguage_p.h"
-#include <QRegularExpression>
-
-#include <cctype>
-
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(ShaderGenerator, "ShaderGenerator", QtWarningMsg)
-
-namespace
-{
- QByteArray toGlsl(QShaderLanguage::StorageQualifier qualifier, const QShaderFormat &format)
- {
- if (format.version().majorVersion() <= 2) {
- // Note we're assuming fragment shader only here, it'd be different
- // values for vertex shader, will need to be fixed properly at some
- // point but isn't necessary yet (this problem already exists in past
- // commits anyway)
- switch (qualifier) {
- case QShaderLanguage::Const:
- return "const";
- case QShaderLanguage::Input:
- if (format.shaderType() == QShaderFormat::Vertex)
- return "attribute";
- else
- return "varying";
- case QShaderLanguage::Output:
- return ""; // Although fragment shaders for <=2 only have fixed outputs
- case QShaderLanguage::Uniform:
- return "uniform";
- case QShaderLanguage::BuiltIn:
- return "//";
- }
- } else {
- switch (qualifier) {
- case QShaderLanguage::Const:
- return "const";
- case QShaderLanguage::Input:
- return "in";
- case QShaderLanguage::Output:
- return "out";
- case QShaderLanguage::Uniform:
- return "uniform";
- case QShaderLanguage::BuiltIn:
- return "//";
- }
- }
-
- Q_UNREACHABLE();
- }
-
- QByteArray toGlsl(QShaderLanguage::VariableType type)
- {
- switch (type) {
- case QShaderLanguage::Bool:
- return "bool";
- case QShaderLanguage::Int:
- return "int";
- case QShaderLanguage::Uint:
- return "uint";
- case QShaderLanguage::Float:
- return "float";
- case QShaderLanguage::Double:
- return "double";
- case QShaderLanguage::Vec2:
- return "vec2";
- case QShaderLanguage::Vec3:
- return "vec3";
- case QShaderLanguage::Vec4:
- return "vec4";
- case QShaderLanguage::DVec2:
- return "dvec2";
- case QShaderLanguage::DVec3:
- return "dvec3";
- case QShaderLanguage::DVec4:
- return "dvec4";
- case QShaderLanguage::BVec2:
- return "bvec2";
- case QShaderLanguage::BVec3:
- return "bvec3";
- case QShaderLanguage::BVec4:
- return "bvec4";
- case QShaderLanguage::IVec2:
- return "ivec2";
- case QShaderLanguage::IVec3:
- return "ivec3";
- case QShaderLanguage::IVec4:
- return "ivec4";
- case QShaderLanguage::UVec2:
- return "uvec2";
- case QShaderLanguage::UVec3:
- return "uvec3";
- case QShaderLanguage::UVec4:
- return "uvec4";
- case QShaderLanguage::Mat2:
- return "mat2";
- case QShaderLanguage::Mat3:
- return "mat3";
- case QShaderLanguage::Mat4:
- return "mat4";
- case QShaderLanguage::Mat2x2:
- return "mat2x2";
- case QShaderLanguage::Mat2x3:
- return "mat2x3";
- case QShaderLanguage::Mat2x4:
- return "mat2x4";
- case QShaderLanguage::Mat3x2:
- return "mat3x2";
- case QShaderLanguage::Mat3x3:
- return "mat3x3";
- case QShaderLanguage::Mat3x4:
- return "mat3x4";
- case QShaderLanguage::Mat4x2:
- return "mat4x2";
- case QShaderLanguage::Mat4x3:
- return "mat4x3";
- case QShaderLanguage::Mat4x4:
- return "mat4x4";
- case QShaderLanguage::DMat2:
- return "dmat2";
- case QShaderLanguage::DMat3:
- return "dmat3";
- case QShaderLanguage::DMat4:
- return "dmat4";
- case QShaderLanguage::DMat2x2:
- return "dmat2x2";
- case QShaderLanguage::DMat2x3:
- return "dmat2x3";
- case QShaderLanguage::DMat2x4:
- return "dmat2x4";
- case QShaderLanguage::DMat3x2:
- return "dmat3x2";
- case QShaderLanguage::DMat3x3:
- return "dmat3x3";
- case QShaderLanguage::DMat3x4:
- return "dmat3x4";
- case QShaderLanguage::DMat4x2:
- return "dmat4x2";
- case QShaderLanguage::DMat4x3:
- return "dmat4x3";
- case QShaderLanguage::DMat4x4:
- return "dmat4x4";
- case QShaderLanguage::Sampler1D:
- return "sampler1D";
- case QShaderLanguage::Sampler2D:
- return "sampler2D";
- case QShaderLanguage::Sampler3D:
- return "sampler3D";
- case QShaderLanguage::SamplerCube:
- return "samplerCube";
- case QShaderLanguage::Sampler2DRect:
- return "sampler2DRect";
- case QShaderLanguage::Sampler2DMs:
- return "sampler2DMS";
- case QShaderLanguage::SamplerBuffer:
- return "samplerBuffer";
- case QShaderLanguage::Sampler1DArray:
- return "sampler1DArray";
- case QShaderLanguage::Sampler2DArray:
- return "sampler2DArray";
- case QShaderLanguage::Sampler2DMsArray:
- return "sampler2DMSArray";
- case QShaderLanguage::SamplerCubeArray:
- return "samplerCubeArray";
- case QShaderLanguage::Sampler1DShadow:
- return "sampler1DShadow";
- case QShaderLanguage::Sampler2DShadow:
- return "sampler2DShadow";
- case QShaderLanguage::Sampler2DRectShadow:
- return "sampler2DRectShadow";
- case QShaderLanguage::Sampler1DArrayShadow:
- return "sampler1DArrayShadow";
- case QShaderLanguage::Sampler2DArrayShadow:
- return "sample2DArrayShadow";
- case QShaderLanguage::SamplerCubeShadow:
- return "samplerCubeShadow";
- case QShaderLanguage::SamplerCubeArrayShadow:
- return "samplerCubeArrayShadow";
- case QShaderLanguage::ISampler1D:
- return "isampler1D";
- case QShaderLanguage::ISampler2D:
- return "isampler2D";
- case QShaderLanguage::ISampler3D:
- return "isampler3D";
- case QShaderLanguage::ISamplerCube:
- return "isamplerCube";
- case QShaderLanguage::ISampler2DRect:
- return "isampler2DRect";
- case QShaderLanguage::ISampler2DMs:
- return "isampler2DMS";
- case QShaderLanguage::ISamplerBuffer:
- return "isamplerBuffer";
- case QShaderLanguage::ISampler1DArray:
- return "isampler1DArray";
- case QShaderLanguage::ISampler2DArray:
- return "isampler2DArray";
- case QShaderLanguage::ISampler2DMsArray:
- return "isampler2DMSArray";
- case QShaderLanguage::ISamplerCubeArray:
- return "isamplerCubeArray";
- case QShaderLanguage::USampler1D:
- return "usampler1D";
- case QShaderLanguage::USampler2D:
- return "usampler2D";
- case QShaderLanguage::USampler3D:
- return "usampler3D";
- case QShaderLanguage::USamplerCube:
- return "usamplerCube";
- case QShaderLanguage::USampler2DRect:
- return "usampler2DRect";
- case QShaderLanguage::USampler2DMs:
- return "usampler2DMS";
- case QShaderLanguage::USamplerBuffer:
- return "usamplerBuffer";
- case QShaderLanguage::USampler1DArray:
- return "usampler1DArray";
- case QShaderLanguage::USampler2DArray:
- return "usampler2DArray";
- case QShaderLanguage::USampler2DMsArray:
- return "usampler2DMSArray";
- case QShaderLanguage::USamplerCubeArray:
- return "usamplerCubeArray";
- }
-
- Q_UNREACHABLE();
- }
-
- QByteArray replaceParameters(const QByteArray &original, const QShaderNode &node, const QShaderFormat &format)
- {
- QByteArray result = original;
-
- const QStringList parameterNames = node.parameterNames();
- for (const QString &parameterName : parameterNames) {
- const QByteArray placeholder = QByteArray(QByteArrayLiteral("$") + parameterName.toUtf8());
- const QVariant parameter = node.parameter(parameterName);
- if (parameter.userType() == qMetaTypeId<QShaderLanguage::StorageQualifier>()) {
- const QShaderLanguage::StorageQualifier qualifier = qvariant_cast<QShaderLanguage::StorageQualifier>(parameter);
- const QByteArray value = toGlsl(qualifier, format);
- result.replace(placeholder, value);
- } else if (parameter.userType() == qMetaTypeId<QShaderLanguage::VariableType>()) {
- const QShaderLanguage::VariableType type = qvariant_cast<QShaderLanguage::VariableType>(parameter);
- const QByteArray value = toGlsl(type);
- result.replace(placeholder, value);
- } else {
- const QByteArray value = parameter.toString().toUtf8();
- result.replace(placeholder, value);
- }
- }
-
- return result;
- }
-}
-
-QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) const
-{
- auto code = QByteArrayList();
-
- if (format.isValid()) {
- const bool isGLES = format.api() == QShaderFormat::OpenGLES;
- const int major = format.version().majorVersion();
- const int minor = format.version().minorVersion();
-
- const int version = major == 2 && isGLES ? 100
- : major == 3 && isGLES ? 300
- : major == 2 ? 100 + 10 * (minor + 1)
- : major == 3 && minor <= 2 ? 100 + 10 * (minor + 3)
- : major * 100 + minor * 10;
-
- const QByteArray profile = isGLES && version > 100 ? QByteArrayLiteral(" es")
- : version >= 150 && format.api() == QShaderFormat::OpenGLCoreProfile ? QByteArrayLiteral(" core")
- : version >= 150 && format.api() == QShaderFormat::OpenGLCompatibilityProfile ? QByteArrayLiteral(" compatibility")
- : QByteArray();
-
- code << (QByteArrayLiteral("#version ") + QByteArray::number(version) + profile);
- code << QByteArray();
- }
-
- const auto intersectsEnabledLayers = [enabledLayers] (const QStringList &layers) {
- return layers.isEmpty()
- || std::any_of(layers.cbegin(), layers.cend(),
- [enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
- };
-
- QList<QString> globalInputVariables;
- const QRegularExpression globalInputExtractRegExp(QStringLiteral("^.*\\s+(\\w+).*;$"));
-
- const QList<QShaderNode> nodes = graph.nodes();
- for (const QShaderNode &node : nodes) {
- if (intersectsEnabledLayers(node.layers())) {
- const QByteArrayList headerSnippets = node.rule(format).headerSnippets;
- for (const QByteArray &snippet : headerSnippets) {
- code << replaceParameters(snippet, node, format);
-
- // If node is an input, record the variable name into the globalInputVariables list
- if (node.type() == QShaderNode::Input) {
- const QRegularExpressionMatch match = globalInputExtractRegExp.match(QString::fromUtf8(code.last()));
- if (match.hasMatch())
- globalInputVariables.push_back(match.captured(1));
- }
- }
- }
- }
-
- code << QByteArray();
- code << QByteArrayLiteral("void main()");
- code << QByteArrayLiteral("{");
-
- const QRegularExpression temporaryVariableToAssignmentRegExp(QStringLiteral("([^;]*\\s+(v\\d+))\\s*=\\s*([^;]*);"));
- const QRegularExpression temporaryVariableInAssignmentRegExp(QStringLiteral("\\W*(v\\d+)\\W*"));
- const QRegularExpression statementRegExp(QStringLiteral("\\s*(\\w+)\\s*=\\s*([^;]*);"));
-
- struct Variable;
-
- struct Assignment
- {
- QString expression;
- QList<Variable *> referencedVariables;
- };
-
- struct Variable
- {
- enum Type {
- GlobalInput,
- TemporaryAssignment,
- Output
- };
-
- QString name;
- QString declaration;
- int referenceCount = 0;
- Assignment assignment;
- Type type = TemporaryAssignment;
- bool substituted = false;
-
- static void substitute(Variable *v)
- {
- if (v->substituted)
- return;
-
- qCDebug(ShaderGenerator) << "Begin Substituting " << v->name << " = " << v->assignment.expression;
- for (Variable *ref : qAsConst(v->assignment.referencedVariables)) {
- // Recursively substitute
- Variable::substitute(ref);
-
- // Replace all variables referenced only once in the assignment
- // by their actual expression
- if (ref->referenceCount == 1 || ref->type == Variable::GlobalInput) {
- const QRegularExpression r(QStringLiteral("(.*\\b)(%1)(\\b.*)").arg(ref->name));
- if (v->assignment.referencedVariables.size() == 1)
- v->assignment.expression.replace(r,
- QStringLiteral("\\1%2\\3").arg(ref->assignment.expression));
- else
- v->assignment.expression.replace(r,
- QStringLiteral("(\\1%2\\3)").arg(ref->assignment.expression));
- }
- }
- qCDebug(ShaderGenerator) << "Done Substituting " << v->name << " = " << v->assignment.expression;
- v->substituted = true;
- }
- };
-
- struct LineContent
- {
- QByteArray rawContent;
- Variable *var = nullptr;
- };
-
- // Table to store temporary variables that should be replaced:
- // - If variable references a a global variables
- // -> we will use the global variable directly
- // - If variable references a function results
- // -> will be kept only if variable is referenced more than once.
- // This avoids having vec3 v56 = vertexPosition; when we could
- // just use vertexPosition directly.
- // The added benefit is when having arrays, we don't try to create
- // mat4 v38 = skinningPalelette[100] which would be invalid
- QList<Variable> temporaryVariables;
- // Reserve more than enough space to ensure no reallocation will take place
- temporaryVariables.reserve(nodes.size() * 8);
-
- QList<LineContent> lines;
-
- auto createVariable = [&] () -> Variable * {
- Q_ASSERT(temporaryVariables.capacity() > 0);
- temporaryVariables.resize(temporaryVariables.size() + 1);
- return &temporaryVariables.last();
- };
-
- auto findVariable = [&] (const QString &name) -> Variable * {
- const auto end = temporaryVariables.end();
- auto it = std::find_if(temporaryVariables.begin(), end,
- [=] (const Variable &a) { return a.name == name; });
- if (it != end)
- return &(*it);
- return nullptr;
- };
-
- auto gatherTemporaryVariablesFromAssignment = [&] (Variable *v, const QString &assignmentContent) {
- QRegularExpressionMatchIterator subMatchIt = temporaryVariableInAssignmentRegExp.globalMatch(assignmentContent);
- while (subMatchIt.hasNext()) {
- const QRegularExpressionMatch subMatch = subMatchIt.next();
- const QString variableName = subMatch.captured(1);
-
- // Variable we care about should already exists -> an expression cannot reference a variable that hasn't been defined
- Variable *u = findVariable(variableName);
- Q_ASSERT(u);
-
- // Increase reference count for u
- ++u->referenceCount;
- // Insert u as reference for variable v
- v->assignment.referencedVariables.push_back(u);
- }
- };
-
- for (const QShaderGraph::Statement &statement : graph.createStatements(enabledLayers)) {
- const QShaderNode node = statement.node;
- QByteArray line = node.rule(format).substitution;
- const QList<QShaderNodePort> ports = node.ports();
-
- struct VariableReplacement {
- QByteArray placeholder;
- QByteArray variable;
- };
-
- QList<VariableReplacement> variableReplacements;
-
- // Generate temporary variable names vN
- for (const QShaderNodePort &port : ports) {
- const QString portName = port.name;
- const QShaderNodePort::Direction portDirection = port.direction;
- const bool isInput = port.direction == QShaderNodePort::Input;
-
- const int portIndex = statement.portIndex(portDirection, portName);
-
- Q_ASSERT(portIndex >= 0);
-
- const int variableIndex = isInput ? statement.inputs.at(portIndex)
- : statement.outputs.at(portIndex);
- if (variableIndex < 0)
- continue;
-
- VariableReplacement replacement;
- replacement.placeholder = QByteArrayLiteral("$") + portName.toUtf8();
- replacement.variable = QByteArrayLiteral("v") + QByteArray::number(variableIndex);
-
- variableReplacements.append(std::move(replacement));
- }
-
- int begin = 0;
- while ((begin = line.indexOf('$', begin)) != -1) {
- int end = begin + 1;
- char endChar = line.at(end);
- const int size = line.size();
- while (end < size && (std::isalnum(endChar) || endChar == '_')) {
- ++end;
- endChar = line.at(end);
- }
-
- const int placeholderLength = end - begin;
-
- const QByteArray variableName = line.mid(begin, placeholderLength);
- const auto replacementIt = std::find_if(variableReplacements.cbegin(), variableReplacements.cend(),
- [&variableName](const VariableReplacement &replacement) {
- return variableName == replacement.placeholder;
- });
-
- if (replacementIt != variableReplacements.cend()) {
- line.replace(begin, placeholderLength, replacementIt->variable);
- begin += replacementIt->variable.length();
- } else {
- begin = end;
- }
- }
-
- // Substitute variable names by generated vN variable names
- const QByteArray substitutionedLine = replaceParameters(line, node, format);
-
- QRegularExpressionMatchIterator matches;
-
- switch (node.type()) {
- case QShaderNode::Input:
- case QShaderNode::Output:
- matches = statementRegExp.globalMatch(QString::fromUtf8(substitutionedLine));
- break;
- case QShaderNode::Function:
- matches = temporaryVariableToAssignmentRegExp.globalMatch(QString::fromUtf8(substitutionedLine));
- break;
- case QShaderNode::Invalid:
- break;
- }
-
- while (matches.hasNext()) {
- QRegularExpressionMatch match = matches.next();
-
- Variable *v = nullptr;
-
- switch (node.type()) {
- // Record name of temporary variable that possibly references a global input
- // We will replace the temporary variables by the matching global variables later
- case QShaderNode::Input: {
- const QString localVariable = match.captured(1);
- const QString globalVariable = match.captured(2);
-
- v = createVariable();
- v->name = localVariable;
- v->type = Variable::GlobalInput;
-
- Assignment assignment;
- assignment.expression = globalVariable;
- v->assignment = assignment;
- break;
- }
-
- case QShaderNode::Function: {
- const QString localVariableDeclaration = match.captured(1);
- const QString localVariableName = match.captured(2);
- const QString assignmentContent = match.captured(3);
-
- // Add new variable -> it cannot exist already
- v = createVariable();
- v->name = localVariableName;
- v->declaration = localVariableDeclaration;
- v->assignment.expression = assignmentContent;
-
- // Find variables that may be referenced in the assignment
- gatherTemporaryVariablesFromAssignment(v, assignmentContent);
- break;
- }
-
- case QShaderNode::Output: {
- const QString outputDeclaration = match.captured(1);
- const QString assignmentContent = match.captured(2);
-
- v = createVariable();
- v->name = outputDeclaration;
- v->declaration = outputDeclaration;
- v->type = Variable::Output;
-
- Assignment assignment;
- assignment.expression = assignmentContent;
- v->assignment = assignment;
-
- // Find variables that may be referenced in the assignment
- gatherTemporaryVariablesFromAssignment(v, assignmentContent);
- break;
- }
- case QShaderNode::Invalid:
- break;
- }
-
- LineContent lineContent;
- lineContent.rawContent = QByteArray(QByteArrayLiteral(" ") + substitutionedLine);
- lineContent.var = v;
- lines << lineContent;
- }
- }
-
- // Go through all lines
- // Perform substitution of line with temporary variables substitution
- for (LineContent &lineContent : lines) {
- Variable *v = lineContent.var;
- qCDebug(ShaderGenerator) << lineContent.rawContent;
- if (v != nullptr) {
- Variable::substitute(v);
-
- qCDebug(ShaderGenerator) << "Line " << lineContent.rawContent << "is assigned to temporary" << v->name;
-
- // Check number of occurrences a temporary variable is referenced
- if (v->referenceCount == 1 || v->type == Variable::GlobalInput) {
- // If it is referenced only once, no point in creating a temporary
- // Clear content for current line
- lineContent.rawContent.clear();
- // We assume expression that were referencing vN will have vN properly substituted
- } else {
- lineContent.rawContent = QStringLiteral(" %1 = %2;").arg(v->declaration)
- .arg(v->assignment.expression)
- .toUtf8();
- }
-
- qCDebug(ShaderGenerator) << "Updated Line is " << lineContent.rawContent;
- }
- }
-
- // Go throug all lines and insert content
- for (const LineContent &lineContent : qAsConst(lines)) {
- if (!lineContent.rawContent.isEmpty()) {
- code << lineContent.rawContent;
- }
- }
-
- code << QByteArrayLiteral("}");
- code << QByteArray();
-
- return code.join('\n');
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/util/qshadergenerator_p.h b/src/gui/util/qshadergenerator_p.h
deleted file mode 100644
index 4d3a09c92f..0000000000
--- a/src/gui/util/qshadergenerator_p.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHADERGENERATOR_P_H
-#define QSHADERGENERATOR_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#include <QtGui/private/qshadergraph_p.h>
-#include <QtCore/QLoggingCategory>
-
-
-QT_BEGIN_NAMESPACE
-
-Q_DECLARE_LOGGING_CATEGORY(ShaderGenerator)
-
-class QShaderGenerator
-{
-public:
- Q_GUI_EXPORT QByteArray createShaderCode(const QStringList &enabledLayers = QStringList()) const;
-
- QShaderGraph graph;
- QShaderFormat format;
-};
-
-Q_DECLARE_TYPEINFO(QShaderGenerator, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QShaderGenerator)
-
-#endif // QSHADERGENERATOR_P_H
diff --git a/src/gui/util/qshadergraph.cpp b/src/gui/util/qshadergraph.cpp
deleted file mode 100644
index 5d2d7f3627..0000000000
--- a/src/gui/util/qshadergraph.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qshadergraph_p.h"
-
-QT_BEGIN_NAMESPACE
-
-
-namespace
-{
- QList<QShaderNode> copyOutputNodes(const QList<QShaderNode> &nodes, const QList<QShaderGraph::Edge> &edges)
- {
- auto res = QList<QShaderNode>();
- std::copy_if(nodes.cbegin(), nodes.cend(),
- std::back_inserter(res),
- [&edges] (const QShaderNode &node) {
- return node.type() == QShaderNode::Output ||
- (node.type() == QShaderNode::Function &&
- !std::any_of(edges.cbegin(),
- edges.cend(),
- [&node] (const QShaderGraph::Edge &edge) {
- return edge.sourceNodeUuid ==
- node.uuid();
- }));
- });
- return res;
- }
-
- QList<QShaderGraph::Edge> incomingEdges(const QList<QShaderGraph::Edge> &edges, const QUuid &uuid)
- {
- auto res = QList<QShaderGraph::Edge>();
- std::copy_if(edges.cbegin(), edges.cend(),
- std::back_inserter(res),
- [uuid] (const QShaderGraph::Edge &edge) {
- return edge.sourceNodeUuid == uuid;
- });
- return res;
- }
-
- QList<QShaderGraph::Edge> outgoingEdges(const QList<QShaderGraph::Edge> &edges, const QUuid &uuid)
- {
- auto res = QList<QShaderGraph::Edge>();
- std::copy_if(edges.cbegin(), edges.cend(),
- std::back_inserter(res),
- [uuid] (const QShaderGraph::Edge &edge) {
- return edge.targetNodeUuid == uuid;
- });
- return res;
- }
-
- QShaderGraph::Statement nodeToStatement(const QShaderNode &node, int &nextVarId)
- {
- auto statement = QShaderGraph::Statement();
- statement.node = node;
-
- const QList<QShaderNodePort> ports = node.ports();
- for (const QShaderNodePort &port : ports) {
- if (port.direction == QShaderNodePort::Input) {
- statement.inputs.append(-1);
- } else {
- statement.outputs.append(nextVarId);
- nextVarId++;
- }
- }
- return statement;
- }
-
- QShaderGraph::Statement completeStatement(const QHash<QUuid, QShaderGraph::Statement> &idHash,
- const QList<QShaderGraph::Edge> edges,
- const QUuid &uuid)
- {
- auto targetStatement = idHash.value(uuid);
- for (const QShaderGraph::Edge &edge : edges) {
- if (edge.targetNodeUuid != uuid)
- continue;
-
- const QShaderGraph::Statement sourceStatement = idHash.value(edge.sourceNodeUuid);
- const int sourcePortIndex = sourceStatement.portIndex(QShaderNodePort::Output, edge.sourcePortName);
- const int targetPortIndex = targetStatement.portIndex(QShaderNodePort::Input, edge.targetPortName);
-
- if (sourcePortIndex < 0 || targetPortIndex < 0)
- continue;
-
- const QList<int> sourceOutputs = sourceStatement.outputs;
- QList<int> &targetInputs = targetStatement.inputs;
- targetInputs[targetPortIndex] = sourceOutputs[sourcePortIndex];
- }
- return targetStatement;
- }
-
- void removeNodesWithUnboundInputs(QList<QShaderGraph::Statement> &statements,
- const QList<QShaderGraph::Edge> &allEdges)
- {
- // A node is invalid if any of its input ports is disconected
- // or connected to the output port of another invalid node.
-
- // Keeps track of the edges from the nodes we know to be valid
- // to unvisited nodes
- auto currentEdges = QList<QShaderGraph::Edge>();
-
- statements.erase(std::remove_if(statements.begin(),
- statements.end(),
- [&currentEdges, &allEdges] (const QShaderGraph::Statement &statement) {
- const QShaderNode &node = statement.node;
- const QList<QShaderGraph::Edge> outgoing = outgoingEdges(currentEdges, node.uuid());
- const QList<QShaderNodePort> ports = node.ports();
-
- bool allInputsConnected = true;
- for (const QShaderNodePort &port : node.ports()) {
- if (port.direction == QShaderNodePort::Output)
- continue;
-
- const auto edgeIt = std::find_if(outgoing.cbegin(),
- outgoing.cend(),
- [&port] (const QShaderGraph::Edge &edge) {
- return edge.targetPortName == port.name;
- });
-
- if (edgeIt != outgoing.cend())
- currentEdges.removeAll(*edgeIt);
- else
- allInputsConnected = false;
- }
-
- if (allInputsConnected) {
- const QList<QShaderGraph::Edge> incoming = incomingEdges(allEdges, node.uuid());
- currentEdges.append(incoming);
- }
-
- return !allInputsConnected;
- }),
- statements.end());
- }
-}
-
-QUuid QShaderGraph::Statement::uuid() const noexcept
-{
- return node.uuid();
-}
-
-int QShaderGraph::Statement::portIndex(QShaderNodePort::Direction direction, const QString &portName) const noexcept
-{
- const QList<QShaderNodePort> ports = node.ports();
- int index = 0;
- for (const QShaderNodePort &port : ports) {
- if (port.name == portName && port.direction == direction)
- return index;
- else if (port.direction == direction)
- index++;
- }
- return -1;
-}
-
-void QShaderGraph::addNode(const QShaderNode &node)
-{
- removeNode(node);
- m_nodes.append(node);
-}
-
-void QShaderGraph::removeNode(const QShaderNode &node)
-{
- const auto it = std::find_if(m_nodes.begin(), m_nodes.end(),
- [node] (const QShaderNode &n) { return n.uuid() == node.uuid(); });
- if (it != m_nodes.end())
- m_nodes.erase(it);
-}
-
-QList<QShaderNode> QShaderGraph::nodes() const noexcept
-{
- return m_nodes;
-}
-
-void QShaderGraph::addEdge(const QShaderGraph::Edge &edge)
-{
- if (m_edges.contains(edge))
- return;
- m_edges.append(edge);
-}
-
-void QShaderGraph::removeEdge(const QShaderGraph::Edge &edge)
-{
- m_edges.removeAll(edge);
-}
-
-QList<QShaderGraph::Edge> QShaderGraph::edges() const noexcept
-{
- return m_edges;
-}
-
-QList<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringList &enabledLayers) const
-{
- const auto intersectsEnabledLayers = [enabledLayers] (const QStringList &layers) {
- return layers.isEmpty()
- || std::any_of(layers.cbegin(), layers.cend(),
- [enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
- };
-
- const QList<QShaderNode> enabledNodes = [this, intersectsEnabledLayers] {
- auto res = QList<QShaderNode>();
- std::copy_if(m_nodes.cbegin(), m_nodes.cend(),
- std::back_inserter(res),
- [intersectsEnabledLayers] (const QShaderNode &node) {
- return intersectsEnabledLayers(node.layers());
- });
- return res;
- }();
-
- const QList<Edge> enabledEdges = [this, intersectsEnabledLayers] {
- auto res = QList<Edge>();
- std::copy_if(m_edges.cbegin(), m_edges.cend(),
- std::back_inserter(res),
- [intersectsEnabledLayers] (const Edge &edge) {
- return intersectsEnabledLayers(edge.layers);
- });
- return res;
- }();
-
- const QHash<QUuid, Statement> idHash = [enabledNodes] {
- auto nextVarId = 0;
- auto res = QHash<QUuid, Statement>();
- for (const QShaderNode &node : enabledNodes)
- res.insert(node.uuid(), nodeToStatement(node, nextVarId));
- return res;
- }();
-
- auto result = QList<Statement>();
- QList<Edge> currentEdges = enabledEdges;
- QList<QUuid> currentUuids = [enabledNodes, enabledEdges] {
- const QList<QShaderNode> inputs = copyOutputNodes(enabledNodes, enabledEdges);
- auto res = QList<QUuid>();
- std::transform(inputs.cbegin(), inputs.cend(),
- std::back_inserter(res),
- [](const QShaderNode &node) { return node.uuid(); });
- return res;
- }();
-
- // Implements Kahn's algorithm to flatten the graph
- // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm
- //
- // We implement it with a small twist though, we follow the edges backward
- // because we want to track the dependencies from the output nodes and not the
- // input nodes
- while (!currentUuids.isEmpty()) {
- const QUuid uuid = currentUuids.takeFirst();
- result.append(completeStatement(idHash, enabledEdges, uuid));
-
- const QList<QShaderGraph::Edge> outgoing = outgoingEdges(currentEdges, uuid);
- for (const QShaderGraph::Edge &outgoingEdge : outgoing) {
- currentEdges.removeAll(outgoingEdge);
- const QUuid nextUuid = outgoingEdge.sourceNodeUuid;
- const QList<QShaderGraph::Edge> incoming = incomingEdges(currentEdges, nextUuid);
- if (incoming.isEmpty()) {
- currentUuids.append(nextUuid);
- }
- }
- }
-
- std::reverse(result.begin(), result.end());
-
- removeNodesWithUnboundInputs(result, enabledEdges);
-
- return result;
-}
-
-bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept
-{
- return lhs.sourceNodeUuid == rhs.sourceNodeUuid
- && lhs.sourcePortName == rhs.sourcePortName
- && lhs.targetNodeUuid == rhs.targetNodeUuid
- && lhs.targetPortName == rhs.targetPortName;
-}
-
-bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept
-{
- return lhs.inputs == rhs.inputs
- && lhs.outputs == rhs.outputs
- && lhs.node.uuid() == rhs.node.uuid();
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/util/qshadergraph_p.h b/src/gui/util/qshadergraph_p.h
deleted file mode 100644
index dbc5f3fab7..0000000000
--- a/src/gui/util/qshadergraph_p.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHADERGRAPH_P_H
-#define QSHADERGRAPH_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#include <QtGui/private/qshadernode_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QShaderGraph
-{
-public:
- class Edge
- {
- public:
- QStringList layers;
- QUuid sourceNodeUuid;
- QString sourcePortName;
- QUuid targetNodeUuid;
- QString targetPortName;
- };
-
- class Statement
- {
- public:
- Q_GUI_EXPORT QUuid uuid() const noexcept;
- Q_GUI_EXPORT int portIndex(QShaderNodePort::Direction direction, const QString &portName) const noexcept;
-
- QShaderNode node;
- QList<int> inputs;
- QList<int> outputs;
- };
-
- Q_GUI_EXPORT void addNode(const QShaderNode &node);
- Q_GUI_EXPORT void removeNode(const QShaderNode &node);
- Q_GUI_EXPORT QList<QShaderNode> nodes() const noexcept;
-
- Q_GUI_EXPORT void addEdge(const Edge &edge);
- Q_GUI_EXPORT void removeEdge(const Edge &edge);
- Q_GUI_EXPORT QList<Edge> edges() const noexcept;
-
- Q_GUI_EXPORT QList<Statement>
- createStatements(const QStringList &enabledLayers = QStringList()) const;
-
-private:
- QList<QShaderNode> m_nodes;
- QList<Edge> m_edges;
-};
-
-Q_GUI_EXPORT bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept;
-
-inline bool operator!=(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-Q_GUI_EXPORT bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept;
-
-inline bool operator!=(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-Q_DECLARE_TYPEINFO(QShaderGraph, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QShaderGraph::Edge, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QShaderGraph::Statement, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QShaderGraph)
-Q_DECLARE_METATYPE(QShaderGraph::Edge)
-Q_DECLARE_METATYPE(QShaderGraph::Statement)
-
-#endif // QSHADERGRAPH_P_H
diff --git a/src/gui/util/qshadergraphloader.cpp b/src/gui/util/qshadergraphloader.cpp
deleted file mode 100644
index defa88b9d3..0000000000
--- a/src/gui/util/qshadergraphloader.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qshadergraphloader_p.h"
-
-#include "qshadernodesloader_p.h"
-
-#include <QtCore/qdebug.h>
-#include <QtCore/qiodevice.h>
-#include <QtCore/qjsonarray.h>
-#include <QtCore/qjsondocument.h>
-#include <QtCore/qjsonobject.h>
-#include <QtCore/qmetaobject.h>
-
-QT_BEGIN_NAMESPACE
-
-void qt_register_ShaderLanguage_enums();
-
-QShaderGraphLoader::QShaderGraphLoader() noexcept
- : m_status(Null),
- m_device(nullptr)
-{
- qt_register_ShaderLanguage_enums();
-}
-
-QShaderGraphLoader::Status QShaderGraphLoader::status() const noexcept
-{
- return m_status;
-}
-
-QShaderGraph QShaderGraphLoader::graph() const noexcept
-{
- return m_graph;
-}
-
-QIODevice *QShaderGraphLoader::device() const noexcept
-{
- return m_device;
-}
-
-void QShaderGraphLoader::setDevice(QIODevice *device) noexcept
-{
- m_device = device;
- m_graph = QShaderGraph();
- m_status = !m_device ? Null
- : (m_device->openMode() & QIODevice::ReadOnly) ? Waiting
- : Error;
-}
-
-QHash<QString, QShaderNode> QShaderGraphLoader::prototypes() const noexcept
-{
- return m_prototypes;
-}
-
-void QShaderGraphLoader::setPrototypes(const QHash<QString, QShaderNode> &prototypes) noexcept
-{
- m_prototypes = prototypes;
-}
-
-void QShaderGraphLoader::load()
-{
- if (m_status == Error)
- return;
-
- auto error = QJsonParseError();
- const QJsonDocument document = QJsonDocument::fromJson(m_device->readAll(), &error);
-
- if (error.error != QJsonParseError::NoError) {
- qWarning() << "Invalid JSON document:" << error.errorString();
- m_status = Error;
- return;
- }
-
- if (document.isEmpty() || !document.isObject()) {
- qWarning() << "Invalid JSON document, root should be an object";
- m_status = Error;
- return;
- }
-
- const QJsonObject root = document.object();
-
- const QJsonValue nodesValue = root.value(QStringLiteral("nodes"));
- if (!nodesValue.isArray()) {
- qWarning() << "Invalid nodes property, should be an array";
- m_status = Error;
- return;
- }
-
- const QJsonValue edgesValue = root.value(QStringLiteral("edges"));
- if (!edgesValue.isArray()) {
- qWarning() << "Invalid edges property, should be an array";
- m_status = Error;
- return;
- }
-
- bool hasError = false;
-
- const QJsonValue prototypesValue = root.value(QStringLiteral("prototypes"));
- if (!prototypesValue.isUndefined()) {
- if (prototypesValue.isObject()) {
- QShaderNodesLoader loader;
- loader.load(prototypesValue.toObject());
- m_prototypes.insert(loader.nodes());
- } else {
- qWarning() << "Invalid prototypes property, should be an object";
- m_status = Error;
- return;
- }
- }
-
- const QJsonArray nodes = nodesValue.toArray();
- for (const QJsonValue nodeValue : nodes) {
- if (!nodeValue.isObject()) {
- qWarning() << "Invalid node found";
- hasError = true;
- continue;
- }
-
- const QJsonObject nodeObject = nodeValue.toObject();
-
- const QString uuidString = nodeObject.value(QStringLiteral("uuid")).toString();
- const QUuid uuid = QUuid(uuidString);
- if (uuid.isNull()) {
- qWarning() << "Invalid UUID found in node:" << uuidString;
- hasError = true;
- continue;
- }
-
- const QString type = nodeObject.value(QStringLiteral("type")).toString();
- if (!m_prototypes.contains(type)) {
- qWarning() << "Unsupported node type found:" << type;
- hasError = true;
- continue;
- }
-
- const QJsonArray layersArray = nodeObject.value(QStringLiteral("layers")).toArray();
- auto layers = QStringList();
- for (const QJsonValue layerValue : layersArray) {
- layers.append(layerValue.toString());
- }
-
- QShaderNode node = m_prototypes.value(type);
- node.setUuid(uuid);
- node.setLayers(layers);
-
- const QJsonValue parametersValue = nodeObject.value(QStringLiteral("parameters"));
- if (parametersValue.isObject()) {
- const QJsonObject parametersObject = parametersValue.toObject();
- for (const QString &parameterName : parametersObject.keys()) {
- const QJsonValue parameterValue = parametersObject.value(parameterName);
- if (parameterValue.isObject()) {
- const QJsonObject parameterObject = parameterValue.toObject();
- const QString type = parameterObject.value(QStringLiteral("type")).toString();
- const auto metaType = QMetaType::fromName(type.toUtf8());
-
- const QString value = parameterObject.value(QStringLiteral("value")).toString();
- auto variant = QVariant(value);
-
- if (metaType.flags() & QMetaType::IsEnumeration) {
- const QMetaObject *metaObject = metaType.metaObject();
- const char *className = metaObject->className();
- const QByteArray enumName = type.mid(static_cast<int>(qstrlen(className)) + 2).toUtf8();
- const QMetaEnum metaEnum = metaObject->enumerator(metaObject->indexOfEnumerator(enumName));
- const int enumValue = metaEnum.keyToValue(value.toUtf8());
- variant = QVariant(enumValue);
- variant.convert(metaType);
- } else {
- variant.convert(metaType);
- }
- node.setParameter(parameterName, variant);
- } else {
- node.setParameter(parameterName, parameterValue.toVariant());
- }
- }
- }
-
- m_graph.addNode(node);
- }
-
- const QJsonArray edges = edgesValue.toArray();
- for (const QJsonValue edgeValue : edges) {
- if (!edgeValue.isObject()) {
- qWarning() << "Invalid edge found";
- hasError = true;
- continue;
- }
-
- const QJsonObject edgeObject = edgeValue.toObject();
-
- const QString sourceUuidString = edgeObject.value(QStringLiteral("sourceUuid")).toString();
- const QUuid sourceUuid = QUuid(sourceUuidString);
- if (sourceUuid.isNull()) {
- qWarning() << "Invalid source UUID found in edge:" << sourceUuidString;
- hasError = true;
- continue;
- }
-
- const QString sourcePort = edgeObject.value(QStringLiteral("sourcePort")).toString();
-
- const QString targetUuidString = edgeObject.value(QStringLiteral("targetUuid")).toString();
- const QUuid targetUuid = QUuid(targetUuidString);
- if (targetUuid.isNull()) {
- qWarning() << "Invalid target UUID found in edge:" << targetUuidString;
- hasError = true;
- continue;
- }
-
- const QString targetPort = edgeObject.value(QStringLiteral("targetPort")).toString();
-
- const QJsonArray layersArray = edgeObject.value(QStringLiteral("layers")).toArray();
- auto layers = QStringList();
- for (const QJsonValue layerValue : layersArray) {
- layers.append(layerValue.toString());
- }
-
- auto edge = QShaderGraph::Edge();
- edge.sourceNodeUuid = sourceUuid;
- edge.sourcePortName = sourcePort;
- edge.targetNodeUuid = targetUuid;
- edge.targetPortName = targetPort;
- edge.layers = layers;
- m_graph.addEdge(edge);
- }
-
- if (hasError) {
- m_status = Error;
- m_graph = QShaderGraph();
- } else {
- m_status = Ready;
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/util/qshadergraphloader_p.h b/src/gui/util/qshadergraphloader_p.h
deleted file mode 100644
index bdd02799f7..0000000000
--- a/src/gui/util/qshadergraphloader_p.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHADERGRAPHLOADER_P_H
-#define QSHADERGRAPHLOADER_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#include <QtGui/private/qshadergraph_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QIODevice;
-
-class QShaderGraphLoader
-{
-public:
- enum Status : char {
- Null,
- Waiting,
- Ready,
- Error
- };
-
- Q_GUI_EXPORT QShaderGraphLoader() noexcept;
-
- Q_GUI_EXPORT Status status() const noexcept;
- Q_GUI_EXPORT QShaderGraph graph() const noexcept;
-
- Q_GUI_EXPORT QIODevice *device() const noexcept;
- Q_GUI_EXPORT void setDevice(QIODevice *device) noexcept;
-
- Q_GUI_EXPORT QHash<QString, QShaderNode> prototypes() const noexcept;
- Q_GUI_EXPORT void setPrototypes(const QHash<QString, QShaderNode> &prototypes) noexcept;
-
- Q_GUI_EXPORT void load();
-
-private:
- Status m_status;
- QIODevice *m_device;
- QHash<QString, QShaderNode> m_prototypes;
- QShaderGraph m_graph;
-};
-
-Q_DECLARE_TYPEINFO(QShaderGraphLoader, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QShaderGraphLoader)
-Q_DECLARE_METATYPE(QShaderGraphLoader::Status)
-
-#endif // QSHADERGRAPHLOADER_P_H
diff --git a/src/gui/util/qshaderlanguage.cpp b/src/gui/util/qshaderlanguage.cpp
deleted file mode 100644
index efd607ba60..0000000000
--- a/src/gui/util/qshaderlanguage.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qshaderlanguage_p.h"
-
-#include <QtCore/qcoreapplication.h>
-
-QT_BEGIN_NAMESPACE
-
-// Note: to be invoked explicitly. Relying for example on
-// Q_COREAPP_STARTUP_FUNCTION would not be acceptable in static builds.
-void qt_register_ShaderLanguage_enums()
-{
- qRegisterMetaType<QShaderLanguage::StorageQualifier>();
- qRegisterMetaType<QShaderLanguage::VariableType>();
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderlanguage_p.h b/src/gui/util/qshaderlanguage_p.h
deleted file mode 100644
index 193f797cc3..0000000000
--- a/src/gui/util/qshaderlanguage_p.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHADERLANGUAGE_P_H
-#define QSHADERLANGUAGE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#include <QtCore/qmetatype.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QShaderLanguage
-{
- Q_NAMESPACE_EXPORT(Q_GUI_EXPORT)
-
- enum StorageQualifier : char {
- Const = 1,
- Input,
- BuiltIn,
- Output,
- Uniform
- };
- Q_ENUM_NS(StorageQualifier)
-
- enum VariableType : int {
- Bool = 1,
- Int,
- Uint,
- Float,
- Double,
- Vec2,
- Vec3,
- Vec4,
- DVec2,
- DVec3,
- DVec4,
- BVec2,
- BVec3,
- BVec4,
- IVec2,
- IVec3,
- IVec4,
- UVec2,
- UVec3,
- UVec4,
- Mat2,
- Mat3,
- Mat4,
- Mat2x2,
- Mat2x3,
- Mat2x4,
- Mat3x2,
- Mat3x3,
- Mat3x4,
- Mat4x2,
- Mat4x3,
- Mat4x4,
- DMat2,
- DMat3,
- DMat4,
- DMat2x2,
- DMat2x3,
- DMat2x4,
- DMat3x2,
- DMat3x3,
- DMat3x4,
- DMat4x2,
- DMat4x3,
- DMat4x4,
- Sampler1D,
- Sampler2D,
- Sampler3D,
- SamplerCube,
- Sampler2DRect,
- Sampler2DMs,
- SamplerBuffer,
- Sampler1DArray,
- Sampler2DArray,
- Sampler2DMsArray,
- SamplerCubeArray,
- Sampler1DShadow,
- Sampler2DShadow,
- Sampler2DRectShadow,
- Sampler1DArrayShadow,
- Sampler2DArrayShadow,
- SamplerCubeShadow,
- SamplerCubeArrayShadow,
- ISampler1D,
- ISampler2D,
- ISampler3D,
- ISamplerCube,
- ISampler2DRect,
- ISampler2DMs,
- ISamplerBuffer,
- ISampler1DArray,
- ISampler2DArray,
- ISampler2DMsArray,
- ISamplerCubeArray,
- USampler1D,
- USampler2D,
- USampler3D,
- USamplerCube,
- USampler2DRect,
- USampler2DMs,
- USamplerBuffer,
- USampler1DArray,
- USampler2DArray,
- USampler2DMsArray,
- USamplerCubeArray
- };
- Q_ENUM_NS(VariableType)
-}
-
-QT_END_NAMESPACE
-
-#endif // QSHADERLANGUAGE_P_H
diff --git a/src/gui/util/qshadernode.cpp b/src/gui/util/qshadernode.cpp
deleted file mode 100644
index 3e53c35037..0000000000
--- a/src/gui/util/qshadernode.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qshadernode_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QShaderNode::Type QShaderNode::type() const noexcept
-{
- int inputCount = 0;
- int outputCount = 0;
- for (const auto &port : qAsConst(m_ports)) {
- switch (port.direction) {
- case QShaderNodePort::Input:
- inputCount++;
- break;
- case QShaderNodePort::Output:
- outputCount++;
- break;
- }
- }
-
- return (inputCount == 0 && outputCount == 0) ? Invalid
- : (inputCount > 0 && outputCount == 0) ? Output
- : (inputCount == 0 && outputCount > 0) ? Input
- : Function;
-}
-
-QUuid QShaderNode::uuid() const noexcept
-{
- return m_uuid;
-}
-
-void QShaderNode::setUuid(const QUuid &uuid) noexcept
-{
- m_uuid = uuid;
-}
-
-QStringList QShaderNode::layers() const noexcept
-{
- return m_layers;
-}
-
-void QShaderNode::setLayers(const QStringList &layers) noexcept
-{
- m_layers = layers;
-}
-
-QList<QShaderNodePort> QShaderNode::ports() const noexcept
-{
- return m_ports;
-}
-
-void QShaderNode::addPort(const QShaderNodePort &port)
-{
- removePort(port);
- m_ports.append(port);
-}
-
-void QShaderNode::removePort(const QShaderNodePort &port)
-{
- const auto it = std::find_if(m_ports.begin(), m_ports.end(),
- [port](const QShaderNodePort &p) {
- return p.name == port.name;
- });
- if (it != m_ports.end())
- m_ports.erase(it);
-}
-
-QStringList QShaderNode::parameterNames() const
-{
- return m_parameters.keys();
-}
-
-QVariant QShaderNode::parameter(const QString &name) const
-{
- return m_parameters.value(name);
-}
-
-void QShaderNode::setParameter(const QString &name, const QVariant &value)
-{
- m_parameters.insert(name, value);
-}
-
-void QShaderNode::clearParameter(const QString &name)
-{
- m_parameters.remove(name);
-}
-
-void QShaderNode::addRule(const QShaderFormat &format, const QShaderNode::Rule &rule)
-{
- removeRule(format);
- m_rules << qMakePair(format, rule);
-}
-
-void QShaderNode::removeRule(const QShaderFormat &format)
-{
- const auto it = std::find_if(m_rules.begin(), m_rules.end(),
- [format](const QPair<QShaderFormat, Rule> &entry) {
- return entry.first == format;
- });
- if (it != m_rules.end())
- m_rules.erase(it);
-}
-
-QList<QShaderFormat> QShaderNode::availableFormats() const
-{
- auto res = QList<QShaderFormat>();
- std::transform(m_rules.cbegin(), m_rules.cend(),
- std::back_inserter(res),
- [](const QPair<QShaderFormat, Rule> &entry) { return entry.first; });
- return res;
-}
-
-QShaderNode::Rule QShaderNode::rule(const QShaderFormat &format) const
-{
- const auto it = std::find_if(m_rules.crbegin(), m_rules.crend(),
- [format](const QPair<QShaderFormat, Rule> &entry) {
- return format.supports(entry.first);
- });
- return it != m_rules.crend() ? it->second : Rule();
-}
-
-QShaderNode::Rule::Rule(const QByteArray &subs, const QByteArrayList &snippets) noexcept
- : substitution(subs),
- headerSnippets(snippets)
-{
-}
-
-bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept
-{
- return lhs.substitution == rhs.substitution
- && lhs.headerSnippets == rhs.headerSnippets;
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernode_p.h b/src/gui/util/qshadernode_p.h
deleted file mode 100644
index 303a404165..0000000000
--- a/src/gui/util/qshadernode_p.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHADERNODE_P_H
-#define QSHADERNODE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#include <QtGui/private/qshaderformat_p.h>
-#include <QtGui/private/qshadernodeport_p.h>
-
-#include <QtCore/quuid.h>
-
-QT_BEGIN_NAMESPACE
-
-class QShaderNode
-{
-public:
- enum Type : char {
- Invalid,
- Input,
- Output,
- Function
- };
-
- class Rule
- {
- public:
- Q_GUI_EXPORT Rule(const QByteArray &substitution = QByteArray(), const QByteArrayList &headerSnippets = QByteArrayList()) noexcept;
-
- QByteArray substitution;
- QByteArrayList headerSnippets;
- };
-
- Q_GUI_EXPORT Type type() const noexcept;
-
- Q_GUI_EXPORT QUuid uuid() const noexcept;
- Q_GUI_EXPORT void setUuid(const QUuid &uuid) noexcept;
-
- Q_GUI_EXPORT QStringList layers() const noexcept;
- Q_GUI_EXPORT void setLayers(const QStringList &layers) noexcept;
-
- Q_GUI_EXPORT QList<QShaderNodePort> ports() const noexcept;
- Q_GUI_EXPORT void addPort(const QShaderNodePort &port);
- Q_GUI_EXPORT void removePort(const QShaderNodePort &port);
-
- Q_GUI_EXPORT QStringList parameterNames() const;
- Q_GUI_EXPORT QVariant parameter(const QString &name) const;
- Q_GUI_EXPORT void setParameter(const QString &name, const QVariant &value);
- Q_GUI_EXPORT void clearParameter(const QString &name);
-
- Q_GUI_EXPORT void addRule(const QShaderFormat &format, const Rule &rule);
- Q_GUI_EXPORT void removeRule(const QShaderFormat &format);
-
- Q_GUI_EXPORT QList<QShaderFormat> availableFormats() const;
- Q_GUI_EXPORT Rule rule(const QShaderFormat &format) const;
-
-private:
- QUuid m_uuid;
- QStringList m_layers;
- QList<QShaderNodePort> m_ports;
- QHash<QString, QVariant> m_parameters;
- QList<QPair<QShaderFormat, QShaderNode::Rule>> m_rules;
-};
-
-Q_GUI_EXPORT bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept;
-
-inline bool operator!=(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-Q_DECLARE_TYPEINFO(QShaderNode, Q_RELOCATABLE_TYPE);
-Q_DECLARE_TYPEINFO(QShaderNode::Rule, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QShaderNode)
-Q_DECLARE_METATYPE(QShaderNode::Rule)
-
-#endif // QSHADERNODE_P_H
diff --git a/src/gui/util/qshadernodeport.cpp b/src/gui/util/qshadernodeport.cpp
deleted file mode 100644
index 15dbc4160e..0000000000
--- a/src/gui/util/qshadernodeport.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qshadernodeport_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QShaderNodePort::QShaderNodePort() noexcept
- : direction(Output)
-{
-}
-
-bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept
-{
- return lhs.direction == rhs.direction
- && lhs.name == rhs.name;
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernodeport_p.h b/src/gui/util/qshadernodeport_p.h
deleted file mode 100644
index e4e11f6826..0000000000
--- a/src/gui/util/qshadernodeport_p.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHADERNODEPORT_P_H
-#define QSHADERNODEPORT_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#include <QtCore/qstring.h>
-#include <QtCore/qvariant.h>
-
-QT_BEGIN_NAMESPACE
-
-class QShaderNodePort
-{
-public:
- enum Direction : char {
- Input,
- Output
- };
-
- Q_GUI_EXPORT QShaderNodePort() noexcept;
-
- QShaderNodePort::Direction direction;
- QString name;
-};
-
-Q_GUI_EXPORT bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept;
-
-inline bool operator!=(const QShaderNodePort &lhs, const QShaderNodePort &rhs) noexcept
-{
- return !(lhs == rhs);
-}
-
-Q_DECLARE_TYPEINFO(QShaderNodePort, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QShaderNodePort)
-
-#endif // QSHADERNODEPORT_P_H
diff --git a/src/gui/util/qshadernodesloader.cpp b/src/gui/util/qshadernodesloader.cpp
deleted file mode 100644
index db1755e33a..0000000000
--- a/src/gui/util/qshadernodesloader.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qshadernodesloader_p.h"
-
-#include <QtCore/qdebug.h>
-#include <QtCore/qiodevice.h>
-#include <QtCore/qjsonarray.h>
-#include <QtCore/qjsondocument.h>
-#include <QtCore/qjsonobject.h>
-#include <QtCore/qmetaobject.h>
-
-QT_BEGIN_NAMESPACE
-
-QShaderNodesLoader::QShaderNodesLoader() noexcept
- : m_status(Null),
- m_device(nullptr)
-{
-}
-
-QShaderNodesLoader::Status QShaderNodesLoader::status() const noexcept
-{
- return m_status;
-}
-
-QHash<QString, QShaderNode> QShaderNodesLoader::nodes() const noexcept
-{
- return m_nodes;
-}
-
-QIODevice *QShaderNodesLoader::device() const noexcept
-{
- return m_device;
-}
-
-void QShaderNodesLoader::setDevice(QIODevice *device) noexcept
-{
- m_device = device;
- m_nodes.clear();
- m_status = !m_device ? Null
- : (m_device->openMode() & QIODevice::ReadOnly) ? Waiting
- : Error;
-}
-
-void QShaderNodesLoader::load()
-{
- if (m_status == Error)
- return;
-
- auto error = QJsonParseError();
- const QJsonDocument document = QJsonDocument::fromJson(m_device->readAll(), &error);
-
- if (error.error != QJsonParseError::NoError) {
- qWarning() << "Invalid JSON document:" << error.errorString();
- m_status = Error;
- return;
- }
-
- if (document.isEmpty() || !document.isObject()) {
- qWarning() << "Invalid JSON document, root should be an object";
- m_status = Error;
- return;
- }
-
- const QJsonObject root = document.object();
- load(root);
-}
-
-void QShaderNodesLoader::load(const QJsonObject &prototypesObject)
-{
- bool hasError = false;
-
- for (const QString &property : prototypesObject.keys()) {
- const QJsonValue nodeValue = prototypesObject.value(property);
- if (!nodeValue.isObject()) {
- qWarning() << "Invalid node found";
- hasError = true;
- break;
- }
-
- const QJsonObject nodeObject = nodeValue.toObject();
-
- auto node = QShaderNode();
-
- const QJsonValue inputsValue = nodeObject.value(QStringLiteral("inputs"));
- if (inputsValue.isArray()) {
- const QJsonArray inputsArray = inputsValue.toArray();
- for (const QJsonValue inputValue : inputsArray) {
- if (!inputValue.isString()) {
- qWarning() << "Non-string value in inputs";
- hasError = true;
- break;
- }
-
- auto input = QShaderNodePort();
- input.direction = QShaderNodePort::Input;
- input.name = inputValue.toString();
- node.addPort(input);
- }
- }
-
- const QJsonValue outputsValue = nodeObject.value(QStringLiteral("outputs"));
- if (outputsValue.isArray()) {
- const QJsonArray outputsArray = outputsValue.toArray();
- for (const QJsonValue outputValue : outputsArray) {
- if (!outputValue.isString()) {
- qWarning() << "Non-string value in outputs";
- hasError = true;
- break;
- }
-
- auto output = QShaderNodePort();
- output.direction = QShaderNodePort::Output;
- output.name = outputValue.toString();
- node.addPort(output);
- }
- }
-
- const QJsonValue parametersValue = nodeObject.value(QStringLiteral("parameters"));
- if (parametersValue.isObject()) {
- const QJsonObject parametersObject = parametersValue.toObject();
- for (const QString &parameterName : parametersObject.keys()) {
- const QJsonValue parameterValue = parametersObject.value(parameterName);
- if (parameterValue.isObject()) {
- const QJsonObject parameterObject = parameterValue.toObject();
- const QString type = parameterObject.value(QStringLiteral("type")).toString();
- const auto metaType = QMetaType::fromName(type.toUtf8());
-
- const QString value = parameterObject.value(QStringLiteral("value")).toString();
- auto variant = QVariant(value);
-
- if (metaType.flags() & QMetaType::IsEnumeration) {
- const QMetaObject *metaObject = metaType.metaObject();
- const char *className = metaObject->className();
- const QByteArray enumName = type.mid(static_cast<int>(qstrlen(className)) + 2).toUtf8();
- const QMetaEnum metaEnum = metaObject->enumerator(metaObject->indexOfEnumerator(enumName));
- const int enumValue = metaEnum.keyToValue(value.toUtf8());
- variant = QVariant(enumValue);
- variant.convert(metaType);
- } else {
- variant.convert(metaType);
- }
- node.setParameter(parameterName, variant);
- } else {
- node.setParameter(parameterName, parameterValue.toVariant());
- }
- }
- }
-
- const QJsonValue rulesValue = nodeObject.value(QStringLiteral("rules"));
- if (rulesValue.isArray()) {
- const QJsonArray rulesArray = rulesValue.toArray();
- for (const QJsonValue ruleValue : rulesArray) {
- if (!ruleValue.isObject()) {
- qWarning() << "Rules should be objects";
- hasError = true;
- break;
- }
-
- const QJsonObject ruleObject = ruleValue.toObject();
-
- const QJsonValue formatValue = ruleObject.value(QStringLiteral("format"));
- if (!formatValue.isObject()) {
- qWarning() << "Format is mandatory in rules and should be an object";
- hasError = true;
- break;
- }
-
- const QJsonObject formatObject = formatValue.toObject();
- auto format = QShaderFormat();
-
- const QJsonValue apiValue = formatObject.value(QStringLiteral("api"));
- if (!apiValue.isString()) {
- qWarning() << "Format API must be a string";
- hasError = true;
- break;
- }
-
- const QString api = apiValue.toString();
- format.setApi(api == QStringLiteral("OpenGLES") ? QShaderFormat::OpenGLES
- : api == QStringLiteral("OpenGLNoProfile") ? QShaderFormat::OpenGLNoProfile
- : api == QStringLiteral("OpenGLCoreProfile") ? QShaderFormat::OpenGLCoreProfile
- : api == QStringLiteral("OpenGLCompatibilityProfile") ? QShaderFormat::OpenGLCompatibilityProfile
- : api == QStringLiteral("VulkanFlavoredGLSL") ? QShaderFormat::VulkanFlavoredGLSL
- : QShaderFormat::NoApi);
- if (format.api() == QShaderFormat::NoApi) {
- qWarning() << "Format API must be one of: OpenGLES, OpenGLNoProfile, OpenGLCoreProfile or OpenGLCompatibilityProfile, VulkanFlavoredGLSL";
- hasError = true;
- break;
- }
-
- const QJsonValue majorValue = formatObject.value(QStringLiteral("major"));
- const QJsonValue minorValue = formatObject.value(QStringLiteral("minor"));
- if (!majorValue.isDouble() || !minorValue.isDouble()) {
- qWarning() << "Format major and minor version must be values";
- hasError = true;
- break;
- }
- format.setVersion(QVersionNumber(majorValue.toInt(), minorValue.toInt()));
-
- const QJsonValue extensionsValue = formatObject.value(QStringLiteral("extensions"));
- const QJsonArray extensionsArray = extensionsValue.toArray();
- auto extensions = QStringList();
- std::transform(extensionsArray.constBegin(), extensionsArray.constEnd(),
- std::back_inserter(extensions),
- [] (const QJsonValue &extensionValue) { return extensionValue.toString(); });
- format.setExtensions(extensions);
-
- const QString vendor = formatObject.value(QStringLiteral("vendor")).toString();
- format.setVendor(vendor);
-
- const QJsonValue substitutionValue = ruleObject.value(QStringLiteral("substitution"));
- if (!substitutionValue.isString()) {
- qWarning() << "Substitution needs to be a string";
- hasError = true;
- break;
- }
-
- // We default out to a Fragment ShaderType if nothing is specified
- // as that was the initial behavior we introduced
- const QString shaderType = formatObject.value(QStringLiteral("shaderType")).toString();
- format.setShaderType(shaderType == QStringLiteral("Fragment") ? QShaderFormat::Fragment
- : shaderType == QStringLiteral("Vertex") ? QShaderFormat::Vertex
- : shaderType == QStringLiteral("TessellationControl") ? QShaderFormat::TessellationControl
- : shaderType == QStringLiteral("TessellationEvaluation") ? QShaderFormat::TessellationEvaluation
- : shaderType == QStringLiteral("Geometry") ? QShaderFormat::Geometry
- : shaderType == QStringLiteral("Compute") ? QShaderFormat::Compute
- : QShaderFormat::Fragment);
-
- const QByteArray substitution = substitutionValue.toString().toUtf8();
-
- const QJsonValue snippetsValue = ruleObject.value(QStringLiteral("headerSnippets"));
- const QJsonArray snippetsArray = snippetsValue.toArray();
- auto snippets = QByteArrayList();
- std::transform(snippetsArray.constBegin(), snippetsArray.constEnd(),
- std::back_inserter(snippets),
- [] (const QJsonValue &snippetValue) { return snippetValue.toString().toUtf8(); });
-
- node.addRule(format, QShaderNode::Rule(substitution, snippets));
- }
- }
-
- m_nodes.insert(property, node);
- }
-
- if (hasError) {
- m_status = Error;
- m_nodes.clear();
- } else {
- m_status = Ready;
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernodesloader_p.h b/src/gui/util/qshadernodesloader_p.h
deleted file mode 100644
index 8afdd294ca..0000000000
--- a/src/gui/util/qshadernodesloader_p.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSHADERNODESLOADER_P_H
-#define QSHADERNODESLOADER_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtGui/private/qtguiglobal_p.h>
-
-#include <QtGui/private/qshadergraph_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QIODevice;
-
-class QShaderNodesLoader
-{
-public:
- enum Status : char {
- Null,
- Waiting,
- Ready,
- Error
- };
-
- Q_GUI_EXPORT QShaderNodesLoader() noexcept;
-
- Q_GUI_EXPORT Status status() const noexcept;
- Q_GUI_EXPORT QHash<QString, QShaderNode> nodes() const noexcept;
-
- Q_GUI_EXPORT QIODevice *device() const noexcept;
- Q_GUI_EXPORT void setDevice(QIODevice *device) noexcept;
-
- Q_GUI_EXPORT void load();
- Q_GUI_EXPORT void load(const QJsonObject &prototypesObject);
-
-private:
- Status m_status;
- QIODevice *m_device;
- QHash<QString, QShaderNode> m_nodes;
-};
-
-Q_DECLARE_TYPEINFO(QShaderNodesLoader, Q_RELOCATABLE_TYPE);
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QShaderNodesLoader)
-Q_DECLARE_METATYPE(QShaderNodesLoader::Status)
-
-#endif // QSHADERNODESLOADER_P_H
diff --git a/src/gui/util/qtexturefiledata.cpp b/src/gui/util/qtexturefiledata.cpp
index 6549206a26..e1fa900b84 100644
--- a/src/gui/util/qtexturefiledata.cpp
+++ b/src/gui/util/qtexturefiledata.cpp
@@ -1,44 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include "QtGui/qimage.h"
#include "qtexturefiledata_p.h"
-#include <QSize>
+#include <QtCore/qsize.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qmap.h>
QT_BEGIN_NAMESPACE
@@ -55,14 +22,17 @@ public:
QTextureFileDataPrivate(const QTextureFileDataPrivate &other)
: QSharedData(other),
+ mode(other.mode),
logName(other.logName),
data(other.data),
offsets(other.offsets),
lengths(other.lengths),
+ images(other.images),
size(other.size),
format(other.format),
numFaces(other.numFaces),
- numLevels(other.numLevels)
+ numLevels(other.numLevels),
+ keyValues(other.keyValues)
{
}
@@ -74,13 +44,18 @@ public:
{
numLevels = force ? levels : qMax(numLevels, levels);
numFaces = force ? faces : qMax(numFaces, faces);
-
- offsets.resize(numFaces);
- lengths.resize(numFaces);
-
- for (auto faceList : { &offsets, &lengths })
- for (auto &levelList : *faceList)
+ if (mode == QTextureFileData::ByteArrayMode) {
+ offsets.resize(numFaces);
+ lengths.resize(numFaces);
+
+ for (auto faceList : { &offsets, &lengths })
+ for (auto &levelList : *faceList)
+ levelList.resize(numLevels);
+ } else {
+ images.resize(numFaces);
+ for (auto &levelList : images)
levelList.resize(numLevels);
+ }
}
bool isValid(int level, int face) const { return level < numLevels && face < numFaces; }
@@ -90,10 +65,12 @@ public:
int getLength(int level, int face) const { return lengths[face][level]; }
void setLength(int value, int level, int face) { lengths[face][level] = value; }
+ QTextureFileData::Mode mode = QTextureFileData::ByteArrayMode;
QByteArray logName;
QByteArray data;
QVarLengthArray<QList<int>, MAX_FACES> offsets; // [Face][Level] = offset
QVarLengthArray<QList<int>, MAX_FACES> lengths; // [Face][Level] = length
+ QVarLengthArray<QList<QImage>, MAX_FACES> images; // [Face][Level] = length
QSize size;
quint32 format = 0;
quint32 internalFormat = 0;
@@ -103,8 +80,10 @@ public:
QMap<QByteArray, QByteArray> keyValues;
};
-QTextureFileData::QTextureFileData()
+QTextureFileData::QTextureFileData(Mode mode)
{
+ d = new QTextureFileDataPrivate;
+ d->mode = mode;
}
QTextureFileData::QTextureFileData(const QTextureFileData &other)
@@ -132,11 +111,14 @@ bool QTextureFileData::isValid() const
if (!d)
return false;
+ if (d->mode == ImageMode)
+ return true; // Manually populated: the caller needs to do verification at that time.
+
if (d->data.isEmpty() || d->size.isEmpty() || (!d->format && !d->internalFormat))
return false;
- const int numFacesOffset = d->offsets.length();
- const int numFacesLength = d->lengths.length();
+ const int numFacesOffset = d->offsets.size();
+ const int numFacesLength = d->lengths.size();
if (numFacesOffset == 0 || numFacesLength == 0 || d->numFaces != numFacesOffset
|| d->numFaces != numFacesLength)
return false;
@@ -173,19 +155,26 @@ QByteArray QTextureFileData::data() const
void QTextureFileData::setData(const QByteArray &data)
{
- if (!d.constData()) //### uh think about this design, this is the only way to create; should be constructor instead at least
- d = new QTextureFileDataPrivate;
-
+ Q_ASSERT(d->mode == ByteArrayMode);
d->data = data;
}
+void QTextureFileData::setData(const QImage &image, int level, int face)
+{
+ Q_ASSERT(d->mode == ImageMode);
+ d->ensureSize(level + 1, face + 1);
+ d->images[face][level] = image;
+}
+
int QTextureFileData::dataOffset(int level, int face) const
{
+ Q_ASSERT(d->mode == ByteArrayMode);
return (d && d->isValid(level, face)) ? d->getOffset(level, face) : 0;
}
void QTextureFileData::setDataOffset(int offset, int level, int face)
{
+ Q_ASSERT(d->mode == ByteArrayMode);
if (d.constData() && level >= 0) {
d->ensureSize(level + 1, face + 1);
d->setOffset(offset, level, face);
@@ -194,22 +183,31 @@ void QTextureFileData::setDataOffset(int offset, int level, int face)
int QTextureFileData::dataLength(int level, int face) const
{
+ Q_ASSERT(d->mode == ByteArrayMode);
return (d && d->isValid(level, face)) ? d->getLength(level, face) : 0;
}
QByteArrayView QTextureFileData::getDataView(int level, int face) const
{
- const int dataLength = this->dataLength(level, face);
- const int dataOffset = this->dataOffset(level, face);
+ if (d->mode == ByteArrayMode) {
+ const int dataLength = this->dataLength(level, face);
+ const int dataOffset = this->dataOffset(level, face);
- if (d == nullptr || dataLength == 0)
- return QByteArrayView();
+ if (d == nullptr || dataLength == 0)
+ return QByteArrayView();
- return QByteArrayView(d->data.constData() + dataOffset, dataLength);
+ return QByteArrayView(d->data.constData() + dataOffset, dataLength);
+ } else {
+ if (!d->isValid(level, face))
+ return QByteArrayView();
+ const QImage &img = d->images[face][level];
+ return img.isNull() ? QByteArrayView() : QByteArrayView(img.constBits(), img.sizeInBytes());
+ }
}
void QTextureFileData::setDataLength(int length, int level, int face)
{
+ Q_ASSERT(d->mode == ByteArrayMode);
if (d.constData() && level >= 0) {
d->ensureSize(level + 1, face + 1);
d->setLength(length, level, face);
@@ -320,9 +318,11 @@ QDebug operator<<(QDebug dbg, const QTextureFileData &d)
dbg << "glInternalFormat:" << glFormatName(d.glInternalFormat());
dbg << "glBaseInternalFormat:" << glFormatName(d.glBaseInternalFormat());
dbg.nospace() << "Levels: " << d.numLevels();
+ dbg.nospace() << "Faces: " << d.numFaces();
if (!d.isValid())
dbg << " {Invalid}";
dbg << ")";
+ dbg << (d.d->mode ? "[bytearray-based]" : "[image-based]");
} else {
dbg << "null)";
}
diff --git a/src/gui/util/qtexturefiledata_p.h b/src/gui/util/qtexturefiledata_p.h
index e553733d69..cd0dbe171c 100644
--- a/src/gui/util/qtexturefiledata_p.h
+++ b/src/gui/util/qtexturefiledata_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTUREFILEDATA_P_H
#define QTEXTUREFILEDATA_P_H
@@ -55,6 +19,7 @@
#include <QSharedDataPointer>
#include <QLoggingCategory>
#include <QDebug>
+#include <private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -65,7 +30,9 @@ class QTextureFileDataPrivate;
class Q_GUI_EXPORT QTextureFileData
{
public:
- QTextureFileData();
+ enum Mode { ByteArrayMode, ImageMode };
+
+ QTextureFileData(Mode mode = ByteArrayMode);
QTextureFileData(const QTextureFileData &other);
QTextureFileData &operator=(const QTextureFileData &other);
~QTextureFileData();
@@ -77,6 +44,7 @@ public:
QByteArray data() const;
void setData(const QByteArray &data);
+ void setData(const QImage &image, int level = 0, int face = 0);
int dataOffset(int level = 0, int face = 0) const;
void setDataOffset(int offset, int level = 0, int face = 0);
@@ -112,6 +80,7 @@ public:
private:
QSharedDataPointer<QTextureFileDataPrivate> d;
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QTextureFileData &d);
};
Q_DECLARE_TYPEINFO(QTextureFileData, Q_RELOCATABLE_TYPE);
diff --git a/src/gui/util/qtexturefilehandler_p.h b/src/gui/util/qtexturefilehandler_p.h
index 3d4f42526f..9fb3130f0b 100644
--- a/src/gui/util/qtexturefilehandler_p.h
+++ b/src/gui/util/qtexturefilehandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTUREFILEHANDLER_P_H
#define QTEXTUREFILEHANDLER_P_H
@@ -63,7 +27,7 @@ public:
{
m_logName = !logName.isEmpty() ? logName : QByteArrayLiteral("(unknown)");
}
- virtual ~QTextureFileHandler() {}
+ virtual ~QTextureFileHandler();
virtual QTextureFileData read() = 0;
QIODevice *device() const { return m_device; }
diff --git a/src/gui/util/qtexturefilereader.cpp b/src/gui/util/qtexturefilereader.cpp
index fefb957323..596c30d2f7 100644
--- a/src/gui/util/qtexturefilereader.cpp
+++ b/src/gui/util/qtexturefilereader.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtexturefilereader_p.h"
@@ -47,6 +11,8 @@
QT_BEGIN_NAMESPACE
+QTextureFileHandler::~QTextureFileHandler() = default;
+
QTextureFileReader::QTextureFileReader(QIODevice *device, const QString &fileName)
: m_device(device), m_fileName(fileName)
{
diff --git a/src/gui/util/qtexturefilereader_p.h b/src/gui/util/qtexturefilereader_p.h
index 2ec0b0cc49..5f7b31ee32 100644
--- a/src/gui/util/qtexturefilereader_p.h
+++ b/src/gui/util/qtexturefilereader_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QTEXTUREFILEREADER_H
#define QTEXTUREFILEREADER_H
diff --git a/src/gui/util/qundogroup.cpp b/src/gui/util/qundogroup.cpp
index 6efebce94d..db5d009ca6 100644
--- a/src/gui/util/qundogroup.cpp
+++ b/src/gui/util/qundogroup.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qundogroup.h"
#include "qundostack.h"
diff --git a/src/gui/util/qundogroup.h b/src/gui/util/qundogroup.h
index ef5b053610..e92f4f46b0 100644
--- a/src/gui/util/qundogroup.h
+++ b/src/gui/util/qundogroup.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QUNDOGROUP_H
#define QUNDOGROUP_H
diff --git a/src/gui/util/qundostack.cpp b/src/gui/util/qundostack.cpp
index f5757c1704..403833d421 100644
--- a/src/gui/util/qundostack.cpp
+++ b/src/gui/util/qundostack.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qdebug.h>
#include "qundostack.h"
@@ -302,7 +266,7 @@ QString QUndoCommand::actionText() const
void QUndoCommand::setText(const QString &text)
{
- int cdpos = text.indexOf(QLatin1Char('\n'));
+ int cdpos = text.indexOf(u'\n');
if (cdpos > 0) {
d->text = text.left(cdpos);
d->actionText = text.mid(cdpos + 1);
@@ -322,7 +286,7 @@ void QUndoCommand::setText(const QString &text)
int QUndoCommand::childCount() const
{
- return d->child_list.count();
+ return d->child_list.size();
}
/*!
@@ -335,7 +299,7 @@ int QUndoCommand::childCount() const
const QUndoCommand *QUndoCommand::child(int index) const
{
- if (index < 0 || index >= d->child_list.count())
+ if (index < 0 || index >= d->child_list.size())
return nullptr;
return d->child_list.at(index);
}
@@ -480,10 +444,10 @@ void QUndoStackPrivate::setIndex(int idx, bool clean)
bool QUndoStackPrivate::checkUndoLimit()
{
- if (undo_limit <= 0 || !macro_stack.isEmpty() || undo_limit >= command_list.count())
+ if (undo_limit <= 0 || !macro_stack.isEmpty() || undo_limit >= command_list.size())
return false;
- int del_count = command_list.count() - undo_limit;
+ int del_count = command_list.size() - undo_limit;
for (int i = 0; i < del_count; ++i)
delete command_list.takeFirst();
@@ -1044,7 +1008,7 @@ void QUndoStackPrivate::setPrefixedText(QAction *action, const QString &prefix,
if (defaultText.isEmpty()) {
QString s = prefix;
if (!prefix.isEmpty() && !text.isEmpty())
- s.append(QLatin1Char(' '));
+ s.append(u' ');
s.append(text);
action->setText(s);
} else {
@@ -1178,7 +1142,7 @@ void QUndoStack::beginMacro(const QString &text)
}
d->macro_stack.append(cmd);
- if (d->macro_stack.count() == 1) {
+ if (d->macro_stack.size() == 1) {
emit canUndoChanged(false);
emit undoTextChanged(QString());
emit canRedoChanged(false);
@@ -1227,7 +1191,7 @@ const QUndoCommand *QUndoStack::command(int index) const
{
Q_D(const QUndoStack);
- if (index < 0 || index >= d->command_list.count())
+ if (index < 0 || index >= d->command_list.size())
return nullptr;
return d->command_list.at(index);
}
diff --git a/src/gui/util/qundostack.h b/src/gui/util/qundostack.h
index c137e7d942..7b18485509 100644
--- a/src/gui/util/qundostack.h
+++ b/src/gui/util/qundostack.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QUNDOSTACK_H
#define QUNDOSTACK_H
diff --git a/src/gui/util/qundostack_p.h b/src/gui/util/qundostack_p.h
index 5f2c438a83..d655d5fdf5 100644
--- a/src/gui/util/qundostack_p.h
+++ b/src/gui/util/qundostack_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QUNDOSTACK_P_H
#define QUNDOSTACK_P_H
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index f15057801b..2a81006657 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qdebug.h>
@@ -367,12 +331,12 @@ QIntValidator::~QIntValidator()
or is a prefix of an integer in the valid range, returns \l Intermediate.
Otherwise, returns \l Invalid.
- If the valid range consists of just positive integers (e.g., 32 to 100)
- and \a input is a negative integer, then Invalid is returned. (On the other
- hand, if the range consists of negative integers (e.g., -100 to -32) and
- \a input is a positive integer, then Intermediate is returned, because
- the user might be just about to type the minus (especially for right-to-left
- languages).
+ If the valid range consists of just positive integers (e.g., 32 to 100) and
+ \a input is a negative integer, then Invalid is returned. (On the other
+ hand, if the range consists of negative integers (e.g., -100 to -32) and \a
+ input is a positive integer without leading plus sign, then Intermediate is
+ returned, because the user might be just about to type the minus (especially
+ for right-to-left languages).
Similarly, if the valid range is between 46 and 53, then 41 and 59 will be
evaluated as \l Intermediate, as otherwise the user wouldn't be able to
@@ -398,34 +362,45 @@ static qlonglong pow10(int exp)
return result;
}
-QValidator::State QIntValidator::validate(QString & input, int&) const
+template <typename T> static inline
+std::optional<QValidator::State> initialResultCheck(T min, T max, const ParsingResult &result)
{
- QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1,
- locale().numberOptions())) {
- return Invalid;
- }
+ if (result.state == ParsingResult::Invalid)
+ return QValidator::Invalid;
+ const CharBuff &buff = result.buff;
if (buff.isEmpty())
- return Intermediate;
+ return QValidator::Intermediate;
- const bool startsWithMinus(buff[0] == '-');
- if (b >= 0 && startsWithMinus)
- return Invalid;
+ char ch = buff[0];
+ const bool signConflicts = (min >= 0 && ch == '-') || (max < 0 && ch == '+');
+ if (signConflicts)
+ return QValidator::Invalid;
- const bool startsWithPlus(buff[0] == '+');
- if (t < 0 && startsWithPlus)
- return Invalid;
+ if (result.state == ParsingResult::Intermediate)
+ return QValidator::Intermediate;
- if (buff.size() == 1 && (startsWithPlus || startsWithMinus))
- return Intermediate;
+ return std::nullopt;
+}
- bool ok;
- qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok);
- if (!ok)
+QValidator::State QIntValidator::validate(QString & input, int&) const
+{
+ ParsingResult result =
+ locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, -1,
+ locale().numberOptions());
+
+ std::optional<State> opt = initialResultCheck(b, t, result);
+ if (opt)
+ return *opt;
+
+ const CharBuff &buff = result.buff;
+ QSimpleParsedNumber r = QLocaleData::bytearrayToLongLong(buff, 10);
+ if (!r.ok())
return Invalid;
+ qint64 entered = r.result;
if (entered >= b && entered <= t) {
+ bool ok = false;
locale().toInt(input, &ok);
return ok ? Acceptable : Intermediate;
}
@@ -437,7 +412,7 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
// of a number of digits equal to or less than the max value as intermediate.
int buffLength = buff.size();
- if (startsWithPlus)
+ if (buff[0] == '+')
buffLength--;
const int tLength = t != 0 ? static_cast<int>(std::log10(qAbs(t))) + 1 : 1;
@@ -450,15 +425,15 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
/*! \reimp */
void QIntValidator::fixup(QString &input) const
{
- QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1,
- locale().numberOptions())) {
+ auto [parseState, buff] =
+ locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, -1,
+ locale().numberOptions());
+ if (parseState == ParsingResult::Invalid)
return;
- }
- bool ok;
- qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok);
- if (ok)
- input = locale().toString(entered);
+
+ QSimpleParsedNumber r = QLocaleData::bytearrayToLongLong(buff, 10);
+ if (r.ok())
+ input = locale().toString(r.result);
}
/*!
@@ -491,7 +466,7 @@ void QIntValidator::setRange(int bottom, int top)
\brief the validator's lowest acceptable value
By default, this property's value is derived from the lowest signed
- integer available (typically -2147483647).
+ integer available (-2147483648).
\sa setRange()
*/
@@ -505,7 +480,7 @@ void QIntValidator::setBottom(int bottom)
\brief the validator's highest acceptable value
By default, this property's value is derived from the highest signed
- integer available (typically 2147483647).
+ integer available (2147483647).
\sa setRange()
*/
@@ -543,6 +518,8 @@ public:
QDoubleValidator::Notation notation;
QValidator::State validateWithLocale(QString & input, QLocaleData::NumberMode numMode, const QLocale &locale) const;
+ void fixupWithLocale(QString &input, QLocaleData::NumberMode numMode,
+ const QLocale &locale) const;
};
@@ -554,8 +531,7 @@ public:
\inmodule QtGui
QDoubleValidator provides an upper bound, a lower bound, and a
- limit on the number of digits after the decimal point. It does not
- provide a fixup() function.
+ limit on the number of digits after the decimal point.
You can set the acceptable range in one call with setRange(), or
with setBottom() and setTop(). Set the number of decimal places
@@ -566,10 +542,11 @@ public:
in the German locale, "1,234" will be accepted as the fractional number
1.234. In Arabic locales, QDoubleValidator will accept Arabic digits.
- \note The QLocale::NumberOptions set on the locale() also affect the
- way the number is interpreted. For example, since QLocale::RejectGroupSeparator
- is not set by default, the validator will accept group separators. It is thus
- recommended to use QLocale::toDouble() to obtain the numeric value.
+ \note The QLocale::NumberOptions set on the locale() also affect the way the
+ number is interpreted. For example, since QLocale::RejectGroupSeparator is
+ not set by default (except on the \c "C" locale), the validator will accept
+ group separators. If the string passes validation, pass it to
+ locale().toDouble() to obtain its numeric value.
\sa QIntValidator, QRegularExpressionValidator, QLocale::toDouble(), {Line Edits Example}
*/
@@ -579,10 +556,23 @@ public:
\since 4.3
This enum defines the allowed notations for entering a double.
- \value StandardNotation The string is written as a standard number
- (i.e. 0.015).
- \value ScientificNotation The string is written in scientific
- form. It may have an exponent part(i.e. 1.5E-2).
+ \value StandardNotation The string is written in the standard format, a
+ whole number part optionally followed by a separator
+ and fractional part, for example \c{"0.015"}.
+
+ \value ScientificNotation The string is written in scientific form, which
+ optionally appends an exponent part to the
+ standard format, for example \c{"1.5E-2"}.
+
+ The whole number part may, as usual, include a sign. This, along with the
+ separators for fractional part, exponent and any digit-grouping, depend on
+ locale. QDoubleValidator doesn't check the placement (which would also
+ depend on locale) of any digit-grouping separators it finds, but it will
+ reject input that contains them if \l QLocale::RejectGroupSeparator is set
+ in \c locale().numberOptions().
+
+ \sa QLocale::numberOptions(), QLocale::decimalPoint(),
+ QLocale::exponential(), QLocale::negativeSign()
*/
/*!
@@ -590,8 +580,8 @@ public:
that accepts any double.
*/
-QDoubleValidator::QDoubleValidator(QObject * parent)
- : QDoubleValidator(-HUGE_VAL, HUGE_VAL, 1000, parent)
+QDoubleValidator::QDoubleValidator(QObject *parent)
+ : QDoubleValidator(-HUGE_VAL, HUGE_VAL, -1, parent)
{
}
@@ -624,14 +614,14 @@ QDoubleValidator::~QDoubleValidator()
/*!
\fn QValidator::State QDoubleValidator::validate(QString &input, int &pos) const
- Returns \l Acceptable if the string \a input contains a double
- that is within the valid range and is in the correct format.
+ Returns \l Acceptable if the string \a input is in the correct format and
+ contains a double within the valid range.
- Returns \l Intermediate if \a input contains a double that is
- outside the range or is in the wrong format; e.g. is empty.
+ Returns \l Intermediate if \a input is in the wrong format or contains a
+ double outside the range.
- Returns \l Invalid if the \a input is not a double or with too many
- digits after the decimal point.
+ Returns \l Invalid if the \a input doesn't represent a double or has too
+ many digits after the decimal point.
Note: If the valid range consists of just positive doubles (e.g. 0.0 to 100.0)
and \a input is a negative double then \l Invalid is returned. If notation()
@@ -667,24 +657,16 @@ QValidator::State QDoubleValidator::validate(QString & input, int &) const
QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QLocaleData::NumberMode numMode, const QLocale &locale) const
{
Q_Q(const QDoubleValidator);
- QByteArray buff;
- if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec, locale.numberOptions())) {
- return QValidator::Invalid;
- }
-
- if (buff.isEmpty())
- return QValidator::Intermediate;
+ ParsingResult result =
+ locale.d->m_data->validateChars(input, numMode, q->dec, locale.numberOptions());
- if (q->b >= 0 && buff.startsWith('-'))
- return QValidator::Invalid;
-
- if (q->t < 0 && buff.startsWith('+'))
- return QValidator::Invalid;
+ std::optional<QValidator::State> opt = initialResultCheck(q->b, q->t, result);
+ if (opt)
+ return *opt;
bool ok = false;
double i = locale.toDouble(input, &ok); // returns 0.0 if !ok
- if (i == qt_qnan())
- return QValidator::Invalid;
+ Q_ASSERT(!qIsNaN(i)); // Would be caught by validateChars()
if (!ok)
return QValidator::Intermediate;
@@ -694,7 +676,11 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL
if (notation == QDoubleValidator::StandardNotation) {
double max = qMax(qAbs(q->b), qAbs(q->t));
qlonglong v;
- if (convertDoubleTo(max, &v)) {
+ // Need a whole number to pass to convertDoubleTo() or it fails. Use
+ // floor, as max is positive so this has the same number of digits
+ // before the decimal point, where qCeil() might take us up to a power
+ // of ten, adding a digit.
+ if (convertDoubleTo(qFloor(max), &v)) {
qlonglong n = pow10(numDigits(v));
// In order to get the highest possible number in the intermediate
// range we need to get 10 to the power of the number of digits
@@ -713,9 +699,98 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL
}
/*!
+ \since 6.3
+ \overload
+
+ Attempts to fix the \a input string to an \l Acceptable representation of a
+ double.
+
+ The format of the number is determined by \l notation(), \l decimals(),
+ \l locale() and the latter's \l {QLocale::}{numberOptions()}.
+
+ To comply with \l notation(), when \l ScientificNotation is used, the fixed
+ value will be represented in its normalized form, which means that any
+ non-zero value will have one non-zero digit before the decimal point.
+
+ \snippet code/src_gui_util_qvalidator.cpp 7
+
+ To comply with \l decimals(), when it is \c {-1} the number of digits used
+ will be determined by \l QLocale::FloatingPointShortest. Otherwise, the
+ fractional part of the number is truncated (with rounding, as appropriate)
+ if its length exceeds \l decimals(). When \l notation() is
+ \l ScientificNotation this is done after the number has been put into its
+ normalized form.
+
+ \snippet code/src_gui_util_qvalidator.cpp 8
+
+ \note If \l decimals() is set to, and the string provides, more than
+ \c {std::numeric_limits<double>::digits10}, digits beyond that many in the
+ fractional part may be changed. The resulting string shall encode the same
+ floating-point number, when parsed to a \c double.
+*/
+void QDoubleValidator::fixup(QString &input) const
+{
+ Q_D(const QDoubleValidator);
+ const auto numberMode = d->notation == StandardNotation ? QLocaleData::DoubleStandardMode
+ : QLocaleData::DoubleScientificMode;
+
+ d->fixupWithLocale(input, numberMode, locale());
+}
+
+void QDoubleValidatorPrivate::fixupWithLocale(QString &input, QLocaleData::NumberMode numMode,
+ const QLocale &locale) const
+{
+ Q_Q(const QDoubleValidator);
+ // Passing -1 as the number of decimals, because fixup() exists to improve
+ // an Intermediate value, if it can.
+ auto [parseState, buff] =
+ locale.d->m_data->validateChars(input, numMode, -1, locale.numberOptions());
+ if (parseState == ParsingResult::Invalid)
+ return;
+
+ // buff contains data in C locale.
+ bool ok = false;
+ const double entered = QByteArrayView(buff).toDouble(&ok);
+ if (ok) {
+ // Here we need to adjust the output format accordingly
+ char mode;
+ if (numMode == QLocaleData::DoubleStandardMode) {
+ mode = 'f';
+ } else {
+ // scientific mode can be either 'e' or 'E'
+ mode = input.contains(QChar::fromLatin1('E')) ? 'E' : 'e';
+ }
+ int precision;
+ if (q->dec < 0) {
+ precision = QLocale::FloatingPointShortest;
+ } else {
+ if (mode == 'f') {
+ const auto decimalPointIndex = buff.indexOf('.');
+ precision = decimalPointIndex >= 0 ? buff.size() - decimalPointIndex - 1 : 0;
+ } else {
+ auto eIndex = buff.indexOf('e');
+ // No need to check for 'E' because we can get only 'e' after a
+ // call to validateChars()
+ if (eIndex < 0)
+ eIndex = buff.size();
+ precision = eIndex - (buff.contains('.') ? 1 : 0)
+ - (buff[0] == '-' || buff[0] == '+' ? 1 : 0);
+ }
+ // Use q->dec to limit the number of decimals, because we want the
+ // fixup() result to pass validate().
+ precision = qMin(precision, q->dec);
+ }
+ input = locale.toString(entered, mode, precision);
+ }
+}
+
+/*!
Sets the validator to accept doubles from \a minimum to \a maximum
inclusive, with at most \a decimals digits after the decimal
point.
+
+ \note Setting the number of decimals to -1 effectively sets it to unlimited.
+ This is also the value used by a default-constructed validator.
*/
void QDoubleValidator::setRange(double minimum, double maximum, int decimals)
@@ -743,6 +818,17 @@ void QDoubleValidator::setRange(double minimum, double maximum, int decimals)
}
/*!
+ \overload
+
+ Sets the validator to accept doubles from \a minimum to \a maximum
+ inclusive without changing the number of digits after the decimal point.
+*/
+void QDoubleValidator::setRange(double minimum, double maximum)
+{
+ setRange(minimum, maximum, decimals());
+}
+
+/*!
\property QDoubleValidator::bottom
\brief the validator's minimum acceptable value
@@ -775,7 +861,8 @@ void QDoubleValidator::setTop(double top)
\property QDoubleValidator::decimals
\brief the validator's maximum number of digits after the decimal point
- By default, this property contains a value of 1000.
+ By default, this property contains a value of -1, which means any number
+ of digits is accepted.
\sa setRange()
*/
@@ -815,6 +902,7 @@ QDoubleValidator::Notation QDoubleValidator::notation() const
/*!
\class QRegularExpressionValidator
+ \inmodule QtGui
\brief The QRegularExpressionValidator class is used to check a string
against a regular expression.
@@ -966,4 +1054,6 @@ void QRegularExpressionValidatorPrivate::setRegularExpression(const QRegularExpr
QT_END_NAMESPACE
+#include "moc_qvalidator.cpp"
+
#endif // QT_NO_VALIDATOR
diff --git a/src/gui/util/qvalidator.h b/src/gui/util/qvalidator.h
index 7e72a60f24..cd757c612d 100644
--- a/src/gui/util/qvalidator.h
+++ b/src/gui/util/qvalidator.h
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVALIDATOR_H
#define QVALIDATOR_H
@@ -140,8 +104,10 @@ public:
};
Q_ENUM(Notation)
QValidator::State validate(QString &, int &) const override;
+ void fixup(QString &input) const override;
- void setRange(double bottom, double top, int decimals = 0);
+ void setRange(double bottom, double top, int decimals);
+ void setRange(double bottom, double top);
void setBottom(double);
void setTop(double);
void setDecimals(int);
diff --git a/src/gui/vulkan/LICENSE.txt b/src/gui/vulkan/LICENSE.txt
index 561385ab46..21dd179fc9 100644
--- a/src/gui/vulkan/LICENSE.txt
+++ b/src/gui/vulkan/LICENSE.txt
@@ -17,3 +17,67 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+
+
+
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+ 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+ 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+ 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+ (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+ (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+ (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+ (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+ 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+ 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+ 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+ 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+ 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/src/gui/vulkan/generated_header.txt b/src/gui/vulkan/generated_header.txt
deleted file mode 100644
index 78222bf040..0000000000
--- a/src/gui/vulkan/generated_header.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
diff --git a/src/gui/vulkan/licenseheader.h.in b/src/gui/vulkan/licenseheader.h.in
new file mode 100644
index 0000000000..3b6a0ea72a
--- /dev/null
+++ b/src/gui/vulkan/licenseheader.h.in
@@ -0,0 +1,2 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
diff --git a/src/gui/vulkan/qbasicvulkanplatforminstance.cpp b/src/gui/vulkan/qbasicvulkanplatforminstance.cpp
index 233f884ce6..bbe9f9e1cb 100644
--- a/src/gui/vulkan/qbasicvulkanplatforminstance.cpp
+++ b/src/gui/vulkan/qbasicvulkanplatforminstance.cpp
@@ -1,46 +1,11 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbasicvulkanplatforminstance_p.h"
#include <QCoreApplication>
#include <QList>
#include <QLoggingCategory>
+#include <QVarLengthArray>
QT_BEGIN_NAMESPACE
@@ -61,11 +26,6 @@ Q_LOGGING_CATEGORY(lcPlatVk, "qt.vulkan")
*/
QBasicPlatformVulkanInstance::QBasicPlatformVulkanInstance()
- : m_vkInst(VK_NULL_HANDLE),
- m_vkGetInstanceProcAddr(nullptr),
- m_ownsVkInst(false),
- m_errorCode(VK_SUCCESS),
- m_debugCallback(VK_NULL_HANDLE)
{
}
@@ -74,26 +34,54 @@ QBasicPlatformVulkanInstance::~QBasicPlatformVulkanInstance()
if (!m_vkInst)
return;
- if (m_debugCallback && m_vkDestroyDebugReportCallbackEXT)
- m_vkDestroyDebugReportCallbackEXT(m_vkInst, m_debugCallback, nullptr);
+#ifdef VK_EXT_debug_utils
+ if (m_debugMessenger)
+ m_vkDestroyDebugUtilsMessengerEXT(m_vkInst, m_debugMessenger, nullptr);
+#endif
if (m_ownsVkInst)
m_vkDestroyInstance(m_vkInst, nullptr);
}
-void QBasicPlatformVulkanInstance::loadVulkanLibrary(const QString &defaultLibraryName)
+void QBasicPlatformVulkanInstance::loadVulkanLibrary(const QString &defaultLibraryName, int defaultLibraryVersion)
{
+ QVarLengthArray<std::pair<QString, int>, 3> loadList;
+
+ // First in the list of libraries to try is the manual override, relevant on
+ // embedded systems without a Vulkan loader and possibly with custom vendor
+ // library names.
if (qEnvironmentVariableIsSet("QT_VULKAN_LIB"))
- m_vulkanLib.setFileName(QString::fromUtf8(qgetenv("QT_VULKAN_LIB")));
- else
- m_vulkanLib.setFileName(defaultLibraryName);
+ loadList.append({ QString::fromUtf8(qgetenv("QT_VULKAN_LIB")), -1 });
+
+ // Then what the platform specified. On Linux the version is likely 1, thus
+ // preferring libvulkan.so.1 over libvulkan.so.
+ loadList.append({ defaultLibraryName, defaultLibraryVersion });
+
+ // If there was a version given, we must still try without it if the first
+ // attempt fails, so that libvulkan.so is picked up if the .so.1 is not
+ // present on the system (so loaderless embedded systems still work).
+ if (defaultLibraryVersion >= 0)
+ loadList.append({ defaultLibraryName, -1 });
+
+ bool ok = false;
+ for (const auto &lib : loadList) {
+ m_vulkanLib.reset(new QLibrary);
+ if (lib.second >= 0)
+ m_vulkanLib->setFileNameAndVersion(lib.first, lib.second);
+ else
+ m_vulkanLib->setFileName(lib.first);
+ if (m_vulkanLib->load()) {
+ ok = true;
+ break;
+ }
+ }
- if (!m_vulkanLib.load()) {
- qWarning("Failed to load %s: %s", qPrintable(m_vulkanLib.fileName()), qPrintable(m_vulkanLib.errorString()));
+ if (!ok) {
+ qWarning("Failed to load %s: %s", qPrintable(m_vulkanLib->fileName()), qPrintable(m_vulkanLib->errorString()));
return;
}
- init(&m_vulkanLib);
+ init(m_vulkanLib.get());
}
void QBasicPlatformVulkanInstance::init(QLibrary *lib)
@@ -159,7 +147,7 @@ void QBasicPlatformVulkanInstance::init(QLibrary *lib)
QList<VkLayerProperties> layerProps(layerCount);
m_vkEnumerateInstanceLayerProperties(&layerCount, layerProps.data());
m_supportedLayers.reserve(layerCount);
- for (const VkLayerProperties &p : qAsConst(layerProps)) {
+ for (const VkLayerProperties &p : std::as_const(layerProps)) {
QVulkanLayer layer;
layer.name = p.layerName;
layer.version = p.implementationVersion;
@@ -178,7 +166,7 @@ void QBasicPlatformVulkanInstance::init(QLibrary *lib)
QList<VkExtensionProperties> extProps(extCount);
m_vkEnumerateInstanceExtensionProperties(nullptr, &extCount, extProps.data());
m_supportedExtensions.reserve(extCount);
- for (const VkExtensionProperties &p : qAsConst(extProps)) {
+ for (const VkExtensionProperties &p : std::as_const(extProps)) {
QVulkanExtension ext;
ext.name = p.extensionName;
ext.version = p.specVersion;
@@ -217,8 +205,7 @@ void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const
m_enabledExtensions = instance->extensions();
if (!m_vkInst) {
- VkApplicationInfo appInfo;
- memset(&appInfo, 0, sizeof(appInfo));
+ VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
QByteArray appName = QCoreApplication::applicationName().toUtf8();
appInfo.pApplicationName = appName.constData();
@@ -229,10 +216,11 @@ void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const
apiVersion.microVersion());
}
- if (!flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))
- m_enabledExtensions.append("VK_EXT_debug_report");
-
m_enabledExtensions.append("VK_KHR_surface");
+ if (!flags.testFlag(QVulkanInstance::NoPortabilityDrivers))
+ m_enabledExtensions.append("VK_KHR_portability_enumeration");
+ if (!flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))
+ m_enabledExtensions.append("VK_EXT_debug_utils");
for (const QByteArray &ext : extraExts)
m_enabledExtensions.append(ext);
@@ -255,37 +243,43 @@ void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const
// No clever stuff with QSet and friends: the order for layers matters
// and the user-provided order must be kept.
- for (int i = 0; i < m_enabledLayers.count(); ++i) {
+ for (int i = 0; i < m_enabledLayers.size(); ++i) {
const QByteArray &layerName(m_enabledLayers[i]);
if (!m_supportedLayers.contains(layerName))
m_enabledLayers.removeAt(i--);
}
qDebug(lcPlatVk) << "Enabling Vulkan instance layers:" << m_enabledLayers;
- for (int i = 0; i < m_enabledExtensions.count(); ++i) {
+ for (int i = 0; i < m_enabledExtensions.size(); ++i) {
const QByteArray &extName(m_enabledExtensions[i]);
if (!m_supportedExtensions.contains(extName))
m_enabledExtensions.removeAt(i--);
}
qDebug(lcPlatVk) << "Enabling Vulkan instance extensions:" << m_enabledExtensions;
- VkInstanceCreateInfo instInfo;
- memset(&instInfo, 0, sizeof(instInfo));
+ VkInstanceCreateInfo instInfo = {};
instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instInfo.pApplicationInfo = &appInfo;
+ if (!flags.testFlag(QVulkanInstance::NoPortabilityDrivers)) {
+ // With old Vulkan SDKs setting a non-zero flags gives a validation error.
+ // Whereas from 1.3.216 on the portability bit is required for MoltenVK to function.
+ // Hence the version check.
+ if (m_supportedApiVersion >= QVersionNumber(1, 3, 216))
+ instInfo.flags |= 0x00000001; // VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR
+ }
QList<const char *> layerNameVec;
- for (const QByteArray &ba : qAsConst(m_enabledLayers))
+ for (const QByteArray &ba : std::as_const(m_enabledLayers))
layerNameVec.append(ba.constData());
if (!layerNameVec.isEmpty()) {
- instInfo.enabledLayerCount = layerNameVec.count();
+ instInfo.enabledLayerCount = layerNameVec.size();
instInfo.ppEnabledLayerNames = layerNameVec.constData();
}
QList<const char *> extNameVec;
- for (const QByteArray &ba : qAsConst(m_enabledExtensions))
+ for (const QByteArray &ba : std::as_const(m_enabledExtensions))
extNameVec.append(ba.constData());
if (!extNameVec.isEmpty()) {
- instInfo.enabledExtensionCount = extNameVec.count();
+ instInfo.enabledExtensionCount = extNameVec.size();
instInfo.ppEnabledExtensionNames = extNameVec.constData();
}
@@ -374,55 +368,93 @@ void QBasicPlatformVulkanInstance::setDebugFilters(const QList<QVulkanInstance::
m_debugFilters = filters;
}
+void QBasicPlatformVulkanInstance::setDebugUtilsFilters(const QList<QVulkanInstance::DebugUtilsFilter> &filters)
+{
+ m_debugUtilsFilters = filters;
+}
+
void QBasicPlatformVulkanInstance::destroySurface(VkSurfaceKHR surface) const
{
if (m_destroySurface && surface)
m_destroySurface(m_vkInst, surface, nullptr);
}
-static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT objectType,
- uint64_t object,
- size_t location,
- int32_t messageCode,
- const char *pLayerPrefix,
- const char *pMessage,
+#ifdef VK_EXT_debug_utils
+static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
+ VkDebugUtilsMessageTypeFlagsEXT messageType,
+ const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
void *pUserData)
{
QBasicPlatformVulkanInstance *self = static_cast<QBasicPlatformVulkanInstance *>(pUserData);
+
+ // legacy filters
for (QVulkanInstance::DebugFilter filter : *self->debugFilters()) {
- if (filter(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage))
+ // As per docs in qvulkaninstance.cpp we pass object, messageCode,
+ // pMessage to the callback with the legacy signature.
+ uint64_t object = 0;
+ if (pCallbackData->objectCount > 0)
+ object = pCallbackData->pObjects[0].objectHandle;
+ if (filter(0, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, object, 0,
+ pCallbackData->messageIdNumber, "", pCallbackData->pMessage))
+ {
+ return VK_FALSE;
+ }
+ }
+
+ // filters with new signature
+ for (QVulkanInstance::DebugUtilsFilter filter : *self->debugUtilsFilters()) {
+ QVulkanInstance::DebugMessageSeverityFlags severity;
+ if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT)
+ severity |= QVulkanInstance::VerboseSeverity;
+ if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT)
+ severity |= QVulkanInstance::InfoSeverity;
+ if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
+ severity |= QVulkanInstance::WarningSeverity;
+ if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
+ severity |= QVulkanInstance::ErrorSeverity;
+ QVulkanInstance::DebugMessageTypeFlags type;
+ if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT)
+ type |= QVulkanInstance::GeneralMessage;
+ if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT)
+ type |= QVulkanInstance::ValidationMessage;
+ if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)
+ type |= QVulkanInstance::PerformanceMessage;
+ if (filter(severity, type, pCallbackData))
return VK_FALSE;
}
// not categorized, just route to plain old qDebug
- qDebug("vkDebug: %s: %d: %s", pLayerPrefix, messageCode, pMessage);
+ qDebug("vkDebug: %s", pCallbackData->pMessage);
return VK_FALSE;
}
+#endif
void QBasicPlatformVulkanInstance::setupDebugOutput()
{
- if (!m_enabledExtensions.contains("VK_EXT_debug_report"))
+#ifdef VK_EXT_debug_utils
+ if (!m_enabledExtensions.contains("VK_EXT_debug_utils"))
return;
- PFN_vkCreateDebugReportCallbackEXT createDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
- m_vkGetInstanceProcAddr(m_vkInst, "vkCreateDebugReportCallbackEXT"));
- m_vkDestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
- m_vkGetInstanceProcAddr(m_vkInst, "vkDestroyDebugReportCallbackEXT"));
-
- VkDebugReportCallbackCreateInfoEXT dbgCallbackInfo;
- memset(&dbgCallbackInfo, 0, sizeof(dbgCallbackInfo));
- dbgCallbackInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
- dbgCallbackInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT
- | VK_DEBUG_REPORT_WARNING_BIT_EXT
- | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
- dbgCallbackInfo.pfnCallback = defaultDebugCallbackFunc;
- dbgCallbackInfo.pUserData = this;
-
- VkResult err = createDebugReportCallback(m_vkInst, &dbgCallbackInfo, nullptr, &m_debugCallback);
+ PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkCreateDebugUtilsMessengerEXT"));
+
+ m_vkDestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkDestroyDebugUtilsMessengerEXT"));
+
+ VkDebugUtilsMessengerCreateInfoEXT messengerInfo = {};
+ messengerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
+ messengerInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ messengerInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
+ | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ messengerInfo.pfnUserCallback = defaultDebugCallbackFunc;
+ messengerInfo.pUserData = this;
+ VkResult err = vkCreateDebugUtilsMessengerEXT(m_vkInst, &messengerInfo, nullptr, &m_debugMessenger);
if (err != VK_SUCCESS)
qWarning("Failed to create debug report callback: %d", err);
+#endif
}
QT_END_NAMESPACE
diff --git a/src/gui/vulkan/qbasicvulkanplatforminstance_p.h b/src/gui/vulkan/qbasicvulkanplatforminstance_p.h
index 2391452f03..dfa5003f16 100644
--- a/src/gui/vulkan/qbasicvulkanplatforminstance_p.h
+++ b/src/gui/vulkan/qbasicvulkanplatforminstance_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBASICVULKANPLATFORMINSTANCE_P_H
#define QBASICVULKANPLATFORMINSTANCE_P_H
@@ -55,6 +19,7 @@
#include <QtCore/QLibrary>
#include <qpa/qplatformvulkaninstance.h>
+#include <private/qglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -75,27 +40,29 @@ public:
PFN_vkVoidFunction getInstanceProcAddr(const char *name) override;
bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override;
void setDebugFilters(const QList<QVulkanInstance::DebugFilter> &filters) override;
+ void setDebugUtilsFilters(const QList<QVulkanInstance::DebugUtilsFilter> &filters) override;
void destroySurface(VkSurfaceKHR surface) const;
const QList<QVulkanInstance::DebugFilter> *debugFilters() const { return &m_debugFilters; }
+ const QList<QVulkanInstance::DebugUtilsFilter> *debugUtilsFilters() const { return &m_debugUtilsFilters; }
protected:
- void loadVulkanLibrary(const QString &defaultLibraryName);
+ void loadVulkanLibrary(const QString &defaultLibraryName, int defaultLibraryVersion = -1);
void init(QLibrary *lib);
void initInstance(QVulkanInstance *instance, const QByteArrayList &extraExts);
- VkInstance m_vkInst;
- PFN_vkGetInstanceProcAddr m_vkGetInstanceProcAddr;
+ VkInstance m_vkInst = VK_NULL_HANDLE;
+ PFN_vkGetInstanceProcAddr m_vkGetInstanceProcAddr = nullptr;
PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_getPhysDevSurfaceSupport;
PFN_vkDestroySurfaceKHR m_destroySurface;
private:
void setupDebugOutput();
- QLibrary m_vulkanLib;
+ std::unique_ptr<QLibrary> m_vulkanLib;
- bool m_ownsVkInst;
- VkResult m_errorCode;
+ bool m_ownsVkInst = false;
+ VkResult m_errorCode = VK_SUCCESS;
QVulkanInfoVector<QVulkanLayer> m_supportedLayers;
QVulkanInfoVector<QVulkanExtension> m_supportedExtensions;
QVersionNumber m_supportedApiVersion;
@@ -108,9 +75,12 @@ private:
PFN_vkDestroyInstance m_vkDestroyInstance;
- VkDebugReportCallbackEXT m_debugCallback;
- PFN_vkDestroyDebugReportCallbackEXT m_vkDestroyDebugReportCallbackEXT;
+#ifdef VK_EXT_debug_utils
+ VkDebugUtilsMessengerEXT m_debugMessenger = VK_NULL_HANDLE;
+ PFN_vkDestroyDebugUtilsMessengerEXT m_vkDestroyDebugUtilsMessengerEXT;
+#endif
QList<QVulkanInstance::DebugFilter> m_debugFilters;
+ QList<QVulkanInstance::DebugUtilsFilter> m_debugUtilsFilters;
};
QT_END_NAMESPACE
diff --git a/src/gui/vulkan/qplatformvulkaninstance.cpp b/src/gui/vulkan/qplatformvulkaninstance.cpp
index 638e8526b2..2685a5c6f8 100644
--- a/src/gui/vulkan/qplatformvulkaninstance.cpp
+++ b/src/gui/vulkan/qplatformvulkaninstance.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformvulkaninstance.h"
@@ -95,4 +59,20 @@ void QPlatformVulkanInstance::setDebugFilters(const QList<QVulkanInstance::Debug
Q_UNUSED(filters);
}
+void QPlatformVulkanInstance::setDebugUtilsFilters(const QList<QVulkanInstance::DebugUtilsFilter> &filters)
+{
+ Q_UNUSED(filters);
+}
+
+void QPlatformVulkanInstance::beginFrame(QWindow *window)
+{
+ Q_UNUSED(window);
+}
+
+void QPlatformVulkanInstance::endFrame(QWindow *window)
+{
+ Q_UNUSED(window);
+}
+
+
QT_END_NAMESPACE
diff --git a/src/gui/vulkan/qplatformvulkaninstance.h b/src/gui/vulkan/qplatformvulkaninstance.h
index b918632b57..d34cb77d1b 100644
--- a/src/gui/vulkan/qplatformvulkaninstance.h
+++ b/src/gui/vulkan/qplatformvulkaninstance.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMVULKANINSTANCE_H
#define QPLATFORMVULKANINSTANCE_H
@@ -51,7 +15,7 @@
#include <QtGui/qtguiglobal.h>
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
#include <qvulkaninstance.h>
@@ -81,6 +45,9 @@ public:
virtual void presentAboutToBeQueued(QWindow *window);
virtual void presentQueued(QWindow *window);
virtual void setDebugFilters(const QList<QVulkanInstance::DebugFilter> &filters);
+ virtual void setDebugUtilsFilters(const QList<QVulkanInstance::DebugUtilsFilter> &filters);
+ virtual void beginFrame(QWindow *window);
+ virtual void endFrame(QWindow *window);
private:
QScopedPointer<QPlatformVulkanInstancePrivate> d_ptr;
@@ -91,7 +58,7 @@ QT_END_NAMESPACE
#endif // QT_CONFIG(vulkan)
-#if defined(Q_CLANG_QDOC)
+#if defined(Q_QDOC)
/*
The following include file did not exist for clang-qdoc running
in macOS, but the classes are documented in qvulkanfunctions.cpp.
@@ -105,7 +72,7 @@ QT_END_NAMESPACE
#include <QtGui/qtguiglobal.h>
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
#ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES
@@ -148,8 +115,8 @@ private:
QT_END_NAMESPACE
-#endif // QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#endif // QT_CONFIG(vulkan) || defined(Q_QDOC)
#endif // QVULKANFUNCTIONS_H;
-#endif // Q_CLANG_QDOC
+#endif // Q_QDOC
#endif // QPLATFORMVULKANINSTANCE_H
diff --git a/src/gui/vulkan/qt_attribution.json b/src/gui/vulkan/qt_attribution.json
index 6791be40ed..b49e59954d 100644
--- a/src/gui/vulkan/qt_attribution.json
+++ b/src/gui/vulkan/qt_attribution.json
@@ -5,13 +5,13 @@
"QDocModule": "qtgui",
"Description": "Vulkan XML API Registry.",
"QtUsage": "Used to dynamically generate the sources for the QVulkan(Device)Functions classes.",
- "Path": "vk.xml",
+ "Files": "vk.xml",
"Homepage": "https://www.khronos.org/",
- "Version": "1.2.166",
- "License": "MIT License",
+ "Version": "1.3.223",
+ "License": "Apache License 2.0 or MIT License",
"LicenseId": "Apache-2.0 OR MIT",
"LicenseFile": "LICENSE.txt",
- "Copyright": "Copyright (c) 2015-2020 The Khronos Group Inc."
+ "Copyright": "Copyright (c) 2015-2022 The Khronos Group Inc."
}
]
diff --git a/src/gui/vulkan/qvulkandefaultinstance.cpp b/src/gui/vulkan/qvulkandefaultinstance.cpp
new file mode 100644
index 0000000000..b4f343cf17
--- /dev/null
+++ b/src/gui/vulkan/qvulkandefaultinstance.cpp
@@ -0,0 +1,85 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qvulkandefaultinstance_p.h"
+#include <rhi/qrhi.h>
+#include <QLoggingCategory>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcGuiVk, "qt.vulkan")
+
+static QVulkanInstance *s_vulkanInstance;
+Q_CONSTINIT static QVulkanDefaultInstance::Flags s_vulkanInstanceFlags;
+
+QVulkanDefaultInstance::Flags QVulkanDefaultInstance::flags()
+{
+ return s_vulkanInstanceFlags;
+}
+
+// As always, calling this when hasInstance() is already true has no effect. (unless cleanup() is called)
+void QVulkanDefaultInstance::setFlag(Flag flag, bool on)
+{
+ s_vulkanInstanceFlags.setFlag(flag, on);
+}
+
+bool QVulkanDefaultInstance::hasInstance()
+{
+ return s_vulkanInstance != nullptr;
+}
+
+QVulkanInstance *QVulkanDefaultInstance::instance()
+{
+ if (s_vulkanInstance)
+ return s_vulkanInstance;
+
+ s_vulkanInstance = new QVulkanInstance;
+
+ // With a Vulkan implementation >= 1.1 we can check what
+ // vkEnumerateInstanceVersion() says and request 1.3/1.2/1.1 based on the
+ // result. To prevent future surprises, be conservative and ignore any > 1.3
+ // versions for now. For 1.0 implementations nothing will be requested, the
+ // default 0 in VkApplicationInfo means 1.0.
+ //
+ // Vulkan 1.0 is actually sufficient for 99% of Qt Quick (3D)'s
+ // functionality. In addition, Vulkan implementations tend to enable 1.1+
+ // functionality regardless of the VkInstance API request. However, the
+ // validation layer seems to take this fairly seriously, so we should be
+ // prepared for using 1.1+ features in a fully correct manner. This also
+ // helps custom Vulkan code in applications, which is not under out
+ // control; it is ideal if Vulkan 1.1+ versions are usable without
+ // requiring such applications to create their own QVulkanInstance just to
+ // be able to make an appropriate setApiVersion() call on it.
+
+ const QVersionNumber supportedVersion = s_vulkanInstance->supportedApiVersion();
+ if (supportedVersion >= QVersionNumber(1, 3))
+ s_vulkanInstance->setApiVersion(QVersionNumber(1, 3));
+ else if (supportedVersion >= QVersionNumber(1, 2))
+ s_vulkanInstance->setApiVersion(QVersionNumber(1, 2));
+ else if (supportedVersion >= QVersionNumber(1, 1))
+ s_vulkanInstance->setApiVersion(QVersionNumber(1, 1));
+ qCDebug(lcGuiVk) << "QVulkanDefaultInstance: Creating Vulkan instance"
+ << "Requesting Vulkan API" << s_vulkanInstance->apiVersion()
+ << "Instance-level version was reported as" << supportedVersion;
+
+ if (s_vulkanInstanceFlags.testFlag(EnableValidation))
+ s_vulkanInstance->setLayers({ "VK_LAYER_KHRONOS_validation" });
+
+ s_vulkanInstance->setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions());
+
+ if (!s_vulkanInstance->create()) {
+ qWarning("QVulkanDefaultInstance: Failed to create Vulkan instance");
+ delete s_vulkanInstance;
+ s_vulkanInstance = nullptr;
+ }
+
+ return s_vulkanInstance;
+}
+
+void QVulkanDefaultInstance::cleanup()
+{
+ delete s_vulkanInstance;
+ s_vulkanInstance = nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/vulkan/qvulkandefaultinstance_p.h b/src/gui/vulkan/qvulkandefaultinstance_p.h
new file mode 100644
index 0000000000..8550f63d6c
--- /dev/null
+++ b/src/gui/vulkan/qvulkandefaultinstance_p.h
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QVULKANDEFAULTINSTANCE_P_H
+#define QVULKANDEFAULTINSTANCE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#if QT_CONFIG(vulkan)
+
+#include <QtGui/qvulkaninstance.h>
+
+QT_BEGIN_NAMESPACE
+
+struct Q_GUI_EXPORT QVulkanDefaultInstance
+{
+ enum Flag {
+ EnableValidation = 0x01
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ static Flags flags();
+ static void setFlag(Flag flag, bool on = true);
+ static bool hasInstance();
+ static QVulkanInstance *instance();
+ static void cleanup();
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QVulkanDefaultInstance::Flags)
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(vulkan)
+
+#endif
diff --git a/src/gui/vulkan/qvulkanfunctions.cpp b/src/gui/vulkan/qvulkanfunctions.cpp
index decf5edd3f..6a30799502 100644
--- a/src/gui/vulkan/qvulkanfunctions.cpp
+++ b/src/gui/vulkan/qvulkanfunctions.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qvulkanfunctions_p.h>
@@ -49,7 +13,7 @@ QT_BEGIN_NAMESPACE
\wrapper
\brief The QVulkanFunctions class provides cross-platform access to the
- instance level core Vulkan 1.2 API.
+ instance level core Vulkan 1.3 API.
Qt and Qt applications do not link to any Vulkan libraries by default.
Instead, all functions are resolved dynamically at run time. Each
@@ -81,17 +45,17 @@ QT_BEGIN_NAMESPACE
\l{https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkGetInstanceProcAddr.html}{the
man page for vkGetInstanceProcAddr} for more information.
- \note The member function prototypes for Vulkan 1.1 and 1.2 commands are
- ifdefed with the appropriate \c{VK_VERSION_1_x} that is defined by the
- Vulkan headers. Therefore these functions will only be callable by an
+ \note The member function prototypes for Vulkan 1.1, 1.2, and 1.3 commands
+ are \c ifdefed with the appropriate \c{VK_VERSION_1_x} that is defined by
+ the Vulkan headers. As such, these functions will only be callable by an
application when the system's (on which the application is built) Vulkan
- header is new enough and it contains 1.1 and 1.2 Vulkan API definitions.
- When building Qt from source, this has an additional consequence: the
- Vulkan headers on the build environment must also be 1.1 and 1.2 capable in
- order to get a Qt build that supports resolving the 1.1 and 1.2 API
- commands. If either of these conditions is not met, applications will only
- be able to call the Vulkan 1.0 commands through QVulkanFunctions and
- QVulkanDeviceFunctions.
+ header is new enough and it contains 1.1, 1.2, or 1.3 Vulkan API
+ definitions. When building Qt from source, this has an additional
+ consequence: the Vulkan headers on the build environment must also be 1.1,
+ 1.2, and 1.3 compatible to get a Qt build that supports resolving
+ the 1.1, 1.2, and 1.3 API commands. If neither of these conditions is met,
+ applications will only be able to call the Vulkan 1.0 commands through
+ QVulkanFunctions and QVulkanDeviceFunctions.
\sa QVulkanInstance, QVulkanDeviceFunctions, QWindow::setVulkanInstance(), QWindow::setSurfaceType()
*/
@@ -104,7 +68,7 @@ QT_BEGIN_NAMESPACE
\wrapper
\brief The QVulkanDeviceFunctions class provides cross-platform access to
- the device level core Vulkan 1.2 API.
+ the device level core Vulkan 1.3 API.
Qt and Qt applications do not link to any Vulkan libraries by default.
Instead, all functions are resolved dynamically at run time. Each
diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp
index fc4a916cb4..6d3020d62d 100644
--- a/src/gui/vulkan/qvulkaninstance.cpp
+++ b/src/gui/vulkan/qvulkaninstance.cpp
@@ -1,44 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qvulkaninstance.h"
-#include <private/qvulkanfunctions_p.h>
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qvulkaninstance_p.h"
#include <qpa/qplatformvulkaninstance.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformnativeinterface.h>
@@ -49,6 +12,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QVulkanInstance
\since 5.10
+ \ingroup painting-3D
\inmodule QtGui
\brief The QVulkanInstance class represents a native Vulkan instance, enabling
@@ -141,7 +105,7 @@ QT_BEGIN_NAMESPACE
\note It is up to the component creating the external instance to ensure
the necessary extensions are enabled on it. These are: \c{VK_KHR_surface},
the WSI-specific \c{VK_KHR_*_surface} that is appropriate for the platform
- in question, and \c{VK_EXT_debug_report} in case QVulkanInstance's debug
+ in question, and \c{VK_EXT_debug_utils} in case QVulkanInstance's debug
output redirection is desired.
\section1 Accessing Core Vulkan Commands
@@ -242,35 +206,10 @@ QT_BEGIN_NAMESPACE
This enum describes the flags that can be passed to setFlags(). These control
the behavior of create().
- \value NoDebugOutputRedirect Disables Vulkan debug output (\c{VK_EXT_debug_report}) redirection to qDebug.
+ \value NoDebugOutputRedirect Disables Vulkan debug output (\c{VK_EXT_debug_utils}) redirection to qDebug.
+ \value [since 6.5] NoPortabilityDrivers Disables enumerating physical devices marked as Vulkan Portability.
*/
-class QVulkanInstancePrivate
-{
-public:
- QVulkanInstancePrivate(QVulkanInstance *q)
- : q_ptr(q),
- vkInst(VK_NULL_HANDLE),
- errorCode(VK_SUCCESS)
- { }
- ~QVulkanInstancePrivate() { reset(); }
-
- bool ensureVulkan();
- void reset();
-
- QVulkanInstance *q_ptr;
- QScopedPointer<QPlatformVulkanInstance> platformInst;
- VkInstance vkInst;
- QVulkanInstance::Flags flags;
- QByteArrayList layers;
- QByteArrayList extensions;
- QVersionNumber apiVersion;
- VkResult errorCode;
- QScopedPointer<QVulkanFunctions> funcs;
- QHash<VkDevice, QVulkanDeviceFunctions *> deviceFuncs;
- QList<QVulkanInstance::DebugFilter> debugFilters;
-};
-
bool QVulkanInstancePrivate::ensureVulkan()
{
if (!platformInst) {
@@ -306,7 +245,8 @@ QVulkanInstance::QVulkanInstance()
/*!
Destructor.
- \note current() will return \nullptr once the instance is destroyed.
+ \note \l {QVulkanInstance::}{vkInstance()} will return \nullptr once the
+ instance is destroyed.
*/
QVulkanInstance::~QVulkanInstance()
{
@@ -315,6 +255,7 @@ QVulkanInstance::~QVulkanInstance()
/*!
\class QVulkanLayer
+ \inmodule QtGui
\brief Represents information about a Vulkan layer.
*/
@@ -358,7 +299,7 @@ QVulkanInstance::~QVulkanInstance()
*/
/*!
- \fn size_t qHash(const QVulkanLayer &key, size_t seed)
+ \fn size_t qHash(const QVulkanLayer &key, size_t seed = 0)
\since 5.10
\relates QVulkanLayer
@@ -368,6 +309,7 @@ QVulkanInstance::~QVulkanInstance()
/*!
\class QVulkanExtension
+ \inmodule QtGui
\brief Represents information about a Vulkan extension.
*/
@@ -401,7 +343,7 @@ QVulkanInstance::~QVulkanInstance()
*/
/*!
- \fn size_t qHash(const QVulkanExtension &key, size_t seed)
+ \fn size_t qHash(const QVulkanExtension &key, size_t seed = 0)
\since 5.10
\relates QVulkanExtension
@@ -411,6 +353,7 @@ QVulkanInstance::~QVulkanInstance()
/*!
\class QVulkanInfoVector
+ \inmodule QtGui
\brief A specialized QList for QVulkanLayer and QVulkanExtension.
*/
@@ -485,7 +428,7 @@ QVersionNumber QVulkanInstance::supportedApiVersion() const
\note \a existingVkInstance must have at least \c{VK_KHR_surface} and the
appropriate WSI-specific \c{VK_KHR_*_surface} extensions enabled. To ensure
- debug output redirection is functional, \c{VK_EXT_debug_report} is needed as
+ debug output redirection is functional, \c{VK_EXT_debug_utils} is needed as
well.
\note This function can only be called before create() and has no effect if
@@ -538,9 +481,14 @@ void QVulkanInstance::setLayers(const QByteArrayList &layers)
/*!
Specifies the list of additional instance \a extensions to enable. It is
safe to specify unsupported extensions as well because these get ignored
- when not supported at run time. The surface-related extensions required by
- Qt will always be added automatically, no need to include them in this
- list.
+ when not supported at run time.
+
+ \note The surface-related extensions required by Qt (for example, \c
+ VK_KHR_win32_surface) will always be added automatically, no need to
+ include them in this list.
+
+ \note \c VK_KHR_portability_enumeration is added automatically unless the
+ NoPortabilityDrivers flag is set. This value was introduced in Qt 6.5.
\note This function can only be called before create() and has no effect if
called afterwards.
@@ -593,11 +541,16 @@ void QVulkanInstance::setApiVersion(const QVersionNumber &vulkanVersion)
\return true if successful, false on error or when Vulkan is not supported.
- When successful, the pointer to this QVulkanInstance is retrievable via the
- static function current().
+ When successful, the pointer to this QVulkanInstance is retrievable via
+ \l {QVulkanInstance::}{vkInstance()}.
The Vulkan instance and library is available as long as this
QVulkanInstance exists, or until destroy() is called.
+
+ By default the VkInstance is created with the flag
+ \l{https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkInstanceCreateFlagBits.html}{VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR}
+ set. This means that Vulkan Portability physical devices get enumerated as
+ well. If this is not desired, set the NoPortabilityDrivers flag.
*/
bool QVulkanInstance::create()
{
@@ -616,6 +569,7 @@ bool QVulkanInstance::create()
d_ptr->errorCode = VK_SUCCESS;
d_ptr->funcs.reset(new QVulkanFunctions(this));
d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters);
+ d_ptr->platformInst->setDebugUtilsFilters(d_ptr->debugUtilsFilters);
return true;
}
@@ -870,12 +824,28 @@ void QVulkanInstance::presentQueued(QWindow *window)
/*!
\typedef QVulkanInstance::DebugFilter
- Typedef for debug filtering callback functions.
+ Typedef for debug filtering callback functions, with the following signature:
+
+ \code
+ bool myDebugFilter(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object,
+ size_t location, int32_t messageCode, const char *pLayerPrefix, const char *pMessage)
+ \endcode
+
+ Returning \c true suppresses the printing of the message.
+
+ \note Starting with Qt 6.5 \c{VK_EXT_debug_utils} is used instead of the
+ deprecated \c{VK_EXT_debug_report}. The callback signature is based on
+ VK_EXT_debug_report. Therefore, not all arguments can be expected to be
+ valid anymore. Avoid relying on arguments other than \c pMessage, \c
+ messageCode, and \c object. Applications wishing to access all the callback
+ data as specified in VK_EXT_debug_utils should migrate to DebugUtilsFilter.
\sa installDebugOutputFilter(), removeDebugOutputFilter()
*/
/*!
+ \overload
+
Installs a \a filter function that is called for every Vulkan debug
message. When the callback returns \c true, the message is stopped (filtered
out) and will not appear on the debug output.
@@ -897,6 +867,8 @@ void QVulkanInstance::installDebugOutputFilter(DebugFilter filter)
}
/*!
+ \overload
+
Removes a \a filter function previously installed by
installDebugOutputFilter().
@@ -911,6 +883,84 @@ void QVulkanInstance::removeDebugOutputFilter(DebugFilter filter)
d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters);
}
+/*!
+ \typedef QVulkanInstance::DebugUtilsFilter
+
+ Typedef for debug filtering callback functions, with the following signature:
+
+ \code
+ std::function<bool(DebugMessageSeverityFlags severity, DebugMessageTypeFlags type, const void *message)>;
+ \endcode
+
+ The \c message argument is a pointer to the
+ VkDebugUtilsMessengerCallbackDataEXT structure. Refer to the documentation
+ of \c{VK_EXT_debug_utils} for details. The Qt headers do not use the real
+ type in order to avoid introducing a dependency on post-1.0 Vulkan headers.
+
+ Returning \c true suppresses the printing of the message.
+
+ \sa installDebugOutputFilter(), removeDebugOutputFilter()
+ \since 6.5
+ */
+
+/*!
+ \enum QVulkanInstance::DebugMessageSeverityFlag
+ \since 6.5
+
+ \value VerboseSeverity
+ \value InfoSeverity
+ \value WarningSeverity
+ \value ErrorSeverity
+ */
+
+/*!
+ \enum QVulkanInstance::DebugMessageTypeFlag
+ \since 6.5
+
+ \value GeneralMessage
+ \value ValidationMessage
+ \value PerformanceMessage
+ */
+
+/*!
+ Installs a \a filter function that is called for every Vulkan debug
+ message. When the callback returns \c true, the message is stopped (filtered
+ out) and will not appear on the debug output.
+
+ \note Filtering is only effective when NoDebugOutputRedirect is not
+ \l{setFlags()}{set}. Installing filters has no effect otherwise.
+
+ \note This function can be called before create().
+
+ \sa clearDebugOutputFilters()
+ \since 6.5
+ */
+void QVulkanInstance::installDebugOutputFilter(DebugUtilsFilter filter)
+{
+ d_ptr->debugUtilsFilters.append(filter);
+ if (d_ptr->platformInst)
+ d_ptr->platformInst->setDebugUtilsFilters(d_ptr->debugUtilsFilters);
+}
+
+/*!
+ Removes all filter functions installed previously by
+ installDebugOutputFilter().
+
+ \note This function can be called before create().
+
+ \sa installDebugOutputFilter()
+ \since 6.5
+ */
+void QVulkanInstance::clearDebugOutputFilters()
+{
+ d_ptr->debugFilters.clear();
+ d_ptr->debugUtilsFilters.clear();
+ if (d_ptr->platformInst) {
+ d_ptr->platformInst->setDebugFilters(d_ptr->debugFilters);
+ d_ptr->platformInst->setDebugUtilsFilters(d_ptr->debugUtilsFilters);
+ }
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QVulkanLayer &layer)
{
diff --git a/src/gui/vulkan/qvulkaninstance.h b/src/gui/vulkan/qvulkaninstance.h
index bfdaf1ab69..221f605fa2 100644
--- a/src/gui/vulkan/qvulkaninstance.h
+++ b/src/gui/vulkan/qvulkaninstance.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVULKANINSTANCE_H
#define QVULKANINSTANCE_H
@@ -47,12 +11,12 @@
#pragma qt_sync_skip_header_check
#endif
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
#ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES
#endif
-#if !defined(Q_CLANG_QDOC) && __has_include(<vulkan/vulkan.h>)
+#if !defined(Q_QDOC) && __has_include(<vulkan/vulkan.h>)
#include <vulkan/vulkan.h>
#else
// QT_CONFIG(vulkan) implies vulkan.h being available at Qt build time, but it
@@ -72,6 +36,7 @@ typedef void* VkPhysicalDevice;
typedef void* VkDevice;
// enums
typedef int VkResult;
+typedef int VkFormat;
typedef int VkImageLayout;
typedef int VkDebugReportFlagsEXT;
typedef int VkDebugReportObjectTypeEXT;
@@ -80,7 +45,7 @@ typedef int VkDebugReportObjectTypeEXT;
// QVulkanInstance itself is only applicable if vulkan.h is available, or if
// it's qdoc. An application that is built on a vulkan.h-less system against a
// Vulkan-enabled Qt gets the dummy typedefs but not QVulkan*.
-#if __has_include(<vulkan/vulkan.h>) || defined(Q_CLANG_QDOC)
+#if __has_include(<vulkan/vulkan.h>) || defined(Q_QDOC)
#include <QtCore/qbytearraylist.h>
#include <QtCore/qdebug.h>
@@ -170,7 +135,8 @@ public:
~QVulkanInstance();
enum Flag {
- NoDebugOutputRedirect = 0x01
+ NoDebugOutputRedirect = 0x01,
+ NoPortabilityDrivers = 0x02
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -222,17 +188,39 @@ public:
void installDebugOutputFilter(DebugFilter filter);
void removeDebugOutputFilter(DebugFilter filter);
+ enum DebugMessageSeverityFlag {
+ VerboseSeverity = 0x01,
+ InfoSeverity = 0x02,
+ WarningSeverity = 0x04,
+ ErrorSeverity = 0x08
+ };
+ Q_DECLARE_FLAGS(DebugMessageSeverityFlags, DebugMessageSeverityFlag)
+
+ enum DebugMessageTypeFlag {
+ GeneralMessage = 0x01,
+ ValidationMessage = 0x02,
+ PerformanceMessage = 0x04
+ };
+ Q_DECLARE_FLAGS(DebugMessageTypeFlags, DebugMessageTypeFlag)
+
+ using DebugUtilsFilter = std::function<bool(DebugMessageSeverityFlags severity, DebugMessageTypeFlags type, const void *message)>;
+ void installDebugOutputFilter(DebugUtilsFilter filter);
+ void clearDebugOutputFilters();
+
private:
+ friend class QVulkanInstancePrivate;
QScopedPointer<QVulkanInstancePrivate> d_ptr;
Q_DISABLE_COPY(QVulkanInstance)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QVulkanInstance::Flags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QVulkanInstance::DebugMessageTypeFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QVulkanInstance::DebugMessageSeverityFlags)
QT_END_NAMESPACE
-#endif // __has_include(<vulkan/vulkan.h>) || defined(Q_CLANG_QDOC)
+#endif // __has_include(<vulkan/vulkan.h>) || defined(Q_QDOC)
-#endif // QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#endif // QT_CONFIG(vulkan) || defined(Q_QDOC)
#endif // QVULKANINSTANCE_H
diff --git a/src/gui/vulkan/qvulkaninstance_p.h b/src/gui/vulkan/qvulkaninstance_p.h
new file mode 100644
index 0000000000..d707b301c6
--- /dev/null
+++ b/src/gui/vulkan/qvulkaninstance_p.h
@@ -0,0 +1,60 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QVULKANINSTANCE_P_H
+#define QVULKANINSTANCE_P_H
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
+
+#include "qvulkaninstance.h"
+#include <private/qvulkanfunctions_p.h>
+#include <QtCore/QHash>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QVulkanInstancePrivate
+{
+public:
+ QVulkanInstancePrivate(QVulkanInstance *q)
+ : q_ptr(q),
+ vkInst(VK_NULL_HANDLE),
+ errorCode(VK_SUCCESS)
+ { }
+ ~QVulkanInstancePrivate() { reset(); }
+ static QVulkanInstancePrivate *get(QVulkanInstance *q) { return q->d_ptr.data(); }
+
+ bool ensureVulkan();
+ void reset();
+
+ QVulkanInstance *q_ptr;
+ QScopedPointer<QPlatformVulkanInstance> platformInst;
+ VkInstance vkInst;
+ QVulkanInstance::Flags flags;
+ QByteArrayList layers;
+ QByteArrayList extensions;
+ QVersionNumber apiVersion;
+ VkResult errorCode;
+ QScopedPointer<QVulkanFunctions> funcs;
+ QHash<VkDevice, QVulkanDeviceFunctions *> deviceFuncs;
+ QList<QVulkanInstance::DebugFilter> debugFilters; // legacy filters based on VK_EXT_debug_report
+ QList<QVulkanInstance::DebugUtilsFilter> debugUtilsFilters; // the modern version based on VK_EXT_debug_utils
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(vulkan)
+
+#endif // QVULKANINSTANCE_P_H
diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp
index c57f3bf372..00a5c5f869 100644
--- a/src/gui/vulkan/qvulkanwindow.cpp
+++ b/src/gui/vulkan/qvulkanwindow.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qvulkanwindow_p.h"
#include "qvulkanfunctions.h"
@@ -47,7 +11,7 @@
QT_BEGIN_NAMESPACE
-Q_LOGGING_CATEGORY(lcGuiVk, "qt.vulkan")
+Q_DECLARE_LOGGING_CATEGORY(lcGuiVk)
/*!
\class QVulkanWindow
@@ -195,6 +159,31 @@ Q_LOGGING_CATEGORY(lcGuiVk, "qt.vulkan")
\note QVulkanWindow does not expose device layers since this functionality
has been deprecated since version 1.0.13 of the Vulkan API.
+ \section1 Layers, device features, and extensions
+
+ To enable instance layers, call QVulkanInstance::setLayers() before creating
+ the QVulkanInstance. To query what instance layer are available, call
+ QVulkanInstance::supportedLayers().
+
+ To enable device extensions, call setDeviceExtensions() early on when setting
+ up the QVulkanWindow. To query what device extensions are available, call
+ supportedDeviceExtensions().
+
+ Specifying an unsupported layer or extension is handled gracefully: this will
+ not fail instance or device creation, but the layer or extension request is
+ rather ignored.
+
+ When it comes to device features, QVulkanWindow enables all Vulkan 1.0
+ features that are reported as supported from vkGetPhysicalDeviceFeatures().
+ As an exception to this rule, \c robustBufferAccess is never enabled. Use the
+ callback mechanism described below, if enabling that feature is desired.
+
+ This is not always desirable, and may be insufficient with Vulkan 1.1 and
+ higher. Therefore, full control over the VkPhysicalDeviceFeatures used for
+ device creation is possible too by registering a callback function with
+ setEnabledFeaturesModifier(). When set, the callback function is invoked,
+ letting it alter the VkPhysicalDeviceFeatures or VkPhysicalDeviceFeatures2.
+
\sa QVulkanInstance, QWindow
*/
@@ -345,7 +334,7 @@ void QVulkanWindow::setPhysicalDeviceIndex(int idx)
qWarning("QVulkanWindow: Attempted to set physical device when already initialized");
return;
}
- const int count = availablePhysicalDevices().count();
+ const int count = availablePhysicalDevices().size();
if (idx < 0 || idx >= count) {
qWarning("QVulkanWindow: Invalid physical device index %d (total physical devices: %d)", idx, count);
return;
@@ -458,7 +447,7 @@ void QVulkanWindow::setPreferredColorFormats(const QList<VkFormat> &formats)
static struct {
VkSampleCountFlagBits mask;
int count;
-} qvk_sampleCounts[] = {
+} q_vk_sampleCounts[] = {
// keep this sorted by 'count'
{ VK_SAMPLE_COUNT_1_BIT, 1 },
{ VK_SAMPLE_COUNT_2_BIT, 2 },
@@ -498,7 +487,7 @@ QList<int> QVulkanWindow::supportedSampleCounts()
VkSampleCountFlags depth = limits->framebufferDepthSampleCounts;
VkSampleCountFlags stencil = limits->framebufferStencilSampleCounts;
- for (const auto &qvk_sampleCount : qvk_sampleCounts) {
+ for (const auto &qvk_sampleCount : q_vk_sampleCounts) {
if ((color & qvk_sampleCount.mask)
&& (depth & qvk_sampleCount.mask)
&& (stencil & qvk_sampleCount.mask))
@@ -547,7 +536,7 @@ void QVulkanWindow::setSampleCount(int sampleCount)
return;
}
- for (const auto &qvk_sampleCount : qvk_sampleCounts) {
+ for (const auto &qvk_sampleCount : q_vk_sampleCounts) {
if (qvk_sampleCount.count == sampleCount) {
d->sampleCount = qvk_sampleCount.mask;
return;
@@ -591,7 +580,7 @@ void QVulkanWindowPrivate::init()
return;
}
- if (physDevIndex < 0 || physDevIndex >= physDevs.count()) {
+ if (physDevIndex < 0 || physDevIndex >= physDevs.size()) {
qWarning("QVulkanWindow: Invalid physical device index; defaulting to 0");
physDevIndex = 0;
}
@@ -610,7 +599,7 @@ void QVulkanWindowPrivate::init()
f->vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueFamilyProps.data());
gfxQueueFamilyIdx = uint32_t(-1);
presQueueFamilyIdx = uint32_t(-1);
- for (int i = 0; i < queueFamilyProps.count(); ++i) {
+ for (int i = 0; i < queueFamilyProps.size(); ++i) {
const bool supportsPresent = inst->supportsPresent(physDev, i, q);
qCDebug(lcGuiVk, "queue family %d: flags=0x%x count=%d supportsPresent=%d", i,
queueFamilyProps[i].queueFlags, queueFamilyProps[i].queueCount, supportsPresent);
@@ -623,7 +612,7 @@ void QVulkanWindowPrivate::init()
presQueueFamilyIdx = gfxQueueFamilyIdx;
} else {
qCDebug(lcGuiVk, "No queue with graphics+present; trying separate queues");
- for (int i = 0; i < queueFamilyProps.count(); ++i) {
+ for (int i = 0; i < queueFamilyProps.size(); ++i) {
if (gfxQueueFamilyIdx == uint32_t(-1) && (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
gfxQueueFamilyIdx = i;
if (presQueueFamilyIdx == uint32_t(-1) && inst->supportsPresent(physDev, i, q))
@@ -667,7 +656,7 @@ void QVulkanWindowPrivate::init()
queueCreateInfoModifier(queueFamilyProps.constData(), queueCount, queueInfo);
bool foundGfxQueue = false;
bool foundPresQueue = false;
- for (const VkDeviceQueueCreateInfo& createInfo : qAsConst(queueInfo)) {
+ for (const VkDeviceQueueCreateInfo& createInfo : std::as_const(queueInfo)) {
foundGfxQueue |= createInfo.queueFamilyIndex == gfxQueueFamilyIdx;
foundPresQueue |= createInfo.queueFamilyIndex == presQueueFamilyIdx;
}
@@ -709,9 +698,26 @@ void QVulkanWindowPrivate::init()
devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
devInfo.queueCreateInfoCount = queueInfo.size();
devInfo.pQueueCreateInfos = queueInfo.constData();
- devInfo.enabledExtensionCount = devExts.count();
+ devInfo.enabledExtensionCount = devExts.size();
devInfo.ppEnabledExtensionNames = devExts.constData();
+ VkPhysicalDeviceFeatures features = {};
+ VkPhysicalDeviceFeatures2 features2 = {};
+ if (enabledFeatures2Modifier) {
+ features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ enabledFeatures2Modifier(features2);
+ devInfo.pNext = &features2;
+ } else if (enabledFeaturesModifier) {
+ enabledFeaturesModifier(features);
+ devInfo.pEnabledFeatures = &features;
+ } else {
+ // Enable all supported 1.0 core features, except ones that likely
+ // involve a performance penalty.
+ f->vkGetPhysicalDeviceFeatures(physDev, &features);
+ features.robustBufferAccess = VK_FALSE;
+ devInfo.pEnabledFeatures = &features;
+ }
+
// Device layers are not supported by QVulkanWindow since that's an already deprecated
// API. However, have a workaround for systems with older API and layers (f.ex. L4T
// 24.2 for the Jetson TX1 provides API 1.0.13 and crashes when the validation layer
@@ -732,7 +738,7 @@ void QVulkanWindowPrivate::init()
err = f->vkEnumerateDeviceLayerProperties(physDev, &count, layerProps.data());
if (err == VK_SUCCESS) {
for (const VkLayerProperties &prop : layerProps) {
- if (!strncmp(prop.layerName, stdValNamePtr, stdValName.count())) {
+ if (!strncmp(prop.layerName, stdValNamePtr, stdValName.size())) {
devInfo.enabledLayerCount = 1;
devInfo.ppEnabledLayerNames = &stdValNamePtr;
break;
@@ -855,7 +861,7 @@ void QVulkanWindowPrivate::init()
// Try to honor the user request.
if (!formats.isEmpty() && !requestedColorFormats.isEmpty()) {
- for (VkFormat reqFmt : qAsConst(requestedColorFormats)) {
+ for (VkFormat reqFmt : std::as_const(requestedColorFormats)) {
auto r = std::find_if(formats.cbegin(), formats.cend(),
[reqFmt](const VkSurfaceFormatKHR &sfmt) { return sfmt.format == reqFmt; });
if (r != formats.cend()) {
@@ -1611,6 +1617,84 @@ void QVulkanWindow::setQueueCreateInfoModifier(const QueueCreateInfoModifier &mo
d->queueCreateInfoModifier = modifier;
}
+/*!
+ \typedef QVulkanWindow::EnabledFeaturesModifier
+
+ A function that is called during graphics initialization to alter the
+ VkPhysicalDeviceFeatures that is passed in when creating a Vulkan device
+ object.
+
+ By default QVulkanWindow enables all Vulkan 1.0 core features that the
+ physical device reports as supported, with certain exceptions. In
+ praticular, \c robustBufferAccess is always disabled in order to avoid
+ unexpected performance hits.
+
+ The VkPhysicalDeviceFeatures reference passed in is all zeroed out at the
+ point when the function is invoked. It is up to the function to change
+ members as it sees fit.
+
+ \note To control Vulkan 1.1, 1.2, or 1.3 features, use
+ EnabledFeatures2Modifier instead.
+
+ \sa setEnabledFeaturesModifier()
+ */
+
+/*!
+ Sets the enabled device features modification function \a modifier.
+
+ \note To control Vulkan 1.1, 1.2, or 1.3 features, use
+ the overload taking a EnabledFeatures2Modifier instead.
+
+ \note \a modifier is passed to the callback function with all members set
+ to false. It is up to the function to change members as it sees fit.
+
+ \since 6.7
+ \sa EnabledFeaturesModifier
+ */
+void QVulkanWindow::setEnabledFeaturesModifier(const EnabledFeaturesModifier &modifier)
+{
+ Q_D(QVulkanWindow);
+ d->enabledFeaturesModifier = modifier;
+}
+
+/*!
+ \typedef QVulkanWindow::EnabledFeatures2Modifier
+
+ A function that is called during graphics initialization to alter the
+ VkPhysicalDeviceFeatures2 that is changed to the VkDeviceCreateInfo.
+
+ By default QVulkanWindow enables all Vulkan 1.0 core features that the
+ physical device reports as supported, with certain exceptions. In
+ praticular, \c robustBufferAccess is always disabled in order to avoid
+ unexpected performance hits.
+
+ This however is not always sufficient when working with Vulkan 1.1, 1.2, or
+ 1.3 features and extensions. Hence this callback mechanism. If only Vulkan
+ 1.0 is relevant at run time, use setEnabledFeaturesModifier() instead.
+
+ The VkPhysicalDeviceFeatures2 reference passed to the callback function
+ with \c sType set, but the rest zeroed out. It is up to the function to
+ change members to true, or set up \c pNext chains as it sees fit.
+
+ \note When setting up \c pNext chains, make sure the referenced objects
+ have a long enough lifetime, for example by storing them as member
+ variables in the QVulkanWindow subclass.
+
+ \since 6.7
+ \sa setEnabledFeaturesModifier()
+ */
+
+/*!
+ Sets the enabled device features modification function \a modifier.
+ \overload
+ \since 6.7
+ \sa EnabledFeatures2Modifier
+*/
+void QVulkanWindow::setEnabledFeaturesModifier(EnabledFeatures2Modifier modifier)
+{
+ Q_D(QVulkanWindow);
+ d->enabledFeatures2Modifier = std::move(modifier);
+}
/*!
Returns true if this window has successfully initialized all Vulkan
@@ -1812,13 +1896,26 @@ void QVulkanWindowRenderer::logicalDeviceLost()
{
}
+QSize QVulkanWindowPrivate::surfacePixelSize() const
+{
+ Q_Q(const QVulkanWindow);
+ VkSurfaceCapabilitiesKHR surfaceCaps = {};
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDevs.at(physDevIndex), surface, &surfaceCaps);
+ VkExtent2D bufferSize = surfaceCaps.currentExtent;
+ if (bufferSize.width == uint32_t(-1)) {
+ Q_ASSERT(bufferSize.height == uint32_t(-1));
+ return q->size() * q->devicePixelRatio();
+ }
+ return QSize(int(bufferSize.width), int(bufferSize.height));
+}
+
void QVulkanWindowPrivate::beginFrame()
{
if (!swapChain || framePending)
return;
Q_Q(QVulkanWindow);
- if (q->size() * q->devicePixelRatio() != swapChainImageSize) {
+ if (swapChainImageSize != surfacePixelSize()) {
recreateSwapChain();
if (!swapChain)
return;
@@ -1887,7 +1984,7 @@ void QVulkanWindowPrivate::beginFrame()
}
if (frameGrabbing)
- frameGrabTargetImage = QImage(swapChainImageSize, QImage::Format_RGBA8888);
+ frameGrabTargetImage = QImage(swapChainImageSize, QImage::Format_RGBA8888); // the format is as documented
if (renderer) {
framePending = true;
@@ -2021,7 +2118,7 @@ void QVulkanWindowPrivate::endFrame()
// order to circumvent driver frame callbacks
inst->presentAboutToBeQueued(q);
- err = vkQueuePresentKHR(gfxQueue, &presInfo);
+ err = vkQueuePresentKHR(presQueue, &presInfo);
if (err != VK_SUCCESS) {
if (err == VK_ERROR_OUT_OF_DATE_KHR) {
recreateSwapChain();
@@ -2233,7 +2330,7 @@ void QVulkanWindowPrivate::finishBlockingReadback()
VkPhysicalDevice QVulkanWindow::physicalDevice() const
{
Q_D(const QVulkanWindow);
- if (d->physDevIndex < d->physDevs.count())
+ if (d->physDevIndex < d->physDevs.size())
return d->physDevs[d->physDevIndex];
qWarning("QVulkanWindow: Physical device not available");
return VK_NULL_HANDLE;
@@ -2249,7 +2346,7 @@ VkPhysicalDevice QVulkanWindow::physicalDevice() const
const VkPhysicalDeviceProperties *QVulkanWindow::physicalDeviceProperties() const
{
Q_D(const QVulkanWindow);
- if (d->physDevIndex < d->physDevProps.count())
+ if (d->physDevIndex < d->physDevProps.size())
return &d->physDevProps[d->physDevIndex];
qWarning("QVulkanWindow: Physical device properties not available");
return nullptr;
@@ -2403,6 +2500,19 @@ VkFormat QVulkanWindow::depthStencilFormat() const
This usually matches the size of the window, but may also differ in case
\c vkGetPhysicalDeviceSurfaceCapabilitiesKHR reports a fixed size.
+ In addition, it has been observed on some platforms that the
+ Vulkan-reported surface size is different with high DPI scaling active,
+ meaning the QWindow-reported
+ \l{QWindow::}{size()} multiplied with the \l{QWindow::}{devicePixelRatio()}
+ was 1 pixel less or more when compared to the value returned from here,
+ presumably due to differences in rounding. Rendering code should be aware
+ of this, and any related rendering logic must be based in the value returned
+ from here, never on the QWindow-reported size. Regardless of which pixel size
+ is correct in theory, Vulkan rendering must only ever rely on the Vulkan
+ API-reported surface size. Otherwise validation errors may occur, e.g. when
+ setting the viewport, because the application-provided values may become
+ out-of-bounds from Vulkan's perspective.
+
\note Calling this function is only valid from the invocation of
QVulkanWindowRenderer::initSwapChainResources() up until
QVulkanWindowRenderer::releaseSwapChainResources().
@@ -2674,6 +2784,12 @@ bool QVulkanWindow::supportsGrab() const
incomplete image, that has the correct size but not the content yet. The
content will be delivered via the frameGrabbed() signal in the latter case.
+ The returned QImage always has a format of QImage::Format_RGBA8888. If the
+ colorFormat() is \c VK_FORMAT_B8G8R8A8_UNORM, the red and blue channels are
+ swapped automatically since this format is commonly used as the default
+ choice for swapchain color buffers. With any other color buffer format,
+ there is no conversion performed by this function.
+
\note This function should not be called when a frame is in progress
(that is, frameReady() has not yet been called back by the application).
@@ -2702,6 +2818,9 @@ QImage QVulkanWindow::grab()
d->frameGrabbing = true;
d->beginFrame();
+ if (d->colorFormat == VK_FORMAT_B8G8R8A8_UNORM)
+ d->frameGrabTargetImage = std::move(d->frameGrabTargetImage).rgbSwapped();
+
return d->frameGrabTargetImage;
}
@@ -2730,3 +2849,5 @@ QMatrix4x4 QVulkanWindow::clipCorrectionMatrix()
}
QT_END_NAMESPACE
+
+#include "moc_qvulkanwindow.cpp"
diff --git a/src/gui/vulkan/qvulkanwindow.h b/src/gui/vulkan/qvulkanwindow.h
index 4325b6317d..537dbc4ae1 100644
--- a/src/gui/vulkan/qvulkanwindow.h
+++ b/src/gui/vulkan/qvulkanwindow.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVULKANWINDOW_H
#define QVULKANWINDOW_H
@@ -47,7 +11,7 @@
#pragma qt_sync_skip_header_check
#endif
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
#include <QtGui/qvulkaninstance.h>
#include <QtGui/qwindow.h>
@@ -55,7 +19,7 @@
#include <QtGui/qmatrix4x4.h>
#include <QtCore/qset.h>
-#ifdef Q_CLANG_QDOC
+#ifdef Q_QDOC
typedef void* VkQueue;
typedef void* VkCommandPool;
typedef void* VkRenderPass;
@@ -90,6 +54,14 @@ public:
virtual void logicalDeviceLost();
};
+#ifndef VK_VERSION_1_1
+typedef struct VkPhysicalDeviceFeatures2 {
+ VkStructureType sType;
+ void* pNext;
+ VkPhysicalDeviceFeatures features;
+} VkPhysicalDeviceFeatures2;
+#endif
+
class Q_GUI_EXPORT QVulkanWindow : public QWindow
{
Q_OBJECT
@@ -113,6 +85,11 @@ public:
QVulkanInfoVector<QVulkanExtension> supportedDeviceExtensions();
void setDeviceExtensions(const QByteArrayList &extensions);
+ typedef std::function<void(VkPhysicalDeviceFeatures &)> EnabledFeaturesModifier;
+ void setEnabledFeaturesModifier(const EnabledFeaturesModifier &modifier);
+ typedef std::function<void(VkPhysicalDeviceFeatures2 &)> EnabledFeatures2Modifier;
+ void setEnabledFeaturesModifier(EnabledFeatures2Modifier modifier);
+
void setPreferredColorFormats(const QList<VkFormat> &formats);
QList<int> supportedSampleCounts();
diff --git a/src/gui/vulkan/qvulkanwindow_p.h b/src/gui/vulkan/qvulkanwindow_p.h
index de69b5c9b0..7a0ee091e6 100644
--- a/src/gui/vulkan/qvulkanwindow_p.h
+++ b/src/gui/vulkan/qvulkanwindow_p.h
@@ -1,48 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QVULKANWINDOW_P_H
#define QVULKANWINDOW_P_H
#include <QtGui/private/qtguiglobal_p.h>
-#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(vulkan) || defined(Q_QDOC)
#include "qvulkanwindow.h"
#include <QtCore/QHash>
@@ -72,6 +36,7 @@ public:
void init();
void reset();
bool createDefaultRenderPass();
+ QSize surfacePixelSize() const;
void recreateSwapChain();
uint32_t chooseTransientImageMemType(VkImage img, uint32_t startIndex);
bool createTransientImage(VkFormat format, VkImageUsageFlags usage, VkImageAspectFlags aspectMask,
@@ -103,6 +68,8 @@ public:
QList<VkFormat> requestedColorFormats;
VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
QVulkanWindow::QueueCreateInfoModifier queueCreateInfoModifier;
+ QVulkanWindow::EnabledFeaturesModifier enabledFeaturesModifier;
+ QVulkanWindow::EnabledFeatures2Modifier enabledFeatures2Modifier;
VkDevice dev = VK_NULL_HANDLE;
QVulkanDeviceFunctions *devFuncs;
diff --git a/src/gui/vulkan/vk.xml b/src/gui/vulkan/vk.xml
index dcba2c17cc..84690f07b2 100644
--- a/src/gui/vulkan/vk.xml
+++ b/src/gui/vulkan/vk.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<registry>
<comment>
-Copyright (c) 2015-2020 The Khronos Group Inc.
+Copyright 2015-2022 The Khronos Group Inc.
SPDX-License-Identifier: Apache-2.0 OR MIT
</comment>
@@ -51,11 +51,12 @@ branch of the member gitlab server.
<tag name="KDAB" author="KDAB" contact="Sean Harmer @seanharmer"/>
<tag name="ANDROID" author="Google LLC" contact="Jesse Hall @critsec"/>
<tag name="CHROMIUM" author="Google LLC" contact="Jesse Hall @critsec"/>
- <tag name="FUCHSIA" author="Google LLC" contact="Craig Stout @cdotstout, Jesse Hall @critsec"/>
+ <tag name="FUCHSIA" author="Google LLC" contact="Craig Stout @cdotstout, Jesse Hall @critsec, John Rosasco @rosasco"/>
<tag name="GGP" author="Google, LLC" contact="Jean-Francois Roy @jfroy, Hai Nguyen @chaoticbob, Jesse Hall @critsec"/>
<tag name="GOOGLE" author="Google LLC" contact="Jesse Hall @critsec"/>
<tag name="QCOM" author="Qualcomm Technologies, Inc." contact="Jeff Leger @jackohounhd"/>
<tag name="LUNARG" author="LunarG, Inc." contact="Karen Ghavam @karenghavam-lunarg"/>
+ <tag name="NZXT" author="NZXT Inc." contact="Jacob Kiesel @xaeroxe"/>
<tag name="SAMSUNG" author="Samsung Electronics Co., Ltd." contact="Alon Or-bach @alonorbach"/>
<tag name="SEC" author="Samsung Electronics Co., Ltd." contact="Alon Or-bach @alonorbach"/>
<tag name="TIZEN" author="Samsung Electronics Co., Ltd." contact="Alon Or-bach @alonorbach"/>
@@ -67,9 +68,12 @@ branch of the member gitlab server.
<tag name="EXT" author="Multivendor" contact="Jon Leech @oddhack"/>
<tag name="MESA" author="Mesa open source project" contact="Chad Versace @chadversary, Daniel Stone @fooishbar, David Airlie @airlied, Jason Ekstrand @jekstrand"/>
<tag name="INTEL" author="Intel Corporation" contact="Slawek Grajewski @sgrajewski"/>
- <tag name="HUAWEI" author="Huawei Technologies Co. Ltd." contact="Hueilong Wang @wyvernathuawei"/>
+ <tag name="HUAWEI" author="Huawei Technologies Co. Ltd." contact="Pan Gao @PanGao-h, Juntao Li @Lawrenceleehw"/>
<tag name="VALVE" author="Valve Corporation" contact="Pierre-Loup Griffais @plagman, Joshua Ashton @Joshua-Ashton, Hans-Kristian Arntzen @HansKristian-Work"/>
<tag name="QNX" author="BlackBerry Limited" contact="Mike Gorchak @mgorchak-blackberry"/>
+ <tag name="JUICE" author="Juice Technologies, Inc." contact="David McCloskey @damcclos, Dean Beeler @canadacow"/>
+ <tag name="FB" author="Facebook, Inc" contact="Artem Bolgar @artyom17"/>
+ <tag name="RASTERGRID" author="RasterGrid Kft." contact="Daniel Rakos @aqnuep1"/>
</tags>
<types comment="Vulkan type definitions">
@@ -85,6 +89,7 @@ branch of the member gitlab server.
<type category="include" name="directfb.h"/>
<type category="include" name="zircon/types.h"/>
<type category="include" name="ggp_c/vulkan_types.h"/>
+ <type category="include" name="screen/screen.h"/>
<comment>
In the current header structure, each platform's interfaces
are confined to a platform-specific header (vulkan_xlib.h,
@@ -123,53 +128,119 @@ branch of the member gitlab server.
<type requires="zircon/types.h" name="zx_handle_t"/>
<type requires="ggp_c/vulkan_types.h" name="GgpStreamDescriptor"/>
<type requires="ggp_c/vulkan_types.h" name="GgpFrameToken"/>
+ <type requires="screen/screen.h" name="_screen_context"/>
+ <type requires="screen/screen.h" name="_screen_window"/>
- <type category="define">#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \
+ <type category="define">// DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead.
+#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \
((((uint32_t)(major)) &lt;&lt; 22) | (((uint32_t)(minor)) &lt;&lt; 12) | ((uint32_t)(patch)))</type>
- <type category="define">#define <name>VK_VERSION_MAJOR</name>(version) ((uint32_t)(version) &gt;&gt; 22)</type>
- <type category="define">#define <name>VK_VERSION_MINOR</name>(version) (((uint32_t)(version) &gt;&gt; 12) &amp; 0x3ff)</type>
- <type category="define">#define <name>VK_VERSION_PATCH</name>(version) ((uint32_t)(version) &amp; 0xfff)</type>
+ <type category="define">// DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead.
+#define <name>VK_VERSION_MAJOR</name>(version) ((uint32_t)(version) &gt;&gt; 22)</type>
+ <type category="define">// DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead.
+#define <name>VK_VERSION_MINOR</name>(version) (((uint32_t)(version) &gt;&gt; 12) &amp; 0x3FFU)</type>
+ <type category="define">// DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead.
+#define <name>VK_VERSION_PATCH</name>(version) ((uint32_t)(version) &amp; 0xFFFU)</type>
+
+ <type category="define">#define <name>VK_MAKE_API_VERSION</name>(variant, major, minor, patch) \
+ ((((uint32_t)(variant)) &lt;&lt; 29) | (((uint32_t)(major)) &lt;&lt; 22) | (((uint32_t)(minor)) &lt;&lt; 12) | ((uint32_t)(patch)))</type>
+ <type category="define">#define <name>VK_API_VERSION_VARIANT</name>(version) ((uint32_t)(version) &gt;&gt; 29)</type>
+ <type category="define">#define <name>VK_API_VERSION_MAJOR</name>(version) (((uint32_t)(version) &gt;&gt; 22) &amp; 0x7FU)</type>
+ <type category="define">#define <name>VK_API_VERSION_MINOR</name>(version) (((uint32_t)(version) &gt;&gt; 12) &amp; 0x3FFU)</type>
+ <type category="define">#define <name>VK_API_VERSION_PATCH</name>(version) ((uint32_t)(version) &amp; 0xFFFU)</type>
<type category="define">// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead.
//#define <name>VK_API_VERSION</name> <type>VK_MAKE_VERSION</type>(1, 0, 0) // Patch version should always be set to 0</type>
- <type category="define">// Vulkan 1.0 version number
-#define <name>VK_API_VERSION_1_0</name> <type>VK_MAKE_VERSION</type>(1, 0, 0)// Patch version should always be set to 0</type>
- <type category="define">// Vulkan 1.1 version number
-#define <name>VK_API_VERSION_1_1</name> <type>VK_MAKE_VERSION</type>(1, 1, 0)// Patch version should always be set to 0</type>
- <type category="define">// Vulkan 1.2 version number
-#define <name>VK_API_VERSION_1_2</name> <type>VK_MAKE_VERSION</type>(1, 2, 0)// Patch version should always be set to 0</type>
+ <type category="define" requires="VK_MAKE_API_VERSION">// Vulkan 1.0 version number
+#define <name>VK_API_VERSION_1_0</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 0, 0)// Patch version should always be set to 0</type>
+ <type category="define" requires="VK_MAKE_API_VERSION">// Vulkan 1.1 version number
+#define <name>VK_API_VERSION_1_1</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 1, 0)// Patch version should always be set to 0</type>
+ <type category="define" requires="VK_MAKE_API_VERSION">// Vulkan 1.2 version number
+#define <name>VK_API_VERSION_1_2</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 2, 0)// Patch version should always be set to 0</type>
+ <type category="define" requires="VK_MAKE_API_VERSION">// Vulkan 1.3 version number
+#define <name>VK_API_VERSION_1_3</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 3, 0)// Patch version should always be set to 0</type>
<type category="define">// Version of this file
-#define <name>VK_HEADER_VERSION</name> 166</type>
+#define <name>VK_HEADER_VERSION</name> 223</type>
<type category="define" requires="VK_HEADER_VERSION">// Complete version of this file
-#define <name>VK_HEADER_VERSION_COMPLETE</name> <type>VK_MAKE_VERSION</type>(1, 2, VK_HEADER_VERSION)</type>
+#define <name>VK_HEADER_VERSION_COMPLETE</name> <type>VK_MAKE_API_VERSION</type>(0, 1, 3, VK_HEADER_VERSION)</type>
<type category="define">
#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;</type>
- <type category="define" name="VK_DEFINE_NON_DISPATCHABLE_HANDLE">
-#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE)
-#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) &amp;&amp; !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+ <type category="define" name="VK_USE_64_BIT_PTR_DEFINES">
+#ifndef VK_USE_64_BIT_PTR_DEFINES
+ #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) &amp;&amp; !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+ #define VK_USE_64_BIT_PTR_DEFINES 1
+ #else
+ #define VK_USE_64_BIT_PTR_DEFINES 0
+ #endif
+#endif</type>
+ <type category="define" requires="VK_USE_64_BIT_PTR_DEFINES" name="VK_NULL_HANDLE">
+#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE
+ #if (VK_USE_64_BIT_PTR_DEFINES==1)
+ #if (defined(__cplusplus) &amp;&amp; (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) &amp;&amp; (_MSVC_LANG >= 201103L))
+ #define VK_NULL_HANDLE nullptr
+ #else
+ #define VK_NULL_HANDLE ((void*)0)
+ #endif
+ #else
+ #define VK_NULL_HANDLE 0ULL
+ #endif
+#endif
+#ifndef VK_NULL_HANDLE
+ #define VK_NULL_HANDLE 0
+#endif</type>
+ <type category="define" requires="VK_NULL_HANDLE" name="VK_DEFINE_NON_DISPATCHABLE_HANDLE">
+#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE
+ #if (VK_USE_64_BIT_PTR_DEFINES==1)
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
-#else
+ #else
#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
-#endif
+ #endif
#endif</type>
- <type category="define">
-#define <name>VK_NULL_HANDLE</name> 0</type>
-
<type category="basetype">struct <name>ANativeWindow</name>;</type>
<type category="basetype">struct <name>AHardwareBuffer</name>;</type>
- <type category="basetype">
-#ifdef __OBJC__
+ <type category="basetype">#ifdef __OBJC__
@class CAMetalLayer;
#else
typedef void <name>CAMetalLayer</name>;
#endif</type>
+ <type category="basetype">#ifdef __OBJC__
+@protocol MTLDevice;
+typedef id&lt;MTLDevice&gt; MTLDevice_id;
+#else
+typedef void* <name>MTLDevice_id</name>;
+#endif</type>
+ <type category="basetype">#ifdef __OBJC__
+@protocol MTLCommandQueue;
+typedef id&lt;MTLCommandQueue&gt; MTLCommandQueue_id;
+#else
+typedef void* <name>MTLCommandQueue_id</name>;
+#endif</type>
+ <type category="basetype">#ifdef __OBJC__
+@protocol MTLBuffer;
+typedef id&lt;MTLBuffer&gt; MTLBuffer_id;
+#else
+typedef void* <name>MTLBuffer_id</name>;
+#endif</type>
+ <type category="basetype">#ifdef __OBJC__
+@protocol MTLTexture;
+typedef id&lt;MTLTexture&gt; MTLTexture_id;
+#else
+typedef void* <name>MTLTexture_id</name>;
+#endif</type>
+ <type category="basetype">#ifdef __OBJC__
+@protocol MTLSharedEvent;
+typedef id&lt;MTLSharedEvent&gt; MTLSharedEvent_id;
+#else
+typedef void* <name>MTLSharedEvent_id</name>;
+#endif</type>
+ <type category="basetype">typedef struct __IOSurface* <name>IOSurfaceRef</name>;</type>
<type category="basetype">typedef <type>uint32_t</type> <name>VkSampleMask</name>;</type>
<type category="basetype">typedef <type>uint32_t</type> <name>VkBool32</name>;</type>
<type category="basetype">typedef <type>uint32_t</type> <name>VkFlags</name>;</type>
+ <type category="basetype">typedef <type>uint64_t</type> <name>VkFlags64</name>;</type>
<type category="basetype">typedef <type>uint64_t</type> <name>VkDeviceSize</name>;</type>
<type category="basetype">typedef <type>uint64_t</type> <name>VkDeviceAddress</name>;</type>
@@ -178,7 +249,9 @@ typedef void <name>CAMetalLayer</name>;
<type requires="vk_platform" name="char"/>
<type requires="vk_platform" name="float"/>
<type requires="vk_platform" name="double"/>
+ <type requires="vk_platform" name="int8_t"/>
<type requires="vk_platform" name="uint8_t"/>
+ <type requires="vk_platform" name="int16_t"/>
<type requires="vk_platform" name="uint16_t"/>
<type requires="vk_platform" name="uint32_t"/>
<type requires="vk_platform" name="uint64_t"/>
@@ -192,11 +265,11 @@ typedef void <name>CAMetalLayer</name>;
<type category="bitmask">typedef <type>VkFlags</type> <name>VkQueryPoolCreateFlags</name>;</type>
<type requires="VkRenderPassCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkRenderPassCreateFlags</name>;</type>
<type requires="VkSamplerCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkSamplerCreateFlags</name>;</type>
- <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineLayoutCreateFlags</name>;</type>
+ <type requires="VkPipelineLayoutCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineLayoutCreateFlags</name>;</type>
<type requires="VkPipelineCacheCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCacheCreateFlags</name>;</type>
- <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineDepthStencilStateCreateFlags</name>;</type>
+ <type requires="VkPipelineDepthStencilStateCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineDepthStencilStateCreateFlags</name>;</type>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineDynamicStateCreateFlags</name>;</type>
- <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineColorBlendStateCreateFlags</name>;</type>
+ <type requires="VkPipelineColorBlendStateCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineColorBlendStateCreateFlags</name>;</type>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineMultisampleStateCreateFlags</name>;</type>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineRasterizationStateCreateFlags</name>;</type>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineViewportStateCreateFlags</name>;</type>
@@ -206,7 +279,7 @@ typedef void <name>CAMetalLayer</name>;
<type requires="VkPipelineShaderStageCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineShaderStageCreateFlags</name>;</type>
<type requires="VkDescriptorSetLayoutCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkDescriptorSetLayoutCreateFlags</name>;</type>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkBufferViewCreateFlags</name>;</type>
- <type category="bitmask">typedef <type>VkFlags</type> <name>VkInstanceCreateFlags</name>;</type>
+ <type requires="VkInstanceCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkInstanceCreateFlags</name>;</type>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkDeviceCreateFlags</name>;</type>
<type requires="VkDeviceQueueCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkDeviceQueueCreateFlags</name>;</type>
<type requires="VkQueueFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkQueueFlags</name>;</type>
@@ -222,13 +295,12 @@ typedef void <name>CAMetalLayer</name>;
<type requires="VkPipelineCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCreateFlags</name>;</type>
<type requires="VkColorComponentFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkColorComponentFlags</name>;</type>
<type requires="VkFenceCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkFenceCreateFlags</name>;</type>
- <comment>When VkSemaphoreCreateFlagBits is first extended, need to add a requires= attribute for it to VkSemaphoreCreateFlags</comment>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkSemaphoreCreateFlags</name>;</type>
<type requires="VkFormatFeatureFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkFormatFeatureFlags</name>;</type>
<type requires="VkQueryControlFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkQueryControlFlags</name>;</type>
<type requires="VkQueryResultFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkQueryResultFlags</name>;</type>
- <type requires="VkShaderModuleCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkShaderModuleCreateFlags</name>;</type>
- <type category="bitmask">typedef <type>VkFlags</type> <name>VkEventCreateFlags</name>;</type>
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkShaderModuleCreateFlags</name>;</type>
+ <type requires="VkEventCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkEventCreateFlags</name>;</type>
<type requires="VkCommandPoolCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkCommandPoolCreateFlags</name>;</type>
<type requires="VkCommandPoolResetFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkCommandPoolResetFlags</name>;</type>
<type requires="VkCommandBufferResetFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkCommandBufferResetFlags</name>;</type>
@@ -256,11 +328,13 @@ typedef void <name>CAMetalLayer</name>;
<type category="bitmask" name="VkGeometryInstanceFlagsNV" alias="VkGeometryInstanceFlagsKHR"/>
<type requires="VkBuildAccelerationStructureFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkBuildAccelerationStructureFlagsKHR</name>;</type>
<type category="bitmask" name="VkBuildAccelerationStructureFlagsNV" alias="VkBuildAccelerationStructureFlagsKHR"/>
- <type requires="VkPrivateDataSlotCreateFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkPrivateDataSlotCreateFlagsEXT</name>;</type>
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPrivateDataSlotCreateFlags</name>;</type>
+ <type category="bitmask" name="VkPrivateDataSlotCreateFlagsEXT" alias="VkPrivateDataSlotCreateFlags"/>
<type requires="VkAccelerationStructureCreateFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkAccelerationStructureCreateFlagsKHR</name>;</type>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkDescriptorUpdateTemplateCreateFlags</name>;</type>
<type category="bitmask" name="VkDescriptorUpdateTemplateCreateFlagsKHR" alias="VkDescriptorUpdateTemplateCreateFlags"/>
- <type requires="VkPipelineCreationFeedbackFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCreationFeedbackFlagsEXT</name>;</type>
+ <type requires="VkPipelineCreationFeedbackFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCreationFeedbackFlags</name>;</type>
+ <type category="bitmask" name="VkPipelineCreationFeedbackFlagsEXT" alias="VkPipelineCreationFeedbackFlags"/>
<type requires="VkPerformanceCounterDescriptionFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkPerformanceCounterDescriptionFlagsKHR</name>;</type>
<type requires="VkAcquireProfilingLockFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkAcquireProfilingLockFlagsKHR</name>;</type>
<type requires="VkSemaphoreWaitFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkSemaphoreWaitFlags</name>;</type>
@@ -268,6 +342,17 @@ typedef void <name>CAMetalLayer</name>;
<type requires="VkPipelineCompilerControlFlagBitsAMD" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCompilerControlFlagsAMD</name>;</type>
<type requires="VkShaderCorePropertiesFlagBitsAMD" category="bitmask">typedef <type>VkFlags</type> <name>VkShaderCorePropertiesFlagsAMD</name>;</type>
<type requires="VkDeviceDiagnosticsConfigFlagBitsNV" category="bitmask">typedef <type>VkFlags</type> <name>VkDeviceDiagnosticsConfigFlagsNV</name>;</type>
+ <type bitvalues="VkAccessFlagBits2" category="bitmask">typedef <type>VkFlags64</type> <name>VkAccessFlags2</name>;</type>
+ <type category="bitmask" name="VkAccessFlags2KHR" alias="VkAccessFlags2"/>
+ <type bitvalues="VkPipelineStageFlagBits2" category="bitmask">typedef <type>VkFlags64</type> <name>VkPipelineStageFlags2</name>;</type>
+ <type category="bitmask" name="VkPipelineStageFlags2KHR" alias="VkPipelineStageFlags2"/>
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkAccelerationStructureMotionInfoFlagsNV</name>;</type>
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkAccelerationStructureMotionInstanceFlagsNV</name>;</type>
+ <type bitvalues="VkFormatFeatureFlagBits2" category="bitmask">typedef <type>VkFlags64</type> <name>VkFormatFeatureFlags2</name>;</type>
+ <type category="bitmask" name="VkFormatFeatureFlags2KHR" alias="VkFormatFeatureFlags2"/>
+ <type requires="VkRenderingFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkRenderingFlags</name>;</type>
+ <type category="bitmask" name="VkRenderingFlagsKHR" alias="VkRenderingFlags"/>
+
<comment>WSI extensions</comment>
<type requires="VkCompositeAlphaFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkCompositeAlphaFlagsKHR</name>;</type>
@@ -289,6 +374,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="bitmask">typedef <type>VkFlags</type> <name>VkImagePipeSurfaceCreateFlagsFUCHSIA</name>;</type>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkStreamDescriptorSurfaceCreateFlagsGGP</name>;</type>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkHeadlessSurfaceCreateFlagsEXT</name>;</type>
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkScreenSurfaceCreateFlagsQNX</name>;</type>
<type requires="VkPeerMemoryFeatureFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkPeerMemoryFeatureFlags</name>;</type>
<type category="bitmask" name="VkPeerMemoryFeatureFlagsKHR" alias="VkPeerMemoryFeatureFlags"/>
<type requires="VkMemoryAllocateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkMemoryAllocateFlags</name>;</type>
@@ -337,7 +423,54 @@ typedef void <name>CAMetalLayer</name>;
<type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineRasterizationStateStreamCreateFlagsEXT</name>;</type>
<type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineRasterizationDepthClipStateCreateFlagsEXT</name>;</type>
<type requires="VkSwapchainImageUsageFlagBitsANDROID" category="bitmask">typedef <type>VkFlags</type> <name>VkSwapchainImageUsageFlagsANDROID</name>;</type>
- <type requires="VkToolPurposeFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkToolPurposeFlagsEXT</name>;</type>
+ <type requires="VkToolPurposeFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkToolPurposeFlags</name>;</type>
+ <type category="bitmask" name="VkToolPurposeFlagsEXT" alias="VkToolPurposeFlags"/>
+ <type requires="VkSubmitFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkSubmitFlags</name>;</type>
+ <type category="bitmask" name="VkSubmitFlagsKHR" alias="VkSubmitFlags"/>
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkImageFormatConstraintsFlagsFUCHSIA</name>;</type>
+ <type requires="VkImageConstraintsInfoFlagBitsFUCHSIA" category="bitmask">typedef <type>VkFlags</type> <name>VkImageConstraintsInfoFlagsFUCHSIA</name>;</type>
+ <type requires="VkGraphicsPipelineLibraryFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkGraphicsPipelineLibraryFlagsEXT</name>;</type>
+ <type requires="VkImageCompressionFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkImageCompressionFlagsEXT</name>;</type>
+ <type requires="VkImageCompressionFixedRateFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkImageCompressionFixedRateFlagsEXT</name>;</type>
+ <type requires="VkExportMetalObjectTypeFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkExportMetalObjectTypeFlagsEXT</name>;</type>
+
+ <comment>Video Core extension</comment>
+ <type requires="VkVideoCodecOperationFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoCodecOperationFlagsKHR</name>;</type>
+ <type requires="VkVideoCapabilityFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoCapabilityFlagsKHR</name>;</type>
+ <type requires="VkVideoSessionCreateFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoSessionCreateFlagsKHR</name>;</type>
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkVideoBeginCodingFlagsKHR</name>;</type>
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEndCodingFlagsKHR</name>;</type>
+ <type requires="VkVideoCodingQualityPresetFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoCodingQualityPresetFlagsKHR</name>;</type>
+ <type requires="VkVideoCodingControlFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoCodingControlFlagsKHR</name>;</type>
+
+ <comment>Video Decode Core extension</comment>
+ <type requires="VkVideoDecodeCapabilityFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoDecodeCapabilityFlagsKHR</name>;</type>
+ <type requires="VkVideoDecodeFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoDecodeFlagsKHR</name>;</type>
+
+ <comment>Video Decode H.264 extension</comment>
+ <type requires="VkVideoDecodeH264PictureLayoutFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoDecodeH264PictureLayoutFlagsEXT</name>;</type>
+
+ <comment>Video Encode Core extension</comment>
+ <type requires="VkVideoEncodeFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeFlagsKHR</name>;</type>
+ <type requires="VkVideoEncodeCapabilityFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeCapabilityFlagsKHR</name>;</type>
+ <type requires="VkVideoEncodeRateControlFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeRateControlFlagsKHR</name>;</type>
+ <type requires="VkVideoEncodeRateControlModeFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeRateControlModeFlagsKHR</name>;</type>
+ <type requires="VkVideoChromaSubsamplingFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoChromaSubsamplingFlagsKHR</name>;</type>
+ <type requires="VkVideoComponentBitDepthFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoComponentBitDepthFlagsKHR</name>;</type>
+
+ <comment>Video Encode H.264 extension</comment>
+ <type requires="VkVideoEncodeH264CapabilityFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeH264CapabilityFlagsEXT</name>;</type>
+ <type requires="VkVideoEncodeH264InputModeFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeH264InputModeFlagsEXT</name>;</type>
+ <type requires="VkVideoEncodeH264OutputModeFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeH264OutputModeFlagsEXT</name>;</type>
+ <type requires="VkVideoEncodeH264RateControlStructureFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeH264RateControlStructureFlagsEXT</name>;</type>
+
+ <comment>Video Encode H.265 extension</comment>
+ <type requires="VkVideoEncodeH265CapabilityFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeH265CapabilityFlagsEXT</name>;</type>
+ <type requires="VkVideoEncodeH265InputModeFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeH265InputModeFlagsEXT</name>;</type>
+ <type requires="VkVideoEncodeH265OutputModeFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeH265OutputModeFlagsEXT</name>;</type>
+ <type requires="VkVideoEncodeH265RateControlStructureFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeH265RateControlStructureFlagsEXT</name>;</type>
+ <type requires="VkVideoEncodeH265CtbSizeFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeH265CtbSizeFlagsEXT</name>;</type>
+ <type requires="VkVideoEncodeH265TransformBlockSizeFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkVideoEncodeH265TransformBlockSizeFlagsEXT</name>;</type>
<comment>Types which can be void pointers or class pointers, selected at compile time</comment>
<type category="handle" objtypeenum="VK_OBJECT_TYPE_INSTANCE"><type>VK_DEFINE_HANDLE</type>(<name>VkInstance</name>)</type>
@@ -374,8 +507,12 @@ typedef void <name>CAMetalLayer</name>;
<type category="handle" parent="VkDevice" objtypeenum="VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkAccelerationStructureKHR</name>)</type>
<type category="handle" parent="VkDevice" objtypeenum="VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkAccelerationStructureNV</name>)</type>
<type category="handle" parent="VkDevice" objtypeenum="VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkPerformanceConfigurationINTEL</name>)</type>
+ <type category="handle" parent="VkDevice" objtypeenum="VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkBufferCollectionFUCHSIA</name>)</type>
<type category="handle" parent="VkDevice" objtypeenum="VK_OBJECT_TYPE_DEFERRED_OPERATION_KHR"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDeferredOperationKHR</name>)</type>
- <type category="handle" parent="VkDevice" objtypeenum="VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkPrivateDataSlotEXT</name>)</type>
+ <type category="handle" parent="VkDevice" objtypeenum="VK_OBJECT_TYPE_PRIVATE_DATA_SLOT"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkPrivateDataSlot</name>)</type>
+ <type category="handle" name="VkPrivateDataSlotEXT" alias="VkPrivateDataSlot"/>
+ <type category="handle" parent="VkDevice" objtypeenum="VK_OBJECT_TYPE_CU_MODULE_NVX"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkCuModuleNVX</name>)</type>
+ <type category="handle" parent="VkDevice" objtypeenum="VK_OBJECT_TYPE_CU_FUNCTION_NVX"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkCuFunctionNVX</name>)</type>
<comment>WSI extensions</comment>
<type category="handle" parent="VkPhysicalDevice" objtypeenum="VK_OBJECT_TYPE_DISPLAY_KHR"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDisplayKHR</name>)</type>
@@ -385,6 +522,10 @@ typedef void <name>CAMetalLayer</name>;
<type category="handle" parent="VkInstance" objtypeenum="VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDebugReportCallbackEXT</name>)</type>
<type category="handle" parent="VkInstance" objtypeenum="VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDebugUtilsMessengerEXT</name>)</type>
+ <comment>Video extensions</comment>
+ <type category="handle" parent="VkDevice" objtypeenum="VK_OBJECT_TYPE_VIDEO_SESSION_KHR"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkVideoSessionKHR</name>)</type>
+ <type category="handle" parent="VkVideoSessionKHR" objtypeenum="VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkVideoSessionParametersKHR</name>)</type>
+
<comment>Types generated from corresponding enums tags below</comment>
<type name="VkAttachmentLoadOp" category="enum"/>
<type name="VkAttachmentStoreOp" category="enum"/>
@@ -463,13 +604,16 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkDescriptorPoolCreateFlagBits" category="enum"/>
<type name="VkDependencyFlagBits" category="enum"/>
<type name="VkObjectType" category="enum"/>
- <comment>When VkSemaphoreCreateFlagBits is first extended, need to add a type enum tag for it here</comment>
+ <type name="VkEventCreateFlagBits" category="enum"/>
+ <type name="VkPipelineLayoutCreateFlagBits" category="enum"/>
+ <type name="VkSemaphoreCreateFlagBits" category="enum"/>
<comment>Extensions</comment>
<type name="VkIndirectCommandsLayoutUsageFlagBitsNV" category="enum"/>
<type name="VkIndirectCommandsTokenTypeNV" category="enum"/>
<type name="VkIndirectStateFlagBitsNV" category="enum"/>
- <type name="VkPrivateDataSlotCreateFlagBitsEXT" category="enum"/>
+ <type name="VkPrivateDataSlotCreateFlagBits" category="enum"/>
+ <type category="enum" name="VkPrivateDataSlotCreateFlagBitsEXT" alias="VkPrivateDataSlotCreateFlagBits"/>
<type name="VkDescriptorUpdateTemplateType" category="enum"/>
<type category="enum" name="VkDescriptorUpdateTemplateTypeKHR" alias="VkDescriptorUpdateTemplateType"/>
<type name="VkViewportCoordinateSwizzleNV" category="enum"/>
@@ -481,7 +625,8 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkCoverageReductionModeNV" category="enum"/>
<type name="VkValidationCacheHeaderVersionEXT" category="enum"/>
<type name="VkShaderInfoTypeAMD" category="enum"/>
- <type name="VkQueueGlobalPriorityEXT" category="enum"/>
+ <type name="VkQueueGlobalPriorityKHR" category="enum"/>
+ <type name="VkQueueGlobalPriorityEXT" category="enum" alias="VkQueueGlobalPriorityKHR"/>
<type name="VkTimeDomainEXT" category="enum"/>
<type name="VkConservativeRasterizationModeEXT" category="enum"/>
<type name="VkResolveModeFlagBits" category="enum"/>
@@ -515,7 +660,8 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkScopeNV" category="enum"/>
<type name="VkComponentTypeNV" category="enum"/>
<type name="VkDeviceDiagnosticsConfigFlagBitsNV" category="enum"/>
- <type name="VkPipelineCreationFeedbackFlagBitsEXT" category="enum"/>
+ <type name="VkPipelineCreationFeedbackFlagBits" category="enum"/>
+ <type category="enum" name="VkPipelineCreationFeedbackFlagBitsEXT" alias="VkPipelineCreationFeedbackFlagBits"/>
<type name="VkPerformanceCounterScopeKHR" category="enum"/>
<type name="VkPerformanceCounterUnitKHR" category="enum"/>
<type name="VkPerformanceCounterStorageKHR" category="enum"/>
@@ -532,9 +678,29 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkShaderModuleCreateFlagBits" category="enum"/>
<type name="VkPipelineCompilerControlFlagBitsAMD" category="enum"/>
<type name="VkShaderCorePropertiesFlagBitsAMD" category="enum"/>
- <type name="VkToolPurposeFlagBitsEXT" category="enum"/>
+ <type name="VkToolPurposeFlagBits" category="enum"/>
+ <type category="enum" name="VkToolPurposeFlagBitsEXT" alias="VkToolPurposeFlagBits"/>
<type name="VkFragmentShadingRateNV" category="enum"/>
<type name="VkFragmentShadingRateTypeNV" category="enum"/>
+ <type name="VkSubpassMergeStatusEXT" category="enum"/>
+ <type name="VkAccessFlagBits2" category="enum"/>
+ <type category="enum" name="VkAccessFlagBits2KHR" alias="VkAccessFlagBits2"/>
+ <type name="VkPipelineStageFlagBits2" category="enum"/>
+ <type category="enum" name="VkPipelineStageFlagBits2KHR" alias="VkPipelineStageFlagBits2"/>
+ <type name="VkProvokingVertexModeEXT" category="enum"/>
+ <type name="VkImageFormatConstraintsFlagBitsFUCHSIA" category="enum"/>
+ <type name="VkImageConstraintsInfoFlagBitsFUCHSIA" category="enum"/>
+ <type name="VkFormatFeatureFlagBits2" category="enum"/>
+ <type category="enum" name="VkFormatFeatureFlagBits2KHR" alias="VkFormatFeatureFlagBits2"/>
+ <type name="VkRenderingFlagBits" category="enum"/>
+ <type category="enum" name="VkRenderingFlagBitsKHR" alias="VkRenderingFlagBits"/>
+ <type name="VkPipelineDepthStencilStateCreateFlagBits" category="enum"/>
+ <type name="VkPipelineColorBlendStateCreateFlagBits" category="enum"/>
+ <type name="VkImageCompressionFlagBitsEXT" category="enum"/>
+ <type name="VkImageCompressionFixedRateFlagBitsEXT" category="enum"/>
+ <type name="VkExportMetalObjectTypeFlagBitsEXT" category="enum"/>
+ <type name="VkPipelineRobustnessBufferBehaviorEXT" category="enum"/>
+ <type name="VkPipelineRobustnessImageBehaviorEXT" category="enum"/>
<comment>WSI extensions</comment>
<type name="VkColorSpaceKHR" category="enum"/>
@@ -596,6 +762,9 @@ typedef void <name>CAMetalLayer</name>;
<type category="enum" name="VkShaderFloatControlsIndependenceKHR" alias="VkShaderFloatControlsIndependence"/>
<type name="VkSwapchainImageUsageFlagBitsANDROID" category="enum"/>
<type name="VkFragmentShadingRateCombinerOpKHR" category="enum"/>
+ <type name="VkSubmitFlagBits" category="enum"/>
+ <type category="enum" name="VkSubmitFlagBitsKHR" alias="VkSubmitFlagBits"/>
+ <type name="VkGraphicsPipelineLibraryFlagBitsEXT" category="enum"/>
<comment>Enumerated types in the header, but not used by the API</comment>
<type name="VkVendorId" category="enum"/>
@@ -605,6 +774,45 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkCoarseSampleOrderTypeNV" category="enum"/>
<type name="VkPipelineExecutableStatisticFormatKHR" category="enum"/>
+ <comment>Video Core extensions</comment>
+ <type name="VkVideoCodecOperationFlagBitsKHR" category="enum"/>
+ <type name="VkVideoChromaSubsamplingFlagBitsKHR" category="enum"/>
+ <type name="VkVideoComponentBitDepthFlagBitsKHR" category="enum"/>
+ <type name="VkVideoCapabilityFlagBitsKHR" category="enum"/>
+ <type name="VkVideoSessionCreateFlagBitsKHR" category="enum"/>
+ <type name="VkVideoCodingQualityPresetFlagBitsKHR" category="enum"/>
+ <type name="VkVideoCodingControlFlagBitsKHR" category="enum"/>
+ <type name="VkQueryResultStatusKHR" category="enum"/>
+
+ <comment>Video Decode extensions</comment>
+ <type name="VkVideoDecodeCapabilityFlagBitsKHR" category="enum"/>
+ <type name="VkVideoDecodeFlagBitsKHR" category="enum"/>
+
+ <comment>Video H.264 Decode extensions</comment>
+ <type name="VkVideoDecodeH264PictureLayoutFlagBitsEXT" category="enum"/>
+
+ <comment>Video H.265 Decode extensions</comment>
+
+ <comment>Video Encode extensions</comment>
+ <type name="VkVideoEncodeFlagBitsKHR" category="enum"/>
+ <type name="VkVideoEncodeCapabilityFlagBitsKHR" category="enum"/>
+ <type name="VkVideoEncodeRateControlFlagBitsKHR" category="enum"/>
+ <type name="VkVideoEncodeRateControlModeFlagBitsKHR" category="enum"/>
+
+ <comment>Video H.264 Encode extensions</comment>
+ <type name="VkVideoEncodeH264CapabilityFlagBitsEXT" category="enum"/>
+ <type name="VkVideoEncodeH264InputModeFlagBitsEXT" category="enum"/>
+ <type name="VkVideoEncodeH264OutputModeFlagBitsEXT" category="enum"/>
+ <type name="VkVideoEncodeH264RateControlStructureFlagBitsEXT" category="enum"/>
+
+ <comment>Video H.265 Encode extensions</comment>
+ <type name="VkVideoEncodeH265CapabilityFlagBitsEXT" category="enum"/>
+ <type name="VkVideoEncodeH265InputModeFlagBitsEXT" category="enum"/>
+ <type name="VkVideoEncodeH265OutputModeFlagBitsEXT" category="enum"/>
+ <type name="VkVideoEncodeH265RateControlStructureFlagBitsEXT" category="enum"/>
+ <type name="VkVideoEncodeH265CtbSizeFlagBitsEXT" category="enum"/>
+ <type name="VkVideoEncodeH265TransformBlockSizeFlagBitsEXT" category="enum"/>
+
<comment>The PFN_vk*Function types are used by VkAllocationCallbacks below</comment>
<type category="funcpointer">typedef void (VKAPI_PTR *<name>PFN_vkInternalAllocationNotification</name>)(
<type>void</type>* pUserData,
@@ -708,15 +916,15 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkComponentSwizzle</type> <name>a</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceProperties" returnedonly="true">
- <member><type>uint32_t</type> <name>apiVersion</name></member>
- <member><type>uint32_t</type> <name>driverVersion</name></member>
- <member><type>uint32_t</type> <name>vendorID</name></member>
- <member><type>uint32_t</type> <name>deviceID</name></member>
- <member><type>VkPhysicalDeviceType</type> <name>deviceType</name></member>
- <member><type>char</type> <name>deviceName</name>[<enum>VK_MAX_PHYSICAL_DEVICE_NAME_SIZE</enum>]</member>
- <member><type>uint8_t</type> <name>pipelineCacheUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
- <member><type>VkPhysicalDeviceLimits</type> <name>limits</name></member>
- <member><type>VkPhysicalDeviceSparseProperties</type> <name>sparseProperties</name></member>
+ <member limittype="noauto"><type>uint32_t</type> <name>apiVersion</name></member>
+ <member limittype="noauto"><type>uint32_t</type> <name>driverVersion</name></member>
+ <member limittype="noauto"><type>uint32_t</type> <name>vendorID</name></member>
+ <member limittype="noauto"><type>uint32_t</type> <name>deviceID</name></member>
+ <member limittype="noauto"><type>VkPhysicalDeviceType</type> <name>deviceType</name></member>
+ <member limittype="noauto"><type>char</type> <name>deviceName</name>[<enum>VK_MAX_PHYSICAL_DEVICE_NAME_SIZE</enum>]</member>
+ <member limittype="noauto"><type>uint8_t</type> <name>pipelineCacheUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
+ <member limittype="struct"><type>VkPhysicalDeviceLimits</type> <name>limits</name></member>
+ <member limittype="struct"><type>VkPhysicalDeviceSparseProperties</type> <name>sparseProperties</name></member>
</type>
<type category="struct" name="VkExtensionProperties" returnedonly="true">
<member><type>char</type> <name>extensionName</name>[<enum>VK_MAX_EXTENSION_NAME_SIZE</enum>]<comment>extension name</comment></member>
@@ -776,10 +984,10 @@ typedef void <name>CAMetalLayer</name>;
<member len="enabledExtensionCount,null-terminated">const <type>char</type>* const* <name>ppEnabledExtensionNames</name><comment>Extension names to be enabled</comment></member>
</type>
<type category="struct" name="VkQueueFamilyProperties" returnedonly="true">
- <member optional="true"><type>VkQueueFlags</type> <name>queueFlags</name><comment>Queue flags</comment></member>
- <member><type>uint32_t</type> <name>queueCount</name></member>
- <member><type>uint32_t</type> <name>timestampValidBits</name></member>
- <member><type>VkExtent3D</type> <name>minImageTransferGranularity</name><comment>Minimum alignment requirement for image transfers</comment></member>
+ <member optional="true" limittype="bitmask"><type>VkQueueFlags</type> <name>queueFlags</name><comment>Queue flags</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>queueCount</name></member>
+ <member limittype="bits"><type>uint32_t</type> <name>timestampValidBits</name></member>
+ <member limittype="min,mul"><type>VkExtent3D</type> <name>minImageTransferGranularity</name><comment>Minimum alignment requirement for image transfers</comment></member>
</type>
<type category="struct" name="VkPhysicalDeviceMemoryProperties" returnedonly="true">
<member><type>uint32_t</type> <name>memoryTypeCount</name></member>
@@ -799,9 +1007,9 @@ typedef void <name>CAMetalLayer</name>;
<member><type>uint32_t</type> <name>memoryTypeBits</name><comment>Bitmask of the allowed memory type indices into memoryTypes[] for this object</comment></member>
</type>
<type category="struct" name="VkSparseImageFormatProperties" returnedonly="true">
- <member optional="true"><type>VkImageAspectFlags</type> <name>aspectMask</name></member>
- <member><type>VkExtent3D</type> <name>imageGranularity</name></member>
- <member optional="true"><type>VkSparseImageFormatFlags</type> <name>flags</name></member>
+ <member limittype="bitmask" optional="true"><type>VkImageAspectFlags</type> <name>aspectMask</name></member>
+ <member limittype="min,mul"><type>VkExtent3D</type> <name>imageGranularity</name></member>
+ <member limittype="bitmask" optional="true"><type>VkSparseImageFormatFlags</type> <name>flags</name></member>
</type>
<type category="struct" name="VkSparseImageMemoryRequirements" returnedonly="true">
<member><type>VkSparseImageFormatProperties</type> <name>formatProperties</name></member>
@@ -826,9 +1034,9 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkDeviceSize</type> <name>size</name><comment>Size of the range within the memory object</comment></member>
</type>
<type category="struct" name="VkFormatProperties" returnedonly="true">
- <member optional="true"><type>VkFormatFeatureFlags</type> <name>linearTilingFeatures</name><comment>Format features in case of linear tiling</comment></member>
- <member optional="true"><type>VkFormatFeatureFlags</type> <name>optimalTilingFeatures</name><comment>Format features in case of optimal tiling</comment></member>
- <member optional="true"><type>VkFormatFeatureFlags</type> <name>bufferFeatures</name><comment>Format features supported by buffers</comment></member>
+ <member optional="true" limittype="bitmask"><type>VkFormatFeatureFlags</type> <name>linearTilingFeatures</name><comment>Format features in case of linear tiling</comment></member>
+ <member optional="true" limittype="bitmask"><type>VkFormatFeatureFlags</type> <name>optimalTilingFeatures</name><comment>Format features in case of optimal tiling</comment></member>
+ <member optional="true" limittype="bitmask"><type>VkFormatFeatureFlags</type> <name>bufferFeatures</name><comment>Format features supported by buffers</comment></member>
</type>
<type category="struct" name="VkImageFormatProperties" returnedonly="true">
<member><type>VkExtent3D</type> <name>maxExtent</name><comment>max image dimensions for this resource type</comment></member>
@@ -883,7 +1091,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkBufferViewCreateInfo">
<member values="VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member optional="true"><type>VkBufferViewCreateFlags</type><name>flags</name></member>
+ <member optional="true"><type>VkBufferViewCreateFlags</type> <name>flags</name></member>
<member><type>VkBuffer</type> <name>buffer</name></member>
<member><type>VkFormat</type> <name>format</name><comment>Optionally specifies format of elements</comment></member>
<member><type>VkDeviceSize</type> <name>offset</name><comment>Specified in bytes</comment></member>
@@ -980,7 +1188,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkDeviceSize</type> <name>size</name><comment>Specified in bytes</comment></member>
<member optional="true"><type>VkDeviceMemory</type> <name>memory</name></member>
<member><type>VkDeviceSize</type> <name>memoryOffset</name><comment>Specified in bytes</comment></member>
- <member optional="true"><type>VkSparseMemoryBindFlags</type><name>flags</name></member>
+ <member optional="true"><type>VkSparseMemoryBindFlags</type> <name>flags</name></member>
</type>
<type category="struct" name="VkSparseImageMemoryBind">
<member><type>VkImageSubresource</type> <name>subresource</name></member>
@@ -988,7 +1196,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkExtent3D</type> <name>extent</name></member>
<member optional="true"><type>VkDeviceMemory</type> <name>memory</name></member>
<member><type>VkDeviceSize</type> <name>memoryOffset</name><comment>Specified in bytes</comment></member>
- <member optional="true"><type>VkSparseMemoryBindFlags</type><name>flags</name></member>
+ <member optional="true"><type>VkSparseMemoryBindFlags</type> <name>flags</name></member>
</type>
<type category="struct" name="VkSparseBufferMemoryBindInfo">
<member><type>VkBuffer</type> <name>buffer</name></member>
@@ -1047,9 +1255,9 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkOffset3D</type> <name>dstOffset</name></member>
<member><type>VkExtent3D</type> <name>extent</name></member>
</type>
- <type category="struct" name="VkShaderModuleCreateInfo">
+ <type category="struct" name="VkShaderModuleCreateInfo" structextends="VkPipelineShaderStageCreateInfo">
<member values="VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member noautovalidity="true" optional="true">const <type>void</type>* <name>pNext</name><comment>noautovalidity because this structure can be either an explicit parameter, or passed in a pNext chain</comment></member>
<member optional="true"><type>VkShaderModuleCreateFlags</type> <name>flags</name></member>
<member><type>size_t</type> <name>codeSize</name><comment>Specified in bytes</comment></member>
<member len="latexmath:[\textrm{codeSize} \over 4]" altlen="codeSize / 4">const <type>uint32_t</type>* <name>pCode</name><comment>Binary code of size codeSize</comment></member>
@@ -1077,7 +1285,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>VkDescriptorPoolCreateFlags</type> <name>flags</name></member>
<member><type>uint32_t</type> <name>maxSets</name></member>
- <member><type>uint32_t</type> <name>poolSizeCount</name></member>
+ <member optional="true"><type>uint32_t</type> <name>poolSizeCount</name></member>
<member len="poolSizeCount">const <type>VkDescriptorPoolSize</type>* <name>pPoolSizes</name></member>
</type>
<type category="struct" name="VkDescriptorSetAllocateInfo">
@@ -1103,7 +1311,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>VkPipelineShaderStageCreateFlags</type> <name>flags</name></member>
<member><type>VkShaderStageFlagBits</type> <name>stage</name><comment>Shader stage</comment></member>
- <member><type>VkShaderModule</type> <name>module</name><comment>Module containing entry point</comment></member>
+ <member optional="true"><type>VkShaderModule</type> <name>module</name><comment>Module containing entry point</comment></member>
<member len="null-terminated">const <type>char</type>* <name>pName</name><comment>Null-terminated entry point name</comment></member>
<member optional="true">const <type>VkSpecializationInfo</type>* <name>pSpecializationInfo</name></member>
</type>
@@ -1238,20 +1446,20 @@ typedef void <name>CAMetalLayer</name>;
<member values="VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>VkPipelineCreateFlags</type> <name>flags</name><comment>Pipeline creation flags</comment></member>
- <member><type>uint32_t</type> <name>stageCount</name></member>
- <member len="stageCount">const <type>VkPipelineShaderStageCreateInfo</type>* <name>pStages</name><comment>One entry for each active shader stage</comment></member>
+ <member noautovalidity="true" optional="true"><type>uint32_t</type> <name>stageCount</name></member>
+ <member noautovalidity="true" len="stageCount" optional="true">const <type>VkPipelineShaderStageCreateInfo</type>* <name>pStages</name><comment>One entry for each active shader stage</comment></member>
<member noautovalidity="true" optional="true">const <type>VkPipelineVertexInputStateCreateInfo</type>* <name>pVertexInputState</name></member>
<member noautovalidity="true" optional="true">const <type>VkPipelineInputAssemblyStateCreateInfo</type>* <name>pInputAssemblyState</name></member>
<member noautovalidity="true" optional="true">const <type>VkPipelineTessellationStateCreateInfo</type>* <name>pTessellationState</name></member>
<member noautovalidity="true" optional="true">const <type>VkPipelineViewportStateCreateInfo</type>* <name>pViewportState</name></member>
- <member>const <type>VkPipelineRasterizationStateCreateInfo</type>* <name>pRasterizationState</name></member>
+ <member noautovalidity="true" optional="true">const <type>VkPipelineRasterizationStateCreateInfo</type>* <name>pRasterizationState</name></member>
<member noautovalidity="true" optional="true">const <type>VkPipelineMultisampleStateCreateInfo</type>* <name>pMultisampleState</name></member>
<member noautovalidity="true" optional="true">const <type>VkPipelineDepthStencilStateCreateInfo</type>* <name>pDepthStencilState</name></member>
<member noautovalidity="true" optional="true">const <type>VkPipelineColorBlendStateCreateInfo</type>* <name>pColorBlendState</name></member>
<member optional="true">const <type>VkPipelineDynamicStateCreateInfo</type>* <name>pDynamicState</name></member>
- <member><type>VkPipelineLayout</type> <name>layout</name><comment>Interface layout of the pipeline</comment></member>
- <member><type>VkRenderPass</type> <name>renderPass</name></member>
- <member><type>uint32_t</type> <name>subpass</name></member>
+ <member noautovalidity="true" optional="true"><type>VkPipelineLayout</type> <name>layout</name><comment>Interface layout of the pipeline</comment></member>
+ <member noautovalidity="true" optional="true"><type>VkRenderPass</type> <name>renderPass</name></member>
+ <member noautovalidity="true"><type>uint32_t</type> <name>subpass</name></member>
<member noautovalidity="true" optional="true"><type>VkPipeline</type> <name>basePipelineHandle</name><comment>If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of</comment></member>
<member><type>int32_t</type> <name>basePipelineIndex</name><comment>If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of</comment></member>
</type>
@@ -1262,6 +1470,14 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true"><type>size_t</type> <name>initialDataSize</name><comment>Size of initial data to populate cache, in bytes</comment></member>
<member len="initialDataSize">const <type>void</type>* <name>pInitialData</name><comment>Initial data to populate cache</comment></member>
</type>
+ <type category="struct" name="VkPipelineCacheHeaderVersionOne">
+ <comment>The fields in this structure are non-normative since structure packing is implementation-defined in C. The specification defines the normative layout.</comment>
+ <member><type>uint32_t</type> <name>headerSize</name></member>
+ <member><type>VkPipelineCacheHeaderVersion</type> <name>headerVersion</name></member>
+ <member><type>uint32_t</type> <name>vendorID</name></member>
+ <member><type>uint32_t</type> <name>deviceID</name></member>
+ <member><type>uint8_t</type> <name>pipelineCacheUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
+ </type>
<type category="struct" name="VkPushConstantRange">
<member><type>VkShaderStageFlags</type> <name>stageFlags</name><comment>Which stages use the range</comment></member>
<member><type>uint32_t</type> <name>offset</name><comment>Start of the range, in bytes</comment></member>
@@ -1272,7 +1488,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>VkPipelineLayoutCreateFlags</type> <name>flags</name></member>
<member optional="true"><type>uint32_t</type> <name>setLayoutCount</name><comment>Number of descriptor sets interfaced by the pipeline</comment></member>
- <member len="setLayoutCount">const <type>VkDescriptorSetLayout</type>* <name>pSetLayouts</name><comment>Array of setCount number of descriptor set layout objects defining the layout of the</comment></member>
+ <member optional="false,true" len="setLayoutCount">const <type>VkDescriptorSetLayout</type>* <name>pSetLayouts</name><comment>Array of setCount number of descriptor set layout objects defining the layout of the</comment></member>
<member optional="true"><type>uint32_t</type> <name>pushConstantRangeCount</name><comment>Number of push-constant ranges used by the pipeline</comment></member>
<member len="pushConstantRangeCount">const <type>VkPushConstantRange</type>* <name>pPushConstantRanges</name><comment>Array of pushConstantRangeCount number of ranges used by various shader stages</comment></member>
</type>
@@ -1332,7 +1548,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkFramebuffer</type> <name>framebuffer</name></member>
<member><type>VkRect2D</type> <name>renderArea</name></member>
<member optional="true"><type>uint32_t</type> <name>clearValueCount</name></member>
- <member len="clearValueCount">const <type>VkClearValue</type>* <name>pClearValues</name></member>
+ <member len="clearValueCount" noautovalidity="true">const <type>VkClearValue</type>* <name>pClearValues</name></member>
</type>
<type category="union" name="VkClearColorValue" comment="// Union allowing specification of floating point, integer, or unsigned integer color data. Actual value selected is based on image/attachment being cleared.">
<member><type>float</type> <name>float32</name>[4]</member>
@@ -1344,13 +1560,13 @@ typedef void <name>CAMetalLayer</name>;
<member><type>uint32_t</type> <name>stencil</name></member>
</type>
<type category="union" name="VkClearValue" comment="// Union allowing specification of color or depth and stencil values. Actual value selected is based on attachment being cleared.">
- <member><type>VkClearColorValue</type> <name>color</name></member>
+ <member noautovalidity="true"><type>VkClearColorValue</type> <name>color</name></member>
<member><type>VkClearDepthStencilValue</type> <name>depthStencil</name></member>
</type>
<type category="struct" name="VkClearAttachment">
<member><type>VkImageAspectFlags</type> <name>aspectMask</name></member>
<member><type>uint32_t</type> <name>colorAttachment</name></member>
- <member><type>VkClearValue</type> <name>clearValue</name></member>
+ <member noautovalidity="true"><type>VkClearValue</type> <name>clearValue</name></member>
</type>
<type category="struct" name="VkAttachmentDescription">
<member optional="true"><type>VkAttachmentDescriptionFlags</type> <name>flags</name></member>
@@ -1382,8 +1598,8 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkSubpassDependency">
<member><type>uint32_t</type> <name>srcSubpass</name></member>
<member><type>uint32_t</type> <name>dstSubpass</name></member>
- <member><type>VkPipelineStageFlags</type> <name>srcStageMask</name></member>
- <member><type>VkPipelineStageFlags</type> <name>dstStageMask</name></member>
+ <member optional="true"><type>VkPipelineStageFlags</type> <name>srcStageMask</name></member>
+ <member optional="true"><type>VkPipelineStageFlags</type> <name>dstStageMask</name></member>
<member optional="true"><type>VkAccessFlags</type> <name>srcAccessMask</name><comment>Memory accesses from the source of the dependency to synchronize</comment></member>
<member optional="true"><type>VkAccessFlags</type> <name>dstAccessMask</name><comment>Memory accesses from the destination of the dependency to synchronize</comment></member>
<member optional="true"><type>VkDependencyFlags</type> <name>dependencyFlags</name></member>
@@ -1420,7 +1636,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBool32</type> <name>dualSrcBlend</name><comment>blend operations which take two sources</comment></member>
<member><type>VkBool32</type> <name>logicOp</name><comment>logic operations</comment></member>
<member><type>VkBool32</type> <name>multiDrawIndirect</name><comment>multi draw indirect</comment></member>
- <member><type>VkBool32</type> <name>drawIndirectFirstInstance</name><comment>indirect draws can use non-zero firstInstance</comment></member>
+ <member><type>VkBool32</type> <name>drawIndirectFirstInstance</name><comment>indirect drawing can use non-zero firstInstance</comment></member>
<member><type>VkBool32</type> <name>depthClamp</name><comment>depth clamping</comment></member>
<member><type>VkBool32</type> <name>depthBiasClamp</name><comment>depth bias clamping</comment></member>
<member><type>VkBool32</type> <name>fillModeNonSolid</name><comment>point and wireframe fill modes</comment></member>
@@ -1467,128 +1683,128 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBool32</type> <name>inheritedQueries</name><comment>Queries may be inherited from primary to secondary command buffers</comment></member>
</type>
<type category="struct" name="VkPhysicalDeviceSparseProperties" returnedonly="true">
- <member><type>VkBool32</type> <name>residencyStandard2DBlockShape</name><comment>Sparse resources support: GPU will access all 2D (single sample) sparse resources using the standard sparse image block shapes (based on pixel format)</comment></member>
- <member><type>VkBool32</type> <name>residencyStandard2DMultisampleBlockShape</name><comment>Sparse resources support: GPU will access all 2D (multisample) sparse resources using the standard sparse image block shapes (based on pixel format)</comment></member>
- <member><type>VkBool32</type> <name>residencyStandard3DBlockShape</name><comment>Sparse resources support: GPU will access all 3D sparse resources using the standard sparse image block shapes (based on pixel format)</comment></member>
- <member><type>VkBool32</type> <name>residencyAlignedMipSize</name><comment>Sparse resources support: Images with mip level dimensions that are NOT a multiple of the sparse image block dimensions will be placed in the mip tail</comment></member>
- <member><type>VkBool32</type> <name>residencyNonResidentStrict</name><comment>Sparse resources support: GPU can consistently access non-resident regions of a resource, all reads return as if data is 0, writes are discarded</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>residencyStandard2DBlockShape</name><comment>Sparse resources support: GPU will access all 2D (single sample) sparse resources using the standard sparse image block shapes (based on pixel format)</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>residencyStandard2DMultisampleBlockShape</name><comment>Sparse resources support: GPU will access all 2D (multisample) sparse resources using the standard sparse image block shapes (based on pixel format)</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>residencyStandard3DBlockShape</name><comment>Sparse resources support: GPU will access all 3D sparse resources using the standard sparse image block shapes (based on pixel format)</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>residencyAlignedMipSize</name><comment>Sparse resources support: Images with mip level dimensions that are NOT a multiple of the sparse image block dimensions will be placed in the mip tail</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>residencyNonResidentStrict</name><comment>Sparse resources support: GPU can consistently access non-resident regions of a resource, all reads return as if data is 0, writes are discarded</comment></member>
</type>
<type category="struct" name="VkPhysicalDeviceLimits" returnedonly="true">
<comment>resource maximum sizes</comment>
- <member><type>uint32_t</type> <name>maxImageDimension1D</name><comment>max 1D image dimension</comment></member>
- <member><type>uint32_t</type> <name>maxImageDimension2D</name><comment>max 2D image dimension</comment></member>
- <member><type>uint32_t</type> <name>maxImageDimension3D</name><comment>max 3D image dimension</comment></member>
- <member><type>uint32_t</type> <name>maxImageDimensionCube</name><comment>max cubemap image dimension</comment></member>
- <member><type>uint32_t</type> <name>maxImageArrayLayers</name><comment>max layers for image arrays</comment></member>
- <member><type>uint32_t</type> <name>maxTexelBufferElements</name><comment>max texel buffer size (fstexels)</comment></member>
- <member><type>uint32_t</type> <name>maxUniformBufferRange</name><comment>max uniform buffer range (bytes)</comment></member>
- <member><type>uint32_t</type> <name>maxStorageBufferRange</name><comment>max storage buffer range (bytes)</comment></member>
- <member><type>uint32_t</type> <name>maxPushConstantsSize</name><comment>max size of the push constants pool (bytes)</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxImageDimension1D</name><comment>max 1D image dimension</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxImageDimension2D</name><comment>max 2D image dimension</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxImageDimension3D</name><comment>max 3D image dimension</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxImageDimensionCube</name><comment>max cubemap image dimension</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxImageArrayLayers</name><comment>max layers for image arrays</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTexelBufferElements</name><comment>max texel buffer size (fstexels)</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxUniformBufferRange</name><comment>max uniform buffer range (bytes)</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxStorageBufferRange</name><comment>max storage buffer range (bytes)</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPushConstantsSize</name><comment>max size of the push constants pool (bytes)</comment></member>
<comment>memory limits</comment>
- <member><type>uint32_t</type> <name>maxMemoryAllocationCount</name><comment>max number of device memory allocations supported</comment></member>
- <member><type>uint32_t</type> <name>maxSamplerAllocationCount</name><comment>max number of samplers that can be allocated on a device</comment></member>
- <member><type>VkDeviceSize</type> <name>bufferImageGranularity</name><comment>Granularity (in bytes) at which buffers and images can be bound to adjacent memory for simultaneous usage</comment></member>
- <member><type>VkDeviceSize</type> <name>sparseAddressSpaceSize</name><comment>Total address space available for sparse allocations (bytes)</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMemoryAllocationCount</name><comment>max number of device memory allocations supported</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxSamplerAllocationCount</name><comment>max number of samplers that can be allocated on a device</comment></member>
+ <member limittype="min,mul"><type>VkDeviceSize</type> <name>bufferImageGranularity</name><comment>Granularity (in bytes) at which buffers and images can be bound to adjacent memory for simultaneous usage</comment></member>
+ <member limittype="max"><type>VkDeviceSize</type> <name>sparseAddressSpaceSize</name><comment>Total address space available for sparse allocations (bytes)</comment></member>
<comment>descriptor set limits</comment>
- <member><type>uint32_t</type> <name>maxBoundDescriptorSets</name><comment>max number of descriptors sets that can be bound to a pipeline</comment></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorSamplers</name><comment>max number of samplers allowed per-stage in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUniformBuffers</name><comment>max number of uniform buffers allowed per-stage in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorStorageBuffers</name><comment>max number of storage buffers allowed per-stage in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorSampledImages</name><comment>max number of sampled images allowed per-stage in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorStorageImages</name><comment>max number of storage images allowed per-stage in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorInputAttachments</name><comment>max number of input attachments allowed per-stage in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxPerStageResources</name><comment>max number of resources allowed by a single stage</comment></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetSamplers</name><comment>max number of samplers allowed in all stages in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUniformBuffers</name><comment>max number of uniform buffers allowed in all stages in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUniformBuffersDynamic</name><comment>max number of dynamic uniform buffers allowed in all stages in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetStorageBuffers</name><comment>max number of storage buffers allowed in all stages in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetStorageBuffersDynamic</name><comment>max number of dynamic storage buffers allowed in all stages in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetSampledImages</name><comment>max number of sampled images allowed in all stages in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetStorageImages</name><comment>max number of storage images allowed in all stages in a descriptor set</comment></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetInputAttachments</name><comment>max number of input attachments allowed in all stages in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxBoundDescriptorSets</name><comment>max number of descriptors sets that can be bound to a pipeline</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorSamplers</name><comment>max number of samplers allowed per-stage in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUniformBuffers</name><comment>max number of uniform buffers allowed per-stage in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorStorageBuffers</name><comment>max number of storage buffers allowed per-stage in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorSampledImages</name><comment>max number of sampled images allowed per-stage in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorStorageImages</name><comment>max number of storage images allowed per-stage in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorInputAttachments</name><comment>max number of input attachments allowed per-stage in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageResources</name><comment>max number of resources allowed by a single stage</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetSamplers</name><comment>max number of samplers allowed in all stages in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUniformBuffers</name><comment>max number of uniform buffers allowed in all stages in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUniformBuffersDynamic</name><comment>max number of dynamic uniform buffers allowed in all stages in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetStorageBuffers</name><comment>max number of storage buffers allowed in all stages in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetStorageBuffersDynamic</name><comment>max number of dynamic storage buffers allowed in all stages in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetSampledImages</name><comment>max number of sampled images allowed in all stages in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetStorageImages</name><comment>max number of storage images allowed in all stages in a descriptor set</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetInputAttachments</name><comment>max number of input attachments allowed in all stages in a descriptor set</comment></member>
<comment>vertex stage limits</comment>
- <member><type>uint32_t</type> <name>maxVertexInputAttributes</name><comment>max number of vertex input attribute slots</comment></member>
- <member><type>uint32_t</type> <name>maxVertexInputBindings</name><comment>max number of vertex input binding slots</comment></member>
- <member><type>uint32_t</type> <name>maxVertexInputAttributeOffset</name><comment>max vertex input attribute offset added to vertex buffer offset</comment></member>
- <member><type>uint32_t</type> <name>maxVertexInputBindingStride</name><comment>max vertex input binding stride</comment></member>
- <member><type>uint32_t</type> <name>maxVertexOutputComponents</name><comment>max number of output components written by vertex shader</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxVertexInputAttributes</name><comment>max number of vertex input attribute slots</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxVertexInputBindings</name><comment>max number of vertex input binding slots</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxVertexInputAttributeOffset</name><comment>max vertex input attribute offset added to vertex buffer offset</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxVertexInputBindingStride</name><comment>max vertex input binding stride</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxVertexOutputComponents</name><comment>max number of output components written by vertex shader</comment></member>
<comment>tessellation control stage limits</comment>
- <member><type>uint32_t</type> <name>maxTessellationGenerationLevel</name><comment>max level supported by tessellation primitive generator</comment></member>
- <member><type>uint32_t</type> <name>maxTessellationPatchSize</name><comment>max patch size (vertices)</comment></member>
- <member><type>uint32_t</type> <name>maxTessellationControlPerVertexInputComponents</name><comment>max number of input components per-vertex in TCS</comment></member>
- <member><type>uint32_t</type> <name>maxTessellationControlPerVertexOutputComponents</name><comment>max number of output components per-vertex in TCS</comment></member>
- <member><type>uint32_t</type> <name>maxTessellationControlPerPatchOutputComponents</name><comment>max number of output components per-patch in TCS</comment></member>
- <member><type>uint32_t</type> <name>maxTessellationControlTotalOutputComponents</name><comment>max total number of per-vertex and per-patch output components in TCS</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTessellationGenerationLevel</name><comment>max level supported by tessellation primitive generator</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTessellationPatchSize</name><comment>max patch size (vertices)</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTessellationControlPerVertexInputComponents</name><comment>max number of input components per-vertex in TCS</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTessellationControlPerVertexOutputComponents</name><comment>max number of output components per-vertex in TCS</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTessellationControlPerPatchOutputComponents</name><comment>max number of output components per-patch in TCS</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTessellationControlTotalOutputComponents</name><comment>max total number of per-vertex and per-patch output components in TCS</comment></member>
<comment>tessellation evaluation stage limits</comment>
- <member><type>uint32_t</type> <name>maxTessellationEvaluationInputComponents</name><comment>max number of input components per vertex in TES</comment></member>
- <member><type>uint32_t</type> <name>maxTessellationEvaluationOutputComponents</name><comment>max number of output components per vertex in TES</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTessellationEvaluationInputComponents</name><comment>max number of input components per vertex in TES</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTessellationEvaluationOutputComponents</name><comment>max number of output components per vertex in TES</comment></member>
<comment>geometry stage limits</comment>
- <member><type>uint32_t</type> <name>maxGeometryShaderInvocations</name><comment>max invocation count supported in geometry shader</comment></member>
- <member><type>uint32_t</type> <name>maxGeometryInputComponents</name><comment>max number of input components read in geometry stage</comment></member>
- <member><type>uint32_t</type> <name>maxGeometryOutputComponents</name><comment>max number of output components written in geometry stage</comment></member>
- <member><type>uint32_t</type> <name>maxGeometryOutputVertices</name><comment>max number of vertices that can be emitted in geometry stage</comment></member>
- <member><type>uint32_t</type> <name>maxGeometryTotalOutputComponents</name><comment>max total number of components (all vertices) written in geometry stage</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxGeometryShaderInvocations</name><comment>max invocation count supported in geometry shader</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxGeometryInputComponents</name><comment>max number of input components read in geometry stage</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxGeometryOutputComponents</name><comment>max number of output components written in geometry stage</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxGeometryOutputVertices</name><comment>max number of vertices that can be emitted in geometry stage</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxGeometryTotalOutputComponents</name><comment>max total number of components (all vertices) written in geometry stage</comment></member>
<comment>fragment stage limits</comment>
- <member><type>uint32_t</type> <name>maxFragmentInputComponents</name><comment>max number of input components read in fragment stage</comment></member>
- <member><type>uint32_t</type> <name>maxFragmentOutputAttachments</name><comment>max number of output attachments written in fragment stage</comment></member>
- <member><type>uint32_t</type> <name>maxFragmentDualSrcAttachments</name><comment>max number of output attachments written when using dual source blending</comment></member>
- <member><type>uint32_t</type> <name>maxFragmentCombinedOutputResources</name><comment>max total number of storage buffers, storage images and output buffers</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxFragmentInputComponents</name><comment>max number of input components read in fragment stage</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxFragmentOutputAttachments</name><comment>max number of output attachments written in fragment stage</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxFragmentDualSrcAttachments</name><comment>max number of output attachments written when using dual source blending</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxFragmentCombinedOutputResources</name><comment>max total number of storage buffers, storage images and output buffers</comment></member>
<comment>compute stage limits</comment>
- <member><type>uint32_t</type> <name>maxComputeSharedMemorySize</name><comment>max total storage size of work group local storage (bytes)</comment></member>
- <member><type>uint32_t</type> <name>maxComputeWorkGroupCount</name>[3]<comment>max num of compute work groups that may be dispatched by a single command (x,y,z)</comment></member>
- <member><type>uint32_t</type> <name>maxComputeWorkGroupInvocations</name><comment>max total compute invocations in a single local work group</comment></member>
- <member><type>uint32_t</type> <name>maxComputeWorkGroupSize</name>[3]<comment>max local size of a compute work group (x,y,z)</comment></member>
- <member><type>uint32_t</type> <name>subPixelPrecisionBits</name><comment>number bits of subpixel precision in screen x and y</comment></member>
- <member><type>uint32_t</type> <name>subTexelPrecisionBits</name><comment>number bits of precision for selecting texel weights</comment></member>
- <member><type>uint32_t</type> <name>mipmapPrecisionBits</name><comment>number bits of precision for selecting mipmap weights</comment></member>
- <member><type>uint32_t</type> <name>maxDrawIndexedIndexValue</name><comment>max index value for indexed draw calls (for 32-bit indices)</comment></member>
- <member><type>uint32_t</type> <name>maxDrawIndirectCount</name><comment>max draw count for indirect draw calls</comment></member>
- <member><type>float</type> <name>maxSamplerLodBias</name><comment>max absolute sampler LOD bias</comment></member>
- <member><type>float</type> <name>maxSamplerAnisotropy</name><comment>max degree of sampler anisotropy</comment></member>
- <member><type>uint32_t</type> <name>maxViewports</name><comment>max number of active viewports</comment></member>
- <member><type>uint32_t</type> <name>maxViewportDimensions</name>[2]<comment>max viewport dimensions (x,y)</comment></member>
- <member><type>float</type> <name>viewportBoundsRange</name>[2]<comment>viewport bounds range (min,max)</comment></member>
- <member><type>uint32_t</type> <name>viewportSubPixelBits</name><comment>number bits of subpixel precision for viewport</comment></member>
- <member><type>size_t</type> <name>minMemoryMapAlignment</name><comment>min required alignment of pointers returned by MapMemory (bytes)</comment></member>
- <member><type>VkDeviceSize</type> <name>minTexelBufferOffsetAlignment</name><comment>min required alignment for texel buffer offsets (bytes) </comment></member>
- <member><type>VkDeviceSize</type> <name>minUniformBufferOffsetAlignment</name><comment>min required alignment for uniform buffer sizes and offsets (bytes)</comment></member>
- <member><type>VkDeviceSize</type> <name>minStorageBufferOffsetAlignment</name><comment>min required alignment for storage buffer offsets (bytes)</comment></member>
- <member><type>int32_t</type> <name>minTexelOffset</name><comment>min texel offset for OpTextureSampleOffset</comment></member>
- <member><type>uint32_t</type> <name>maxTexelOffset</name><comment>max texel offset for OpTextureSampleOffset</comment></member>
- <member><type>int32_t</type> <name>minTexelGatherOffset</name><comment>min texel offset for OpTextureGatherOffset</comment></member>
- <member><type>uint32_t</type> <name>maxTexelGatherOffset</name><comment>max texel offset for OpTextureGatherOffset</comment></member>
- <member><type>float</type> <name>minInterpolationOffset</name><comment>furthest negative offset for interpolateAtOffset</comment></member>
- <member><type>float</type> <name>maxInterpolationOffset</name><comment>furthest positive offset for interpolateAtOffset</comment></member>
- <member><type>uint32_t</type> <name>subPixelInterpolationOffsetBits</name><comment>number of subpixel bits for interpolateAtOffset</comment></member>
- <member><type>uint32_t</type> <name>maxFramebufferWidth</name><comment>max width for a framebuffer</comment></member>
- <member><type>uint32_t</type> <name>maxFramebufferHeight</name><comment>max height for a framebuffer</comment></member>
- <member><type>uint32_t</type> <name>maxFramebufferLayers</name><comment>max layer count for a layered framebuffer</comment></member>
- <member optional="true"><type>VkSampleCountFlags</type> <name>framebufferColorSampleCounts</name><comment>supported color sample counts for a framebuffer</comment></member>
- <member optional="true"><type>VkSampleCountFlags</type> <name>framebufferDepthSampleCounts</name><comment>supported depth sample counts for a framebuffer</comment></member>
- <member optional="true"><type>VkSampleCountFlags</type> <name>framebufferStencilSampleCounts</name><comment>supported stencil sample counts for a framebuffer</comment></member>
- <member optional="true"><type>VkSampleCountFlags</type> <name>framebufferNoAttachmentsSampleCounts</name><comment>supported sample counts for a subpass which uses no attachments</comment></member>
- <member><type>uint32_t</type> <name>maxColorAttachments</name><comment>max number of color attachments per subpass</comment></member>
- <member optional="true"><type>VkSampleCountFlags</type> <name>sampledImageColorSampleCounts</name><comment>supported color sample counts for a non-integer sampled image</comment></member>
- <member optional="true"><type>VkSampleCountFlags</type> <name>sampledImageIntegerSampleCounts</name><comment>supported sample counts for an integer image</comment></member>
- <member optional="true"><type>VkSampleCountFlags</type> <name>sampledImageDepthSampleCounts</name><comment>supported depth sample counts for a sampled image</comment></member>
- <member optional="true"><type>VkSampleCountFlags</type> <name>sampledImageStencilSampleCounts</name><comment>supported stencil sample counts for a sampled image</comment></member>
- <member optional="true"><type>VkSampleCountFlags</type> <name>storageImageSampleCounts</name><comment>supported sample counts for a storage image</comment></member>
- <member><type>uint32_t</type> <name>maxSampleMaskWords</name><comment>max number of sample mask words</comment></member>
- <member><type>VkBool32</type> <name>timestampComputeAndGraphics</name><comment>timestamps on graphics and compute queues</comment></member>
- <member><type>float</type> <name>timestampPeriod</name><comment>number of nanoseconds it takes for timestamp query value to increment by 1</comment></member>
- <member><type>uint32_t</type> <name>maxClipDistances</name><comment>max number of clip distances</comment></member>
- <member><type>uint32_t</type> <name>maxCullDistances</name><comment>max number of cull distances</comment></member>
- <member><type>uint32_t</type> <name>maxCombinedClipAndCullDistances</name><comment>max combined number of user clipping</comment></member>
- <member><type>uint32_t</type> <name>discreteQueuePriorities</name><comment>distinct queue priorities available </comment></member>
- <member><type>float</type> <name>pointSizeRange</name>[2]<comment>range (min,max) of supported point sizes</comment></member>
- <member><type>float</type> <name>lineWidthRange</name>[2]<comment>range (min,max) of supported line widths</comment></member>
- <member><type>float</type> <name>pointSizeGranularity</name><comment>granularity of supported point sizes</comment></member>
- <member><type>float</type> <name>lineWidthGranularity</name><comment>granularity of supported line widths</comment></member>
- <member><type>VkBool32</type> <name>strictLines</name><comment>line rasterization follows preferred rules</comment></member>
- <member><type>VkBool32</type> <name>standardSampleLocations</name><comment>supports standard sample locations for all supported sample counts</comment></member>
- <member><type>VkDeviceSize</type> <name>optimalBufferCopyOffsetAlignment</name><comment>optimal offset of buffer copies</comment></member>
- <member><type>VkDeviceSize</type> <name>optimalBufferCopyRowPitchAlignment</name><comment>optimal pitch of buffer copies</comment></member>
- <member><type>VkDeviceSize</type> <name>nonCoherentAtomSize</name><comment>minimum size and alignment for non-coherent host-mapped device memory access</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxComputeSharedMemorySize</name><comment>max total storage size of work group local storage (bytes)</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxComputeWorkGroupCount</name>[3]<comment>max num of compute work groups that may be dispatched by a single command (x,y,z)</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxComputeWorkGroupInvocations</name><comment>max total compute invocations in a single local work group</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxComputeWorkGroupSize</name>[3]<comment>max local size of a compute work group (x,y,z)</comment></member>
+ <member limittype="bits"><type>uint32_t</type> <name>subPixelPrecisionBits</name><comment>number bits of subpixel precision in screen x and y</comment></member>
+ <member limittype="bits"><type>uint32_t</type> <name>subTexelPrecisionBits</name><comment>number bits of precision for selecting texel weights</comment></member>
+ <member limittype="bits"><type>uint32_t</type> <name>mipmapPrecisionBits</name><comment>number bits of precision for selecting mipmap weights</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDrawIndexedIndexValue</name><comment>max index value for indexed draw calls (for 32-bit indices)</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDrawIndirectCount</name><comment>max draw count for indirect drawing calls</comment></member>
+ <member limittype="max"><type>float</type> <name>maxSamplerLodBias</name><comment>max absolute sampler LOD bias</comment></member>
+ <member limittype="max"><type>float</type> <name>maxSamplerAnisotropy</name><comment>max degree of sampler anisotropy</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxViewports</name><comment>max number of active viewports</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxViewportDimensions</name>[2]<comment>max viewport dimensions (x,y)</comment></member>
+ <member limittype="range"><type>float</type> <name>viewportBoundsRange</name>[2]<comment>viewport bounds range (min,max)</comment></member>
+ <member limittype="bits"><type>uint32_t</type> <name>viewportSubPixelBits</name><comment>number bits of subpixel precision for viewport</comment></member>
+ <member limittype="min,pot"><type>size_t</type> <name>minMemoryMapAlignment</name><comment>min required alignment of pointers returned by MapMemory (bytes)</comment></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>minTexelBufferOffsetAlignment</name><comment>min required alignment for texel buffer offsets (bytes) </comment></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>minUniformBufferOffsetAlignment</name><comment>min required alignment for uniform buffer sizes and offsets (bytes)</comment></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>minStorageBufferOffsetAlignment</name><comment>min required alignment for storage buffer offsets (bytes)</comment></member>
+ <member limittype="min"><type>int32_t</type> <name>minTexelOffset</name><comment>min texel offset for OpTextureSampleOffset</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTexelOffset</name><comment>max texel offset for OpTextureSampleOffset</comment></member>
+ <member limittype="min"><type>int32_t</type> <name>minTexelGatherOffset</name><comment>min texel offset for OpTextureGatherOffset</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTexelGatherOffset</name><comment>max texel offset for OpTextureGatherOffset</comment></member>
+ <member limittype="min"><type>float</type> <name>minInterpolationOffset</name><comment>furthest negative offset for interpolateAtOffset</comment></member>
+ <member limittype="max"><type>float</type> <name>maxInterpolationOffset</name><comment>furthest positive offset for interpolateAtOffset</comment></member>
+ <member limittype="bits"><type>uint32_t</type> <name>subPixelInterpolationOffsetBits</name><comment>number of subpixel bits for interpolateAtOffset</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxFramebufferWidth</name><comment>max width for a framebuffer</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxFramebufferHeight</name><comment>max height for a framebuffer</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxFramebufferLayers</name><comment>max layer count for a layered framebuffer</comment></member>
+ <member limittype="bitmask" optional="true"><type>VkSampleCountFlags</type> <name>framebufferColorSampleCounts</name><comment>supported color sample counts for a framebuffer</comment></member>
+ <member limittype="bitmask" optional="true"><type>VkSampleCountFlags</type> <name>framebufferDepthSampleCounts</name><comment>supported depth sample counts for a framebuffer</comment></member>
+ <member limittype="bitmask" optional="true"><type>VkSampleCountFlags</type> <name>framebufferStencilSampleCounts</name><comment>supported stencil sample counts for a framebuffer</comment></member>
+ <member limittype="bitmask" optional="true"><type>VkSampleCountFlags</type> <name>framebufferNoAttachmentsSampleCounts</name><comment>supported sample counts for a subpass which uses no attachments</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxColorAttachments</name><comment>max number of color attachments per subpass</comment></member>
+ <member limittype="bitmask" optional="true"><type>VkSampleCountFlags</type> <name>sampledImageColorSampleCounts</name><comment>supported color sample counts for a non-integer sampled image</comment></member>
+ <member limittype="bitmask" optional="true"><type>VkSampleCountFlags</type> <name>sampledImageIntegerSampleCounts</name><comment>supported sample counts for an integer image</comment></member>
+ <member limittype="bitmask" optional="true"><type>VkSampleCountFlags</type> <name>sampledImageDepthSampleCounts</name><comment>supported depth sample counts for a sampled image</comment></member>
+ <member limittype="bitmask" optional="true"><type>VkSampleCountFlags</type> <name>sampledImageStencilSampleCounts</name><comment>supported stencil sample counts for a sampled image</comment></member>
+ <member limittype="bitmask" optional="true"><type>VkSampleCountFlags</type> <name>storageImageSampleCounts</name><comment>supported sample counts for a storage image</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxSampleMaskWords</name><comment>max number of sample mask words</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>timestampComputeAndGraphics</name><comment>timestamps on graphics and compute queues</comment></member>
+ <member limittype="min,mul"><type>float</type> <name>timestampPeriod</name><comment>number of nanoseconds it takes for timestamp query value to increment by 1</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxClipDistances</name><comment>max number of clip distances</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxCullDistances</name><comment>max number of cull distances</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxCombinedClipAndCullDistances</name><comment>max combined number of user clipping</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>discreteQueuePriorities</name><comment>distinct queue priorities available </comment></member>
+ <member limittype="range"><type>float</type> <name>pointSizeRange</name>[2]<comment>range (min,max) of supported point sizes</comment></member>
+ <member limittype="range"><type>float</type> <name>lineWidthRange</name>[2]<comment>range (min,max) of supported line widths</comment></member>
+ <member limittype="min,mul"><type>float</type> <name>pointSizeGranularity</name><comment>granularity of supported point sizes</comment></member>
+ <member limittype="min,mul"><type>float</type> <name>lineWidthGranularity</name><comment>granularity of supported line widths</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>strictLines</name><comment>line rasterization follows preferred rules</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>standardSampleLocations</name><comment>supports standard sample locations for all supported sample counts</comment></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>optimalBufferCopyOffsetAlignment</name><comment>optimal offset of buffer copies</comment></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>optimalBufferCopyRowPitchAlignment</name><comment>optimal pitch of buffer copies</comment></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>nonCoherentAtomSize</name><comment>minimum size and alignment for non-coherent host-mapped device memory access</comment></member>
</type>
<type category="struct" name="VkSemaphoreCreateInfo">
<member values="VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
@@ -1607,7 +1823,7 @@ typedef void <name>CAMetalLayer</name>;
<member values="VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>VkFramebufferCreateFlags</type> <name>flags</name></member>
- <member><type>VkRenderPass</type> <name>renderPass</name></member>
+ <member><type>VkRenderPass</type> <name>renderPass</name></member>
<member optional="true"><type>uint32_t</type> <name>attachmentCount</name></member>
<member noautovalidity="true" len="attachmentCount">const <type>VkImageView</type>* <name>pAttachments</name></member>
<member><type>uint32_t</type> <name>width</name></member>
@@ -1632,6 +1848,15 @@ typedef void <name>CAMetalLayer</name>;
<member noautovalidity="true"><type>uint32_t</type> <name>y</name></member>
<member noautovalidity="true"><type>uint32_t</type> <name>z</name></member>
</type>
+ <type category="struct" name="VkMultiDrawInfoEXT">
+ <member><type>uint32_t</type> <name>firstVertex</name></member>
+ <member><type>uint32_t</type> <name>vertexCount</name></member>
+ </type>
+ <type category="struct" name="VkMultiDrawIndexedInfoEXT">
+ <member><type>uint32_t</type> <name>firstIndex</name></member>
+ <member><type>uint32_t</type> <name>indexCount</name></member>
+ <member><type>int32_t</type> <name>vertexOffset</name></member>
+ </type>
<type category="struct" name="VkSubmitInfo">
<member values="VK_STRUCTURE_TYPE_SUBMIT_INFO"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
@@ -1708,10 +1933,10 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkExtent2D</type> <name>minImageExtent</name><comment>Supported minimum image width and height for the surface</comment></member>
<member><type>VkExtent2D</type> <name>maxImageExtent</name><comment>Supported maximum image width and height for the surface</comment></member>
<member><type>uint32_t</type> <name>maxImageArrayLayers</name><comment>Supported maximum number of image layers for the surface</comment></member>
- <member optional="true"><type>VkSurfaceTransformFlagsKHR</type> <name>supportedTransforms</name><comment>1 or more bits representing the transforms supported</comment></member>
+ <member><type>VkSurfaceTransformFlagsKHR</type> <name>supportedTransforms</name><comment>1 or more bits representing the transforms supported</comment></member>
<member><type>VkSurfaceTransformFlagBitsKHR</type> <name>currentTransform</name><comment>The surface's current transform relative to the device's natural orientation</comment></member>
- <member optional="true"><type>VkCompositeAlphaFlagsKHR</type> <name>supportedCompositeAlpha</name><comment>1 or more bits representing the alpha compositing modes supported</comment></member>
- <member optional="true"><type>VkImageUsageFlags</type> <name>supportedUsageFlags</name><comment>Supported image usage flags for the surface</comment></member>
+ <member><type>VkCompositeAlphaFlagsKHR</type> <name>supportedCompositeAlpha</name><comment>1 or more bits representing the alpha compositing modes supported</comment></member>
+ <member><type>VkImageUsageFlags</type> <name>supportedUsageFlags</name><comment>Supported image usage flags for the surface</comment></member>
</type>
<type category="struct" name="VkAndroidSurfaceCreateInfoKHR">
<member values="VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
@@ -1772,6 +1997,13 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true"><type>VkStreamDescriptorSurfaceCreateFlagsGGP</type> <name>flags</name></member>
<member><type>GgpStreamDescriptor</type> <name>streamDescriptor</name></member>
</type>
+ <type category="struct" name="VkScreenSurfaceCreateInfoQNX">
+ <member values="VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkScreenSurfaceCreateFlagsQNX</type> <name>flags</name></member>
+ <member noautovalidity="true">struct <type>_screen_context</type>* <name>context</name></member>
+ <member noautovalidity="true">struct <type>_screen_window</type>* <name>window</name></member>
+ </type>
<type category="struct" name="VkSurfaceFormatKHR" returnedonly="true">
<member><type>VkFormat</type> <name>format</name><comment>Supported pair of rendering format</comment></member>
<member><type>VkColorSpaceKHR</type> <name>colorSpace</name><comment>and color space for the surface</comment></member>
@@ -1836,14 +2068,14 @@ typedef void <name>CAMetalLayer</name>;
<member values="VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkDebugReportObjectTypeEXT</type> <name>objectType</name><comment>The type of the object</comment></member>
- <member><type>uint64_t</type> <name>object</name><comment>The handle of the object, cast to uint64_t</comment></member>
+ <member objecttype="objectType"><type>uint64_t</type> <name>object</name><comment>The handle of the object, cast to uint64_t</comment></member>
<member len="null-terminated">const <type>char</type>* <name>pObjectName</name><comment>Name to apply to the object</comment></member>
</type>
<type category="struct" name="VkDebugMarkerObjectTagInfoEXT">
<member values="VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkDebugReportObjectTypeEXT</type> <name>objectType</name><comment>The type of the object</comment></member>
- <member><type>uint64_t</type> <name>object</name><comment>The handle of the object, cast to uint64_t</comment></member>
+ <member objecttype="objectType"><type>uint64_t</type> <name>object</name><comment>The handle of the object, cast to uint64_t</comment></member>
<member><type>uint64_t</type> <name>tagName</name><comment>The name of the tag to set on the object</comment></member>
<member><type>size_t</type> <name>tagSize</name><comment>The length in bytes of the tag data</comment></member>
<member len="tagSize">const <type>void</type>* <name>pTag</name><comment>Tag data to attach to the object</comment></member>
@@ -1852,7 +2084,7 @@ typedef void <name>CAMetalLayer</name>;
<member values="VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member len="null-terminated">const <type>char</type>* <name>pMarkerName</name><comment>Name of the debug marker</comment></member>
- <member optional="true"><type>float</type> <name>color</name>[4]<comment>Optional color for debug marker</comment></member>
+ <member><type>float</type> <name>color</name>[4]<comment>Optional color for debug marker</comment></member>
</type>
<type category="struct" name="VkDedicatedAllocationImageCreateInfoNV" structextends="VkImageCreateInfo">
<member values="VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
@@ -1898,7 +2130,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>SECURITY_ATTRIBUTES</type>* <name>pAttributes</name></member>
<member optional="true"><type>DWORD</type> <name>dwAccess</name></member>
</type>
- <type category="struct" name="VkWin32KeyedMutexAcquireReleaseInfoNV" structextends="VkSubmitInfo">
+ <type category="struct" name="VkWin32KeyedMutexAcquireReleaseInfoNV" structextends="VkSubmitInfo,VkSubmitInfo2">
<member values="VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>uint32_t</type> <name>acquireCount</name></member>
@@ -1910,37 +2142,45 @@ typedef void <name>CAMetalLayer</name>;
<member len="releaseCount">const <type>uint64_t</type>* <name>pReleaseKeys</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceDeviceGeneratedCommandsFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>deviceGeneratedCommands</name></member>
</type>
- <type category="struct" name="VkDevicePrivateDataCreateInfoEXT" allowduplicate="true" structextends="VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <type category="struct" name="VkDevicePrivateDataCreateInfo" allowduplicate="true" structextends="VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>uint32_t</type> <name>privateDataSlotRequestCount</name></member>
</type>
- <type category="struct" name="VkPrivateDataSlotCreateInfoEXT">
- <member values="VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <type category="struct" name="VkDevicePrivateDataCreateInfoEXT" alias="VkDevicePrivateDataCreateInfo"/>
+ <type category="struct" name="VkPrivateDataSlotCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkPrivateDataSlotCreateFlagsEXT</type> <name>flags</name></member>
+ <member><type>VkPrivateDataSlotCreateFlags</type> <name>flags</name></member>
</type>
- <type category="struct" name="VkPhysicalDevicePrivateDataFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <type category="struct" name="VkPrivateDataSlotCreateInfoEXT" alias="VkPrivateDataSlotCreateInfo"/>
+ <type category="struct" name="VkPhysicalDevicePrivateDataFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>privateData</name></member>
</type>
+ <type category="struct" name="VkPhysicalDevicePrivateDataFeaturesEXT" alias="VkPhysicalDevicePrivateDataFeatures"/>
<type category="struct" name="VkPhysicalDeviceDeviceGeneratedCommandsPropertiesNV" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxGraphicsShaderGroupCount</name></member>
- <member><type>uint32_t</type> <name>maxIndirectSequenceCount</name></member>
- <member><type>uint32_t</type> <name>maxIndirectCommandsTokenCount</name></member>
- <member><type>uint32_t</type> <name>maxIndirectCommandsStreamCount</name></member>
- <member><type>uint32_t</type> <name>maxIndirectCommandsTokenOffset</name></member>
- <member><type>uint32_t</type> <name>maxIndirectCommandsStreamStride</name></member>
- <member><type>uint32_t</type> <name>minSequencesCountBufferOffsetAlignment</name></member>
- <member><type>uint32_t</type> <name>minSequencesIndexBufferOffsetAlignment</name></member>
- <member><type>uint32_t</type> <name>minIndirectCommandsBufferOffsetAlignment</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxGraphicsShaderGroupCount</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxIndirectSequenceCount</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxIndirectCommandsTokenCount</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxIndirectCommandsStreamCount</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxIndirectCommandsTokenOffset</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxIndirectCommandsStreamStride</name></member>
+ <member limittype="min"><type>uint32_t</type> <name>minSequencesCountBufferOffsetAlignment</name></member>
+ <member limittype="min"><type>uint32_t</type> <name>minSequencesIndexBufferOffsetAlignment</name></member>
+ <member limittype="min"><type>uint32_t</type> <name>minIndirectCommandsBufferOffsetAlignment</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceMultiDrawPropertiesEXT" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMultiDrawCount</name></member>
</type>
<type category="struct" name="VkGraphicsShaderGroupCreateInfoNV">
<member values="VK_STRUCTURE_TYPE_GRAPHICS_SHADER_GROUP_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
@@ -1952,8 +2192,8 @@ typedef void <name>CAMetalLayer</name>;
</type>
<type category="struct" name="VkGraphicsPipelineShaderGroupsCreateInfoNV" structextends="VkGraphicsPipelineCreateInfo">
<member values="VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_SHADER_GROUPS_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>groupCount</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>uint32_t</type> <name>groupCount</name></member>
<member len="groupCount">const <type>VkGraphicsShaderGroupCreateInfoNV</type>* <name>pGroups</name></member>
<member optional="true"><type>uint32_t</type> <name>pipelineCount</name></member>
<member len="pipelineCount">const <type>VkPipeline</type>* <name>pPipelines</name></member>
@@ -1998,7 +2238,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkIndirectCommandsLayoutCreateInfoNV">
<member values="VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkIndirectCommandsLayoutUsageFlagsNV</type> <name>flags</name></member>
+ <member optional="true"><type>VkIndirectCommandsLayoutUsageFlagsNV</type> <name>flags</name></member>
<member><type>VkPipelineBindPoint</type> <name>pipelineBindPoint</name></member>
<member><type>uint32_t</type> <name>tokenCount</name></member>
<member len="tokenCount">const <type>VkIndirectCommandsLayoutTokenNV</type>* <name>pTokens</name></member>
@@ -2018,9 +2258,9 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkDeviceSize</type> <name>preprocessOffset</name></member>
<member><type>VkDeviceSize</type> <name>preprocessSize</name></member>
<member optional="true"><type>VkBuffer</type> <name>sequencesCountBuffer</name></member>
- <member optional="true"><type>VkDeviceSize</type> <name>sequencesCountOffset</name></member>
+ <member><type>VkDeviceSize</type> <name>sequencesCountOffset</name></member>
<member optional="true"><type>VkBuffer</type> <name>sequencesIndexBuffer</name></member>
- <member optional="true"><type>VkDeviceSize</type> <name>sequencesIndexOffset</name></member>
+ <member><type>VkDeviceSize</type> <name>sequencesIndexOffset</name></member>
</type>
<type category="struct" name="VkGeneratedCommandsMemoryRequirementsInfoNV">
<member values="VK_STRUCTURE_TYPE_GENERATED_COMMANDS_MEMORY_REQUIREMENTS_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
@@ -2039,7 +2279,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkPhysicalDeviceProperties</type> <name>properties</name></member>
+ <member limittype="struct"><type>VkPhysicalDeviceProperties</type> <name>properties</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceProperties2KHR" alias="VkPhysicalDeviceProperties2"/>
<type category="struct" name="VkFormatProperties2" returnedonly="true">
@@ -2067,7 +2307,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkQueueFamilyProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkQueueFamilyProperties</type> <name>queueFamilyProperties</name></member>
+ <member limittype="struct"><type>VkQueueFamilyProperties</type> <name>queueFamilyProperties</name></member>
</type>
<type category="struct" name="VkQueueFamilyProperties2KHR" alias="VkQueueFamilyProperties2"/>
<type category="struct" name="VkPhysicalDeviceMemoryProperties2" returnedonly="true">
@@ -2079,7 +2319,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkSparseImageFormatProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkSparseImageFormatProperties</type> <name>properties</name></member>
+ <member limittype="struct"><type>VkSparseImageFormatProperties</type> <name>properties</name></member>
</type>
<type category="struct" name="VkSparseImageFormatProperties2KHR" alias="VkSparseImageFormatProperties2"/>
<type category="struct" name="VkPhysicalDeviceSparseImageFormatInfo2">
@@ -2095,7 +2335,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDevicePushDescriptorPropertiesKHR" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxPushDescriptors</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPushDescriptors</name></member>
</type>
<type category="struct" name="VkConformanceVersion">
<member><type>uint8_t</type> <name>major</name></member>
@@ -2107,10 +2347,10 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceDriverProperties" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkDriverId</type> <name>driverID</name></member>
- <member><type>char</type> <name>driverName</name>[<enum>VK_MAX_DRIVER_NAME_SIZE</enum>]</member>
- <member><type>char</type> <name>driverInfo</name>[<enum>VK_MAX_DRIVER_INFO_SIZE</enum>]</member>
- <member><type>VkConformanceVersion</type> <name>conformanceVersion</name></member>
+ <member limittype="exact"><type>VkDriverId</type> <name>driverID</name></member>
+ <member limittype="exact"><type>char</type> <name>driverName</name>[<enum>VK_MAX_DRIVER_NAME_SIZE</enum>]</member>
+ <member limittype="exact"><type>char</type> <name>driverInfo</name>[<enum>VK_MAX_DRIVER_INFO_SIZE</enum>]</member>
+ <member limittype="exact"><type>VkConformanceVersion</type> <name>conformanceVersion</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceDriverPropertiesKHR" alias="VkPhysicalDeviceDriverProperties"/>
<type category="struct" name="VkPresentRegionsKHR" structextends="VkPresentInfoKHR">
@@ -2172,11 +2412,11 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceIDProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint8_t</type> <name>deviceUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
- <member><type>uint8_t</type> <name>driverUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
- <member><type>uint8_t</type> <name>deviceLUID</name>[<enum>VK_LUID_SIZE</enum>]</member>
- <member><type>uint32_t</type> <name>deviceNodeMask</name></member>
- <member><type>VkBool32</type> <name>deviceLUIDValid</name></member>
+ <member limittype="noauto"><type>uint8_t</type> <name>deviceUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
+ <member limittype="noauto"><type>uint8_t</type> <name>driverUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
+ <member limittype="noauto"><type>uint8_t</type> <name>deviceLUID</name>[<enum>VK_LUID_SIZE</enum>]</member>
+ <member limittype="noauto"><type>uint32_t</type> <name>deviceNodeMask</name></member>
+ <member limittype="noauto"><type>VkBool32</type> <name>deviceLUIDValid</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceIDPropertiesKHR" alias="VkPhysicalDeviceIDProperties"/>
<type category="struct" name="VkExternalMemoryImageCreateInfo" structextends="VkImageCreateInfo">
@@ -2211,6 +2451,23 @@ typedef void <name>CAMetalLayer</name>;
<member><type>DWORD</type> <name>dwAccess</name></member>
<member><type>LPCWSTR</type> <name>name</name></member>
</type>
+ <type category="struct" name="VkImportMemoryZirconHandleInfoFUCHSIA" structextends="VkMemoryAllocateInfo">
+ <member values="VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkExternalMemoryHandleTypeFlagBits</type> <name>handleType</name></member>
+ <member optional="true"><type>zx_handle_t</type> <name>handle</name></member>
+ </type>
+ <type category="struct" name="VkMemoryZirconHandlePropertiesFUCHSIA" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>memoryTypeBits</name></member>
+ </type>
+ <type category="struct" name="VkMemoryGetZirconHandleInfoFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkDeviceMemory</type> <name>memory</name></member>
+ <member><type>VkExternalMemoryHandleTypeFlagBits</type> <name>handleType</name></member>
+ </type>
<type category="struct" name="VkMemoryWin32HandlePropertiesKHR" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -2239,7 +2496,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkDeviceMemory</type> <name>memory</name></member>
<member><type>VkExternalMemoryHandleTypeFlagBits</type> <name>handleType</name></member>
</type>
- <type category="struct" name="VkWin32KeyedMutexAcquireReleaseInfoKHR" structextends="VkSubmitInfo">
+ <type category="struct" name="VkWin32KeyedMutexAcquireReleaseInfoKHR" structextends="VkSubmitInfo,VkSubmitInfo2">
<member values="VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>uint32_t</type> <name>acquireCount</name></member>
@@ -2275,7 +2532,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member externsync="true"><type>VkSemaphore</type> <name>semaphore</name></member>
<member optional="true"><type>VkSemaphoreImportFlags</type> <name>flags</name></member>
- <member optional="true"><type>VkExternalSemaphoreHandleTypeFlagBits</type> <name>handleType</name></member>
+ <member noautovalidity="true"><type>VkExternalSemaphoreHandleTypeFlagBits</type> <name>handleType</name></member>
<member optional="true"><type>HANDLE</type> <name>handle</name></member>
<member optional="true"><type>LPCWSTR</type> <name>name</name></member>
</type>
@@ -2314,6 +2571,20 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkSemaphore</type> <name>semaphore</name></member>
<member><type>VkExternalSemaphoreHandleTypeFlagBits</type> <name>handleType</name></member>
</type>
+ <type category="struct" name="VkImportSemaphoreZirconHandleInfoFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member externsync="true"><type>VkSemaphore</type> <name>semaphore</name></member>
+ <member optional="true"><type>VkSemaphoreImportFlags</type> <name>flags</name></member>
+ <member><type>VkExternalSemaphoreHandleTypeFlagBits</type> <name>handleType</name></member>
+ <member><type>zx_handle_t</type> <name>zirconHandle</name></member>
+ </type>
+ <type category="struct" name="VkSemaphoreGetZirconHandleInfoFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkSemaphore</type> <name>semaphore</name></member>
+ <member><type>VkExternalSemaphoreHandleTypeFlagBits</type> <name>handleType</name></member>
+ </type>
<type category="struct" name="VkPhysicalDeviceExternalFenceInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
@@ -2339,7 +2610,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member externsync="true"><type>VkFence</type> <name>fence</name></member>
<member optional="true"><type>VkFenceImportFlags</type> <name>flags</name></member>
- <member optional="true"><type>VkExternalFenceHandleTypeFlagBits</type> <name>handleType</name></member>
+ <member noautovalidity="true"><type>VkExternalFenceHandleTypeFlagBits</type> <name>handleType</name></member>
<member optional="true"><type>HANDLE</type> <name>handle</name></member>
<member optional="true"><type>LPCWSTR</type> <name>name</name></member>
</type>
@@ -2381,8 +2652,8 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceMultiviewProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxMultiviewViewCount</name><comment>max number of views in a subpass</comment></member>
- <member><type>uint32_t</type> <name>maxMultiviewInstanceIndex</name><comment>max instance index for a draw in a multiview subpass</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMultiviewViewCount</name><comment>max number of views in a subpass</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMultiviewInstanceIndex</name><comment>max instance index for a draw in a multiview subpass</comment></member>
</type>
<type category="struct" name="VkPhysicalDeviceMultiviewPropertiesKHR" alias="VkPhysicalDeviceMultiviewProperties"/>
<type category="struct" name="VkRenderPassMultiviewCreateInfo" structextends="VkRenderPassCreateInfo">
@@ -2405,10 +2676,10 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkExtent2D</type> <name>minImageExtent</name><comment>Supported minimum image width and height for the surface</comment></member>
<member><type>VkExtent2D</type> <name>maxImageExtent</name><comment>Supported maximum image width and height for the surface</comment></member>
<member><type>uint32_t</type> <name>maxImageArrayLayers</name><comment>Supported maximum number of image layers for the surface</comment></member>
- <member optional="true"><type>VkSurfaceTransformFlagsKHR</type> <name>supportedTransforms</name><comment>1 or more bits representing the transforms supported</comment></member>
+ <member><type>VkSurfaceTransformFlagsKHR</type> <name>supportedTransforms</name><comment>1 or more bits representing the transforms supported</comment></member>
<member><type>VkSurfaceTransformFlagBitsKHR</type> <name>currentTransform</name><comment>The surface's current transform relative to the device's natural orientation</comment></member>
- <member optional="true"><type>VkCompositeAlphaFlagsKHR</type> <name>supportedCompositeAlpha</name><comment>1 or more bits representing the alpha compositing modes supported</comment></member>
- <member optional="true"><type>VkImageUsageFlags</type> <name>supportedUsageFlags</name><comment>Supported image usage flags for the surface</comment></member>
+ <member><type>VkCompositeAlphaFlagsKHR</type> <name>supportedCompositeAlpha</name><comment>1 or more bits representing the alpha compositing modes supported</comment></member>
+ <member><type>VkImageUsageFlags</type> <name>supportedUsageFlags</name><comment>Supported image usage flags for the surface</comment></member>
<member optional="true"><type>VkSurfaceCounterFlagsEXT</type> <name>supportedSurfaceCounters</name></member>
</type>
<type category="struct" name="VkDisplayPowerInfoEXT">
@@ -2478,7 +2749,7 @@ typedef void <name>CAMetalLayer</name>;
<member len="splitInstanceBindRegionCount">const <type>VkRect2D</type>* <name>pSplitInstanceBindRegions</name></member>
</type>
<type category="struct" name="VkBindImageMemoryDeviceGroupInfoKHR" alias="VkBindImageMemoryDeviceGroupInfo"/>
- <type category="struct" name="VkDeviceGroupRenderPassBeginInfo" structextends="VkRenderPassBeginInfo">
+ <type category="struct" name="VkDeviceGroupRenderPassBeginInfo" structextends="VkRenderPassBeginInfo,VkRenderingInfo">
<member values="VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>uint32_t</type> <name>deviceMask</name></member>
@@ -2512,7 +2783,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkDeviceGroupBindSparseInfoKHR" alias="VkDeviceGroupBindSparseInfo"/>
<type category="struct" name="VkDeviceGroupPresentCapabilitiesKHR" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>uint32_t</type> <name>presentMask</name>[<enum>VK_MAX_DEVICE_GROUP_SIZE</enum>]</member>
<member><type>VkDeviceGroupPresentModeFlagsKHR</type> <name>modes</name></member>
</type>
@@ -2573,7 +2844,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkDescriptorUpdateTemplateType</type> <name>templateType</name></member>
<member noautovalidity="true"><type>VkDescriptorSetLayout</type> <name>descriptorSetLayout</name></member>
<member noautovalidity="true"><type>VkPipelineBindPoint</type> <name>pipelineBindPoint</name></member>
- <member noautovalidity="true"><type>VkPipelineLayout</type><name>pipelineLayout</name><comment>If used for push descriptors, this is the only allowed layout</comment></member>
+ <member noautovalidity="true"><type>VkPipelineLayout</type> <name>pipelineLayout</name><comment>If used for push descriptors, this is the only allowed layout</comment></member>
<member noautovalidity="true"><type>uint32_t</type> <name>set</name></member>
</type>
<type category="struct" name="VkDescriptorUpdateTemplateCreateInfoKHR" alias="VkDescriptorUpdateTemplateCreateInfo"/>
@@ -2581,6 +2852,22 @@ typedef void <name>CAMetalLayer</name>;
<member><type>float</type> <name>x</name></member>
<member><type>float</type> <name>y</name></member>
</type>
+ <type category="struct" name="VkPhysicalDevicePresentIdFeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>presentId</name><comment>Present ID in VkPresentInfoKHR</comment></member>
+ </type>
+ <type category="struct" name="VkPresentIdKHR" structextends="VkPresentInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_PRESENT_ID_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>swapchainCount</name><comment>Copy of VkPresentInfoKHR::swapchainCount</comment></member>
+ <member len="swapchainCount" optional="true">const <type>uint64_t</type>* <name>pPresentIds</name><comment>Present ID values for each swapchain</comment></member>
+ </type>
+ <type category="struct" name="VkPhysicalDevicePresentWaitFeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>presentWait</name><comment>vkWaitForPresentKHR is supported</comment></member>
+ </type>
<type category="struct" name="VkHdrMetadataEXT">
<comment>Display primary in chromaticity coordinates</comment>
<member values="VK_STRUCTURE_TYPE_HDR_METADATA_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -2671,7 +2958,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceDiscardRectanglePropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxDiscardRectangles</name><comment>max number of active discard rectangles</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDiscardRectangles</name><comment>max number of active discard rectangles</comment></member>
</type>
<type category="struct" name="VkPipelineDiscardRectangleStateCreateInfoEXT" structextends="VkGraphicsPipelineCreateInfo">
<member values="VK_STRUCTURE_TYPE_PIPELINE_DISCARD_RECTANGLE_STATE_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -2684,7 +2971,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceMultiviewPerViewAttributesPropertiesNVX" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkBool32</type> <name>perViewPositionAllComponents</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>perViewPositionAllComponents</name></member>
</type>
<type category="struct" name="VkInputAttachmentAspectReference">
<member><type>uint32_t</type> <name>subpass</name></member>
@@ -2702,7 +2989,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceSurfaceInfo2KHR">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkSurfaceKHR</type> <name>surface</name></member>
+ <member optional="true"><type>VkSurfaceKHR</type> <name>surface</name></member>
</type>
<type category="struct" name="VkSurfaceCapabilities2KHR" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
@@ -2757,10 +3044,10 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceSubgroupProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member noautovalidity="true"><type>uint32_t</type> <name>subgroupSize</name><comment>The size of a subgroup for this queue.</comment></member>
- <member noautovalidity="true"><type>VkShaderStageFlags</type> <name>supportedStages</name><comment>Bitfield of what shader stages support subgroup operations</comment></member>
- <member noautovalidity="true"><type>VkSubgroupFeatureFlags</type> <name>supportedOperations</name><comment>Bitfield of what subgroup operations are supported.</comment></member>
- <member noautovalidity="true"><type>VkBool32</type> <name>quadOperationsInAllStages</name><comment>Flag to specify whether quad operations are available in all stages.</comment></member>
+ <member limittype="min,pot" noautovalidity="true"><type>uint32_t</type> <name>subgroupSize</name><comment>The size of a subgroup for this queue.</comment></member>
+ <member limittype="bitmask" noautovalidity="true"><type>VkShaderStageFlags</type> <name>supportedStages</name><comment>Bitfield of what shader stages support subgroup operations</comment></member>
+ <member limittype="bitmask" noautovalidity="true"><type>VkSubgroupFeatureFlags</type> <name>supportedOperations</name><comment>Bitfield of what subgroup operations are supported.</comment></member>
+ <member limittype="bitmask" noautovalidity="true"><type>VkBool32</type> <name>quadOperationsInAllStages</name><comment>Flag to specify whether quad operations are available in all stages.</comment></member>
</type>
<type category="struct" name="VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
@@ -2774,6 +3061,12 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBuffer</type> <name>buffer</name></member>
</type>
<type category="struct" name="VkBufferMemoryRequirementsInfo2KHR" alias="VkBufferMemoryRequirementsInfo2"/>
+ <type category="struct" name="VkDeviceBufferMemoryRequirements">
+ <member values="VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member>const <type>VkBufferCreateInfo</type>* <name>pCreateInfo</name></member>
+ </type>
+ <type category="struct" name="VkDeviceBufferMemoryRequirementsKHR" alias="VkDeviceBufferMemoryRequirements"/>
<type category="struct" name="VkImageMemoryRequirementsInfo2">
<member values="VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
@@ -2786,6 +3079,13 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkImage</type> <name>image</name></member>
</type>
<type category="struct" name="VkImageSparseMemoryRequirementsInfo2KHR" alias="VkImageSparseMemoryRequirementsInfo2"/>
+ <type category="struct" name="VkDeviceImageMemoryRequirements">
+ <member values="VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member>const <type>VkImageCreateInfo</type>* <name>pCreateInfo</name></member>
+ <member optional="true"><type>VkImageAspectFlagBits</type> <name>planeAspect</name></member>
+ </type>
+ <type category="struct" name="VkDeviceImageMemoryRequirementsKHR" alias="VkDeviceImageMemoryRequirements"/>
<type category="struct" name="VkMemoryRequirements2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -2801,7 +3101,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDevicePointClippingProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkPointClippingBehavior</type> <name>pointClippingBehavior</name></member>
+ <member limittype="exact"><type>VkPointClippingBehavior</type> <name>pointClippingBehavior</name></member>
</type>
<type category="struct" name="VkPhysicalDevicePointClippingPropertiesKHR" alias="VkPhysicalDevicePointClippingProperties"/>
<type category="struct" name="VkMemoryDedicatedRequirements" returnedonly="true" structextends="VkMemoryRequirements2">
@@ -2898,7 +3198,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceProtectedMemoryProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkBool32</type> <name>protectedNoFault</name></member>
+ <member limittype="exact"><type>VkBool32</type> <name>protectedNoFault</name></member>
</type>
<type category="struct" name="VkDeviceQueueInfo2">
<member values="VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2"><type>VkStructureType</type> <name>sType</name></member>
@@ -2917,18 +3217,18 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceSamplerFilterMinmaxProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkBool32</type> <name>filterMinmaxSingleComponentFormats</name></member>
- <member><type>VkBool32</type> <name>filterMinmaxImageComponentMapping</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>filterMinmaxSingleComponentFormats</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>filterMinmaxImageComponentMapping</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT" alias="VkPhysicalDeviceSamplerFilterMinmaxProperties"/>
<type category="struct" name="VkSampleLocationEXT">
<member><type>float</type> <name>x</name></member>
<member><type>float</type> <name>y</name></member>
</type>
- <type category="struct" name="VkSampleLocationsInfoEXT" structextends="VkImageMemoryBarrier">
+ <type category="struct" name="VkSampleLocationsInfoEXT" structextends="VkImageMemoryBarrier,VkImageMemoryBarrier2">
<member values="VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member optional="true"><type>VkSampleCountFlagBits</type> <name>sampleLocationsPerPixel</name></member>
+ <member noautovalidity="true"><type>VkSampleCountFlagBits</type> <name>sampleLocationsPerPixel</name></member>
<member><type>VkExtent2D</type> <name>sampleLocationGridSize</name></member>
<member optional="true"><type>uint32_t</type> <name>sampleLocationsCount</name></member>
<member len="sampleLocationsCount">const <type>VkSampleLocationEXT</type>* <name>pSampleLocations</name></member>
@@ -2958,11 +3258,11 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceSampleLocationsPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkSampleCountFlags</type> <name>sampleLocationSampleCounts</name></member>
- <member><type>VkExtent2D</type> <name>maxSampleLocationGridSize</name></member>
- <member><type>float</type> <name>sampleLocationCoordinateRange</name>[2]</member>
- <member><type>uint32_t</type> <name>sampleLocationSubPixelBits</name></member>
- <member><type>VkBool32</type> <name>variableSampleLocations</name></member>
+ <member limittype="bitmask"><type>VkSampleCountFlags</type> <name>sampleLocationSampleCounts</name></member>
+ <member limittype="max"><type>VkExtent2D</type> <name>maxSampleLocationGridSize</name></member>
+ <member limittype="range"><type>float</type> <name>sampleLocationCoordinateRange</name>[2]</member>
+ <member limittype="bits"><type>uint32_t</type> <name>sampleLocationSubPixelBits</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>variableSampleLocations</name></member>
</type>
<type category="struct" name="VkMultisamplePropertiesEXT" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_MULTISAMPLE_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -2980,15 +3280,20 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>advancedBlendCoherentOperations</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceMultiDrawFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>multiDraw</name></member>
+ </type>
<type category="struct" name="VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>advancedBlendMaxColorAttachments</name></member>
- <member><type>VkBool32</type> <name>advancedBlendIndependentBlend</name></member>
- <member><type>VkBool32</type> <name>advancedBlendNonPremultipliedSrcColor</name></member>
- <member><type>VkBool32</type> <name>advancedBlendNonPremultipliedDstColor</name></member>
- <member><type>VkBool32</type> <name>advancedBlendCorrelatedOverlap</name></member>
- <member><type>VkBool32</type> <name>advancedBlendAllOperations</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>advancedBlendMaxColorAttachments</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>advancedBlendIndependentBlend</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>advancedBlendNonPremultipliedSrcColor</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>advancedBlendNonPremultipliedDstColor</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>advancedBlendCorrelatedOverlap</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>advancedBlendAllOperations</name></member>
</type>
<type category="struct" name="VkPipelineColorBlendAdvancedStateCreateInfoEXT" structextends="VkPipelineColorBlendStateCreateInfo">
<member values="VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_ADVANCED_STATE_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -2997,32 +3302,36 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBool32</type> <name>dstPremultiplied</name></member>
<member><type>VkBlendOverlapEXT</type> <name>blendOverlap</name></member>
</type>
- <type category="struct" name="VkPhysicalDeviceInlineUniformBlockFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <type category="struct" name="VkPhysicalDeviceInlineUniformBlockFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>inlineUniformBlock</name></member>
<member><type>VkBool32</type> <name>descriptorBindingInlineUniformBlockUpdateAfterBind</name></member>
</type>
- <type category="struct" name="VkPhysicalDeviceInlineUniformBlockPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <type category="struct" name="VkPhysicalDeviceInlineUniformBlockFeaturesEXT" alias="VkPhysicalDeviceInlineUniformBlockFeatures"/>
+ <type category="struct" name="VkPhysicalDeviceInlineUniformBlockProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxInlineUniformBlockSize</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorInlineUniformBlocks</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetInlineUniformBlocks</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindInlineUniformBlocks</name></member>
- </type>
- <type category="struct" name="VkWriteDescriptorSetInlineUniformBlockEXT" structextends="VkWriteDescriptorSet">
- <member values="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>dataSize</name></member>
- <member len="dataSize">const <type>void</type>* <name>pData</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxInlineUniformBlockSize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorInlineUniformBlocks</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetInlineUniformBlocks</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindInlineUniformBlocks</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceInlineUniformBlockPropertiesEXT" alias="VkPhysicalDeviceInlineUniformBlockProperties"/>
+ <type category="struct" name="VkWriteDescriptorSetInlineUniformBlock" structextends="VkWriteDescriptorSet">
+ <member values="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>dataSize</name></member>
+ <member len="dataSize">const <type>void</type>* <name>pData</name></member>
</type>
- <type category="struct" name="VkDescriptorPoolInlineUniformBlockCreateInfoEXT" structextends="VkDescriptorPoolCreateInfo">
- <member values="VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxInlineUniformBlockBindings</name></member>
+ <type category="struct" name="VkWriteDescriptorSetInlineUniformBlockEXT" alias="VkWriteDescriptorSetInlineUniformBlock"/>
+ <type category="struct" name="VkDescriptorPoolInlineUniformBlockCreateInfo" structextends="VkDescriptorPoolCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>maxInlineUniformBlockBindings</name></member>
</type>
+ <type category="struct" name="VkDescriptorPoolInlineUniformBlockCreateInfoEXT" alias="VkDescriptorPoolInlineUniformBlockCreateInfo"/>
<type category="struct" name="VkPipelineCoverageModulationStateCreateInfoNV" structextends="VkPipelineMultisampleStateCreateInfo">
<member values="VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
@@ -3046,7 +3355,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true"><type>size_t</type> <name>initialDataSize</name></member>
<member len="initialDataSize">const <type>void</type>* <name>pInitialData</name></member>
</type>
- <type category="struct" name="VkShaderModuleValidationCacheCreateInfoEXT" structextends="VkShaderModuleCreateInfo">
+ <type category="struct" name="VkShaderModuleValidationCacheCreateInfoEXT" structextends="VkShaderModuleCreateInfo,VkPipelineShaderStageCreateInfo">
<member values="VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkValidationCacheEXT</type> <name>validationCache</name></member>
@@ -3054,10 +3363,22 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceMaintenance3Properties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxPerSetDescriptors</name></member>
- <member><type>VkDeviceSize</type> <name>maxMemoryAllocationSize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerSetDescriptors</name></member>
+ <member limittype="max"><type>VkDeviceSize</type> <name>maxMemoryAllocationSize</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceMaintenance3PropertiesKHR" alias="VkPhysicalDeviceMaintenance3Properties"/>
+ <type category="struct" name="VkPhysicalDeviceMaintenance4Features" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>maintenance4</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceMaintenance4FeaturesKHR" alias="VkPhysicalDeviceMaintenance4Features"/>
+ <type category="struct" name="VkPhysicalDeviceMaintenance4Properties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="max"><type>VkDeviceSize</type> <name>maxBufferSize</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceMaintenance4PropertiesKHR" alias="VkPhysicalDeviceMaintenance4Properties"/>
<type category="struct" name="VkDescriptorSetLayoutSupport" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -3081,23 +3402,23 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceFloatControlsProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkShaderFloatControlsIndependence</type> <name>denormBehaviorIndependence</name></member>
- <member><type>VkShaderFloatControlsIndependence</type> <name>roundingModeIndependence</name></member>
- <member><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat16</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
- <member><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat32</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
- <member><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat64</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormPreserveFloat16</name><comment>An implementation can preserve denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormPreserveFloat32</name><comment>An implementation can preserve denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormPreserveFloat64</name><comment>An implementation can preserve denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat16</name><comment>An implementation can flush to zero denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat32</name><comment>An implementation can flush to zero denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat64</name><comment>An implementation can flush to zero denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTEFloat16</name><comment>An implementation can support RTE</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTEFloat32</name><comment>An implementation can support RTE</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTEFloat64</name><comment>An implementation can support RTE</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTZFloat16</name><comment>An implementation can support RTZ</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTZFloat32</name><comment>An implementation can support RTZ</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTZFloat64</name><comment>An implementation can support RTZ</comment></member>
+ <member limittype="exact"><type>VkShaderFloatControlsIndependence</type> <name>denormBehaviorIndependence</name></member>
+ <member limittype="exact"><type>VkShaderFloatControlsIndependence</type> <name>roundingModeIndependence</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat16</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat32</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat64</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormPreserveFloat16</name><comment>An implementation can preserve denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormPreserveFloat32</name><comment>An implementation can preserve denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormPreserveFloat64</name><comment>An implementation can preserve denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat16</name><comment>An implementation can flush to zero denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat32</name><comment>An implementation can flush to zero denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat64</name><comment>An implementation can flush to zero denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTEFloat16</name><comment>An implementation can support RTE</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTEFloat32</name><comment>An implementation can support RTE</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTEFloat64</name><comment>An implementation can support RTE</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTZFloat16</name><comment>An implementation can support RTZ</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTZFloat32</name><comment>An implementation can support RTZ</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTZFloat64</name><comment>An implementation can support RTZ</comment></member>
</type>
<type category="struct" name="VkPhysicalDeviceFloatControlsPropertiesKHR" alias="VkPhysicalDeviceFloatControlsProperties"/>
<type category="struct" name="VkPhysicalDeviceHostQueryResetFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
@@ -3145,23 +3466,37 @@ typedef void <name>CAMetalLayer</name>;
<member><type>uint32_t</type> <name>numAvailableSgprs</name></member>
<member><type>uint32_t</type> <name>computeWorkGroupSize</name>[3]</member>
</type>
- <type category="struct" name="VkDeviceQueueGlobalPriorityCreateInfoEXT" structextends="VkDeviceQueueCreateInfo">
- <member values="VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <type category="struct" name="VkDeviceQueueGlobalPriorityCreateInfoKHR" structextends="VkDeviceQueueCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkQueueGlobalPriorityEXT</type> <name>globalPriority</name></member>
+ <member><type>VkQueueGlobalPriorityKHR</type> <name>globalPriority</name></member>
</type>
- <type category="struct" name="VkDebugUtilsObjectNameInfoEXT">
+ <type category="struct" name="VkDeviceQueueGlobalPriorityCreateInfoEXT" alias="VkDeviceQueueGlobalPriorityCreateInfoKHR"/>
+ <type category="struct" name="VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>globalPriorityQuery</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT" alias="VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR"/>
+ <type category="struct" name="VkQueueFamilyGlobalPriorityPropertiesKHR" structextends="VkQueueFamilyProperties2">
+ <member values="VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>priorityCount</name></member>
+ <member limittype="bitmask"><type>VkQueueGlobalPriorityKHR</type> <name>priorities</name>[<enum>VK_MAX_GLOBAL_PRIORITY_SIZE_KHR</enum>]</member>
+ </type>
+ <type category="struct" name="VkQueueFamilyGlobalPriorityPropertiesEXT" alias="VkQueueFamilyGlobalPriorityPropertiesKHR"/>
+ <type category="struct" name="VkDebugUtilsObjectNameInfoEXT" structextends="VkPipelineShaderStageCreateInfo">
<member values="VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkObjectType</type> <name>objectType</name></member>
- <member><type>uint64_t</type> <name>objectHandle</name></member>
+ <member objecttype="objectType"><type>uint64_t</type> <name>objectHandle</name></member>
<member optional="true" len="null-terminated">const <type>char</type>* <name>pObjectName</name></member>
</type>
<type category="struct" name="VkDebugUtilsObjectTagInfoEXT">
<member values="VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_TAG_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkObjectType</type> <name>objectType</name></member>
- <member><type>uint64_t</type> <name>objectHandle</name></member>
+ <member objecttype="objectType"><type>uint64_t</type> <name>objectHandle</name></member>
<member><type>uint64_t</type> <name>tagName</name></member>
<member><type>size_t</type> <name>tagSize</name></member>
<member len="tagSize">const <type>void</type>* <name>pTag</name></member>
@@ -3170,7 +3505,7 @@ typedef void <name>CAMetalLayer</name>;
<member values="VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member len="null-terminated">const <type>char</type>* <name>pLabelName</name></member>
- <member optional="true"><type>float</type> <name>color</name>[4]</member>
+ <member><type>float</type> <name>color</name>[4]</member>
</type>
<type category="struct" name="VkDebugUtilsMessengerCreateInfoEXT" allowduplicate="true" structextends="VkInstanceCreateInfo">
<member values="VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -3186,7 +3521,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>VkDebugUtilsMessengerCallbackDataFlagsEXT</type> <name>flags</name></member>
<member optional="true" len="null-terminated">const <type>char</type>* <name>pMessageIdName</name></member>
- <member optional="true"><type>int32_t</type> <name>messageIdNumber</name></member>
+ <member><type>int32_t</type> <name>messageIdNumber</name></member>
<member len="null-terminated">const <type>char</type>* <name>pMessage</name></member>
<member optional="true"><type>uint32_t</type> <name>queueLabelCount</name></member>
<member len="queueLabelCount">const <type>VkDebugUtilsLabelEXT</type>* <name>pQueueLabels</name></member>
@@ -3209,14 +3544,14 @@ typedef void <name>CAMetalLayer</name>;
</type>
<type category="struct" name="VkDeviceMemoryReportCallbackDataEXT" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_DEVICE_MEMORY_REPORT_CALLBACK_DATA_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkDeviceMemoryReportFlagsEXT</type> <name>flags</name></member>
<member><type>VkDeviceMemoryReportEventTypeEXT</type> <name>type</name></member>
<member><type>uint64_t</type> <name>memoryObjectId</name></member>
- <member optional="true"><type>VkDeviceSize</type> <name>size</name></member>
- <member optional="true"><type>VkObjectType</type> <name>objectType</name></member>
- <member optional="true"><type>uint64_t</type> <name>objectHandle</name></member>
- <member optional="true"><type>uint32_t</type> <name>heapIndex</name></member>
+ <member><type>VkDeviceSize</type> <name>size</name></member>
+ <member><type>VkObjectType</type> <name>objectType</name></member>
+ <member objecttype="objectType"><type>uint64_t</type> <name>objectHandle</name></member>
+ <member><type>uint32_t</type> <name>heapIndex</name></member>
</type>
<type category="struct" name="VkImportMemoryHostPointerInfoEXT" structextends="VkMemoryAllocateInfo">
<member values="VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -3232,20 +3567,20 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceExternalMemoryHostPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkDeviceSize</type> <name>minImportedHostPointerAlignment</name></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>minImportedHostPointerAlignment</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceConservativeRasterizationPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>float</type> <name>primitiveOverestimationSize</name><comment>The size in pixels the primitive is enlarged at each edge during conservative rasterization</comment></member>
- <member><type>float</type> <name>maxExtraPrimitiveOverestimationSize</name><comment>The maximum additional overestimation the client can specify in the pipeline state</comment></member>
- <member><type>float</type> <name>extraPrimitiveOverestimationSizeGranularity</name><comment>The granularity of extra overestimation sizes the implementations supports between 0 and maxExtraOverestimationSize</comment></member>
- <member><type>VkBool32</type> <name>primitiveUnderestimation</name><comment>true if the implementation supports conservative rasterization underestimation mode</comment></member>
- <member><type>VkBool32</type> <name>conservativePointAndLineRasterization</name><comment>true if conservative rasterization also applies to points and lines</comment></member>
- <member><type>VkBool32</type> <name>degenerateTrianglesRasterized</name><comment>true if degenerate triangles (those with zero area after snap) are rasterized</comment></member>
- <member><type>VkBool32</type> <name>degenerateLinesRasterized</name><comment>true if degenerate lines (those with zero length after snap) are rasterized</comment></member>
- <member><type>VkBool32</type> <name>fullyCoveredFragmentShaderInputVariable</name><comment>true if the implementation supports the FullyCoveredEXT SPIR-V builtin fragment shader input variable</comment></member>
- <member><type>VkBool32</type> <name>conservativeRasterizationPostDepthCoverage</name><comment>true if the implementation supports both conservative rasterization and post depth coverage sample coverage mask</comment></member>
+ <member limittype="exact"><type>float</type> <name>primitiveOverestimationSize</name><comment>The size in pixels the primitive is enlarged at each edge during conservative rasterization</comment></member>
+ <member limittype="max"><type>float</type> <name>maxExtraPrimitiveOverestimationSize</name><comment>The maximum additional overestimation the client can specify in the pipeline state</comment></member>
+ <member limittype="min,mul"><type>float</type> <name>extraPrimitiveOverestimationSizeGranularity</name><comment>The granularity of extra overestimation sizes the implementations supports between 0 and maxExtraOverestimationSize</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>primitiveUnderestimation</name><comment>true if the implementation supports conservative rasterization underestimation mode</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>conservativePointAndLineRasterization</name><comment>true if conservative rasterization also applies to points and lines</comment></member>
+ <member limittype="exact"><type>VkBool32</type> <name>degenerateTrianglesRasterized</name><comment>true if degenerate triangles (those with zero area after snap) are rasterized</comment></member>
+ <member limittype="exact"><type>VkBool32</type> <name>degenerateLinesRasterized</name><comment>true if degenerate lines (those with zero length after snap) are rasterized</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>fullyCoveredFragmentShaderInputVariable</name><comment>true if the implementation supports the FullyCoveredEXT SPIR-V builtin fragment shader input variable</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>conservativeRasterizationPostDepthCoverage</name><comment>true if the implementation supports both conservative rasterization and post depth coverage sample coverage mask</comment></member>
</type>
<type category="struct" name="VkCalibratedTimestampInfoEXT">
<member values="VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -3255,26 +3590,26 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceShaderCorePropertiesAMD" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>shaderEngineCount</name><comment>number of shader engines</comment></member>
- <member><type>uint32_t</type> <name>shaderArraysPerEngineCount</name><comment>number of shader arrays</comment></member>
- <member><type>uint32_t</type> <name>computeUnitsPerShaderArray</name><comment>number of physical CUs per shader array</comment></member>
- <member><type>uint32_t</type> <name>simdPerComputeUnit</name><comment>number of SIMDs per compute unit</comment></member>
- <member><type>uint32_t</type> <name>wavefrontsPerSimd</name><comment>number of wavefront slots in each SIMD</comment></member>
- <member><type>uint32_t</type> <name>wavefrontSize</name><comment>maximum number of threads per wavefront</comment></member>
- <member><type>uint32_t</type> <name>sgprsPerSimd</name><comment>number of physical SGPRs per SIMD</comment></member>
- <member><type>uint32_t</type> <name>minSgprAllocation</name><comment>minimum number of SGPRs that can be allocated by a wave</comment></member>
- <member><type>uint32_t</type> <name>maxSgprAllocation</name><comment>number of available SGPRs</comment></member>
- <member><type>uint32_t</type> <name>sgprAllocationGranularity</name><comment>SGPRs are allocated in groups of this size</comment></member>
- <member><type>uint32_t</type> <name>vgprsPerSimd</name><comment>number of physical VGPRs per SIMD</comment></member>
- <member><type>uint32_t</type> <name>minVgprAllocation</name><comment>minimum number of VGPRs that can be allocated by a wave</comment></member>
- <member><type>uint32_t</type> <name>maxVgprAllocation</name><comment>number of available VGPRs</comment></member>
- <member><type>uint32_t</type> <name>vgprAllocationGranularity</name><comment>VGPRs are allocated in groups of this size</comment></member>
+ <member limittype="exact"><type>uint32_t</type> <name>shaderEngineCount</name><comment>number of shader engines</comment></member>
+ <member limittype="exact"><type>uint32_t</type> <name>shaderArraysPerEngineCount</name><comment>number of shader arrays</comment></member>
+ <member limittype="exact"><type>uint32_t</type> <name>computeUnitsPerShaderArray</name><comment>number of physical CUs per shader array</comment></member>
+ <member limittype="exact"><type>uint32_t</type> <name>simdPerComputeUnit</name><comment>number of SIMDs per compute unit</comment></member>
+ <member limittype="exact"><type>uint32_t</type> <name>wavefrontsPerSimd</name><comment>number of wavefront slots in each SIMD</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>wavefrontSize</name><comment>maximum number of threads per wavefront</comment></member>
+ <member limittype="exact"><type>uint32_t</type> <name>sgprsPerSimd</name><comment>number of physical SGPRs per SIMD</comment></member>
+ <member limittype="min"><type>uint32_t</type> <name>minSgprAllocation</name><comment>minimum number of SGPRs that can be allocated by a wave</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxSgprAllocation</name><comment>number of available SGPRs</comment></member>
+ <member limittype="min,mul"><type>uint32_t</type> <name>sgprAllocationGranularity</name><comment>SGPRs are allocated in groups of this size</comment></member>
+ <member limittype="exact"><type>uint32_t</type> <name>vgprsPerSimd</name><comment>number of physical VGPRs per SIMD</comment></member>
+ <member limittype="min"><type>uint32_t</type> <name>minVgprAllocation</name><comment>minimum number of VGPRs that can be allocated by a wave</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxVgprAllocation</name><comment>number of available VGPRs</comment></member>
+ <member limittype="min,mul"><type>uint32_t</type> <name>vgprAllocationGranularity</name><comment>VGPRs are allocated in groups of this size</comment></member>
</type>
<type category="struct" name="VkPhysicalDeviceShaderCoreProperties2AMD" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name><comment>Pointer to next structure</comment></member>
- <member><type>VkShaderCorePropertiesFlagsAMD</type> <name>shaderCoreFeatures</name><comment>features supported by the shader core</comment></member>
- <member><type>uint32_t</type> <name>activeComputeUnitCount</name><comment>number of active compute units across all shader engines/arrays</comment></member>
+ <member limittype="bitmask"><type>VkShaderCorePropertiesFlagsAMD</type> <name>shaderCoreFeatures</name><comment>features supported by the shader core</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>activeComputeUnitCount</name><comment>number of active compute units across all shader engines/arrays</comment></member>
</type>
<type category="struct" name="VkPipelineRasterizationConservativeStateCreateInfoEXT" structextends="VkPipelineRasterizationStateCreateInfo">
<member values="VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -3311,29 +3646,29 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceDescriptorIndexingProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxUpdateAfterBindDescriptorsInAllPools</name></member>
- <member><type>VkBool32</type> <name>shaderUniformBufferArrayNonUniformIndexingNative</name></member>
- <member><type>VkBool32</type> <name>shaderSampledImageArrayNonUniformIndexingNative</name></member>
- <member><type>VkBool32</type> <name>shaderStorageBufferArrayNonUniformIndexingNative</name></member>
- <member><type>VkBool32</type> <name>shaderStorageImageArrayNonUniformIndexingNative</name></member>
- <member><type>VkBool32</type> <name>shaderInputAttachmentArrayNonUniformIndexingNative</name></member>
- <member><type>VkBool32</type> <name>robustBufferAccessUpdateAfterBind</name></member>
- <member><type>VkBool32</type> <name>quadDivergentImplicitLod</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindSamplers</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindUniformBuffers</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindStorageBuffers</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindSampledImages</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindStorageImages</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindInputAttachments</name></member>
- <member><type>uint32_t</type> <name>maxPerStageUpdateAfterBindResources</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindSamplers</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindUniformBuffers</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindUniformBuffersDynamic</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageBuffers</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageBuffersDynamic</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindSampledImages</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageImages</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindInputAttachments</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxUpdateAfterBindDescriptorsInAllPools</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderUniformBufferArrayNonUniformIndexingNative</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderSampledImageArrayNonUniformIndexingNative</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderStorageBufferArrayNonUniformIndexingNative</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderStorageImageArrayNonUniformIndexingNative</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderInputAttachmentArrayNonUniformIndexingNative</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>robustBufferAccessUpdateAfterBind</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>quadDivergentImplicitLod</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindSamplers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindUniformBuffers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindStorageBuffers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindSampledImages</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindStorageImages</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindInputAttachments</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageUpdateAfterBindResources</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindSamplers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindUniformBuffers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindUniformBuffersDynamic</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageBuffers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageBuffersDynamic</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindSampledImages</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageImages</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindInputAttachments</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceDescriptorIndexingPropertiesEXT" alias="VkPhysicalDeviceDescriptorIndexingProperties"/>
<type category="struct" name="VkDescriptorSetLayoutBindingFlagsCreateInfo" structextends="VkDescriptorSetLayoutCreateInfo">
@@ -3399,12 +3734,12 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>uint32_t</type> <name>srcSubpass</name></member>
<member><type>uint32_t</type> <name>dstSubpass</name></member>
- <member><type>VkPipelineStageFlags</type> <name>srcStageMask</name></member>
- <member><type>VkPipelineStageFlags</type> <name>dstStageMask</name></member>
+ <member optional="true"><type>VkPipelineStageFlags</type> <name>srcStageMask</name></member>
+ <member optional="true"><type>VkPipelineStageFlags</type> <name>dstStageMask</name></member>
<member optional="true"><type>VkAccessFlags</type> <name>srcAccessMask</name></member>
<member optional="true"><type>VkAccessFlags</type> <name>dstAccessMask</name></member>
<member optional="true"><type>VkDependencyFlags</type> <name>dependencyFlags</name></member>
- <member optional="true"><type>int32_t</type> <name>viewOffset</name></member>
+ <member><type>int32_t</type> <name>viewOffset</name></member>
</type>
<type category="struct" name="VkSubpassDependency2KHR" alias="VkSubpassDependency2"/>
<type category="struct" name="VkRenderPassCreateInfo2">
@@ -3441,7 +3776,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceTimelineSemaphoreProperties" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint64_t</type> <name>maxTimelineSemaphoreValueDifference</name></member>
+ <member limittype="max"><type>uint64_t</type> <name>maxTimelineSemaphoreValueDifference</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceTimelineSemaphorePropertiesKHR" alias="VkPhysicalDeviceTimelineSemaphoreProperties"/>
<type category="struct" name="VkSemaphoreTypeCreateInfo" structextends="VkSemaphoreCreateInfo,VkPhysicalDeviceExternalSemaphoreInfo">
@@ -3489,15 +3824,15 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxVertexAttribDivisor</name><comment>max value of vertex attribute divisor</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxVertexAttribDivisor</name><comment>max value of vertex attribute divisor</comment></member>
</type>
<type category="struct" name="VkPhysicalDevicePCIBusInfoPropertiesEXT" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>pciDomain</name></member>
- <member><type>uint32_t</type> <name>pciBus</name></member>
- <member><type>uint32_t</type> <name>pciDevice</name></member>
- <member><type>uint32_t</type> <name>pciFunction</name></member>
+ <member limittype="noauto"><type>uint32_t</type> <name>pciDomain</name></member>
+ <member limittype="noauto"><type>uint32_t</type> <name>pciBus</name></member>
+ <member limittype="noauto"><type>uint32_t</type> <name>pciDevice</name></member>
+ <member limittype="noauto"><type>uint32_t</type> <name>pciFunction</name></member>
</type>
<type category="struct" name="VkImportAndroidHardwareBufferInfoANDROID" structextends="VkMemoryAllocateInfo">
<member values="VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID"><type>VkStructureType</type> <name>sType</name></member>
@@ -3587,6 +3922,22 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBool32</type> <name>sparseImageFloat32Atomics</name></member>
<member><type>VkBool32</type> <name>sparseImageFloat32AtomicAdd</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>shaderBufferFloat16Atomics</name></member>
+ <member><type>VkBool32</type> <name>shaderBufferFloat16AtomicAdd</name></member>
+ <member><type>VkBool32</type> <name>shaderBufferFloat16AtomicMinMax</name></member>
+ <member><type>VkBool32</type> <name>shaderBufferFloat32AtomicMinMax</name></member>
+ <member><type>VkBool32</type> <name>shaderBufferFloat64AtomicMinMax</name></member>
+ <member><type>VkBool32</type> <name>shaderSharedFloat16Atomics</name></member>
+ <member><type>VkBool32</type> <name>shaderSharedFloat16AtomicAdd</name></member>
+ <member><type>VkBool32</type> <name>shaderSharedFloat16AtomicMinMax</name></member>
+ <member><type>VkBool32</type> <name>shaderSharedFloat32AtomicMinMax</name></member>
+ <member><type>VkBool32</type> <name>shaderSharedFloat64AtomicMinMax</name></member>
+ <member><type>VkBool32</type> <name>shaderImageFloat32AtomicMinMax</name></member>
+ <member><type>VkBool32</type> <name>sparseImageFloat32AtomicMinMax</name></member>
+ </type>
<type category="struct" name="VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -3596,7 +3947,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkQueueFamilyCheckpointPropertiesNV" structextends="VkQueueFamilyProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkPipelineStageFlags</type> <name>checkpointExecutionStageMask</name></member>
+ <member limittype="bitmask"><type>VkPipelineStageFlags</type> <name>checkpointExecutionStageMask</name></member>
</type>
<type category="struct" name="VkCheckpointDataNV" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV"><type>VkStructureType</type> <name>sType</name></member>
@@ -3607,10 +3958,10 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceDepthStencilResolveProperties" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkResolveModeFlags</type> <name>supportedDepthResolveModes</name><comment>supported depth resolve modes</comment></member>
- <member><type>VkResolveModeFlags</type> <name>supportedStencilResolveModes</name><comment>supported stencil resolve modes</comment></member>
- <member><type>VkBool32</type> <name>independentResolveNone</name><comment>depth and stencil resolve modes can be set independently if one of them is none</comment></member>
- <member><type>VkBool32</type> <name>independentResolve</name><comment>depth and stencil resolve modes can be set independently</comment></member>
+ <member limittype="bitmask"><type>VkResolveModeFlags</type> <name>supportedDepthResolveModes</name><comment>supported depth resolve modes</comment></member>
+ <member limittype="bitmask"><type>VkResolveModeFlags</type> <name>supportedStencilResolveModes</name><comment>supported stencil resolve modes</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>independentResolveNone</name><comment>depth and stencil resolve modes can be set independently if one of them is none</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>independentResolve</name><comment>depth and stencil resolve modes can be set independently</comment></member>
</type>
<type category="struct" name="VkPhysicalDeviceDepthStencilResolvePropertiesKHR" alias="VkPhysicalDeviceDepthStencilResolveProperties"/>
<type category="struct" name="VkSubpassDescriptionDepthStencilResolve" structextends="VkSubpassDescription2">
@@ -3640,16 +3991,16 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceTransformFeedbackPropertiesEXT" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxTransformFeedbackStreams</name></member>
- <member><type>uint32_t</type> <name>maxTransformFeedbackBuffers</name></member>
- <member><type>VkDeviceSize</type> <name>maxTransformFeedbackBufferSize</name></member>
- <member><type>uint32_t</type> <name>maxTransformFeedbackStreamDataSize</name></member>
- <member><type>uint32_t</type> <name>maxTransformFeedbackBufferDataSize</name></member>
- <member><type>uint32_t</type> <name>maxTransformFeedbackBufferDataStride</name></member>
- <member><type>VkBool32</type> <name>transformFeedbackQueries</name></member>
- <member><type>VkBool32</type> <name>transformFeedbackStreamsLinesTriangles</name></member>
- <member><type>VkBool32</type> <name>transformFeedbackRasterizationStreamSelect</name></member>
- <member><type>VkBool32</type> <name>transformFeedbackDraw</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTransformFeedbackStreams</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTransformFeedbackBuffers</name></member>
+ <member limittype="max"><type>VkDeviceSize</type> <name>maxTransformFeedbackBufferSize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTransformFeedbackStreamDataSize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTransformFeedbackBufferDataSize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTransformFeedbackBufferDataStride</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>transformFeedbackQueries</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>transformFeedbackStreamsLinesTriangles</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>transformFeedbackRasterizationStreamSelect</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>transformFeedbackDraw</name></member>
</type>
<type category="struct" name="VkPipelineRasterizationStateStreamCreateInfoEXT" structextends="VkPipelineRasterizationStateCreateInfo">
<member values="VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -3658,7 +4009,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>uint32_t</type> <name>rasterizationStream</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceRepresentativeFragmentTestFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>representativeFragmentTest</name></member>
</type>
@@ -3689,11 +4040,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBool32</type> <name>computeDerivativeGroupQuads</name></member>
<member><type>VkBool32</type> <name>computeDerivativeGroupLinear</name></member>
</type>
- <type category="struct" name="VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkBool32</type> <name>fragmentShaderBarycentric</name></member>
- </type>
+ <type category="struct" name="VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV" alias="VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR"/>
<type category="struct" name="VkPhysicalDeviceShaderImageFootprintFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_FOOTPRINT_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -3724,9 +4071,14 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceShadingRateImagePropertiesNV" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkExtent2D</type> <name>shadingRateTexelSize</name></member>
- <member><type>uint32_t</type> <name>shadingRatePaletteSize</name></member>
- <member><type>uint32_t</type> <name>shadingRateMaxCoarseSamples</name></member>
+ <member limittype="exact"><type>VkExtent2D</type> <name>shadingRateTexelSize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>shadingRatePaletteSize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>shadingRateMaxCoarseSamples</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceInvocationMaskFeaturesHUAWEI" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>invocationMask</name></member>
</type>
<type category="struct" name="VkCoarseSampleLocationNV">
<member><type>uint32_t</type> <name>pixelX</name></member>
@@ -3755,19 +4107,19 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceMeshShaderPropertiesNV" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxDrawMeshTasksCount</name></member>
- <member><type>uint32_t</type> <name>maxTaskWorkGroupInvocations</name></member>
- <member><type>uint32_t</type> <name>maxTaskWorkGroupSize</name>[3]</member>
- <member><type>uint32_t</type> <name>maxTaskTotalMemorySize</name></member>
- <member><type>uint32_t</type> <name>maxTaskOutputCount</name></member>
- <member><type>uint32_t</type> <name>maxMeshWorkGroupInvocations</name></member>
- <member><type>uint32_t</type> <name>maxMeshWorkGroupSize</name>[3]</member>
- <member><type>uint32_t</type> <name>maxMeshTotalMemorySize</name></member>
- <member><type>uint32_t</type> <name>maxMeshOutputVertices</name></member>
- <member><type>uint32_t</type> <name>maxMeshOutputPrimitives</name></member>
- <member><type>uint32_t</type> <name>maxMeshMultiviewViewCount</name></member>
- <member><type>uint32_t</type> <name>meshOutputPerVertexGranularity</name></member>
- <member><type>uint32_t</type> <name>meshOutputPerPrimitiveGranularity</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDrawMeshTasksCount</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTaskWorkGroupInvocations</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTaskWorkGroupSize</name>[3]</member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTaskTotalMemorySize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxTaskOutputCount</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMeshWorkGroupInvocations</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMeshWorkGroupSize</name>[3]</member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMeshTotalMemorySize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMeshOutputVertices</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMeshOutputPrimitives</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMeshMultiviewViewCount</name></member>
+ <member limittype="min,mul"><type>uint32_t</type> <name>meshOutputPerVertexGranularity</name></member>
+ <member limittype="min,mul"><type>uint32_t</type> <name>meshOutputPerPrimitiveGranularity</name></member>
</type>
<type category="struct" name="VkDrawMeshTasksIndirectCommandNV">
<member><type>uint32_t</type> <name>taskCount</name></member>
@@ -3859,7 +4211,7 @@ typedef void <name>CAMetalLayer</name>;
<member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkAccelerationStructureTypeNV</type> <name>type</name></member>
- <member optional="true"><type>VkBuildAccelerationStructureFlagsNV</type><name>flags</name></member>
+ <member optional="true"><type>VkBuildAccelerationStructureFlagsNV</type> <name>flags</name></member>
<member optional="true"><type>uint32_t</type> <name>instanceCount</name></member>
<member optional="true"><type>uint32_t</type> <name>geometryCount</name></member>
<member len="geometryCount">const <type>VkGeometryNV</type>* <name>pGeometries</name></member>
@@ -3923,38 +4275,38 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceAccelerationStructurePropertiesKHR" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint64_t</type> <name>maxGeometryCount</name></member>
- <member><type>uint64_t</type> <name>maxInstanceCount</name></member>
- <member><type>uint64_t</type> <name>maxPrimitiveCount</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorAccelerationStructures</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindAccelerationStructures</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetAccelerationStructures</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindAccelerationStructures</name></member>
- <member><type>uint32_t</type> <name>minAccelerationStructureScratchOffsetAlignment</name></member>
+ <member limittype="max"><type>uint64_t</type> <name>maxGeometryCount</name></member>
+ <member limittype="max"><type>uint64_t</type> <name>maxInstanceCount</name></member>
+ <member limittype="max"><type>uint64_t</type> <name>maxPrimitiveCount</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorAccelerationStructures</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindAccelerationStructures</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetAccelerationStructures</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindAccelerationStructures</name></member>
+ <member limittype="min"><type>uint32_t</type> <name>minAccelerationStructureScratchOffsetAlignment</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceRayTracingPipelinePropertiesKHR" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>shaderGroupHandleSize</name></member>
- <member><type>uint32_t</type> <name>maxRayRecursionDepth</name></member>
- <member><type>uint32_t</type> <name>maxShaderGroupStride</name></member>
- <member><type>uint32_t</type> <name>shaderGroupBaseAlignment</name></member>
- <member><type>uint32_t</type> <name>shaderGroupHandleCaptureReplaySize</name></member>
- <member><type>uint32_t</type> <name>maxRayDispatchInvocationCount</name></member>
- <member><type>uint32_t</type> <name>shaderGroupHandleAlignment</name></member>
- <member><type>uint32_t</type> <name>maxRayHitAttributeSize</name></member>
+ <member limittype="exact"><type>uint32_t</type> <name>shaderGroupHandleSize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxRayRecursionDepth</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxShaderGroupStride</name></member>
+ <member limittype="exact"><type>uint32_t</type> <name>shaderGroupBaseAlignment</name></member>
+ <member limittype="exact"><type>uint32_t</type> <name>shaderGroupHandleCaptureReplaySize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxRayDispatchInvocationCount</name></member>
+ <member limittype="min,pot"><type>uint32_t</type> <name>shaderGroupHandleAlignment</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxRayHitAttributeSize</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceRayTracingPropertiesNV" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>shaderGroupHandleSize</name></member>
- <member><type>uint32_t</type> <name>maxRecursionDepth</name></member>
- <member><type>uint32_t</type> <name>maxShaderGroupStride</name></member>
- <member><type>uint32_t</type> <name>shaderGroupBaseAlignment</name></member>
- <member><type>uint64_t</type> <name>maxGeometryCount</name></member>
- <member><type>uint64_t</type> <name>maxInstanceCount</name></member>
- <member><type>uint64_t</type> <name>maxTriangleCount</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetAccelerationStructures</name></member>
+ <member limittype="exact"><type>uint32_t</type> <name>shaderGroupHandleSize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxRecursionDepth</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxShaderGroupStride</name></member>
+ <member limittype="exact"><type>uint32_t</type> <name>shaderGroupBaseAlignment</name></member>
+ <member limittype="max"><type>uint64_t</type> <name>maxGeometryCount</name></member>
+ <member limittype="max"><type>uint64_t</type> <name>maxInstanceCount</name></member>
+ <member limittype="max"><type>uint64_t</type> <name>maxTriangleCount</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetAccelerationStructures</name></member>
</type>
<type category="struct" name="VkStridedDeviceAddressRegionKHR">
<member optional="true"><type>VkDeviceAddress</type> <name>deviceAddress</name></member>
@@ -3966,11 +4318,33 @@ typedef void <name>CAMetalLayer</name>;
<member><type>uint32_t</type> <name>height</name></member>
<member><type>uint32_t</type> <name>depth</name></member>
</type>
+ <type category="struct" name="VkTraceRaysIndirectCommand2KHR">
+ <member><type>VkDeviceAddress</type> <name>raygenShaderRecordAddress</name></member>
+ <member><type>VkDeviceSize</type> <name>raygenShaderRecordSize</name></member>
+ <member><type>VkDeviceAddress</type> <name>missShaderBindingTableAddress</name></member>
+ <member><type>VkDeviceSize</type> <name>missShaderBindingTableSize</name></member>
+ <member><type>VkDeviceSize</type> <name>missShaderBindingTableStride</name></member>
+ <member><type>VkDeviceAddress</type> <name>hitShaderBindingTableAddress</name></member>
+ <member><type>VkDeviceSize</type> <name>hitShaderBindingTableSize</name></member>
+ <member><type>VkDeviceSize</type> <name>hitShaderBindingTableStride</name></member>
+ <member><type>VkDeviceAddress</type> <name>callableShaderBindingTableAddress</name></member>
+ <member><type>VkDeviceSize</type> <name>callableShaderBindingTableSize</name></member>
+ <member><type>VkDeviceSize</type> <name>callableShaderBindingTableStride</name></member>
+ <member><type>uint32_t</type> <name>width</name></member>
+ <member><type>uint32_t</type> <name>height</name></member>
+ <member><type>uint32_t</type> <name>depth</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>rayTracingMaintenance1</name></member>
+ <member><type>VkBool32</type> <name>rayTracingPipelineTraceRaysIndirect2</name></member>
+ </type>
<type category="struct" name="VkDrmFormatModifierPropertiesListEXT" returnedonly="true" structextends="VkFormatProperties2">
<member values="VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member optional="true"><type>uint32_t</type> <name>drmFormatModifierCount</name></member>
- <member optional="true,false" len="drmFormatModifierCount"><type>VkDrmFormatModifierPropertiesEXT</type>* <name>pDrmFormatModifierProperties</name></member>
+ <member optional="true" len="drmFormatModifierCount"><type>VkDrmFormatModifierPropertiesEXT</type>* <name>pDrmFormatModifierProperties</name></member>
</type>
<type category="struct" name="VkDrmFormatModifierPropertiesEXT" returnedonly="true">
<member><type>uint64_t</type> <name>drmFormatModifier</name></member>
@@ -4026,26 +4400,42 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>fragmentDensityMapDeferred</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>fragmentDensityMapOffset</name></member>
+ </type>
<type category="struct" name="VkPhysicalDeviceFragmentDensityMapPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkExtent2D</type> <name>minFragmentDensityTexelSize</name></member>
- <member><type>VkExtent2D</type> <name>maxFragmentDensityTexelSize</name></member>
- <member><type>VkBool32</type> <name>fragmentDensityInvocations</name></member>
+ <member limittype="min"><type>VkExtent2D</type> <name>minFragmentDensityTexelSize</name></member>
+ <member limittype="max"><type>VkExtent2D</type> <name>maxFragmentDensityTexelSize</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>fragmentDensityInvocations</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceFragmentDensityMap2PropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkBool32</type> <name>subsampledLoads</name></member>
- <member><type>VkBool32</type> <name>subsampledCoarseReconstructionEarlyAccess</name></member>
- <member><type>uint32_t</type> <name>maxSubsampledArrayLayers</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetSubsampledSamplers</name></member>
+ <member limittype="exact"><type>VkBool32</type> <name>subsampledLoads</name></member>
+ <member limittype="exact"><type>VkBool32</type> <name>subsampledCoarseReconstructionEarlyAccess</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxSubsampledArrayLayers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetSubsampledSamplers</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="min,mul"><type>VkExtent2D</type> <name>fragmentDensityOffsetGranularity</name></member>
</type>
<type category="struct" name="VkRenderPassFragmentDensityMapCreateInfoEXT" structextends="VkRenderPassCreateInfo,VkRenderPassCreateInfo2">
<member values="VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkAttachmentReference</type> <name>fragmentDensityMapAttachment</name></member>
</type>
+ <type category="struct" name="VkSubpassFragmentDensityMapOffsetEndInfoQCOM" structextends="VkSubpassEndInfo">
+ <member values="VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>uint32_t</type> <name>fragmentDensityOffsetCount</name></member>
+ <member len="fragmentDensityOffsetCount">const <type>VkOffset2D</type>* <name>pFragmentDensityOffsets</name></member>
+ </type>
<type category="struct" name="VkPhysicalDeviceScalarBlockLayoutFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -4090,6 +4480,11 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>float</type> <name>priority</name></member>
</type>
+ <type category="struct" name="VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>pageableDeviceLocalMemory</name></member>
+ </type>
<type category="struct" name="VkPhysicalDeviceBufferDeviceAddressFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -4162,16 +4557,17 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkFramebufferAttachmentImageInfoKHR" alias="VkFramebufferAttachmentImageInfo"/>
<type category="struct" name="VkRenderPassAttachmentBeginInfo" structextends="VkRenderPassBeginInfo">
<member values="VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>uint32_t</type> <name>attachmentCount</name></member>
<member len="attachmentCount">const <type>VkImageView</type>* <name>pAttachments</name></member>
</type>
<type category="struct" name="VkRenderPassAttachmentBeginInfoKHR" alias="VkRenderPassAttachmentBeginInfo"/>
- <type category="struct" name="VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <type category="struct" name="VkPhysicalDeviceTextureCompressionASTCHDRFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>textureCompressionASTC_HDR</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT" alias="VkPhysicalDeviceTextureCompressionASTCHDRFeatures"/>
<type category="struct" name="VkPhysicalDeviceCooperativeMatrixFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -4181,7 +4577,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceCooperativeMatrixPropertiesNV" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkShaderStageFlags</type> <name>cooperativeMatrixSupportedStages</name></member>
+ <member limittype="bitmask"><type>VkShaderStageFlags</type> <name>cooperativeMatrixSupportedStages</name></member>
</type>
<type category="struct" name="VkCooperativeMatrixPropertiesNV">
<member values="VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
@@ -4218,17 +4614,19 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>GgpFrameToken</type> <name>frameToken</name></member>
</type>
- <type category="struct" name="VkPipelineCreationFeedbackEXT" returnedonly="true">
- <member><type>VkPipelineCreationFeedbackFlagsEXT</type> <name>flags</name></member>
+ <type category="struct" name="VkPipelineCreationFeedback" returnedonly="true">
+ <member><type>VkPipelineCreationFeedbackFlags</type> <name>flags</name></member>
<member><type>uint64_t</type> <name>duration</name></member>
</type>
- <type category="struct" name="VkPipelineCreationFeedbackCreateInfoEXT" structextends="VkGraphicsPipelineCreateInfo,VkComputePipelineCreateInfo,VkRayTracingPipelineCreateInfoNV,VkRayTracingPipelineCreateInfoKHR">
- <member values="VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkPipelineCreationFeedbackEXT</type>* <name>pPipelineCreationFeedback</name><comment>Output pipeline creation feedback.</comment></member>
- <member><type>uint32_t</type> <name>pipelineStageCreationFeedbackCount</name></member>
- <member len="pipelineStageCreationFeedbackCount"><type>VkPipelineCreationFeedbackEXT</type>* <name>pPipelineStageCreationFeedbacks</name><comment>One entry for each shader stage specified in the parent Vk*PipelineCreateInfo struct</comment></member>
+ <type category="struct" name="VkPipelineCreationFeedbackEXT" alias="VkPipelineCreationFeedback"/>
+ <type category="struct" name="VkPipelineCreationFeedbackCreateInfo" structextends="VkGraphicsPipelineCreateInfo,VkComputePipelineCreateInfo,VkRayTracingPipelineCreateInfoNV,VkRayTracingPipelineCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkPipelineCreationFeedback</type>* <name>pPipelineCreationFeedback</name><comment>Output pipeline creation feedback.</comment></member>
+ <member optional="true"><type>uint32_t</type> <name>pipelineStageCreationFeedbackCount</name></member>
+ <member len="pipelineStageCreationFeedbackCount"><type>VkPipelineCreationFeedback</type>* <name>pPipelineStageCreationFeedbacks</name><comment>One entry for each shader stage specified in the parent Vk*PipelineCreateInfo struct</comment></member>
</type>
+ <type category="struct" name="VkPipelineCreationFeedbackCreateInfoEXT" alias="VkPipelineCreationFeedbackCreateInfo"/>
<type category="struct" name="VkSurfaceFullScreenExclusiveInfoEXT" structextends="VkPhysicalDeviceSurfaceInfo2KHR,VkSwapchainCreateInfoKHR">
<member values="VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -4253,11 +4651,11 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDevicePerformanceQueryPropertiesKHR" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member noautovalidity="true"><type>VkBool32</type> <name>allowCommandBufferQueryCopies</name><comment>Flag to specify whether performance queries are allowed to be used in vkCmdCopyQueryPoolResults</comment></member>
+ <member limittype="bitmask" noautovalidity="true"><type>VkBool32</type> <name>allowCommandBufferQueryCopies</name><comment>Flag to specify whether performance queries are allowed to be used in vkCmdCopyQueryPoolResults</comment></member>
</type>
<type category="struct" name="VkPerformanceCounterKHR" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkPerformanceCounterUnitKHR</type> <name>unit</name></member>
<member><type>VkPerformanceCounterScopeKHR</type> <name>scope</name></member>
<member><type>VkPerformanceCounterStorageKHR</type> <name>storage</name></member>
@@ -4265,7 +4663,7 @@ typedef void <name>CAMetalLayer</name>;
</type>
<type category="struct" name="VkPerformanceCounterDescriptionKHR" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PERFORMANCE_COUNTER_DESCRIPTION_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
<member optional="true"><type>VkPerformanceCounterDescriptionFlagsKHR</type> <name>flags</name></member>
<member><type>char</type> <name>name</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member>
<member><type>char</type> <name>category</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member>
@@ -4273,7 +4671,7 @@ typedef void <name>CAMetalLayer</name>;
</type>
<type category="struct" name="VkQueryPoolPerformanceCreateInfoKHR" structextends="VkQueryPoolCreateInfo">
<member values="VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>uint32_t</type> <name>queueFamilyIndex</name></member>
<member><type>uint32_t</type> <name>counterIndexCount</name></member>
<member len="counterIndexCount">const <type>uint32_t</type>* <name>pCounterIndices</name></member>
@@ -4292,7 +4690,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true"><type>VkAcquireProfilingLockFlagsKHR</type> <name>flags</name><comment>Acquire profiling lock flags</comment></member>
<member><type>uint64_t</type> <name>timeout</name></member>
</type>
- <type category="struct" name="VkPerformanceQuerySubmitInfoKHR" structextends="VkSubmitInfo">
+ <type category="struct" name="VkPerformanceQuerySubmitInfoKHR" structextends="VkSubmitInfo,VkSubmitInfo2">
<member values="VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>uint32_t</type> <name>counterPassIndex</name><comment>Index for which counter pass to submit</comment></member>
@@ -4303,7 +4701,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true"><type>VkHeadlessSurfaceCreateFlagsEXT</type> <name>flags</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceCoverageReductionModeFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COVERAGE_REDUCTION_MODE_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>coverageReductionMode</name></member>
</type>
@@ -4335,7 +4733,7 @@ typedef void <name>CAMetalLayer</name>;
</type>
<type category="struct" name="VkPerformanceValueINTEL">
<member><type>VkPerformanceValueTypeINTEL</type> <name>type</name></member>
- <member selector="type"><type>VkPerformanceValueDataINTEL</type> <name>data</name></member>
+ <member selector="type" noautovalidity="true"><type>VkPerformanceValueDataINTEL</type> <name>data</name></member>
</type>
<type category="struct" name="VkInitializePerformanceApiInfoINTEL" >
<member values="VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL"><type>VkStructureType</type> <name>sType</name></member>
@@ -4384,11 +4782,11 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceShaderSMBuiltinsPropertiesNV" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>shaderSMCount</name></member>
- <member><type>uint32_t</type> <name>shaderWarpsPerSM</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>shaderSMCount</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>shaderWarpsPerSM</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceShaderSMBuiltinsFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SM_BUILTINS_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>shaderSMBuiltins</name></member>
</type>
@@ -4400,19 +4798,25 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBool32</type> <name>fragmentShaderShadingRateInterlock</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>separateDepthStencilLayouts</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR" alias="VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures"/>
<type category="struct" name="VkAttachmentReferenceStencilLayout" structextends="VkAttachmentReference2">
- <member values="VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkImageLayout</type> <name>stencilLayout</name></member>
</type>
+ <type category="struct" name="VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>primitiveTopologyListRestart</name></member>
+ <member><type>VkBool32</type> <name>primitiveTopologyPatchListRestart</name></member>
+ </type>
<type category="struct" name="VkAttachmentReferenceStencilLayoutKHR" alias="VkAttachmentReferenceStencilLayout"/>
<type category="struct" name="VkAttachmentDescriptionStencilLayout" structextends="VkAttachmentDescription2">
- <member values="VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkImageLayout</type> <name>stencilInitialLayout</name></member>
<member><type>VkImageLayout</type> <name>stencilFinalLayout</name></member>
@@ -4428,6 +4832,7 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkPipeline</type> <name>pipeline</name></member>
</type>
+ <type category="struct" name="VkPipelineInfoEXT" alias="VkPipelineInfoKHR"/>
<type category="struct" name="VkPipelineExecutablePropertiesKHR" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -4454,7 +4859,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>char</type> <name>name</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member>
<member><type>char</type> <name>description</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member>
<member><type>VkPipelineExecutableStatisticFormatKHR</type> <name>format</name></member>
- <member selector="format"><type>VkPipelineExecutableStatisticValueKHR</type> <name>value</name></member>
+ <member selector="format" noautovalidity="true"><type>VkPipelineExecutableStatisticValueKHR</type> <name>value</name></member>
</type>
<type category="struct" name="VkPipelineExecutableInternalRepresentationKHR" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR"><type>VkStructureType</type> <name>sType</name></member>
@@ -4462,45 +4867,61 @@ typedef void <name>CAMetalLayer</name>;
<member><type>char</type> <name>name</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member>
<member><type>char</type> <name>description</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member>
<member><type>VkBool32</type> <name>isText</name></member>
- <member optional="true"><type>size_t</type> <name>dataSize</name></member>
+ <member><type>size_t</type> <name>dataSize</name></member>
<member optional="true" len="dataSize"><type>void</type>* <name>pData</name></member>
</type>
- <type category="struct" name="VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkBool32</type> <name>shaderDemoteToHelperInvocation</name></member>
+ <type category="struct" name="VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>shaderDemoteToHelperInvocation</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT" alias="VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures"/>
<type category="struct" name="VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>texelBufferAlignment</name></member>
</type>
- <type category="struct" name="VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <type category="struct" name="VkPhysicalDeviceTexelBufferAlignmentProperties" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkDeviceSize</type> <name>storageTexelBufferOffsetAlignmentBytes</name></member>
- <member><type>VkBool32</type> <name>storageTexelBufferOffsetSingleTexelAlignment</name></member>
- <member><type>VkDeviceSize</type> <name>uniformTexelBufferOffsetAlignmentBytes</name></member>
- <member><type>VkBool32</type> <name>uniformTexelBufferOffsetSingleTexelAlignment</name></member>
- </type>
- <type category="struct" name="VkPhysicalDeviceSubgroupSizeControlFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>storageTexelBufferOffsetAlignmentBytes</name></member>
+ <member limittype="exact"><type>VkBool32</type> <name>storageTexelBufferOffsetSingleTexelAlignment</name></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>uniformTexelBufferOffsetAlignmentBytes</name></member>
+ <member limittype="exact"><type>VkBool32</type> <name>uniformTexelBufferOffsetSingleTexelAlignment</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT" alias="VkPhysicalDeviceTexelBufferAlignmentProperties"/>
+ <type category="struct" name="VkPhysicalDeviceSubgroupSizeControlFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>subgroupSizeControl</name></member>
+ <member><type>VkBool32</type> <name>computeFullSubgroups</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceSubgroupSizeControlFeaturesEXT" alias="VkPhysicalDeviceSubgroupSizeControlFeatures"/>
+ <type category="struct" name="VkPhysicalDeviceSubgroupSizeControlProperties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkBool32</type> <name>subgroupSizeControl</name></member>
- <member><type>VkBool32</type> <name>computeFullSubgroups</name></member>
+ <member limittype="min,pot" noautovalidity="true"><type>uint32_t</type> <name>minSubgroupSize</name><comment>The minimum subgroup size supported by this device</comment></member>
+ <member limittype="max,pot" noautovalidity="true"><type>uint32_t</type> <name>maxSubgroupSize</name><comment>The maximum subgroup size supported by this device</comment></member>
+ <member limittype="max" noautovalidity="true"><type>uint32_t</type> <name>maxComputeWorkgroupSubgroups</name><comment>The maximum number of subgroups supported in a workgroup</comment></member>
+ <member limittype="bitmask"><type>VkShaderStageFlags</type> <name>requiredSubgroupSizeStages</name><comment>The shader stages that support specifying a subgroup size</comment></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceSubgroupSizeControlPropertiesEXT" alias="VkPhysicalDeviceSubgroupSizeControlProperties"/>
+ <type category="struct" name="VkPipelineShaderStageRequiredSubgroupSizeCreateInfo" returnedonly="true" structextends="VkPipelineShaderStageCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>requiredSubgroupSize</name></member>
</type>
- <type category="struct" name="VkPhysicalDeviceSubgroupSizeControlPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true"><type>void</type>* <name>pNext</name></member>
- <member noautovalidity="true"><type>uint32_t</type> <name>minSubgroupSize</name><comment>The minimum subgroup size supported by this device</comment></member>
- <member noautovalidity="true"><type>uint32_t</type> <name>maxSubgroupSize</name><comment>The maximum subgroup size supported by this device</comment></member>
- <member noautovalidity="true"><type>uint32_t</type> <name>maxComputeWorkgroupSubgroups</name><comment>The maximum number of subgroups supported in a workgroup</comment></member>
- <member><type>VkShaderStageFlags</type> <name>requiredSubgroupSizeStages</name><comment>The shader stages that support specifying a subgroup size</comment></member>
+ <type category="struct" name="VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT" alias="VkPipelineShaderStageRequiredSubgroupSizeCreateInfo"/>
+ <type category="struct" name="VkSubpassShadingPipelineCreateInfoHUAWEI" returnedonly="true" structextends="VkComputePipelineCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkRenderPass</type> <name>renderPass</name></member>
+ <member><type>uint32_t</type> <name>subpass</name></member>
</type>
- <type category="struct" name="VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT" returnedonly="true" structextends="VkPipelineShaderStageCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <type category="struct" name="VkPhysicalDeviceSubpassShadingPropertiesHUAWEI" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>requiredSubgroupSize</name></member>
+ <member limittype="max,pot"><type>uint32_t</type> <name>maxSubpassShadingWorkgroupSizeAspectRatio</name></member>
</type>
<type category="struct" name="VkMemoryOpaqueCaptureAddressAllocateInfo" structextends="VkMemoryAllocateInfo">
<member values="VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
@@ -4527,23 +4948,24 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceLineRasterizationPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>lineSubPixelPrecisionBits</name></member>
+ <member limittype="bits"><type>uint32_t</type> <name>lineSubPixelPrecisionBits</name></member>
</type>
<type category="struct" name="VkPipelineRasterizationLineStateCreateInfoEXT" structextends="VkPipelineRasterizationStateCreateInfo">
<member values="VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkLineRasterizationModeEXT</type> <name>lineRasterizationMode</name></member>
<member><type>VkBool32</type> <name>stippledLineEnable</name></member>
- <member optional="true"><type>uint32_t</type> <name>lineStippleFactor</name></member>
- <member optional="true"><type>uint16_t</type> <name>lineStipplePattern</name></member>
+ <member><type>uint32_t</type> <name>lineStippleFactor</name></member>
+ <member><type>uint16_t</type> <name>lineStipplePattern</name></member>
</type>
- <type category="struct" name="VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <type category="struct" name="VkPhysicalDevicePipelineCreationCacheControlFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkBool32</type> <name>pipelineCreationCacheControl</name></member>
+ <member><type>VkBool32</type> <name>pipelineCreationCacheControl</name></member>
</type>
+ <type category="struct" name="VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT" alias="VkPhysicalDevicePipelineCreationCacheControlFeatures"/>
<type category="struct" name="VkPhysicalDeviceVulkan11Features" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>storageBuffer16BitAccess</name><comment>16-bit integer/floating-point variables supported in BufferBlock</comment></member>
<member><type>VkBool32</type> <name>uniformAndStorageBuffer16BitAccess</name><comment>16-bit integer/floating-point variables supported in BufferBlock and Block</comment></member>
@@ -4559,26 +4981,26 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBool32</type> <name>shaderDrawParameters</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceVulkan11Properties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint8_t</type> <name>deviceUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
- <member><type>uint8_t</type> <name>driverUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
- <member><type>uint8_t</type> <name>deviceLUID</name>[<enum>VK_LUID_SIZE</enum>]</member>
- <member><type>uint32_t</type> <name>deviceNodeMask</name></member>
- <member><type>VkBool32</type> <name>deviceLUIDValid</name></member>
- <member noautovalidity="true"><type>uint32_t</type> <name>subgroupSize</name><comment>The size of a subgroup for this queue.</comment></member>
- <member noautovalidity="true"><type>VkShaderStageFlags</type> <name>subgroupSupportedStages</name><comment>Bitfield of what shader stages support subgroup operations</comment></member>
- <member noautovalidity="true"><type>VkSubgroupFeatureFlags</type> <name>subgroupSupportedOperations</name><comment>Bitfield of what subgroup operations are supported.</comment></member>
- <member noautovalidity="true"><type>VkBool32</type> <name>subgroupQuadOperationsInAllStages</name><comment>Flag to specify whether quad operations are available in all stages.</comment></member>
- <member><type>VkPointClippingBehavior</type> <name>pointClippingBehavior</name></member>
- <member><type>uint32_t</type> <name>maxMultiviewViewCount</name><comment>max number of views in a subpass</comment></member>
- <member><type>uint32_t</type> <name>maxMultiviewInstanceIndex</name><comment>max instance index for a draw in a multiview subpass</comment></member>
- <member><type>VkBool32</type> <name>protectedNoFault</name></member>
- <member><type>uint32_t</type> <name>maxPerSetDescriptors</name></member>
- <member><type>VkDeviceSize</type> <name>maxMemoryAllocationSize</name></member>
+ <member limittype="exact"><type>uint8_t</type> <name>deviceUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
+ <member limittype="exact"><type>uint8_t</type> <name>driverUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
+ <member limittype="exact"><type>uint8_t</type> <name>deviceLUID</name>[<enum>VK_LUID_SIZE</enum>]</member>
+ <member limittype="exact"><type>uint32_t</type> <name>deviceNodeMask</name></member>
+ <member limittype="exact"><type>VkBool32</type> <name>deviceLUIDValid</name></member>
+ <member limittype="min,pot" noautovalidity="true"><type>uint32_t</type> <name>subgroupSize</name><comment>The size of a subgroup for this queue.</comment></member>
+ <member limittype="bitmask" noautovalidity="true"><type>VkShaderStageFlags</type> <name>subgroupSupportedStages</name><comment>Bitfield of what shader stages support subgroup operations</comment></member>
+ <member limittype="bitmask" noautovalidity="true"><type>VkSubgroupFeatureFlags</type> <name>subgroupSupportedOperations</name><comment>Bitfield of what subgroup operations are supported.</comment></member>
+ <member limittype="bitmask" noautovalidity="true"><type>VkBool32</type> <name>subgroupQuadOperationsInAllStages</name><comment>Flag to specify whether quad operations are available in all stages.</comment></member>
+ <member limittype="exact"><type>VkPointClippingBehavior</type> <name>pointClippingBehavior</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMultiviewViewCount</name><comment>max number of views in a subpass</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxMultiviewInstanceIndex</name><comment>max instance index for a draw in a multiview subpass</comment></member>
+ <member limittype="exact"><type>VkBool32</type> <name>protectedNoFault</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerSetDescriptors</name></member>
+ <member limittype="max"><type>VkDeviceSize</type> <name>maxMemoryAllocationSize</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceVulkan12Features" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>samplerMirrorClampToEdge</name></member>
<member><type>VkBool32</type> <name>drawIndirectCount</name></member>
@@ -4629,60 +5051,128 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBool32</type> <name>subgroupBroadcastDynamicId</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceVulkan12Properties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkDriverId</type> <name>driverID</name></member>
- <member><type>char</type> <name>driverName</name>[<enum>VK_MAX_DRIVER_NAME_SIZE</enum>]</member>
- <member><type>char</type> <name>driverInfo</name>[<enum>VK_MAX_DRIVER_INFO_SIZE</enum>]</member>
- <member><type>VkConformanceVersion</type> <name>conformanceVersion</name></member>
- <member><type>VkShaderFloatControlsIndependence</type><name>denormBehaviorIndependence</name></member>
- <member><type>VkShaderFloatControlsIndependence</type><name>roundingModeIndependence</name></member>
- <member><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat16</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
- <member><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat32</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
- <member><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat64</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormPreserveFloat16</name><comment>An implementation can preserve denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormPreserveFloat32</name><comment>An implementation can preserve denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormPreserveFloat64</name><comment>An implementation can preserve denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat16</name><comment>An implementation can flush to zero denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat32</name><comment>An implementation can flush to zero denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat64</name><comment>An implementation can flush to zero denormals</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTEFloat16</name><comment>An implementation can support RTE</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTEFloat32</name><comment>An implementation can support RTE</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTEFloat64</name><comment>An implementation can support RTE</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTZFloat16</name><comment>An implementation can support RTZ</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTZFloat32</name><comment>An implementation can support RTZ</comment></member>
- <member><type>VkBool32</type> <name>shaderRoundingModeRTZFloat64</name><comment>An implementation can support RTZ</comment></member>
- <member><type>uint32_t</type> <name>maxUpdateAfterBindDescriptorsInAllPools</name></member>
- <member><type>VkBool32</type> <name>shaderUniformBufferArrayNonUniformIndexingNative</name></member>
- <member><type>VkBool32</type> <name>shaderSampledImageArrayNonUniformIndexingNative</name></member>
- <member><type>VkBool32</type> <name>shaderStorageBufferArrayNonUniformIndexingNative</name></member>
- <member><type>VkBool32</type> <name>shaderStorageImageArrayNonUniformIndexingNative</name></member>
- <member><type>VkBool32</type> <name>shaderInputAttachmentArrayNonUniformIndexingNative</name></member>
- <member><type>VkBool32</type> <name>robustBufferAccessUpdateAfterBind</name></member>
- <member><type>VkBool32</type> <name>quadDivergentImplicitLod</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindSamplers</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindUniformBuffers</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindStorageBuffers</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindSampledImages</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindStorageImages</name></member>
- <member><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindInputAttachments</name></member>
- <member><type>uint32_t</type> <name>maxPerStageUpdateAfterBindResources</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindSamplers</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindUniformBuffers</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindUniformBuffersDynamic</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageBuffers</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageBuffersDynamic</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindSampledImages</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageImages</name></member>
- <member><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindInputAttachments</name></member>
- <member><type>VkResolveModeFlags</type> <name>supportedDepthResolveModes</name><comment>supported depth resolve modes</comment></member>
- <member><type>VkResolveModeFlags</type> <name>supportedStencilResolveModes</name><comment>supported stencil resolve modes</comment></member>
- <member><type>VkBool32</type> <name>independentResolveNone</name><comment>depth and stencil resolve modes can be set independently if one of them is none</comment></member>
- <member><type>VkBool32</type> <name>independentResolve</name><comment>depth and stencil resolve modes can be set independently</comment></member>
- <member><type>VkBool32</type> <name>filterMinmaxSingleComponentFormats</name></member>
- <member><type>VkBool32</type> <name>filterMinmaxImageComponentMapping</name></member>
- <member><type>uint64_t</type> <name>maxTimelineSemaphoreValueDifference</name></member>
- <member optional="true"><type>VkSampleCountFlags</type> <name>framebufferIntegerColorSampleCounts</name></member>
+ <member limittype="noauto"><type>VkDriverId</type> <name>driverID</name></member>
+ <member limittype="noauto"><type>char</type> <name>driverName</name>[<enum>VK_MAX_DRIVER_NAME_SIZE</enum>]</member>
+ <member limittype="noauto"><type>char</type> <name>driverInfo</name>[<enum>VK_MAX_DRIVER_INFO_SIZE</enum>]</member>
+ <member limittype="noauto"><type>VkConformanceVersion</type> <name>conformanceVersion</name></member>
+ <member limittype="exact"><type>VkShaderFloatControlsIndependence</type> <name>denormBehaviorIndependence</name></member>
+ <member limittype="exact"><type>VkShaderFloatControlsIndependence</type> <name>roundingModeIndependence</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat16</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat32</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderSignedZeroInfNanPreserveFloat64</name><comment>An implementation can preserve signed zero, nan, inf</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormPreserveFloat16</name><comment>An implementation can preserve denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormPreserveFloat32</name><comment>An implementation can preserve denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormPreserveFloat64</name><comment>An implementation can preserve denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat16</name><comment>An implementation can flush to zero denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat32</name><comment>An implementation can flush to zero denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderDenormFlushToZeroFloat64</name><comment>An implementation can flush to zero denormals</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTEFloat16</name><comment>An implementation can support RTE</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTEFloat32</name><comment>An implementation can support RTE</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTEFloat64</name><comment>An implementation can support RTE</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTZFloat16</name><comment>An implementation can support RTZ</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTZFloat32</name><comment>An implementation can support RTZ</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderRoundingModeRTZFloat64</name><comment>An implementation can support RTZ</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxUpdateAfterBindDescriptorsInAllPools</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderUniformBufferArrayNonUniformIndexingNative</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderSampledImageArrayNonUniformIndexingNative</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderStorageBufferArrayNonUniformIndexingNative</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderStorageImageArrayNonUniformIndexingNative</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>shaderInputAttachmentArrayNonUniformIndexingNative</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>robustBufferAccessUpdateAfterBind</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>quadDivergentImplicitLod</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindSamplers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindUniformBuffers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindStorageBuffers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindSampledImages</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindStorageImages</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindInputAttachments</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageUpdateAfterBindResources</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindSamplers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindUniformBuffers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindUniformBuffersDynamic</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageBuffers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageBuffersDynamic</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindSampledImages</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindStorageImages</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindInputAttachments</name></member>
+ <member limittype="bitmask"><type>VkResolveModeFlags</type> <name>supportedDepthResolveModes</name><comment>supported depth resolve modes</comment></member>
+ <member limittype="bitmask"><type>VkResolveModeFlags</type> <name>supportedStencilResolveModes</name><comment>supported stencil resolve modes</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>independentResolveNone</name><comment>depth and stencil resolve modes can be set independently if one of them is none</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>independentResolve</name><comment>depth and stencil resolve modes can be set independently</comment></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>filterMinmaxSingleComponentFormats</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>filterMinmaxImageComponentMapping</name></member>
+ <member limittype="max"><type>uint64_t</type> <name>maxTimelineSemaphoreValueDifference</name></member>
+ <member limittype="bitmask" optional="true"><type>VkSampleCountFlags</type> <name>framebufferIntegerColorSampleCounts</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceVulkan13Features" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>robustImageAccess</name></member>
+ <member><type>VkBool32</type> <name>inlineUniformBlock</name></member>
+ <member><type>VkBool32</type> <name>descriptorBindingInlineUniformBlockUpdateAfterBind</name></member>
+ <member><type>VkBool32</type> <name>pipelineCreationCacheControl</name></member>
+ <member><type>VkBool32</type> <name>privateData</name></member>
+ <member><type>VkBool32</type> <name>shaderDemoteToHelperInvocation</name></member>
+ <member><type>VkBool32</type> <name>shaderTerminateInvocation</name></member>
+ <member><type>VkBool32</type> <name>subgroupSizeControl</name></member>
+ <member><type>VkBool32</type> <name>computeFullSubgroups</name></member>
+ <member><type>VkBool32</type> <name>synchronization2</name></member>
+ <member><type>VkBool32</type> <name>textureCompressionASTC_HDR</name></member>
+ <member><type>VkBool32</type> <name>shaderZeroInitializeWorkgroupMemory</name></member>
+ <member><type>VkBool32</type> <name>dynamicRendering</name></member>
+ <member><type>VkBool32</type> <name>shaderIntegerDotProduct</name></member>
+ <member><type>VkBool32</type> <name>maintenance4</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceVulkan13Properties" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="min,pot" noautovalidity="true"><type>uint32_t</type> <name>minSubgroupSize</name><comment>The minimum subgroup size supported by this device</comment></member>
+ <member limittype="max,pot" noautovalidity="true"><type>uint32_t</type> <name>maxSubgroupSize</name><comment>The maximum subgroup size supported by this device</comment></member>
+ <member limittype="max" noautovalidity="true"><type>uint32_t</type> <name>maxComputeWorkgroupSubgroups</name><comment>The maximum number of subgroups supported in a workgroup</comment></member>
+ <member limittype="bitmask"><type>VkShaderStageFlags</type> <name>requiredSubgroupSizeStages</name><comment>The shader stages that support specifying a subgroup size</comment></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxInlineUniformBlockSize</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorInlineUniformBlocks</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetInlineUniformBlocks</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxDescriptorSetUpdateAfterBindInlineUniformBlocks</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxInlineUniformTotalSize</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct8BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct8BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct8BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct4x8BitPackedUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct4x8BitPackedSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct4x8BitPackedMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct16BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct16BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct16BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct32BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct32BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct32BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct64BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct64BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct64BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating8BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating8BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating16BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating16BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating32BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating32BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating64BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating64BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated</name></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>storageTexelBufferOffsetAlignmentBytes</name></member>
+ <member limittype="exact"><type>VkBool32</type> <name>storageTexelBufferOffsetSingleTexelAlignment</name></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>uniformTexelBufferOffsetAlignmentBytes</name></member>
+ <member limittype="exact"><type>VkBool32</type> <name>uniformTexelBufferOffsetSingleTexelAlignment</name></member>
+ <member limittype="max"><type>VkDeviceSize</type> <name>maxBufferSize</name></member>
</type>
<type category="struct" name="VkPipelineCompilerControlCreateInfoAMD" structextends="VkGraphicsPipelineCreateInfo,VkComputePipelineCreateInfo">
<member values="VK_STRUCTURE_TYPE_PIPELINE_COMPILER_CONTROL_CREATE_INFO_AMD"><type>VkStructureType</type> <name>sType</name></member>
@@ -4694,25 +5184,26 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>deviceCoherentMemory</name></member>
</type>
- <type category="struct" name="VkPhysicalDeviceToolPropertiesEXT" returnedonly="true">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <type category="struct" name="VkPhysicalDeviceToolProperties" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>char</type> <name>name</name>[<enum>VK_MAX_EXTENSION_NAME_SIZE</enum>]</member>
- <member><type>char</type> <name>version</name>[<enum>VK_MAX_EXTENSION_NAME_SIZE</enum>]</member>
- <member><type>VkToolPurposeFlagsEXT</type> <name>purposes</name></member>
- <member><type>char</type> <name>description</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member>
- <member><type>char</type> <name>layer</name>[<enum>VK_MAX_EXTENSION_NAME_SIZE</enum>]</member>
+ <member><type>char</type> <name>name</name>[<enum>VK_MAX_EXTENSION_NAME_SIZE</enum>]</member>
+ <member><type>char</type> <name>version</name>[<enum>VK_MAX_EXTENSION_NAME_SIZE</enum>]</member>
+ <member><type>VkToolPurposeFlags</type> <name>purposes</name></member>
+ <member><type>char</type> <name>description</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member>
+ <member><type>char</type> <name>layer</name>[<enum>VK_MAX_EXTENSION_NAME_SIZE</enum>]</member>
</type>
+ <type category="struct" name="VkPhysicalDeviceToolPropertiesEXT" alias="VkPhysicalDeviceToolProperties"/>
<type category="struct" name="VkSamplerCustomBorderColorCreateInfoEXT" structextends="VkSamplerCreateInfo">
<member values="VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkClearColorValue</type> <name>customBorderColor</name></member>
+ <member noautovalidity="true"><type>VkClearColorValue</type> <name>customBorderColor</name></member>
<member><type>VkFormat</type> <name>format</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceCustomBorderColorPropertiesEXT" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>maxCustomBorderColorSamplers</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxCustomBorderColorSamplers</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceCustomBorderColorFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
@@ -4720,6 +5211,18 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkBool32</type> <name>customBorderColors</name></member>
<member><type>VkBool32</type> <name>customBorderColorWithoutFormat</name></member>
</type>
+ <type category="struct" name="VkSamplerBorderColorComponentMappingCreateInfoEXT" structextends="VkSamplerCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkComponentMapping</type> <name>components</name></member>
+ <member><type>VkBool32</type> <name>srgb</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceBorderColorSwizzleFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>borderColorSwizzle</name></member>
+ <member><type>VkBool32</type> <name>borderColorSwizzleFromImage</name></member>
+ </type>
<type category="union" name="VkDeviceOrHostAddressKHR">
<member noautovalidity="true"><type>VkDeviceAddress</type> <name>deviceAddress</name></member>
<member noautovalidity="true"><type>void</type>* <name>hostAddress</name></member>
@@ -4730,26 +5233,26 @@ typedef void <name>CAMetalLayer</name>;
</type>
<type category="struct" name="VkAccelerationStructureGeometryTrianglesDataKHR">
<member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkFormat</type> <name>vertexFormat</name></member>
- <member><type>VkDeviceOrHostAddressConstKHR</type> <name>vertexData</name></member>
+ <member noautovalidity="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>vertexData</name></member>
<member><type>VkDeviceSize</type> <name>vertexStride</name></member>
<member><type>uint32_t</type> <name>maxVertex</name></member>
<member><type>VkIndexType</type> <name>indexType</name></member>
- <member optional="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>indexData</name></member>
- <member optional="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>transformData</name></member>
+ <member noautovalidity="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>indexData</name></member>
+ <member noautovalidity="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>transformData</name></member>
</type>
<type category="struct" name="VkAccelerationStructureGeometryAabbsDataKHR">
<member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_AABBS_DATA_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkDeviceOrHostAddressConstKHR</type> <name>data</name></member>
+ <member noautovalidity="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>data</name></member>
<member><type>VkDeviceSize</type> <name>stride</name></member>
</type>
<type category="struct" name="VkAccelerationStructureGeometryInstancesDataKHR">
<member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>arrayOfPointers</name></member>
- <member><type>VkDeviceOrHostAddressConstKHR</type> <name>data</name></member>
+ <member noautovalidity="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>data</name></member>
</type>
<type category="union" name="VkAccelerationStructureGeometryDataKHR">
<member selection="VK_GEOMETRY_TYPE_TRIANGLES_KHR"><type>VkAccelerationStructureGeometryTrianglesDataKHR</type> <name>triangles</name></member>
@@ -4774,13 +5277,13 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true"><type>uint32_t</type> <name>geometryCount</name></member>
<member len="geometryCount" optional="true">const <type>VkAccelerationStructureGeometryKHR</type>* <name>pGeometries</name></member>
<member len="geometryCount,1" optional="true,false">const <type>VkAccelerationStructureGeometryKHR</type>* const* <name>ppGeometries</name></member>
- <member><type>VkDeviceOrHostAddressKHR</type> <name>scratchData</name></member>
+ <member noautovalidity="true"><type>VkDeviceOrHostAddressKHR</type> <name>scratchData</name></member>
</type>
<type category="struct" name="VkAccelerationStructureBuildRangeInfoKHR">
<member><type>uint32_t</type> <name>primitiveCount</name></member>
<member><type>uint32_t</type> <name>primitiveOffset</name></member>
- <member optional="true"><type>uint32_t</type> <name>firstVertex</name></member>
- <member optional="true"><type>uint32_t</type> <name>transformOffset</name></member>
+ <member><type>uint32_t</type> <name>firstVertex</name></member>
+ <member><type>uint32_t</type> <name>transformOffset</name></member>
</type>
<type category="struct" name="VkAccelerationStructureCreateInfoKHR">
<member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
@@ -4823,7 +5326,7 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkAccelerationStructureVersionInfoKHR">
<member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_VERSION_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member len="2*ename:VK_UUID_SIZE" altlen="2*VK_UUID_SIZE">const <type>uint8_t</type>* <name>pVersionData</name></member>
+ <member len="latexmath:[2 \times \mathtt{VK\_UUID\_SIZE}]" altlen="2*VK_UUID_SIZE">const <type>uint8_t</type>* <name>pVersionData</name></member>
</type>
<type category="struct" name="VkCopyAccelerationStructureInfoKHR">
<member values="VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
@@ -4836,13 +5339,13 @@ typedef void <name>CAMetalLayer</name>;
<member values="VK_STRUCTURE_TYPE_COPY_ACCELERATION_STRUCTURE_TO_MEMORY_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkAccelerationStructureKHR</type> <name>src</name></member>
- <member><type>VkDeviceOrHostAddressKHR</type> <name>dst</name></member>
+ <member noautovalidity="true"><type>VkDeviceOrHostAddressKHR</type> <name>dst</name></member>
<member><type>VkCopyAccelerationStructureModeKHR</type> <name>mode</name></member>
</type>
<type category="struct" name="VkCopyMemoryToAccelerationStructureInfoKHR">
<member values="VK_STRUCTURE_TYPE_COPY_MEMORY_TO_ACCELERATION_STRUCTURE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkDeviceOrHostAddressConstKHR</type> <name>src</name></member>
+ <member noautovalidity="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>src</name></member>
<member><type>VkAccelerationStructureKHR</type> <name>dst</name></member>
<member><type>VkCopyAccelerationStructureModeKHR</type> <name>mode</name></member>
</type>
@@ -4852,7 +5355,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>uint32_t</type> <name>maxPipelineRayPayloadSize</name></member>
<member><type>uint32_t</type> <name>maxPipelineRayHitAttributeSize</name></member>
</type>
- <type category="struct" name="VkPipelineLibraryCreateInfoKHR">
+ <type category="struct" name="VkPipelineLibraryCreateInfoKHR" structextends="VkGraphicsPipelineCreateInfo">
<member values="VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>uint32_t</type> <name>libraryCount</name></member>
@@ -4863,12 +5366,19 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>extendedDynamicState</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceExtendedDynamicState2FeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>extendedDynamicState2</name></member>
+ <member><type>VkBool32</type> <name>extendedDynamicState2LogicOp</name></member>
+ <member><type>VkBool32</type> <name>extendedDynamicState2PatchControlPoints</name></member>
+ </type>
<type category="struct" name="VkRenderPassTransformBeginInfoQCOM" structextends="VkRenderPassBeginInfo">
<member values="VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name><comment>Pointer to next structure</comment></member>
<member noautovalidity="true"><type>VkSurfaceTransformFlagBitsKHR</type> <name>transform</name></member>
</type>
- <type category="struct" name="VkCopyCommandTransformInfoQCOM" structextends="VkBufferImageCopy2KHR,VkImageBlit2KHR">
+ <type category="struct" name="VkCopyCommandTransformInfoQCOM" structextends="VkBufferImageCopy2,VkImageBlit2">
<member values="VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true" noautovalidity="true">const <type>void</type>* <name>pNext</name></member>
<member noautovalidity="true"><type>VkSurfaceTransformFlagBitsKHR</type> <name>transform</name></member>
@@ -4880,7 +5390,7 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkRect2D</type> <name>renderArea</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceDiagnosticsConfigFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV"><type>VkStructureType</type><name>sType</name></member>
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>diagnosticsConfig</name></member>
</type>
@@ -4889,24 +5399,44 @@ typedef void <name>CAMetalLayer</name>;
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>VkDeviceDiagnosticsConfigFlagsNV</type> <name>flags</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>shaderZeroInitializeWorkgroupMemory</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR" alias="VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures"/>
+ <type category="struct" name="VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>shaderSubgroupUniformControlFlow</name></member>
+ </type>
<type category="struct" name="VkPhysicalDeviceRobustness2FeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>robustBufferAccess2</name></member>
<member><type>VkBool32</type> <name>robustImageAccess2</name></member>
<member><type>VkBool32</type> <name>nullDescriptor</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceRobustness2PropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkDeviceSize</type> <name>robustStorageBufferAccessSizeAlignment</name></member>
- <member><type>VkDeviceSize</type> <name>robustUniformBufferAccessSizeAlignment</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>robustStorageBufferAccessSizeAlignment</name></member>
+ <member limittype="min,pot"><type>VkDeviceSize</type> <name>robustUniformBufferAccessSizeAlignment</name></member>
</type>
- <type category="struct" name="VkPhysicalDeviceImageRobustnessFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <type category="struct" name="VkPhysicalDeviceImageRobustnessFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>robustImageAccess</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceImageRobustnessFeaturesEXT" alias="VkPhysicalDeviceImageRobustnessFeatures"/>
+ <type category="struct" name="VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>workgroupMemoryExplicitLayout</name></member>
+ <member><type>VkBool32</type> <name>workgroupMemoryExplicitLayoutScalarBlockLayout</name></member>
+ <member><type>VkBool32</type> <name>workgroupMemoryExplicitLayout8BitAccess</name></member>
+ <member><type>VkBool32</type> <name>workgroupMemoryExplicitLayout16BitAccess</name></member>
+ </type>
<type category="struct" name="VkPhysicalDevicePortabilitySubsetFeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -4929,114 +5459,130 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDevicePortabilitySubsetPropertiesKHR" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>uint32_t</type> <name>minVertexInputBindingStrideAlignment</name></member>
+ <member limittype="min,pot"><type>uint32_t</type> <name>minVertexInputBindingStrideAlignment</name></member>
</type>
<type category="struct" name="VkPhysicalDevice4444FormatsFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>formatA4R4G4B4</name></member>
<member><type>VkBool32</type> <name>formatA4B4G4R4</name></member>
</type>
- <type category="struct" name="VkBufferCopy2KHR">
- <member values="VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkDeviceSize</type> <name>srcOffset</name><comment>Specified in bytes</comment></member>
- <member><type>VkDeviceSize</type> <name>dstOffset</name><comment>Specified in bytes</comment></member>
- <member noautovalidity="true"><type>VkDeviceSize</type> <name>size</name><comment>Specified in bytes</comment></member>
- </type>
- <type category="struct" name="VkImageCopy2KHR">
- <member values="VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkImageSubresourceLayers</type> <name>srcSubresource</name></member>
- <member><type>VkOffset3D</type> <name>srcOffset</name><comment>Specified in pixels for both compressed and uncompressed images</comment></member>
- <member><type>VkImageSubresourceLayers</type> <name>dstSubresource</name></member>
- <member><type>VkOffset3D</type> <name>dstOffset</name><comment>Specified in pixels for both compressed and uncompressed images</comment></member>
- <member><type>VkExtent3D</type> <name>extent</name><comment>Specified in pixels for both compressed and uncompressed images</comment></member>
- </type>
- <type category="struct" name="VkImageBlit2KHR">
- <member values="VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkImageSubresourceLayers</type> <name>srcSubresource</name></member>
- <member><type>VkOffset3D</type> <name>srcOffsets</name>[2]<comment>Specified in pixels for both compressed and uncompressed images</comment></member>
- <member><type>VkImageSubresourceLayers</type> <name>dstSubresource</name></member>
- <member><type>VkOffset3D</type> <name>dstOffsets</name>[2]<comment>Specified in pixels for both compressed and uncompressed images</comment></member>
- </type>
- <type category="struct" name="VkBufferImageCopy2KHR">
- <member values="VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkDeviceSize</type> <name>bufferOffset</name><comment>Specified in bytes</comment></member>
- <member><type>uint32_t</type> <name>bufferRowLength</name><comment>Specified in texels</comment></member>
- <member><type>uint32_t</type> <name>bufferImageHeight</name></member>
- <member><type>VkImageSubresourceLayers</type> <name>imageSubresource</name></member>
- <member><type>VkOffset3D</type> <name>imageOffset</name><comment>Specified in pixels for both compressed and uncompressed images</comment></member>
- <member><type>VkExtent3D</type> <name>imageExtent</name><comment>Specified in pixels for both compressed and uncompressed images</comment></member>
- </type>
- <type category="struct" name="VkImageResolve2KHR">
- <member values="VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkImageSubresourceLayers</type> <name>srcSubresource</name></member>
- <member><type>VkOffset3D</type> <name>srcOffset</name></member>
- <member><type>VkImageSubresourceLayers</type> <name>dstSubresource</name></member>
- <member><type>VkOffset3D</type> <name>dstOffset</name></member>
- <member><type>VkExtent3D</type> <name>extent</name></member>
- </type>
- <type category="struct" name="VkCopyBufferInfo2KHR">
- <member values="VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkBuffer</type> <name>srcBuffer</name></member>
- <member><type>VkBuffer</type> <name>dstBuffer</name></member>
- <member><type>uint32_t</type> <name>regionCount</name></member>
- <member len="regionCount">const <type>VkBufferCopy2KHR</type>* <name>pRegions</name></member>
+ <type category="struct" name="VkPhysicalDeviceSubpassShadingFeaturesHUAWEI" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>subpassShading</name></member>
</type>
- <type category="struct" name="VkCopyImageInfo2KHR">
- <member values="VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkImage</type> <name>srcImage</name></member>
- <member><type>VkImageLayout</type> <name>srcImageLayout</name></member>
- <member><type>VkImage</type> <name>dstImage</name></member>
- <member><type>VkImageLayout</type> <name>dstImageLayout</name></member>
- <member><type>uint32_t</type> <name>regionCount</name></member>
- <member len="regionCount">const <type>VkImageCopy2KHR</type>* <name>pRegions</name></member>
- </type>
- <type category="struct" name="VkBlitImageInfo2KHR">
- <member values="VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkImage</type> <name>srcImage</name></member>
- <member><type>VkImageLayout</type> <name>srcImageLayout</name></member>
- <member><type>VkImage</type> <name>dstImage</name></member>
- <member><type>VkImageLayout</type> <name>dstImageLayout</name></member>
- <member><type>uint32_t</type> <name>regionCount</name></member>
- <member len="regionCount">const <type>VkImageBlit2KHR</type>* <name>pRegions</name></member>
- <member><type>VkFilter</type> <name>filter</name></member>
- </type>
- <type category="struct" name="VkCopyBufferToImageInfo2KHR">
- <member values="VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkBuffer</type> <name>srcBuffer</name></member>
- <member><type>VkImage</type> <name>dstImage</name></member>
- <member><type>VkImageLayout</type> <name>dstImageLayout</name></member>
- <member><type>uint32_t</type> <name>regionCount</name></member>
- <member len="regionCount">const <type>VkBufferImageCopy2KHR</type>* <name>pRegions</name></member>
- </type>
- <type category="struct" name="VkCopyImageToBufferInfo2KHR">
- <member values="VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkImage</type> <name>srcImage</name></member>
- <member><type>VkImageLayout</type> <name>srcImageLayout</name></member>
- <member><type>VkBuffer</type> <name>dstBuffer</name></member>
- <member><type>uint32_t</type> <name>regionCount</name></member>
- <member len="regionCount">const <type>VkBufferImageCopy2KHR</type>* <name>pRegions</name></member>
- </type>
- <type category="struct" name="VkResolveImageInfo2KHR">
- <member values="VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkImage</type> <name>srcImage</name></member>
- <member><type>VkImageLayout</type> <name>srcImageLayout</name></member>
- <member><type>VkImage</type> <name>dstImage</name></member>
- <member><type>VkImageLayout</type> <name>dstImageLayout</name></member>
- <member><type>uint32_t</type> <name>regionCount</name></member>
- <member len="regionCount">const <type>VkImageResolve2KHR</type>* <name>pRegions</name></member>
+ <type category="struct" name="VkBufferCopy2">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_COPY_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkDeviceSize</type> <name>srcOffset</name><comment>Specified in bytes</comment></member>
+ <member><type>VkDeviceSize</type> <name>dstOffset</name><comment>Specified in bytes</comment></member>
+ <member noautovalidity="true"><type>VkDeviceSize</type> <name>size</name><comment>Specified in bytes</comment></member>
</type>
+ <type category="struct" name="VkBufferCopy2KHR" alias="VkBufferCopy2"/>
+ <type category="struct" name="VkImageCopy2">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_COPY_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImageSubresourceLayers</type> <name>srcSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>srcOffset</name><comment>Specified in pixels for both compressed and uncompressed images</comment></member>
+ <member><type>VkImageSubresourceLayers</type> <name>dstSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>dstOffset</name><comment>Specified in pixels for both compressed and uncompressed images</comment></member>
+ <member><type>VkExtent3D</type> <name>extent</name><comment>Specified in pixels for both compressed and uncompressed images</comment></member>
+ </type>
+ <type category="struct" name="VkImageCopy2KHR" alias="VkImageCopy2"/>
+ <type category="struct" name="VkImageBlit2">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_BLIT_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImageSubresourceLayers</type> <name>srcSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>srcOffsets</name>[2]<comment>Specified in pixels for both compressed and uncompressed images</comment></member>
+ <member><type>VkImageSubresourceLayers</type> <name>dstSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>dstOffsets</name>[2]<comment>Specified in pixels for both compressed and uncompressed images</comment></member>
+ </type>
+ <type category="struct" name="VkImageBlit2KHR" alias="VkImageBlit2"/>
+ <type category="struct" name="VkBufferImageCopy2">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkDeviceSize</type> <name>bufferOffset</name><comment>Specified in bytes</comment></member>
+ <member><type>uint32_t</type> <name>bufferRowLength</name><comment>Specified in texels</comment></member>
+ <member><type>uint32_t</type> <name>bufferImageHeight</name></member>
+ <member><type>VkImageSubresourceLayers</type> <name>imageSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>imageOffset</name><comment>Specified in pixels for both compressed and uncompressed images</comment></member>
+ <member><type>VkExtent3D</type> <name>imageExtent</name><comment>Specified in pixels for both compressed and uncompressed images</comment></member>
+ </type>
+ <type category="struct" name="VkBufferImageCopy2KHR" alias="VkBufferImageCopy2"/>
+ <type category="struct" name="VkImageResolve2">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImageSubresourceLayers</type> <name>srcSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>srcOffset</name></member>
+ <member><type>VkImageSubresourceLayers</type> <name>dstSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>dstOffset</name></member>
+ <member><type>VkExtent3D</type> <name>extent</name></member>
+ </type>
+ <type category="struct" name="VkImageResolve2KHR" alias="VkImageResolve2"/>
+ <type category="struct" name="VkCopyBufferInfo2">
+ <member values="VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBuffer</type> <name>srcBuffer</name></member>
+ <member><type>VkBuffer</type> <name>dstBuffer</name></member>
+ <member><type>uint32_t</type> <name>regionCount</name></member>
+ <member len="regionCount">const <type>VkBufferCopy2</type>* <name>pRegions</name></member>
+ </type>
+ <type category="struct" name="VkCopyBufferInfo2KHR" alias="VkCopyBufferInfo2"/>
+ <type category="struct" name="VkCopyImageInfo2">
+ <member values="VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImage</type> <name>srcImage</name></member>
+ <member><type>VkImageLayout</type> <name>srcImageLayout</name></member>
+ <member><type>VkImage</type> <name>dstImage</name></member>
+ <member><type>VkImageLayout</type> <name>dstImageLayout</name></member>
+ <member><type>uint32_t</type> <name>regionCount</name></member>
+ <member len="regionCount">const <type>VkImageCopy2</type>* <name>pRegions</name></member>
+ </type>
+ <type category="struct" name="VkCopyImageInfo2KHR" alias="VkCopyImageInfo2"/>
+ <type category="struct" name="VkBlitImageInfo2">
+ <member values="VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImage</type> <name>srcImage</name></member>
+ <member><type>VkImageLayout</type> <name>srcImageLayout</name></member>
+ <member><type>VkImage</type> <name>dstImage</name></member>
+ <member><type>VkImageLayout</type> <name>dstImageLayout</name></member>
+ <member><type>uint32_t</type> <name>regionCount</name></member>
+ <member len="regionCount">const <type>VkImageBlit2</type>* <name>pRegions</name></member>
+ <member><type>VkFilter</type> <name>filter</name></member>
+ </type>
+ <type category="struct" name="VkBlitImageInfo2KHR" alias="VkBlitImageInfo2"/>
+ <type category="struct" name="VkCopyBufferToImageInfo2">
+ <member values="VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBuffer</type> <name>srcBuffer</name></member>
+ <member><type>VkImage</type> <name>dstImage</name></member>
+ <member><type>VkImageLayout</type> <name>dstImageLayout</name></member>
+ <member><type>uint32_t</type> <name>regionCount</name></member>
+ <member len="regionCount">const <type>VkBufferImageCopy2</type>* <name>pRegions</name></member>
+ </type>
+ <type category="struct" name="VkCopyBufferToImageInfo2KHR" alias="VkCopyBufferToImageInfo2"/>
+ <type category="struct" name="VkCopyImageToBufferInfo2">
+ <member values="VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImage</type> <name>srcImage</name></member>
+ <member><type>VkImageLayout</type> <name>srcImageLayout</name></member>
+ <member><type>VkBuffer</type> <name>dstBuffer</name></member>
+ <member><type>uint32_t</type> <name>regionCount</name></member>
+ <member len="regionCount">const <type>VkBufferImageCopy2</type>* <name>pRegions</name></member>
+ </type>
+ <type category="struct" name="VkCopyImageToBufferInfo2KHR" alias="VkCopyImageToBufferInfo2"/>
+ <type category="struct" name="VkResolveImageInfo2">
+ <member values="VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImage</type> <name>srcImage</name></member>
+ <member><type>VkImageLayout</type> <name>srcImageLayout</name></member>
+ <member><type>VkImage</type> <name>dstImage</name></member>
+ <member><type>VkImageLayout</type> <name>dstImageLayout</name></member>
+ <member><type>uint32_t</type> <name>regionCount</name></member>
+ <member len="regionCount">const <type>VkImageResolve2</type>* <name>pRegions</name></member>
+ </type>
+ <type category="struct" name="VkResolveImageInfo2KHR" alias="VkResolveImageInfo2"/>
<type category="struct" name="VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_IMAGE_ATOMIC_INT64_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
@@ -5046,14 +5592,14 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkFragmentShadingRateAttachmentInfoKHR" structextends="VkSubpassDescription2">
<member values="VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member>const <type>VkAttachmentReference2</type>* <name>pFragmentShadingRateAttachment</name></member>
+ <member optional="true">const <type>VkAttachmentReference2</type>* <name>pFragmentShadingRateAttachment</name></member>
<member><type>VkExtent2D</type> <name>shadingRateAttachmentTexelSize</name></member>
</type>
<type category="struct" name="VkPipelineFragmentShadingRateStateCreateInfoKHR" structextends="VkGraphicsPipelineCreateInfo">
<member values="VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
<member><type>VkExtent2D</type> <name>fragmentSize</name></member>
- <member><type>VkFragmentShadingRateCombinerOpKHR</type> <name>combinerOps</name>[2]</member>
+ <member noautovalidity="true"><type>VkFragmentShadingRateCombinerOpKHR</type> <name>combinerOps</name>[2]</member>
</type>
<type category="struct" name="VkPhysicalDeviceFragmentShadingRateFeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR"><type>VkStructureType</type> <name>sType</name></member>
@@ -5065,23 +5611,23 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceFragmentShadingRatePropertiesKHR" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkExtent2D</type> <name>minFragmentShadingRateAttachmentTexelSize</name></member>
- <member><type>VkExtent2D</type> <name>maxFragmentShadingRateAttachmentTexelSize</name></member>
- <member><type>uint32_t</type> <name>maxFragmentShadingRateAttachmentTexelSizeAspectRatio</name></member>
- <member><type>VkBool32</type> <name>primitiveFragmentShadingRateWithMultipleViewports</name></member>
- <member><type>VkBool32</type> <name>layeredShadingRateAttachments</name></member>
- <member><type>VkBool32</type> <name>fragmentShadingRateNonTrivialCombinerOps</name></member>
- <member><type>VkExtent2D</type> <name>maxFragmentSize</name></member>
- <member><type>uint32_t</type> <name>maxFragmentSizeAspectRatio</name></member>
- <member><type>uint32_t</type> <name>maxFragmentShadingRateCoverageSamples</name></member>
- <member><type>VkSampleCountFlagBits</type> <name>maxFragmentShadingRateRasterizationSamples</name></member>
- <member><type>VkBool32</type> <name>fragmentShadingRateWithShaderDepthStencilWrites</name></member>
- <member><type>VkBool32</type> <name>fragmentShadingRateWithSampleMask</name></member>
- <member><type>VkBool32</type> <name>fragmentShadingRateWithShaderSampleMask</name></member>
- <member><type>VkBool32</type> <name>fragmentShadingRateWithConservativeRasterization</name></member>
- <member><type>VkBool32</type> <name>fragmentShadingRateWithFragmentShaderInterlock</name></member>
- <member><type>VkBool32</type> <name>fragmentShadingRateWithCustomSampleLocations</name></member>
- <member><type>VkBool32</type> <name>fragmentShadingRateStrictMultiplyCombiner</name></member>
+ <member limittype="min"><type>VkExtent2D</type> <name>minFragmentShadingRateAttachmentTexelSize</name></member>
+ <member limittype="max"><type>VkExtent2D</type> <name>maxFragmentShadingRateAttachmentTexelSize</name></member>
+ <member limittype="max,pot"><type>uint32_t</type> <name>maxFragmentShadingRateAttachmentTexelSizeAspectRatio</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>primitiveFragmentShadingRateWithMultipleViewports</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>layeredShadingRateAttachments</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>fragmentShadingRateNonTrivialCombinerOps</name></member>
+ <member limittype="max"><type>VkExtent2D</type> <name>maxFragmentSize</name></member>
+ <member limittype="max,pot"><type>uint32_t</type> <name>maxFragmentSizeAspectRatio</name></member>
+ <member limittype="max"><type>uint32_t</type> <name>maxFragmentShadingRateCoverageSamples</name></member>
+ <member limittype="max"><type>VkSampleCountFlagBits</type> <name>maxFragmentShadingRateRasterizationSamples</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>fragmentShadingRateWithShaderDepthStencilWrites</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>fragmentShadingRateWithSampleMask</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>fragmentShadingRateWithShaderSampleMask</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>fragmentShadingRateWithConservativeRasterization</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>fragmentShadingRateWithFragmentShaderInterlock</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>fragmentShadingRateWithCustomSampleLocations</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>fragmentShadingRateStrictMultiplyCombiner</name></member>
</type>
<type category="struct" name="VkPhysicalDeviceFragmentShadingRateKHR" returnedonly="true">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR"><type>VkStructureType</type> <name>sType</name></member>
@@ -5089,14 +5635,15 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkSampleCountFlags</type> <name>sampleCounts</name></member>
<member><type>VkExtent2D</type> <name>fragmentSize</name></member>
</type>
- <type category="struct" name="VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
- <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR"><type>VkStructureType</type><name>sType</name></member>
+ <type category="struct" name="VkPhysicalDeviceShaderTerminateInvocationFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkBool32</type> <name>shaderTerminateInvocation</name></member>
+ <member><type>VkBool32</type> <name>shaderTerminateInvocation</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR" alias="VkPhysicalDeviceShaderTerminateInvocationFeatures"/>
<type category="struct" name="VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
- <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>fragmentShadingRateEnums</name></member>
<member><type>VkBool32</type> <name>supersampleFragmentShadingRates</name></member>
<member><type>VkBool32</type> <name>noInvocationFragmentShadingRates</name></member>
@@ -5104,14 +5651,14 @@ typedef void <name>CAMetalLayer</name>;
<type category="struct" name="VkPhysicalDeviceFragmentShadingRateEnumsPropertiesNV" structextends="VkPhysicalDeviceProperties2">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_ENUMS_PROPERTIES_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true"><type>void</type>* <name>pNext</name></member>
- <member><type>VkSampleCountFlagBits</type> <name>maxFragmentShadingRateInvocationCount</name></member>
+ <member limittype="max"><type>VkSampleCountFlagBits</type> <name>maxFragmentShadingRateInvocationCount</name></member>
</type>
<type category="struct" name="VkPipelineFragmentShadingRateEnumStateCreateInfoNV" structextends="VkGraphicsPipelineCreateInfo">
<member values="VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
<member optional="true">const <type>void</type>* <name>pNext</name></member>
- <member><type>VkFragmentShadingRateTypeNV</type> <name>shadingRateType</name></member>
- <member><type>VkFragmentShadingRateNV</type> <name>shadingRate</name></member>
- <member><type>VkFragmentShadingRateCombinerOpKHR</type> <name>combinerOps</name>[2]</member>
+ <member noautovalidity="true"><type>VkFragmentShadingRateTypeNV</type> <name>shadingRateType</name></member>
+ <member noautovalidity="true"><type>VkFragmentShadingRateNV</type> <name>shadingRate</name></member>
+ <member noautovalidity="true"><type>VkFragmentShadingRateCombinerOpKHR</type> <name>combinerOps</name>[2]</member>
</type>
<type category="struct" name="VkAccelerationStructureBuildSizesInfoKHR">
<member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
@@ -5120,9 +5667,15 @@ typedef void <name>CAMetalLayer</name>;
<member><type>VkDeviceSize</type> <name>updateScratchSize</name></member>
<member><type>VkDeviceSize</type> <name>buildScratchSize</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceImage2DViewOf3DFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>image2DViewOf3D</name></member>
+ <member><type>VkBool32</type> <name>sampler2DViewOf3D</name></member>
+ </type>
<type category="struct" name="VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
<member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE"><type>VkStructureType</type> <name>sType</name></member>
- <member noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
<member><type>VkBool32</type> <name>mutableDescriptorType</name></member>
</type>
<type category="struct" name="VkMutableDescriptorTypeListVALVE">
@@ -5131,43 +5684,1446 @@ typedef void <name>CAMetalLayer</name>;
</type>
<type category="struct" name="VkMutableDescriptorTypeCreateInfoVALVE" structextends="VkDescriptorSetLayoutCreateInfo,VkDescriptorPoolCreateInfo">
<member values="VK_STRUCTURE_TYPE_MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_VALVE"><type>VkStructureType</type> <name>sType</name></member>
- <member>const <type>void</type>* <name>pNext</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
<member optional="true"><type>uint32_t</type> <name>mutableDescriptorTypeListCount</name></member>
<member len="mutableDescriptorTypeListCount">const <type>VkMutableDescriptorTypeListVALVE</type>* <name>pMutableDescriptorTypeLists</name></member>
</type>
+ <type category="struct" name="VkPhysicalDeviceDepthClipControlFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>depthClipControl</name></member>
+ </type>
+ <type category="struct" name="VkPipelineViewportDepthClipControlCreateInfoEXT" structextends="VkPipelineViewportStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>negativeOneToOne</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>vertexInputDynamicState</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceExternalMemoryRDMAFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>externalMemoryRDMA</name></member>
+ </type>
+ <type category="struct" name="VkVertexInputBindingDescription2EXT">
+ <member values="VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>binding</name></member>
+ <member><type>uint32_t</type> <name>stride</name></member>
+ <member><type>VkVertexInputRate</type> <name>inputRate</name></member>
+ <member><type>uint32_t</type> <name>divisor</name></member>
+ </type>
+ <type category="struct" name="VkVertexInputAttributeDescription2EXT">
+ <member values="VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>location</name><comment>location of the shader vertex attrib</comment></member>
+ <member><type>uint32_t</type> <name>binding</name><comment>Vertex buffer binding id</comment></member>
+ <member><type>VkFormat</type> <name>format</name><comment>format of source data</comment></member>
+ <member><type>uint32_t</type> <name>offset</name><comment>Offset of first element in bytes from base of vertex</comment></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceColorWriteEnableFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>colorWriteEnable</name></member>
+ </type>
+ <type category="struct" name="VkPipelineColorWriteCreateInfoEXT" structextends="VkPipelineColorBlendStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>uint32_t</type> <name>attachmentCount</name><comment># of pAttachments</comment></member>
+ <member len="attachmentCount">const <type>VkBool32</type>* <name>pColorWriteEnables</name></member>
+ </type>
+ <type category="struct" name="VkMemoryBarrier2" structextends="VkSubpassDependency2">
+ <member values="VK_STRUCTURE_TYPE_MEMORY_BARRIER_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkPipelineStageFlags2</type> <name>srcStageMask</name></member>
+ <member optional="true"><type>VkAccessFlags2</type> <name>srcAccessMask</name></member>
+ <member optional="true"><type>VkPipelineStageFlags2</type> <name>dstStageMask</name></member>
+ <member optional="true"><type>VkAccessFlags2</type> <name>dstAccessMask</name></member>
+ </type>
+ <type category="struct" name="VkMemoryBarrier2KHR" alias="VkMemoryBarrier2"/>
+ <type category="struct" name="VkImageMemoryBarrier2">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkPipelineStageFlags2</type> <name>srcStageMask</name></member>
+ <member optional="true"><type>VkAccessFlags2</type> <name>srcAccessMask</name></member>
+ <member optional="true"><type>VkPipelineStageFlags2</type> <name>dstStageMask</name></member>
+ <member optional="true"><type>VkAccessFlags2</type> <name>dstAccessMask</name></member>
+ <member><type>VkImageLayout</type> <name>oldLayout</name></member>
+ <member><type>VkImageLayout</type> <name>newLayout</name></member>
+ <member><type>uint32_t</type> <name>srcQueueFamilyIndex</name></member>
+ <member><type>uint32_t</type> <name>dstQueueFamilyIndex</name></member>
+ <member><type>VkImage</type> <name>image</name></member>
+ <member><type>VkImageSubresourceRange</type> <name>subresourceRange</name></member>
+ </type>
+ <type category="struct" name="VkImageMemoryBarrier2KHR" alias="VkImageMemoryBarrier2"/>
+ <type category="struct" name="VkBufferMemoryBarrier2">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkPipelineStageFlags2</type> <name>srcStageMask</name></member>
+ <member optional="true"><type>VkAccessFlags2</type> <name>srcAccessMask</name></member>
+ <member optional="true"><type>VkPipelineStageFlags2</type> <name>dstStageMask</name></member>
+ <member optional="true"><type>VkAccessFlags2</type> <name>dstAccessMask</name></member>
+ <member><type>uint32_t</type> <name>srcQueueFamilyIndex</name></member>
+ <member><type>uint32_t</type> <name>dstQueueFamilyIndex</name></member>
+ <member><type>VkBuffer</type> <name>buffer</name></member>
+ <member><type>VkDeviceSize</type> <name>offset</name></member>
+ <member><type>VkDeviceSize</type> <name>size</name></member>
+ </type>
+ <type category="struct" name="VkBufferMemoryBarrier2KHR" alias="VkBufferMemoryBarrier2"/>
+ <type category="struct" name="VkDependencyInfo">
+ <member values="VK_STRUCTURE_TYPE_DEPENDENCY_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkDependencyFlags</type> <name>dependencyFlags</name></member>
+ <member optional="true"><type>uint32_t</type> <name>memoryBarrierCount</name></member>
+ <member len="memoryBarrierCount">const <type>VkMemoryBarrier2</type>* <name>pMemoryBarriers</name></member>
+ <member optional="true"><type>uint32_t</type> <name>bufferMemoryBarrierCount</name></member>
+ <member len="bufferMemoryBarrierCount">const <type>VkBufferMemoryBarrier2</type>* <name>pBufferMemoryBarriers</name></member>
+ <member optional="true"><type>uint32_t</type> <name>imageMemoryBarrierCount</name></member>
+ <member len="imageMemoryBarrierCount">const <type>VkImageMemoryBarrier2</type>* <name>pImageMemoryBarriers</name></member>
+ </type>
+ <type category="struct" name="VkDependencyInfoKHR" alias="VkDependencyInfo"/>
+ <type category="struct" name="VkSemaphoreSubmitInfo">
+ <member values="VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkSemaphore</type> <name>semaphore</name></member>
+ <member><type>uint64_t</type> <name>value</name></member>
+ <member optional="true"><type>VkPipelineStageFlags2</type> <name>stageMask</name></member>
+ <member><type>uint32_t</type> <name>deviceIndex</name></member>
+ </type>
+ <type category="struct" name="VkSemaphoreSubmitInfoKHR" alias="VkSemaphoreSubmitInfo"/>
+ <type category="struct" name="VkCommandBufferSubmitInfo">
+ <member values="VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkCommandBuffer</type> <name>commandBuffer</name></member>
+ <member><type>uint32_t</type> <name>deviceMask</name></member>
+ </type>
+ <type category="struct" name="VkCommandBufferSubmitInfoKHR" alias="VkCommandBufferSubmitInfo"/>
+ <type category="struct" name="VkSubmitInfo2">
+ <member values="VK_STRUCTURE_TYPE_SUBMIT_INFO_2"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkSubmitFlags</type> <name>flags</name></member>
+ <member optional="true"><type>uint32_t</type> <name>waitSemaphoreInfoCount</name></member>
+ <member len="waitSemaphoreInfoCount">const <type>VkSemaphoreSubmitInfo</type>* <name>pWaitSemaphoreInfos</name></member>
+ <member optional="true"><type>uint32_t</type> <name>commandBufferInfoCount</name></member>
+ <member len="commandBufferInfoCount">const <type>VkCommandBufferSubmitInfo</type>* <name>pCommandBufferInfos</name></member>
+ <member optional="true"><type>uint32_t</type> <name>signalSemaphoreInfoCount</name></member>
+ <member len="signalSemaphoreInfoCount">const <type>VkSemaphoreSubmitInfo</type>* <name>pSignalSemaphoreInfos</name></member>
+ </type>
+ <type category="struct" name="VkSubmitInfo2KHR" alias="VkSubmitInfo2"/>
+ <type category="struct" name="VkQueueFamilyCheckpointProperties2NV" structextends="VkQueueFamilyProperties2" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="bitmask"><type>VkPipelineStageFlags2</type> <name>checkpointExecutionStageMask</name></member>
+ </type>
+ <type category="struct" name="VkCheckpointData2NV" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkPipelineStageFlags2</type> <name>stage</name></member>
+ <member noautovalidity="true"><type>void</type>* <name>pCheckpointMarker</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceSynchronization2Features" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>synchronization2</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceSynchronization2FeaturesKHR" alias="VkPhysicalDeviceSynchronization2Features"/>
+ <type category="struct" name="VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>primitivesGeneratedQuery</name></member>
+ <member><type>VkBool32</type> <name>primitivesGeneratedQueryWithRasterizerDiscard</name></member>
+ <member><type>VkBool32</type> <name>primitivesGeneratedQueryWithNonZeroStreams</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>multisampledRenderToSingleSampled</name></member>
+ </type>
+ <type category="struct" name="VkSubpassResolvePerformanceQueryEXT" returnedonly="true" structextends="VkFormatProperties2">
+ <member values="VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>optimal</name></member>
+ </type>
+ <type category="struct" name="VkMultisampledRenderToSingleSampledInfoEXT" structextends="VkSubpassDescription2,VkRenderingInfo">
+ <member values="VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>multisampledRenderToSingleSampledEnable</name></member>
+ <member><type>VkSampleCountFlagBits</type> <name>rasterizationSamples</name></member>
+ </type>
+ <type category="struct" name="VkVideoQueueFamilyProperties2KHR" structextends="VkQueueFamilyProperties2">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_QUEUE_FAMILY_PROPERTIES_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="bitmask"><type>VkVideoCodecOperationFlagsKHR</type> <name>videoCodecOperations</name></member>
+ </type>
+ <type category="struct" name="VkQueueFamilyQueryResultStatusProperties2KHR" structextends="VkQueueFamilyProperties2">
+ <member values="VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>queryResultStatusSupport</name></member>
+ </type>
+ <type category="struct" name="VkVideoProfilesKHR" structextends="VkPhysicalDeviceImageFormatInfo2,VkPhysicalDeviceVideoFormatInfoKHR,VkImageCreateInfo,VkBufferCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>uint32_t</type> <name>profileCount</name></member>
+ <member len="profileCount">const <type>VkVideoProfileKHR</type>* <name>pProfiles</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceVideoFormatInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR"> <type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkImageUsageFlags</type> <name>imageUsage</name></member>
+ </type>
+ <type category="struct" name="VkVideoFormatPropertiesKHR" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkFormat</type> <name>format</name></member>
+ <member><type>VkComponentMapping</type> <name>componentMapping</name></member>
+ <member><type>VkImageCreateFlags</type> <name>imageCreateFlags</name></member>
+ <member><type>VkImageType</type> <name>imageType</name></member>
+ <member><type>VkImageTiling</type> <name>imageTiling</name></member>
+ <member><type>VkImageUsageFlags</type> <name>imageUsageFlags</name></member>
+ </type>
+ <type category="struct" name="VkVideoProfileKHR" structextends="VkQueryPoolCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkVideoCodecOperationFlagBitsKHR</type> <name>videoCodecOperation</name></member>
+ <member><type>VkVideoChromaSubsamplingFlagsKHR</type> <name>chromaSubsampling</name></member>
+ <member><type>VkVideoComponentBitDepthFlagsKHR</type> <name>lumaBitDepth</name></member>
+ <member><type>VkVideoComponentBitDepthFlagsKHR</type> <name>chromaBitDepth</name></member>
+ </type>
+ <type category="struct" name="VkVideoCapabilitiesKHR" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkVideoCapabilityFlagsKHR</type> <name>capabilityFlags</name></member>
+ <member><type>VkDeviceSize</type> <name>minBitstreamBufferOffsetAlignment</name></member>
+ <member><type>VkDeviceSize</type> <name>minBitstreamBufferSizeAlignment</name></member>
+ <member><type>VkExtent2D</type> <name>videoPictureExtentGranularity</name></member>
+ <member><type>VkExtent2D</type> <name>minExtent</name></member>
+ <member><type>VkExtent2D</type> <name>maxExtent</name></member>
+ <member><type>uint32_t</type> <name>maxReferencePicturesSlotsCount</name></member>
+ <member><type>uint32_t</type> <name>maxReferencePicturesActiveCount</name></member>
+ <member><type>VkExtensionProperties</type> <name>stdHeaderVersion</name></member>
+ </type>
+ <type category="struct" name="VkVideoGetMemoryPropertiesKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_GET_MEMORY_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>memoryBindIndex</name></member>
+ <member><type>VkMemoryRequirements2</type>* <name>pMemoryRequirements</name></member>
+ </type>
+ <type category="struct" name="VkVideoBindMemoryKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_BIND_MEMORY_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>memoryBindIndex</name></member>
+ <member><type>VkDeviceMemory</type> <name>memory</name></member>
+ <member><type>VkDeviceSize</type> <name>memoryOffset</name></member>
+ <member><type>VkDeviceSize</type> <name>memorySize</name></member>
+ </type>
+ <type category="struct" name="VkVideoPictureResourceKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkOffset2D</type> <name>codedOffset</name><comment>The offset to be used for the picture resource, currently only used in field mode</comment></member>
+ <member><type>VkExtent2D</type> <name>codedExtent</name><comment>The extent to be used for the picture resource</comment></member>
+ <member><type>uint32_t</type> <name>baseArrayLayer</name><comment>The first array layer to be accessed for the Decode or Encode Operations</comment></member>
+ <member><type>VkImageView</type> <name>imageViewBinding</name><comment>The ImageView binding of the resource</comment></member>
+ </type>
+ <type category="struct" name="VkVideoReferenceSlotKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>int8_t</type> <name>slotIndex</name><comment>The reference slot index</comment></member>
+ <member>const <type>VkVideoPictureResourceKHR</type>* <name>pPictureResource</name><comment>The reference picture resource</comment></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeCapabilitiesKHR" returnedonly="true" structextends="VkVideoCapabilitiesKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member noautovalidity="true"><type>VkVideoDecodeCapabilityFlagsKHR</type> <name>flags</name></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkVideoDecodeFlagsKHR</type> <name>flags</name></member>
+ <member><type>VkBuffer</type> <name>srcBuffer</name></member>
+ <member><type>VkDeviceSize</type> <name>srcBufferOffset</name></member>
+ <member><type>VkDeviceSize</type> <name>srcBufferRange</name></member>
+ <member><type>VkVideoPictureResourceKHR</type> <name>dstPictureResource</name></member>
+ <member>const <type>VkVideoReferenceSlotKHR</type>* <name>pSetupReferenceSlot</name></member>
+ <member optional="true"><type>uint32_t</type> <name>referenceSlotCount</name></member>
+ <member len="referenceSlotCount">const <type>VkVideoReferenceSlotKHR</type>* <name>pReferenceSlots</name></member>
+ </type>
+ <comment>Video Decode Codec Standard specific structures</comment>
+ <type category="include" name="vk_video/vulkan_video_codec_h264std.h">#include "vk_video/vulkan_video_codec_h264std.h"</type>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264ProfileIdc"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264Level"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264ChromaFormatIdc"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264PocType"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264SpsFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264ScalingLists"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264SequenceParameterSetVui"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264AspectRatioIdc"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264HrdParameters"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264SpsVuiFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264WeightedBipredIdc"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264PpsFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264SliceType"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264CabacInitIdc"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264DisableDeblockingFilterIdc"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264PictureType"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264ModificationOfPicNumsIdc"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264MemMgmtControlOp"/>
+ <type category="include" name="vk_video/vulkan_video_codec_h264std_decode.h">#include "vk_video/vulkan_video_codec_h264std_decode.h"</type>
+ <type requires="vk_video/vulkan_video_codec_h264std_decode.h" name="StdVideoDecodeH264PictureInfo"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_decode.h" name="StdVideoDecodeH264ReferenceInfo"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_decode.h" name="StdVideoDecodeH264Mvc"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_decode.h" name="StdVideoDecodeH264PictureInfoFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_decode.h" name="StdVideoDecodeH264ReferenceInfoFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_decode.h" name="StdVideoDecodeH264MvcElement"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_decode.h" name="StdVideoDecodeH264MvcElementFlags"/>
+ <type category="struct" name="VkVideoDecodeH264ProfileEXT" structextends="VkVideoProfileKHR,VkQueryPoolCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>StdVideoH264ProfileIdc</type> <name>stdProfileIdc</name></member>
+ <member noautovalidity="true"><type>VkVideoDecodeH264PictureLayoutFlagsEXT</type> <name>pictureLayout</name></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeH264CapabilitiesEXT" returnedonly="true" structextends="VkVideoDecodeCapabilitiesKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>StdVideoH264Level</type> <name>maxLevel</name></member>
+ <member><type>VkOffset2D</type> <name>fieldOffsetGranularity</name></member>
+ </type>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264SequenceParameterSet"/>
+ <type requires="vk_video/vulkan_video_codec_h264std.h" name="StdVideoH264PictureParameterSet"/>
+ <type category="struct" name="VkVideoDecodeH264SessionParametersAddInfoEXT" structextends="VkVideoSessionParametersUpdateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>spsStdCount</name></member>
+ <member len="spsStdCount" optional="true">const <type>StdVideoH264SequenceParameterSet</type>* <name>pSpsStd</name></member>
+ <member><type>uint32_t</type> <name>ppsStdCount</name></member>
+ <member len="ppsStdCount" optional="true">const <type>StdVideoH264PictureParameterSet</type>* <name>pPpsStd</name><comment>List of Picture Parameters associated with the spsStd, above</comment></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeH264SessionParametersCreateInfoEXT" structextends="VkVideoSessionParametersCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>maxSpsStdCount</name></member>
+ <member><type>uint32_t</type> <name>maxPpsStdCount</name></member>
+ <member optional="true">const <type>VkVideoDecodeH264SessionParametersAddInfoEXT</type>* <name>pParametersAddInfo</name></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeH264PictureInfoEXT" structextends="VkVideoDecodeInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true">const <type>void</type>* <name>pNext</name></member>
+ <member>const <type>StdVideoDecodeH264PictureInfo</type>* <name>pStdPictureInfo</name></member>
+ <member><type>uint32_t</type> <name>slicesCount</name></member>
+ <member len="slicesCount">const <type>uint32_t</type>* <name>pSlicesDataOffsets</name></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeH264DpbSlotInfoEXT" structextends="VkVideoReferenceSlotKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member>const <type>StdVideoDecodeH264ReferenceInfo</type>* <name>pStdReferenceInfo</name></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeH264MvcEXT" structextends="VkVideoDecodeH264PictureInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_MVC_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true">const <type>void</type>*<name>pNext</name></member>
+ <member>const <type>StdVideoDecodeH264Mvc</type>* <name>pStdMvc</name></member>
+ </type>
+ <type category="include" name="vk_video/vulkan_video_codec_h265std.h">#include "vk_video/vulkan_video_codec_h265std.h"</type>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265ProfileIdc"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265VideoParameterSet"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265SequenceParameterSet"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265PictureParameterSet"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265DecPicBufMgr"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265HrdParameters"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265VpsFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265Level"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265SpsFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265ScalingLists"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265SequenceParameterSetVui"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265PredictorPaletteEntries"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265PpsFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265SubLayerHrdParameters"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265HrdFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265SpsVuiFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265SliceType"/>
+ <type requires="vk_video/vulkan_video_codec_h265std.h" name="StdVideoH265PictureType"/>
+ <type category="include" name="vk_video/vulkan_video_codec_h265std_decode.h">#include "vk_video/vulkan_video_codec_h265std_decode.h"</type>
+ <type requires="vk_video/vulkan_video_codec_h265std_decode.h" name="StdVideoDecodeH265PictureInfo"/>
+ <type requires="vk_video/vulkan_video_codec_h265std_decode.h" name="StdVideoDecodeH265ReferenceInfo"/>
+ <type requires="vk_video/vulkan_video_codec_h265std_decode.h" name="StdVideoDecodeH265PictureInfoFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h265std_decode.h" name="StdVideoDecodeH265ReferenceInfoFlags"/>
+ <type category="struct" name="VkVideoDecodeH265ProfileEXT" structextends="VkVideoProfileKHR,VkQueryPoolCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>StdVideoH265ProfileIdc</type> <name>stdProfileIdc</name></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeH265CapabilitiesEXT" returnedonly="true" structextends="VkVideoDecodeCapabilitiesKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>StdVideoH265Level</type> <name>maxLevel</name></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeH265SessionParametersAddInfoEXT" structextends="VkVideoSessionParametersUpdateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>vpsStdCount</name></member>
+ <member len="vpsStdCount" optional="true">const <type>StdVideoH265VideoParameterSet</type>* <name>pVpsStd</name></member>
+ <member><type>uint32_t</type> <name>spsStdCount</name></member>
+ <member len="spsStdCount" optional="true">const <type>StdVideoH265SequenceParameterSet</type>* <name>pSpsStd</name></member>
+ <member><type>uint32_t</type> <name>ppsStdCount</name></member>
+ <member len="ppsStdCount" optional="true">const <type>StdVideoH265PictureParameterSet</type>* <name>pPpsStd</name><comment>List of Picture Parameters associated with the spsStd, above</comment></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeH265SessionParametersCreateInfoEXT" structextends="VkVideoSessionParametersCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>maxVpsStdCount</name></member>
+ <member><type>uint32_t</type> <name>maxSpsStdCount</name></member>
+ <member><type>uint32_t</type> <name>maxPpsStdCount</name></member>
+ <member optional="true">const <type>VkVideoDecodeH265SessionParametersAddInfoEXT</type>* <name>pParametersAddInfo</name></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeH265PictureInfoEXT" structextends="VkVideoDecodeInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>StdVideoDecodeH265PictureInfo</type>* <name>pStdPictureInfo</name></member>
+ <member><type>uint32_t</type> <name>slicesCount</name></member>
+ <member len="slicesCount">const <type>uint32_t</type>* <name>pSlicesDataOffsets</name></member>
+ </type>
+ <type category="struct" name="VkVideoDecodeH265DpbSlotInfoEXT" structextends="VkVideoReferenceSlotKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member>const <type>StdVideoDecodeH265ReferenceInfo</type>* <name>pStdReferenceInfo</name></member>
+ </type>
+ <type category="struct" name="VkVideoSessionCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>queueFamilyIndex</name></member>
+ <member optional="true"><type>VkVideoSessionCreateFlagsKHR</type> <name>flags</name></member>
+ <member>const <type>VkVideoProfileKHR</type>* <name>pVideoProfile</name></member>
+ <member><type>VkFormat</type> <name>pictureFormat</name></member>
+ <member><type>VkExtent2D</type> <name>maxCodedExtent</name></member>
+ <member><type>VkFormat</type> <name>referencePicturesFormat</name></member>
+ <member><type>uint32_t</type> <name>maxReferencePicturesSlotsCount</name></member>
+ <member><type>uint32_t</type> <name>maxReferencePicturesActiveCount</name></member>
+ <member>const <type>VkExtensionProperties</type>* <name>pStdHeaderVersion</name></member>
+ </type>
+ <type category="struct" name="VkVideoSessionParametersCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkVideoSessionParametersKHR</type> <name>videoSessionParametersTemplate</name></member>
+ <member><type>VkVideoSessionKHR</type> <name>videoSession</name></member>
+ </type>
+ <type category="struct" name="VkVideoSessionParametersUpdateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>updateSequenceCount</name></member>
+ </type>
+ <type category="struct" name="VkVideoBeginCodingInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkVideoBeginCodingFlagsKHR</type> <name>flags</name></member>
+ <member><type>VkVideoCodingQualityPresetFlagsKHR</type> <name>codecQualityPreset</name></member>
+ <member><type>VkVideoSessionKHR</type> <name>videoSession</name></member>
+ <member optional="true"><type>VkVideoSessionParametersKHR</type> <name>videoSessionParameters</name></member>
+ <member optional="true"><type>uint32_t</type> <name>referenceSlotCount</name></member>
+ <member len="referenceSlotCount">const <type>VkVideoReferenceSlotKHR</type>* <name>pReferenceSlots</name></member>
+ </type>
+ <type category="struct" name="VkVideoEndCodingInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkVideoEndCodingFlagsKHR</type> <name>flags</name></member>
+ </type>
+ <type category="struct" name="VkVideoCodingControlInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkVideoCodingControlFlagsKHR</type> <name>flags</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkVideoEncodeFlagsKHR</type> <name>flags</name></member>
+ <member><type>uint32_t</type> <name>qualityLevel</name></member>
+ <member><type>VkBuffer</type> <name>dstBitstreamBuffer</name></member>
+ <member><type>VkDeviceSize</type> <name>dstBitstreamBufferOffset</name></member>
+ <member><type>VkDeviceSize</type> <name>dstBitstreamBufferMaxRange</name></member>
+ <member><type>VkVideoPictureResourceKHR</type> <name>srcPictureResource</name></member>
+ <member>const <type>VkVideoReferenceSlotKHR</type>* <name>pSetupReferenceSlot</name></member>
+ <member optional="true"><type>uint32_t</type> <name>referenceSlotCount</name></member>
+ <member len="referenceSlotCount">const <type>VkVideoReferenceSlotKHR</type>* <name>pReferenceSlots</name></member>
+ <member><type>uint32_t</type> <name>precedingExternallyEncodedBytes</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeRateControlInfoKHR" structextends="VkVideoCodingControlInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member noautovalidity="true"><type>VkVideoEncodeRateControlFlagsKHR</type> <name>flags</name></member>
+ <member><type>VkVideoEncodeRateControlModeFlagBitsKHR</type> <name>rateControlMode</name></member>
+ <member><type>uint8_t</type> <name>layerCount</name></member>
+ <member len="layerCount">const <type>VkVideoEncodeRateControlLayerInfoKHR</type>* <name>pLayerConfigs</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeRateControlLayerInfoKHR" structextends="VkVideoCodingControlInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>averageBitrate</name></member>
+ <member><type>uint32_t</type> <name>maxBitrate</name></member>
+ <member><type>uint32_t</type> <name>frameRateNumerator</name></member>
+ <member><type>uint32_t</type> <name>frameRateDenominator</name></member>
+ <member><type>uint32_t</type> <name>virtualBufferSizeInMs</name></member>
+ <member><type>uint32_t</type> <name>initialVirtualBufferSizeInMs</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeCapabilitiesKHR" returnedonly="true" structextends="VkVideoCapabilitiesKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member noautovalidity="true"><type>VkVideoEncodeCapabilityFlagsKHR</type> <name>flags</name></member>
+ <member><type>VkVideoEncodeRateControlModeFlagsKHR</type> <name>rateControlModes</name></member>
+ <member><type>uint8_t</type> <name>rateControlLayerCount</name></member>
+ <member><type>uint8_t</type> <name>qualityLevelCount</name></member>
+ <member><type>VkExtent2D</type> <name>inputImageDataFillAlignment</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264CapabilitiesEXT" returnedonly="true" structextends="VkVideoEncodeCapabilitiesKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member noautovalidity="true"><type>VkVideoEncodeH264CapabilityFlagsEXT</type> <name>flags</name></member>
+ <member><type>VkVideoEncodeH264InputModeFlagsEXT</type> <name>inputModeFlags</name></member>
+ <member><type>VkVideoEncodeH264OutputModeFlagsEXT</type> <name>outputModeFlags</name></member>
+ <member><type>uint8_t</type> <name>maxPPictureL0ReferenceCount</name></member>
+ <member><type>uint8_t</type> <name>maxBPictureL0ReferenceCount</name></member>
+ <member><type>uint8_t</type> <name>maxL1ReferenceCount</name></member>
+ <member><type>VkBool32</type> <name>motionVectorsOverPicBoundariesFlag</name></member>
+ <member><type>uint32_t</type> <name>maxBytesPerPicDenom</name></member>
+ <member><type>uint32_t</type> <name>maxBitsPerMbDenom</name></member>
+ <member><type>uint32_t</type> <name>log2MaxMvLengthHorizontal</name></member>
+ <member><type>uint32_t</type> <name>log2MaxMvLengthVertical</name></member>
+ </type>
+ <type category="include" name="vk_video/vulkan_video_codec_h264std_encode.h">#include "vk_video/vulkan_video_codec_h264std_encode.h"</type>
+ <type requires="vk_video/vulkan_video_codec_h264std_encode.h" name="StdVideoEncodeH264SliceHeader"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_encode.h" name="StdVideoEncodeH264PictureInfo"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_encode.h" name="StdVideoEncodeH264ReferenceInfo"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_encode.h" name="StdVideoEncodeH264SliceHeaderFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_encode.h" name="StdVideoEncodeH264RefMemMgmtCtrlOperations"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_encode.h" name="StdVideoEncodeH264PictureInfoFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_encode.h" name="StdVideoEncodeH264ReferenceInfoFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_encode.h" name="StdVideoEncodeH264RefMgmtFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_encode.h" name="StdVideoEncodeH264RefListModEntry"/>
+ <type requires="vk_video/vulkan_video_codec_h264std_encode.h" name="StdVideoEncodeH264RefPicMarkingEntry"/>
+ <type category="struct" name="VkVideoEncodeH264SessionParametersAddInfoEXT" structextends="VkVideoSessionParametersUpdateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>spsStdCount</name></member>
+ <member len="spsStdCount" optional="true">const <type>StdVideoH264SequenceParameterSet</type>* <name>pSpsStd</name></member>
+ <member><type>uint32_t</type> <name>ppsStdCount</name></member>
+ <member len="ppsStdCount" optional="true">const <type>StdVideoH264PictureParameterSet</type>* <name>pPpsStd</name><comment>List of Picture Parameters associated with the spsStd, above</comment></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264SessionParametersCreateInfoEXT" structextends="VkVideoSessionParametersCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>maxSpsStdCount</name></member>
+ <member><type>uint32_t</type> <name>maxPpsStdCount</name></member>
+ <member optional="true">const <type>VkVideoEncodeH264SessionParametersAddInfoEXT</type>* <name>pParametersAddInfo</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264DpbSlotInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>int8_t</type> <name>slotIndex</name></member>
+ <member>const <type>StdVideoEncodeH264ReferenceInfo</type>* <name>pStdReferenceInfo</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264VclFrameInfoEXT" structextends="VkVideoEncodeInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true">const <type>VkVideoEncodeH264ReferenceListsEXT</type>* <name>pReferenceFinalLists</name></member>
+ <member><type>uint32_t</type> <name>naluSliceEntryCount</name></member>
+ <member len="naluSliceEntryCount">const <type>VkVideoEncodeH264NaluSliceEXT</type>* <name>pNaluSliceEntries</name></member>
+ <member>const <type>StdVideoEncodeH264PictureInfo</type>* <name>pCurrentPictureInfo</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264ReferenceListsEXT">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>uint8_t</type> <name>referenceList0EntryCount</name></member>
+ <member len="referenceList0EntryCount">const <type>VkVideoEncodeH264DpbSlotInfoEXT</type>* <name>pReferenceList0Entries</name></member>
+ <member optional="true"><type>uint8_t</type> <name>referenceList1EntryCount</name></member>
+ <member len="referenceList1EntryCount">const <type>VkVideoEncodeH264DpbSlotInfoEXT</type>* <name>pReferenceList1Entries</name></member>
+ <member>const <type>StdVideoEncodeH264RefMemMgmtCtrlOperations</type>* <name>pMemMgmtCtrlOperations</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264EmitPictureParametersEXT" structextends="VkVideoEncodeInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint8_t</type> <name>spsId</name></member>
+ <member><type>VkBool32</type> <name>emitSpsEnable</name></member>
+ <member><type>uint32_t</type> <name>ppsIdEntryCount</name></member>
+ <member len="ppsIdEntryCount">const <type>uint8_t</type>* <name>ppsIdEntries</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264ProfileEXT" structextends="VkVideoProfileKHR,VkQueryPoolCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>StdVideoH264ProfileIdc</type> <name>stdProfileIdc</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264NaluSliceEXT">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>mbCount</name></member>
+ <member optional="true">const <type>VkVideoEncodeH264ReferenceListsEXT</type>* <name>pReferenceFinalLists</name></member>
+ <member>const <type>StdVideoEncodeH264SliceHeader</type>* <name>pSliceHeaderStd</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264RateControlInfoEXT" structextends="VkVideoEncodeRateControlInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>gopFrameCount</name></member>
+ <member><type>uint32_t</type> <name>idrPeriod</name></member>
+ <member><type>uint32_t</type> <name>consecutiveBFrameCount</name></member>
+ <member><type>VkVideoEncodeH264RateControlStructureFlagBitsEXT</type> <name>rateControlStructure</name></member>
+ <member><type>uint8_t</type> <name>temporalLayerCount</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264QpEXT">
+ <member noautovalidity="true"><type>int32_t</type> <name>qpI</name></member>
+ <member noautovalidity="true"><type>int32_t</type> <name>qpP</name></member>
+ <member noautovalidity="true"><type>int32_t</type> <name>qpB</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264FrameSizeEXT">
+ <member noautovalidity="true"><type>uint32_t</type> <name>frameISize</name></member>
+ <member noautovalidity="true"><type>uint32_t</type> <name>framePSize</name></member>
+ <member noautovalidity="true"><type>uint32_t</type> <name>frameBSize</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH264RateControlLayerInfoEXT" structextends="VkVideoEncodeRateControlLayerInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint8_t</type> <name>temporalLayerId</name></member>
+ <member><type>VkBool32</type> <name>useInitialRcQp</name></member>
+ <member><type>VkVideoEncodeH264QpEXT</type> <name>initialRcQp</name></member>
+ <member><type>VkBool32</type> <name>useMinQp</name></member>
+ <member><type>VkVideoEncodeH264QpEXT</type> <name>minQp</name></member>
+ <member><type>VkBool32</type> <name>useMaxQp</name></member>
+ <member><type>VkVideoEncodeH264QpEXT</type> <name>maxQp</name></member>
+ <member><type>VkBool32</type> <name>useMaxFrameSize</name></member>
+ <member><type>VkVideoEncodeH264FrameSizeEXT</type> <name>maxFrameSize</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265CapabilitiesEXT" returnedonly="true" structextends="VkVideoEncodeCapabilitiesKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member noautovalidity="true"><type>VkVideoEncodeH265CapabilityFlagsEXT</type> <name>flags</name></member>
+ <member><type>VkVideoEncodeH265InputModeFlagsEXT</type> <name>inputModeFlags</name></member>
+ <member><type>VkVideoEncodeH265OutputModeFlagsEXT</type> <name>outputModeFlags</name></member>
+ <member><type>VkVideoEncodeH265CtbSizeFlagsEXT</type> <name>ctbSizes</name></member>
+ <member><type>VkVideoEncodeH265TransformBlockSizeFlagsEXT</type> <name>transformBlockSizes</name></member>
+ <member><type>uint8_t</type> <name>maxPPictureL0ReferenceCount</name></member>
+ <member><type>uint8_t</type> <name>maxBPictureL0ReferenceCount</name></member>
+ <member><type>uint8_t</type> <name>maxL1ReferenceCount</name></member>
+ <member><type>uint8_t</type> <name>maxSubLayersCount</name></member>
+ <member><type>uint8_t</type> <name>minLog2MinLumaCodingBlockSizeMinus3</name></member>
+ <member><type>uint8_t</type> <name>maxLog2MinLumaCodingBlockSizeMinus3</name></member>
+ <member><type>uint8_t</type> <name>minLog2MinLumaTransformBlockSizeMinus2</name></member>
+ <member><type>uint8_t</type> <name>maxLog2MinLumaTransformBlockSizeMinus2</name></member>
+ <member><type>uint8_t</type> <name>minMaxTransformHierarchyDepthInter</name></member>
+ <member><type>uint8_t</type> <name>maxMaxTransformHierarchyDepthInter</name></member>
+ <member><type>uint8_t</type> <name>minMaxTransformHierarchyDepthIntra</name></member>
+ <member><type>uint8_t</type> <name>maxMaxTransformHierarchyDepthIntra</name></member>
+ <member><type>uint8_t</type> <name>maxDiffCuQpDeltaDepth</name></member>
+ <member><type>uint8_t</type> <name>minMaxNumMergeCand</name></member>
+ <member><type>uint8_t</type> <name>maxMaxNumMergeCand</name></member>
+ </type>
+ <type category="include" name="vk_video/vulkan_video_codec_h265std_encode.h">#include "vk_video/vulkan_video_codec_h265std_encode.h"</type>
+ <type requires="vk_video/vulkan_video_codec_h265std_encode.h" name="StdVideoEncodeH265PictureInfoFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h265std_encode.h" name="StdVideoEncodeH265PictureInfo"/>
+ <type requires="vk_video/vulkan_video_codec_h265std_encode.h" name="StdVideoEncodeH265SliceSegmentHeader"/>
+ <type requires="vk_video/vulkan_video_codec_h265std_encode.h" name="StdVideoEncodeH265ReferenceInfo"/>
+ <type requires="vk_video/vulkan_video_codec_h265std_encode.h" name="StdVideoEncodeH265ReferenceModifications"/>
+ <type requires="vk_video/vulkan_video_codec_h265std_encode.h" name="StdVideoEncodeH265SliceSegmentHeaderFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h265std_encode.h" name="StdVideoEncodeH265ReferenceInfoFlags"/>
+ <type requires="vk_video/vulkan_video_codec_h265std_encode.h" name="StdVideoEncodeH265ReferenceModificationFlags"/>
+ <type category="struct" name="VkVideoEncodeH265SessionParametersAddInfoEXT" structextends="VkVideoSessionParametersUpdateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>vpsStdCount</name></member>
+ <member len="vpsStdCount" optional="true">const <type>StdVideoH265VideoParameterSet</type>* <name>pVpsStd</name></member>
+ <member><type>uint32_t</type> <name>spsStdCount</name></member>
+ <member len="spsStdCount" optional="true">const <type>StdVideoH265SequenceParameterSet</type>* <name>pSpsStd</name></member>
+ <member><type>uint32_t</type> <name>ppsStdCount</name></member>
+ <member len="ppsStdCount" optional="true">const <type>StdVideoH265PictureParameterSet</type>* <name>pPpsStd</name><comment>List of Picture Parameters associated with the spsStd, above</comment></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265SessionParametersCreateInfoEXT" structextends="VkVideoSessionParametersCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>maxVpsStdCount</name></member>
+ <member><type>uint32_t</type> <name>maxSpsStdCount</name></member>
+ <member><type>uint32_t</type> <name>maxPpsStdCount</name></member>
+ <member optional="true">const <type>VkVideoEncodeH265SessionParametersAddInfoEXT</type>* <name>pParametersAddInfo</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265VclFrameInfoEXT" structextends="VkVideoEncodeInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true">const <type>VkVideoEncodeH265ReferenceListsEXT</type>* <name>pReferenceFinalLists</name></member>
+ <member><type>uint32_t</type> <name>naluSliceSegmentEntryCount</name></member>
+ <member len="naluSliceSegmentEntryCount">const <type>VkVideoEncodeH265NaluSliceSegmentEXT</type>* <name>pNaluSliceSegmentEntries</name></member>
+ <member>const <type>StdVideoEncodeH265PictureInfo</type>* <name>pCurrentPictureInfo</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265EmitPictureParametersEXT" structextends="VkVideoEncodeInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint8_t</type> <name>vpsId</name></member>
+ <member><type>uint8_t</type> <name>spsId</name></member>
+ <member><type>VkBool32</type> <name>emitVpsEnable</name></member>
+ <member><type>VkBool32</type> <name>emitSpsEnable</name></member>
+ <member optional="true"><type>uint32_t</type> <name>ppsIdEntryCount</name></member>
+ <member len="ppsIdEntryCount">const <type>uint8_t</type>* <name>ppsIdEntries</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265NaluSliceSegmentEXT">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>ctbCount</name></member>
+ <member optional="true">const <type>VkVideoEncodeH265ReferenceListsEXT</type>* <name>pReferenceFinalLists</name></member>
+ <member>const <type>StdVideoEncodeH265SliceSegmentHeader</type>* <name>pSliceSegmentHeaderStd</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265RateControlInfoEXT" structextends="VkVideoEncodeRateControlInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>gopFrameCount</name></member>
+ <member><type>uint32_t</type> <name>idrPeriod</name></member>
+ <member><type>uint32_t</type> <name>consecutiveBFrameCount</name></member>
+ <member><type>VkVideoEncodeH265RateControlStructureFlagBitsEXT</type> <name>rateControlStructure</name></member>
+ <member><type>uint8_t</type> <name>subLayerCount</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265QpEXT">
+ <member noautovalidity="true"><type>int32_t</type> <name>qpI</name></member>
+ <member noautovalidity="true"><type>int32_t</type> <name>qpP</name></member>
+ <member noautovalidity="true"><type>int32_t</type> <name>qpB</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265FrameSizeEXT">
+ <member noautovalidity="true"><type>uint32_t</type> <name>frameISize</name></member>
+ <member noautovalidity="true"><type>uint32_t</type> <name>framePSize</name></member>
+ <member noautovalidity="true"><type>uint32_t</type> <name>frameBSize</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265RateControlLayerInfoEXT" structextends="VkVideoEncodeRateControlLayerInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint8_t</type> <name>temporalId</name></member>
+ <member><type>VkBool32</type> <name>useInitialRcQp</name></member>
+ <member><type>VkVideoEncodeH265QpEXT</type> <name>initialRcQp</name></member>
+ <member><type>VkBool32</type> <name>useMinQp</name></member>
+ <member><type>VkVideoEncodeH265QpEXT</type> <name>minQp</name></member>
+ <member><type>VkBool32</type> <name>useMaxQp</name></member>
+ <member><type>VkVideoEncodeH265QpEXT</type> <name>maxQp</name></member>
+ <member><type>VkBool32</type> <name>useMaxFrameSize</name></member>
+ <member><type>VkVideoEncodeH265FrameSizeEXT</type> <name>maxFrameSize</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265ProfileEXT" structextends="VkVideoProfileKHR,VkQueryPoolCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>StdVideoH265ProfileIdc</type> <name>stdProfileIdc</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265DpbSlotInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>int8_t</type> <name>slotIndex</name></member>
+ <member>const <type>StdVideoEncodeH265ReferenceInfo</type>* <name>pStdReferenceInfo</name></member>
+ </type>
+ <type category="struct" name="VkVideoEncodeH265ReferenceListsEXT">
+ <member values="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>uint8_t</type> <name>referenceList0EntryCount</name></member>
+ <member len="referenceList0EntryCount">const <type>VkVideoEncodeH265DpbSlotInfoEXT</type>* <name>pReferenceList0Entries</name></member>
+ <member optional="true"><type>uint8_t</type> <name>referenceList1EntryCount</name></member>
+ <member len="referenceList1EntryCount">const <type>VkVideoEncodeH265DpbSlotInfoEXT</type>* <name>pReferenceList1Entries</name></member>
+ <member>const <type>StdVideoEncodeH265ReferenceModifications</type>* <name>pReferenceModifications</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceInheritedViewportScissorFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>inheritedViewportScissor2D</name></member>
+ </type>
+ <type category="struct" name="VkCommandBufferInheritanceViewportScissorInfoNV" structextends="VkCommandBufferInheritanceInfo">
+ <member values="VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>viewportScissor2D</name></member>
+ <member><type>uint32_t</type> <name>viewportDepthCount</name></member>
+ <member noautovalidity="true">const <type>VkViewport</type>* <name>pViewportDepths</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>ycbcr2plane444Formats</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceProvokingVertexFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>provokingVertexLast</name></member>
+ <member><type>VkBool32</type> <name>transformFeedbackPreservesProvokingVertex</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceProvokingVertexPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>provokingVertexModePerPipeline</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>transformFeedbackPreservesTriangleFanProvokingVertex</name></member>
+ </type>
+ <type category="struct" name="VkPipelineRasterizationProvokingVertexStateCreateInfoEXT" structextends="VkPipelineRasterizationStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkProvokingVertexModeEXT</type> <name>provokingVertexMode</name></member>
+ </type>
+ <type category="struct" name="VkCuModuleCreateInfoNVX">
+ <member values="VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>size_t</type> <name>dataSize</name></member>
+ <member len="dataSize">const <type>void</type>* <name>pData</name></member>
+ </type>
+ <type category="struct" name="VkCuFunctionCreateInfoNVX">
+ <member values="VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkCuModuleNVX</type> <name>module</name></member>
+ <member len="null-terminated">const <type>char</type>* <name>pName</name></member>
+ </type>
+ <type category="struct" name="VkCuLaunchInfoNVX">
+ <member values="VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkCuFunctionNVX</type> <name>function</name></member>
+ <member><type>uint32_t</type> <name>gridDimX</name></member>
+ <member><type>uint32_t</type> <name>gridDimY</name></member>
+ <member><type>uint32_t</type> <name>gridDimZ</name></member>
+ <member><type>uint32_t</type> <name>blockDimX</name></member>
+ <member><type>uint32_t</type> <name>blockDimY</name></member>
+ <member><type>uint32_t</type> <name>blockDimZ</name></member>
+ <member><type>uint32_t</type> <name>sharedMemBytes</name></member>
+ <member optional="true"><type>size_t</type> <name>paramCount</name></member>
+ <member len="paramCount">const <type>void</type>* const * <name>pParams</name></member>
+ <member optional="true"><type>size_t</type> <name>extraCount</name></member>
+ <member len="extraCount">const <type>void</type>* const * <name>pExtras</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceShaderIntegerDotProductFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>shaderIntegerDotProduct</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR" alias="VkPhysicalDeviceShaderIntegerDotProductFeatures"/>
+ <type category="struct" name="VkPhysicalDeviceShaderIntegerDotProductProperties" structextends="VkPhysicalDeviceProperties2" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct8BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct8BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct8BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct4x8BitPackedUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct4x8BitPackedSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct4x8BitPackedMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct16BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct16BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct16BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct32BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct32BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct32BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct64BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct64BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProduct64BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating8BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating8BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating16BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating16BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating32BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating32BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating64BitUnsignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating64BitSignedAccelerated</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR" alias="VkPhysicalDeviceShaderIntegerDotProductProperties"/>
+ <type category="struct" name="VkPhysicalDeviceDrmPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>hasPrimary</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>hasRender</name></member>
+ <member limittype="noauto"><type>int64_t</type> <name>primaryMajor</name></member>
+ <member limittype="noauto"><type>int64_t</type> <name>primaryMinor</name></member>
+ <member limittype="noauto"><type>int64_t</type> <name>renderMajor</name></member>
+ <member limittype="noauto"><type>int64_t</type> <name>renderMinor</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>fragmentShaderBarycentric</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>triStripVertexOrderIndependentOfProvokingVertex</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceRayTracingMotionBlurFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>rayTracingMotionBlur</name></member>
+ <member><type>VkBool32</type> <name>rayTracingMotionBlurPipelineTraceRaysIndirect</name></member>
+ </type>
+ <type name="VkAccelerationStructureMotionInstanceTypeNV" category="enum"/>
+ <type category="struct" name="VkAccelerationStructureGeometryMotionTrianglesDataNV" structextends="VkAccelerationStructureGeometryTrianglesDataKHR">
+ <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member noautovalidity="true"><type>VkDeviceOrHostAddressConstKHR</type> <name>vertexData</name></member>
+ </type>
+ <type category="struct" name="VkAccelerationStructureMotionInfoNV" structextends="VkAccelerationStructureCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>maxInstances</name></member>
+ <member optional="true"><type>VkAccelerationStructureMotionInfoFlagsNV</type> <name>flags</name></member>
+ </type>
+ <type category="struct" name="VkSRTDataNV">
+ <member><type>float</type> <name>sx</name></member>
+ <member><type>float</type> <name>a</name></member>
+ <member><type>float</type> <name>b</name></member>
+ <member><type>float</type> <name>pvx</name></member>
+ <member><type>float</type> <name>sy</name></member>
+ <member><type>float</type> <name>c</name></member>
+ <member><type>float</type> <name>pvy</name></member>
+ <member><type>float</type> <name>sz</name></member>
+ <member><type>float</type> <name>pvz</name></member>
+ <member><type>float</type> <name>qx</name></member>
+ <member><type>float</type> <name>qy</name></member>
+ <member><type>float</type> <name>qz</name></member>
+ <member><type>float</type> <name>qw</name></member>
+ <member><type>float</type> <name>tx</name></member>
+ <member><type>float</type> <name>ty</name></member>
+ <member><type>float</type> <name>tz</name></member>
+ </type>
+ <type category="struct" name="VkAccelerationStructureSRTMotionInstanceNV">
+ <comment>The bitfields in this structure are non-normative since bitfield ordering is implementation-defined in C. The specification defines the normative layout.</comment>
+ <member><type>VkSRTDataNV</type> <name>transformT0</name></member>
+ <member><type>VkSRTDataNV</type> <name>transformT1</name></member>
+ <member><type>uint32_t</type> <name>instanceCustomIndex</name>:24</member>
+ <member><type>uint32_t</type> <name>mask</name>:8</member>
+ <member><type>uint32_t</type> <name>instanceShaderBindingTableRecordOffset</name>:24</member>
+ <member optional="true"><type>VkGeometryInstanceFlagsKHR</type> <name>flags</name>:8</member>
+ <member><type>uint64_t</type> <name>accelerationStructureReference</name></member>
+ </type>
+ <type category="struct" name="VkAccelerationStructureMatrixMotionInstanceNV">
+ <comment>The bitfields in this structure are non-normative since bitfield ordering is implementation-defined in C. The specification defines the normative layout.</comment>
+ <member><type>VkTransformMatrixKHR</type> <name>transformT0</name></member>
+ <member><type>VkTransformMatrixKHR</type> <name>transformT1</name></member>
+ <member><type>uint32_t</type> <name>instanceCustomIndex</name>:24</member>
+ <member><type>uint32_t</type> <name>mask</name>:8</member>
+ <member><type>uint32_t</type> <name>instanceShaderBindingTableRecordOffset</name>:24</member>
+ <member optional="true"><type>VkGeometryInstanceFlagsKHR</type> <name>flags</name>:8</member>
+ <member><type>uint64_t</type> <name>accelerationStructureReference</name></member>
+ </type>
+ <type category="union" name="VkAccelerationStructureMotionInstanceDataNV">
+ <member selection="VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV"><type>VkAccelerationStructureInstanceKHR</type> <name>staticInstance</name></member>
+ <member selection="VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV"><type>VkAccelerationStructureMatrixMotionInstanceNV</type> <name>matrixMotionInstance</name></member>
+ <member selection="VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV"><type>VkAccelerationStructureSRTMotionInstanceNV</type> <name>srtMotionInstance</name></member>
+ </type>
+ <type category="struct" name="VkAccelerationStructureMotionInstanceNV">
+ <member><type>VkAccelerationStructureMotionInstanceTypeNV</type> <name>type</name></member>
+ <member optional="true"><type>VkAccelerationStructureMotionInstanceFlagsNV</type> <name>flags</name></member>
+ <member selector="type"><type>VkAccelerationStructureMotionInstanceDataNV</type> <name>data</name></member>
+ </type>
+ <type category="basetype">typedef <type>void</type>* <name>VkRemoteAddressNV</name>;</type>
+ <type category="struct" name="VkMemoryGetRemoteAddressInfoNV">
+ <member values="VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkDeviceMemory</type> <name>memory</name></member>
+ <member><type>VkExternalMemoryHandleTypeFlagBits</type> <name>handleType</name></member>
+ </type>
+ <type category="struct" name="VkImportMemoryBufferCollectionFUCHSIA" structextends="VkMemoryAllocateInfo">
+ <member values="VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></member>
+ <member><type>uint32_t</type> <name>index</name></member>
+ </type>
+ <type category="struct" name="VkBufferCollectionImageCreateInfoFUCHSIA" structextends="VkImageCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></member>
+ <member><type>uint32_t</type> <name>index</name></member>
+ </type>
+ <type category="struct" name="VkBufferCollectionBufferCreateInfoFUCHSIA" structextends="VkBufferCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></member>
+ <member><type>uint32_t</type> <name>index</name></member>
+ </type>
+ <type category="struct" name="VkBufferCollectionCreateInfoFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>zx_handle_t</type> <name>collectionToken</name></member>
+ </type>
+ <type category="struct" name="VkBufferCollectionPropertiesFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>memoryTypeBits</name></member>
+ <member><type>uint32_t</type> <name>bufferCount</name></member>
+ <member><type>uint32_t</type> <name>createInfoIndex</name></member>
+ <member><type>uint64_t</type> <name>sysmemPixelFormat</name></member>
+ <member><type>VkFormatFeatureFlags</type> <name>formatFeatures</name></member>
+ <member><type>VkSysmemColorSpaceFUCHSIA</type> <name>sysmemColorSpaceIndex</name></member>
+ <member><type>VkComponentMapping</type> <name>samplerYcbcrConversionComponents</name></member>
+ <member><type>VkSamplerYcbcrModelConversion</type> <name>suggestedYcbcrModel</name></member>
+ <member><type>VkSamplerYcbcrRange</type> <name>suggestedYcbcrRange</name></member>
+ <member><type>VkChromaLocation</type> <name>suggestedXChromaOffset</name></member>
+ <member><type>VkChromaLocation</type> <name>suggestedYChromaOffset</name></member>
+ </type>
+ <type category="struct" name="VkBufferConstraintsInfoFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBufferCreateInfo</type> <name>createInfo</name></member>
+ <member optional="true"><type>VkFormatFeatureFlags</type> <name>requiredFormatFeatures</name></member>
+ <member><type>VkBufferCollectionConstraintsInfoFUCHSIA</type> <name>bufferCollectionConstraints</name></member>
+ </type>
+ <type category="struct" name="VkSysmemColorSpaceFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>colorSpace</name></member>
+ </type>
+ <type category="struct" name="VkImageFormatConstraintsInfoFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImageCreateInfo</type> <name>imageCreateInfo</name></member>
+ <member><type>VkFormatFeatureFlags</type> <name>requiredFormatFeatures</name></member>
+ <member optional="true"><type>VkImageFormatConstraintsFlagsFUCHSIA</type> <name>flags</name></member>
+ <member optional="true"><type>uint64_t</type> <name>sysmemPixelFormat</name></member>
+ <member><type>uint32_t</type> <name>colorSpaceCount</name></member>
+ <member len="colorSpaceCount">const <type>VkSysmemColorSpaceFUCHSIA</type>* <name>pColorSpaces</name></member>
+ </type>
+ <type category="struct" name="VkImageConstraintsInfoFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>formatConstraintsCount</name></member>
+ <member len="formatConstraintsCount">const <type>VkImageFormatConstraintsInfoFUCHSIA</type>* <name>pFormatConstraints</name></member>
+ <member><type>VkBufferCollectionConstraintsInfoFUCHSIA</type> <name>bufferCollectionConstraints</name></member>
+ <member optional="true"><type>VkImageConstraintsInfoFlagsFUCHSIA</type> <name>flags</name></member>
+ </type>
+ <type category="struct" name="VkBufferCollectionConstraintsInfoFUCHSIA">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>minBufferCount</name></member>
+ <member><type>uint32_t</type> <name>maxBufferCount</name></member>
+ <member><type>uint32_t</type> <name>minBufferCountForCamping</name></member>
+ <member><type>uint32_t</type> <name>minBufferCountForDedicatedSlack</name></member>
+ <member><type>uint32_t</type> <name>minBufferCountForSharedSlack</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>formatRgba10x6WithoutYCbCrSampler</name></member>
+ </type>
+ <type category="struct" name="VkFormatProperties3" returnedonly="true" structextends="VkFormatProperties2">
+ <member values="VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member optional="true" limittype="bitmask"><type>VkFormatFeatureFlags2</type> <name>linearTilingFeatures</name></member>
+ <member optional="true" limittype="bitmask"><type>VkFormatFeatureFlags2</type> <name>optimalTilingFeatures</name></member>
+ <member optional="true" limittype="bitmask"><type>VkFormatFeatureFlags2</type> <name>bufferFeatures</name></member>
+ </type>
+ <type category="struct" name="VkFormatProperties3KHR" alias="VkFormatProperties3"/>
+ <type category="struct" name="VkDrmFormatModifierPropertiesList2EXT" returnedonly="true" structextends="VkFormatProperties2">
+ <member values="VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>uint32_t</type> <name>drmFormatModifierCount</name></member>
+ <member optional="true" len="drmFormatModifierCount"><type>VkDrmFormatModifierProperties2EXT</type>* <name>pDrmFormatModifierProperties</name></member>
+ </type>
+ <type category="struct" name="VkDrmFormatModifierProperties2EXT" returnedonly="true">
+ <member><type>uint64_t</type> <name>drmFormatModifier</name></member>
+ <member><type>uint32_t</type> <name>drmFormatModifierPlaneCount</name></member>
+ <member><type>VkFormatFeatureFlags2</type> <name>drmFormatModifierTilingFeatures</name></member>
+ </type>
+ <type category="struct" name="VkAndroidHardwareBufferFormatProperties2ANDROID" structextends="VkAndroidHardwareBufferPropertiesANDROID" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkFormat</type> <name>format</name></member>
+ <member><type>uint64_t</type> <name>externalFormat</name></member>
+ <member><type>VkFormatFeatureFlags2</type> <name>formatFeatures</name></member>
+ <member><type>VkComponentMapping</type> <name>samplerYcbcrConversionComponents</name></member>
+ <member><type>VkSamplerYcbcrModelConversion</type> <name>suggestedYcbcrModel</name></member>
+ <member><type>VkSamplerYcbcrRange</type> <name>suggestedYcbcrRange</name></member>
+ <member><type>VkChromaLocation</type> <name>suggestedXChromaOffset</name></member>
+ <member><type>VkChromaLocation</type> <name>suggestedYChromaOffset</name></member>
+ </type>
+ <type category="struct" name="VkPipelineRenderingCreateInfo" structextends="VkGraphicsPipelineCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>viewMask</name></member>
+ <member optional="true"><type>uint32_t</type> <name>colorAttachmentCount</name></member>
+ <member noautovalidity="true" len="colorAttachmentCount">const <type>VkFormat</type>* <name>pColorAttachmentFormats</name></member>
+ <member noautovalidity="true"><type>VkFormat</type> <name>depthAttachmentFormat</name></member>
+ <member noautovalidity="true"><type>VkFormat</type> <name>stencilAttachmentFormat</name></member>
+ </type>
+ <type category="struct" name="VkPipelineRenderingCreateInfoKHR" alias="VkPipelineRenderingCreateInfo"/>
+ <type category="struct" name="VkRenderingInfo">
+ <member values="VK_STRUCTURE_TYPE_RENDERING_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkRenderingFlags</type> <name>flags</name></member>
+ <member><type>VkRect2D</type> <name>renderArea</name></member>
+ <member><type>uint32_t</type> <name>layerCount</name></member>
+ <member><type>uint32_t</type> <name>viewMask</name></member>
+ <member optional="true"><type>uint32_t</type> <name>colorAttachmentCount</name></member>
+ <member len="colorAttachmentCount">const <type>VkRenderingAttachmentInfo</type>* <name>pColorAttachments</name></member>
+ <member optional="true">const <type>VkRenderingAttachmentInfo</type>* <name>pDepthAttachment</name></member>
+ <member optional="true">const <type>VkRenderingAttachmentInfo</type>* <name>pStencilAttachment</name></member>
+ </type>
+ <type category="struct" name="VkRenderingInfoKHR" alias="VkRenderingInfo"/>
+ <type category="struct" name="VkRenderingAttachmentInfo">
+ <member values="VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkImageView</type> <name>imageView</name></member>
+ <member><type>VkImageLayout</type> <name>imageLayout</name></member>
+ <member optional="true"><type>VkResolveModeFlagBits</type> <name>resolveMode</name></member>
+ <member optional="true"><type>VkImageView</type> <name>resolveImageView</name></member>
+ <member><type>VkImageLayout</type> <name>resolveImageLayout</name></member>
+ <member><type>VkAttachmentLoadOp</type> <name>loadOp</name></member>
+ <member><type>VkAttachmentStoreOp</type> <name>storeOp</name></member>
+ <member><type>VkClearValue</type> <name>clearValue</name></member>
+ </type>
+ <type category="struct" name="VkRenderingAttachmentInfoKHR" alias="VkRenderingAttachmentInfo"/>
+ <type category="struct" name="VkRenderingFragmentShadingRateAttachmentInfoKHR" structextends="VkRenderingInfo">
+ <member values="VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkImageView</type> <name>imageView</name></member>
+ <member><type>VkImageLayout</type> <name>imageLayout</name></member>
+ <member><type>VkExtent2D</type> <name>shadingRateAttachmentTexelSize</name></member>
+ </type>
+ <type category="struct" name="VkRenderingFragmentDensityMapAttachmentInfoEXT" structextends="VkRenderingInfo">
+ <member values="VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImageView</type> <name>imageView</name></member>
+ <member><type>VkImageLayout</type> <name>imageLayout</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceDynamicRenderingFeatures" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>dynamicRendering</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceDynamicRenderingFeaturesKHR" alias="VkPhysicalDeviceDynamicRenderingFeatures"/>
+ <type category="struct" name="VkCommandBufferInheritanceRenderingInfo" structextends="VkCommandBufferInheritanceInfo">
+ <member values="VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkRenderingFlags</type> <name>flags</name></member>
+ <member><type>uint32_t</type> <name>viewMask</name></member>
+ <member optional="true"><type>uint32_t</type> <name>colorAttachmentCount</name></member>
+ <member len="colorAttachmentCount">const <type>VkFormat</type>* <name>pColorAttachmentFormats</name></member>
+ <member><type>VkFormat</type> <name>depthAttachmentFormat</name></member>
+ <member><type>VkFormat</type> <name>stencilAttachmentFormat</name></member>
+ <member optional="true"><type>VkSampleCountFlagBits</type> <name>rasterizationSamples</name></member>
+ </type>
+ <type category="struct" name="VkCommandBufferInheritanceRenderingInfoKHR" alias="VkCommandBufferInheritanceRenderingInfo"/>
+ <type category="struct" name="VkAttachmentSampleCountInfoAMD" structextends="VkCommandBufferInheritanceInfo,VkGraphicsPipelineCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>uint32_t</type> <name>colorAttachmentCount</name></member>
+ <member noautovalidity="true" len="colorAttachmentCount">const <type>VkSampleCountFlagBits</type>* <name>pColorAttachmentSamples</name></member>
+ <member noautovalidity="true" optional="true"><type>VkSampleCountFlagBits</type> <name>depthStencilAttachmentSamples</name></member>
+ </type>
+ <type category="struct" name="VkAttachmentSampleCountInfoNV" alias="VkAttachmentSampleCountInfoAMD"/>
+ <type category="struct" name="VkMultiviewPerViewAttributesInfoNVX" structextends="VkCommandBufferInheritanceInfo,VkGraphicsPipelineCreateInfo,VkRenderingInfo">
+ <member values="VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>perViewAttributes</name></member>
+ <member><type>VkBool32</type> <name>perViewAttributesPositionXOnly</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceImageViewMinLodFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>minLod</name></member>
+ </type>
+ <type category="struct" name="VkImageViewMinLodCreateInfoEXT" structextends="VkImageViewCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>float</type> <name>minLod</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>rasterizationOrderColorAttachmentAccess</name></member>
+ <member><type>VkBool32</type> <name>rasterizationOrderDepthAttachmentAccess</name></member>
+ <member><type>VkBool32</type> <name>rasterizationOrderStencilAttachmentAccess</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceLinearColorAttachmentFeaturesNV" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>linearColorAttachment</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>graphicsPipelineLibrary</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>graphicsPipelineLibraryFastLinking</name></member>
+ <member limittype="bitmask"><type>VkBool32</type> <name>graphicsPipelineLibraryIndependentInterpolationDecoration</name></member>
+ </type>
+ <type category="struct" name="VkGraphicsPipelineLibraryCreateInfoEXT" structextends="VkGraphicsPipelineCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkGraphicsPipelineLibraryFlagsEXT</type> <name>flags</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>descriptorSetHostMapping</name></member>
+ </type>
+ <type category="struct" name="VkDescriptorSetBindingReferenceVALVE">
+ <member values="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkDescriptorSetLayout</type> <name>descriptorSetLayout</name></member>
+ <member><type>uint32_t</type> <name>binding</name></member>
+ </type>
+ <type category="struct" name="VkDescriptorSetLayoutHostMappingInfoVALVE">
+ <member values="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>size_t</type> <name>descriptorOffset</name></member>
+ <member><type>uint32_t</type> <name>descriptorSize</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>shaderModuleIdentifier</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="noauto"><type>uint8_t</type> <name>shaderModuleIdentifierAlgorithmUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
+ </type>
+ <type category="struct" name="VkPipelineShaderStageModuleIdentifierCreateInfoEXT" structextends="VkPipelineShaderStageCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>uint32_t</type> <name>identifierSize</name></member>
+ <member len="identifierSize">const <type>uint8_t</type>* <name>pIdentifier</name></member>
+ </type>
+ <type category="struct" name="VkShaderModuleIdentifierEXT" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_SHADER_MODULE_IDENTIFIER_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member noautovalidity="true"><type>uint32_t</type> <name>identifierSize</name></member>
+ <member><type>uint8_t</type> <name>identifier</name>[<enum>VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT</enum>]</member>
+ </type>
+ <type category="struct" name="VkImageCompressionControlEXT" structextends="VkImageCreateInfo,VkSwapchainCreateInfoKHR,VkPhysicalDeviceImageFormatInfo2">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member noautovalidity="true"><type>VkImageCompressionFlagsEXT</type> <name>flags</name></member>
+ <member optional="true"><type>uint32_t</type> <name>compressionControlPlaneCount</name></member>
+ <member noautovalidity="true" len="compressionControlPlaneCount"><type>VkImageCompressionFixedRateFlagsEXT</type>* <name>pFixedRateFlags</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceImageCompressionControlFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>imageCompressionControl</name></member>
+ </type>
+ <type category="struct" name="VkImageCompressionPropertiesEXT" structextends="VkImageFormatProperties2,VkSurfaceFormat2KHR,VkSubresourceLayout2EXT" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkImageCompressionFlagsEXT</type> <name>imageCompressionFlags</name></member>
+ <member><type>VkImageCompressionFixedRateFlagsEXT</type> <name>imageCompressionFixedRateFlags</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>imageCompressionControlSwapchain</name></member>
+ </type>
+ <type category="struct" name="VkImageSubresource2EXT">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkImageSubresource</type> <name>imageSubresource</name></member>
+ </type>
+ <type category="struct" name="VkSubresourceLayout2EXT" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkSubresourceLayout</type> <name>subresourceLayout</name></member>
+ </type>
+ <type category="struct" name="VkRenderPassCreationControlEXT" structextends="VkRenderPassCreateInfo2,VkSubpassDescription2">
+ <member values="VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>disallowMerging</name></member>
+ </type>
+ <type category="struct" name="VkRenderPassCreationFeedbackInfoEXT" returnedonly="true">
+ <member><type>uint32_t</type> <name>postMergeSubpassCount</name></member>
+ </type>
+ <type category="struct" name="VkRenderPassCreationFeedbackCreateInfoEXT" structextends="VkRenderPassCreateInfo2">
+ <member values="VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkRenderPassCreationFeedbackInfoEXT</type>* <name>pRenderPassFeedback</name></member>
+ </type>
+ <type category="struct" name="VkRenderPassSubpassFeedbackInfoEXT" returnedonly="true">
+ <member><type>VkSubpassMergeStatusEXT</type> <name>subpassMergeStatus</name></member>
+ <member><type>char</type> <name>description</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member>
+ <member><type>uint32_t</type> <name>postMergeIndex</name></member>
+ </type>
+ <type category="struct" name="VkRenderPassSubpassFeedbackCreateInfoEXT" structextends="VkSubpassDescription2">
+ <member values="VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkRenderPassSubpassFeedbackInfoEXT</type>* <name>pSubpassFeedback</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>subpassMergeFeedback</name></member>
+ </type>
+ <type category="struct" name="VkPipelinePropertiesIdentifierEXT">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>uint8_t</type> <name>pipelineIdentifier</name>[<enum>VK_UUID_SIZE</enum>]</member>
+ </type>
+ <type category="struct" name="VkPhysicalDevicePipelinePropertiesFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>pipelinePropertiesIdentifier</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD"><type>VkStructureType</type> <name>sType</name></member>
+ <member noautovalidity="true" optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>shaderEarlyAndLateFragmentTests</name></member>
+ </type>
+ <type category="struct" name="VkExportMetalObjectCreateInfoEXT" structextends="VkInstanceCreateInfo,VkMemoryAllocateInfo,VkImageCreateInfo,VkImageViewCreateInfo,VkBufferViewCreateInfo,VkSemaphoreCreateInfo,VkEventCreateInfo" allowduplicate="true">
+ <member values="VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkExportMetalObjectTypeFlagBitsEXT</type> <name>exportObjectType</name></member>
+ </type>
+ <type category="struct" name="VkExportMetalObjectsInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ </type>
+ <type category="struct" name="VkExportMetalDeviceInfoEXT" structextends="VkExportMetalObjectsInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>MTLDevice_id</type> <name>mtlDevice</name></member>
+ </type>
+ <type category="struct" name="VkExportMetalCommandQueueInfoEXT" structextends="VkExportMetalObjectsInfoEXT" allowduplicate="true">
+ <member values="VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkQueue</type> <name>queue</name></member>
+ <member><type>MTLCommandQueue_id</type> <name>mtlCommandQueue</name></member>
+ </type>
+ <type category="struct" name="VkExportMetalBufferInfoEXT" structextends="VkExportMetalObjectsInfoEXT" allowduplicate="true">
+ <member values="VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkDeviceMemory</type> <name>memory</name></member>
+ <member><type>MTLBuffer_id</type> <name>mtlBuffer</name></member>
+ </type>
+ <type category="struct" name="VkImportMetalBufferInfoEXT" structextends="VkMemoryAllocateInfo" allowduplicate="false">
+ <member values="VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>MTLBuffer_id</type> <name>mtlBuffer</name></member>
+ </type>
+ <type category="struct" name="VkExportMetalTextureInfoEXT" structextends="VkExportMetalObjectsInfoEXT" allowduplicate="true">
+ <member values="VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkImage</type> <name>image</name></member>
+ <member optional="true"><type>VkImageView</type> <name>imageView</name></member>
+ <member optional="true"><type>VkBufferView</type> <name>bufferView</name></member>
+ <member><type>VkImageAspectFlagBits</type> <name>plane</name></member>
+ <member><type>MTLTexture_id</type> <name>mtlTexture</name></member>
+ </type>
+ <type category="struct" name="VkImportMetalTextureInfoEXT" structextends="VkImageCreateInfo" allowduplicate="true">
+ <member values="VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImageAspectFlagBits</type> <name>plane</name></member>
+ <member><type>MTLTexture_id</type> <name>mtlTexture</name></member>
+ </type>
+ <type category="struct" name="VkExportMetalIOSurfaceInfoEXT" structextends="VkExportMetalObjectsInfoEXT" allowduplicate="true">
+ <member values="VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkImage</type> <name>image</name></member>
+ <member><type>IOSurfaceRef</type> <name>ioSurface</name></member>
+ </type>
+ <type category="struct" name="VkImportMetalIOSurfaceInfoEXT" structextends="VkImageCreateInfo" allowduplicate="false">
+ <member values="VK_STRUCTURE_TYPE_IMPORT_METAL_IO_SURFACE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>IOSurfaceRef</type> <name>ioSurface</name></member>
+ </type>
+ <type category="struct" name="VkExportMetalSharedEventInfoEXT" structextends="VkExportMetalObjectsInfoEXT" allowduplicate="true">
+ <member values="VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkSemaphore</type> <name>semaphore</name></member>
+ <member optional="true"><type>VkEvent</type> <name>event</name></member>
+ <member><type>MTLSharedEvent_id</type> <name>mtlSharedEvent</name></member>
+ </type>
+ <type category="struct" name="VkImportMetalSharedEventInfoEXT" structextends="VkSemaphoreCreateInfo,VkEventCreateInfo" allowduplicate="false">
+ <member values="VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>MTLSharedEvent_id</type> <name>mtlSharedEvent</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>nonSeamlessCubeMap</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDevicePipelineRobustnessFeaturesEXT" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member noautovalidity="true" optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>pipelineRobustness</name></member>
+ </type>
+ <type category="struct" name="VkPipelineRobustnessCreateInfoEXT" structextends="VkGraphicsPipelineCreateInfo,VkComputePipelineCreateInfo,VkPipelineShaderStageCreateInfo,VkRayTracingPipelineCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member noautovalidity="true" optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkPipelineRobustnessBufferBehaviorEXT</type> <name>storageBuffers</name></member>
+ <member><type>VkPipelineRobustnessBufferBehaviorEXT</type> <name>uniformBuffers</name></member>
+ <member><type>VkPipelineRobustnessBufferBehaviorEXT</type> <name>vertexInputs</name></member>
+ <member><type>VkPipelineRobustnessImageBehaviorEXT</type> <name>images</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDevicePipelineRobustnessPropertiesEXT" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="exact"><type>VkPipelineRobustnessBufferBehaviorEXT</type> <name>defaultRobustnessStorageBuffers</name></member>
+ <member limittype="exact"><type>VkPipelineRobustnessBufferBehaviorEXT</type> <name>defaultRobustnessUniformBuffers</name></member>
+ <member limittype="exact"><type>VkPipelineRobustnessBufferBehaviorEXT</type> <name>defaultRobustnessVertexInputs</name></member>
+ <member limittype="exact"><type>VkPipelineRobustnessImageBehaviorEXT</type> <name>defaultRobustnessImages</name></member>
+ </type>
+ <type category="struct" name="VkImageViewSampleWeightCreateInfoQCOM" structextends="VkImageViewCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true">const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkOffset2D</type> <name>filterCenter</name></member>
+ <member><type>VkExtent2D</type> <name>filterSize</name></member>
+ <member><type>uint32_t</type> <name>numPhases</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceImageProcessingFeaturesQCOM" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true" noautovalidity="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>textureSampleWeighted</name></member>
+ <member><type>VkBool32</type> <name>textureBoxFilter</name></member>
+ <member><type>VkBool32</type> <name>textureBlockMatch</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceImageProcessingPropertiesQCOM" returnedonly="true" structextends="VkPhysicalDeviceProperties2">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member limittype="max" optional="true"><type>uint32_t</type> <name>maxWeightFilterPhases</name></member>
+ <member limittype="max" optional="true"><type>VkExtent2D</type> <name>maxWeightFilterDimension</name></member>
+ <member limittype="max" optional="true"><type>VkExtent2D</type> <name>maxBlockMatchRegion</name></member>
+ <member limittype="max" optional="true"><type>VkExtent2D</type> <name>maxBoxFilterBlockSize</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceTilePropertiesFeaturesQCOM" structextends="VkPhysicalDeviceFeatures2,VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>tileProperties</name></member>
+ </type>
+ <type category="struct" name="VkTilePropertiesQCOM">
+ <member values="VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM"><type>VkStructureType</type> <name>sType</name></member>
+ <member optional="true"><type>void</type>* <name>pNext</name></member>
+ <member><type>VkExtent3D</type> <name>tileSize</name></member>
+ <member><type>VkExtent2D</type> <name>apronSize</name></member>
+ <member><type>VkOffset2D</type> <name>origin</name></member>
+ </type>
</types>
-
<comment>Vulkan enumerant (token) definitions</comment>
<enums name="API Constants" comment="Vulkan hardcoded constants - not an enumerated type, part of the header boilerplate">
- <enum value="256" name="VK_MAX_PHYSICAL_DEVICE_NAME_SIZE"/>
- <enum value="16" name="VK_UUID_SIZE"/>
- <enum value="8" name="VK_LUID_SIZE"/>
- <enum name="VK_LUID_SIZE_KHR" alias="VK_LUID_SIZE"/>
- <enum value="256" name="VK_MAX_EXTENSION_NAME_SIZE"/>
- <enum value="256" name="VK_MAX_DESCRIPTION_SIZE"/>
- <enum value="32" name="VK_MAX_MEMORY_TYPES"/>
- <enum value="16" name="VK_MAX_MEMORY_HEAPS" comment="The maximum number of unique memory heaps, each of which supporting 1 or more memory types"/>
- <enum value="1000.0f" name="VK_LOD_CLAMP_NONE"/>
- <enum value="(~0U)" name="VK_REMAINING_MIP_LEVELS"/>
- <enum value="(~0U)" name="VK_REMAINING_ARRAY_LAYERS"/>
- <enum value="(~0ULL)" name="VK_WHOLE_SIZE"/>
- <enum value="(~0U)" name="VK_ATTACHMENT_UNUSED"/>
- <enum value="1" name="VK_TRUE"/>
- <enum value="0" name="VK_FALSE"/>
- <enum value="(~0U)" name="VK_QUEUE_FAMILY_IGNORED"/>
- <enum value="(~0U-1)" name="VK_QUEUE_FAMILY_EXTERNAL"/>
- <enum name="VK_QUEUE_FAMILY_EXTERNAL_KHR" alias="VK_QUEUE_FAMILY_EXTERNAL"/>
- <enum value="(~0U-2)" name="VK_QUEUE_FAMILY_FOREIGN_EXT"/>
- <enum value="(~0U)" name="VK_SUBPASS_EXTERNAL"/>
- <enum value="32" name="VK_MAX_DEVICE_GROUP_SIZE"/>
- <enum name="VK_MAX_DEVICE_GROUP_SIZE_KHR" alias="VK_MAX_DEVICE_GROUP_SIZE"/>
- <enum value="256" name="VK_MAX_DRIVER_NAME_SIZE"/>
- <enum name="VK_MAX_DRIVER_NAME_SIZE_KHR" alias="VK_MAX_DRIVER_NAME_SIZE"/>
- <enum value="256" name="VK_MAX_DRIVER_INFO_SIZE"/>
- <enum name="VK_MAX_DRIVER_INFO_SIZE_KHR" alias="VK_MAX_DRIVER_INFO_SIZE"/>
- <enum value="(~0U)" name="VK_SHADER_UNUSED_KHR"/>
- <enum name="VK_SHADER_UNUSED_NV" alias="VK_SHADER_UNUSED_KHR"/>
+ <enum type="uint32_t" value="256" name="VK_MAX_PHYSICAL_DEVICE_NAME_SIZE"/>
+ <enum type="uint32_t" value="16" name="VK_UUID_SIZE"/>
+ <enum type="uint32_t" value="8" name="VK_LUID_SIZE"/>
+ <enum name="VK_LUID_SIZE_KHR" alias="VK_LUID_SIZE"/>
+ <enum type="uint32_t" value="256" name="VK_MAX_EXTENSION_NAME_SIZE"/>
+ <enum type="uint32_t" value="256" name="VK_MAX_DESCRIPTION_SIZE"/>
+ <enum type="uint32_t" value="32" name="VK_MAX_MEMORY_TYPES"/>
+ <enum type="uint32_t" value="16" name="VK_MAX_MEMORY_HEAPS" comment="The maximum number of unique memory heaps, each of which supporting 1 or more memory types"/>
+ <enum type="float" value="1000.0F" name="VK_LOD_CLAMP_NONE"/>
+ <enum type="uint32_t" value="(~0U)" name="VK_REMAINING_MIP_LEVELS"/>
+ <enum type="uint32_t" value="(~0U)" name="VK_REMAINING_ARRAY_LAYERS"/>
+ <enum type="uint64_t" value="(~0ULL)" name="VK_WHOLE_SIZE"/>
+ <enum type="uint32_t" value="(~0U)" name="VK_ATTACHMENT_UNUSED"/>
+ <enum type="uint32_t" value="1" name="VK_TRUE"/>
+ <enum type="uint32_t" value="0" name="VK_FALSE"/>
+ <enum type="uint32_t" value="(~0U)" name="VK_QUEUE_FAMILY_IGNORED"/>
+ <enum type="uint32_t" value="(~1U)" name="VK_QUEUE_FAMILY_EXTERNAL"/>
+ <enum name="VK_QUEUE_FAMILY_EXTERNAL_KHR" alias="VK_QUEUE_FAMILY_EXTERNAL"/>
+ <enum type="uint32_t" value="(~2U)" name="VK_QUEUE_FAMILY_FOREIGN_EXT"/>
+ <enum type="uint32_t" value="(~0U)" name="VK_SUBPASS_EXTERNAL"/>
+ <enum type="uint32_t" value="32" name="VK_MAX_DEVICE_GROUP_SIZE"/>
+ <enum name="VK_MAX_DEVICE_GROUP_SIZE_KHR" alias="VK_MAX_DEVICE_GROUP_SIZE"/>
+ <enum type="uint32_t" value="256" name="VK_MAX_DRIVER_NAME_SIZE"/>
+ <enum name="VK_MAX_DRIVER_NAME_SIZE_KHR" alias="VK_MAX_DRIVER_NAME_SIZE"/>
+ <enum type="uint32_t" value="256" name="VK_MAX_DRIVER_INFO_SIZE"/>
+ <enum name="VK_MAX_DRIVER_INFO_SIZE_KHR" alias="VK_MAX_DRIVER_INFO_SIZE"/>
+ <enum type="uint32_t" value="(~0U)" name="VK_SHADER_UNUSED_KHR"/>
+ <enum name="VK_SHADER_UNUSED_NV" alias="VK_SHADER_UNUSED_KHR"/>
+ <enum type="uint32_t" value="16" name="VK_MAX_GLOBAL_PRIORITY_SIZE_KHR"/>
+ <enum name="VK_MAX_GLOBAL_PRIORITY_SIZE_EXT" alias="VK_MAX_GLOBAL_PRIORITY_SIZE_KHR"/>
+ <enum type="uint32_t" value="32" name="VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT"/>
</enums>
<comment>
@@ -5263,7 +7219,8 @@ typedef void <name>CAMetalLayer</name>;
<enums name="VkPipelineCacheHeaderVersion" type="enum">
<enum value="1" name="VK_PIPELINE_CACHE_HEADER_VERSION_ONE"/>
</enums>
- <enums name="VkPipelineCacheCreateFlagBits" type="bitmask"></enums>
+ <enums name="VkPipelineCacheCreateFlagBits" type="bitmask">
+ </enums>
<enums name="VkPrimitiveTopology" type="enum">
<enum value="0" name="VK_PRIMITIVE_TOPOLOGY_POINT_LIST"/>
<enum value="1" name="VK_PRIMITIVE_TOPOLOGY_LINE_LIST"/>
@@ -5653,7 +7610,7 @@ typedef void <name>CAMetalLayer</name>;
<comment>Error codes (negative values)</comment>
<enum value="-1" name="VK_ERROR_OUT_OF_HOST_MEMORY" comment="A host memory allocation has failed"/>
<enum value="-2" name="VK_ERROR_OUT_OF_DEVICE_MEMORY" comment="A device memory allocation has failed"/>
- <enum value="-3" name="VK_ERROR_INITIALIZATION_FAILED" comment="Initialization of a object has failed"/>
+ <enum value="-3" name="VK_ERROR_INITIALIZATION_FAILED" comment="Initialization of an object has failed"/>
<enum value="-4" name="VK_ERROR_DEVICE_LOST" comment="The logical device has been lost. See &lt;&lt;devsandqueues-lost-device&gt;&gt;"/>
<enum value="-5" name="VK_ERROR_MEMORY_MAP_FAILED" comment="Mapping of a memory object has failed"/>
<enum value="-6" name="VK_ERROR_LAYER_NOT_PRESENT" comment="Layer specified does not exist"/>
@@ -5722,8 +7679,10 @@ typedef void <name>CAMetalLayer</name>;
<enum bitpos="1" name="VK_CULL_MODE_BACK_BIT"/>
<enum value="0x00000003" name="VK_CULL_MODE_FRONT_AND_BACK"/>
</enums>
- <enums name="VkRenderPassCreateFlagBits" type="bitmask"></enums>
- <enums name="VkDeviceQueueCreateFlagBits" type="bitmask"></enums>
+ <enums name="VkRenderPassCreateFlagBits" type="bitmask">
+ </enums>
+ <enums name="VkDeviceQueueCreateFlagBits" type="bitmask">
+ </enums>
<enums name="VkMemoryPropertyFlagBits" type="bitmask">
<enum bitpos="0" name="VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT" comment="If otherwise stated, then allocate memory on device"/>
<enum bitpos="1" name="VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT" comment="Memory is mappable by host"/>
@@ -5767,7 +7726,7 @@ typedef void <name>CAMetalLayer</name>;
<enums name="VkBufferCreateFlagBits" type="bitmask">
<enum bitpos="0" name="VK_BUFFER_CREATE_SPARSE_BINDING_BIT" comment="Buffer should support sparse backing"/>
<enum bitpos="1" name="VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT" comment="Buffer should support sparse backing with partial residency"/>
- <enum bitpos="2" name="VK_BUFFER_CREATE_SPARSE_ALIASED_BIT" comment="Buffer should support constent data access to physical memory ranges mapped into multiple locations of sparse buffers"/>
+ <enum bitpos="2" name="VK_BUFFER_CREATE_SPARSE_ALIASED_BIT" comment="Buffer should support constant data access to physical memory ranges mapped into multiple locations of sparse buffers"/>
</enums>
<enums name="VkShaderStageFlagBits" type="bitmask">
<enum bitpos="0" name="VK_SHADER_STAGE_VERTEX_BIT"/>
@@ -5792,7 +7751,7 @@ typedef void <name>CAMetalLayer</name>;
<enums name="VkImageCreateFlagBits" type="bitmask">
<enum bitpos="0" name="VK_IMAGE_CREATE_SPARSE_BINDING_BIT" comment="Image should support sparse backing"/>
<enum bitpos="1" name="VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT" comment="Image should support sparse backing with partial residency"/>
- <enum bitpos="2" name="VK_IMAGE_CREATE_SPARSE_ALIASED_BIT" comment="Image should support constent data access to physical memory ranges mapped into multiple locations of sparse images"/>
+ <enum bitpos="2" name="VK_IMAGE_CREATE_SPARSE_ALIASED_BIT" comment="Image should support constant data access to physical memory ranges mapped into multiple locations of sparse images"/>
<enum bitpos="3" name="VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT" comment="Allows image views to have different format than the base image"/>
<enum bitpos="4" name="VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT" comment="Allows creating image views with cube type from the created image"/>
</enums>
@@ -5800,7 +7759,7 @@ typedef void <name>CAMetalLayer</name>;
</enums>
<enums name="VkSamplerCreateFlagBits" type="bitmask">
</enums>
- <enums name="VkPipelineCreateFlagBits" type="bitmask">
+ <enums name="VkPipelineCreateFlagBits" type="bitmask" comment="Note that the gap at bitpos 10 is unused, and can be reserved">
<enum bitpos="0" name="VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT"/>
<enum bitpos="1" name="VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT"/>
<enum bitpos="2" name="VK_PIPELINE_CREATE_DERIVATIVE_BIT"/>
@@ -5816,7 +7775,8 @@ typedef void <name>CAMetalLayer</name>;
<enums name="VkFenceCreateFlagBits" type="bitmask">
<enum bitpos="0" name="VK_FENCE_CREATE_SIGNALED_BIT"/>
</enums>
- <comment>When VkSemaphoreCreateFlagBits is first extended, need to add a bitmask enums tag for it here</comment>
+ <enums name="VkSemaphoreCreateFlagBits" type="bitmask">
+ </enums>
<enums name="VkFormatFeatureFlagBits" type="bitmask">
<enum bitpos="0" name="VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT" comment="Format can be used for sampled images (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)"/>
<enum bitpos="1" name="VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT" comment="Format can be used for storage images (STORAGE_IMAGE descriptor type)"/>
@@ -5918,7 +7878,7 @@ typedef void <name>CAMetalLayer</name>;
<enum bitpos="0" name="VK_STENCIL_FACE_FRONT_BIT" comment="Front face"/>
<enum bitpos="1" name="VK_STENCIL_FACE_BACK_BIT" comment="Back face"/>
<enum value="0x00000003" name="VK_STENCIL_FACE_FRONT_AND_BACK" comment="Front and back faces"/>
- <enum name="VK_STENCIL_FRONT_AND_BACK" alias="VK_STENCIL_FACE_FRONT_AND_BACK" comment="Alias for backwards compatibility"/>
+ <enum name="VK_STENCIL_FRONT_AND_BACK" alias="VK_STENCIL_FACE_FRONT_AND_BACK" comment="Backwards-compatible alias containing a typo"/>
</enums>
<enums name="VkDescriptorPoolCreateFlagBits" type="bitmask">
<enum bitpos="0" name="VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT" comment="Descriptor sets may be freed individually"/>
@@ -6017,8 +7977,10 @@ typedef void <name>CAMetalLayer</name>;
<enum name="VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT" alias="VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT" comment="Backwards-compatible alias containing a typo"/>
<enum value="29" name="VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT"/>
<enum value="30" name="VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT"/>
- <!--<enum value="31" name="VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT" comment="Removed NVX_device_generated_commands"/>-->
- <!--<enum value="32" name="VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT" comment="Removed NVX_device_generated_commands"/>-->
+ <comment>NVX_device_generated_commands formerly used these enum values, but that extension has been removed
+ value 31 / name VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT
+ value 32 / name VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT
+ </comment>
<enum value="33" name="VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT"/>
<enum name="VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT" alias="VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT" comment="Backwards-compatible alias containing a typo"/>
</enums>
@@ -6063,6 +8025,7 @@ typedef void <name>CAMetalLayer</name>;
<enum value="4" name="VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT"/>
<enum value="5" name="VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT"/>
<enum value="6" name="VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT"/>
+ <enum value="7" name="VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT"/>
</enums>
<enums name="VkSubgroupFeatureFlagBits" type="bitmask">
<enum bitpos="0" name="VK_SUBGROUP_FEATURE_BASIC_BIT" comment="Basic subgroup operations"/>
@@ -6092,7 +8055,7 @@ typedef void <name>CAMetalLayer</name>;
<enum value="6" name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_NV"/>
<enum value="7" name="VK_INDIRECT_COMMANDS_TOKEN_TYPE_DRAW_TASKS_NV"/>
</enums>
- <enums name="VkPrivateDataSlotCreateFlagBitsEXT" type="bitmask">
+ <enums name="VkPrivateDataSlotCreateFlagBits" type="bitmask">
</enums>
<enums name="VkDescriptorSetLayoutCreateFlagBits" type="bitmask">
</enums>
@@ -6237,11 +8200,15 @@ typedef void <name>CAMetalLayer</name>;
<enum value="1" name="VK_SHADER_INFO_TYPE_BINARY_AMD"/>
<enum value="2" name="VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD"/>
</enums>
- <enums name="VkQueueGlobalPriorityEXT" type="enum">
- <enum value="128" name="VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT"/>
- <enum value="256" name="VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT"/>
- <enum value="512" name="VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT"/>
- <enum value="1024" name="VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT"/>
+ <enums name="VkQueueGlobalPriorityKHR" type="enum">
+ <enum value="128" name="VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR"/>
+ <enum value="256" name="VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR"/>
+ <enum value="512" name="VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR"/>
+ <enum value="1024" name="VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR"/>
+ <enum name="VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT" alias="VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR"/>
+ <enum name="VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT" alias="VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR"/>
+ <enum name="VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT" alias="VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR"/>
+ <enum name="VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT" alias="VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR"/>
</enums>
<enums name="VkDebugUtilsMessageSeverityFlagBitsEXT" type="bitmask">
<enum bitpos="0" name="VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT"/>
@@ -6295,6 +8262,15 @@ typedef void <name>CAMetalLayer</name>;
<enum value="12" name="VK_DRIVER_ID_BROADCOM_PROPRIETARY" comment="Broadcom Inc."/>
<enum value="13" name="VK_DRIVER_ID_MESA_LLVMPIPE" comment="Mesa"/>
<enum value="14" name="VK_DRIVER_ID_MOLTENVK" comment="MoltenVK"/>
+ <enum value="15" name="VK_DRIVER_ID_COREAVI_PROPRIETARY" comment="Core Avionics &amp; Industrial Inc."/>
+ <enum value="16" name="VK_DRIVER_ID_JUICE_PROPRIETARY" comment="Juice Technologies, Inc."/>
+ <enum value="17" name="VK_DRIVER_ID_VERISILICON_PROPRIETARY" comment="Verisilicon, Inc."/>
+ <enum value="18" name="VK_DRIVER_ID_MESA_TURNIP" comment="Mesa open source project"/>
+ <enum value="19" name="VK_DRIVER_ID_MESA_V3DV" comment="Mesa open source project"/>
+ <enum value="20" name="VK_DRIVER_ID_MESA_PANVK" comment="Mesa open source project"/>
+ <enum value="21" name="VK_DRIVER_ID_SAMSUNG_PROPRIETARY" comment="Samsung Electronics Co., Ltd."/>
+ <enum value="22" name="VK_DRIVER_ID_MESA_VENUS" comment="Mesa open source project"/>
+ <enum value="23" name="VK_DRIVER_ID_MESA_DOZEN" comment="Mesa open source project"/>
</enums>
<enums name="VkConditionalRenderingFlagBitsEXT" type="bitmask">
<enum bitpos="0" name="VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT"/>
@@ -6328,9 +8304,10 @@ typedef void <name>CAMetalLayer</name>;
</enums>
<enums name="VkGeometryInstanceFlagBitsKHR" type="bitmask">
<enum bitpos="0" name="VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR"/>
- <enum bitpos="1" name="VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR"/>
+ <enum bitpos="1" name="VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR"/>
<enum bitpos="2" name="VK_GEOMETRY_INSTANCE_FORCE_OPAQUE_BIT_KHR"/>
<enum bitpos="3" name="VK_GEOMETRY_INSTANCE_FORCE_NO_OPAQUE_BIT_KHR"/>
+ <enum name="VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR" alias="VK_GEOMETRY_INSTANCE_TRIANGLE_FLIP_FACING_BIT_KHR"/>
</enums>
<enums name="VkGeometryFlagBitsKHR" type="bitmask">
<enum bitpos="0" name="VK_GEOMETRY_OPAQUE_BIT_KHR"/>
@@ -6421,11 +8398,15 @@ typedef void <name>CAMetalLayer</name>;
<enum bitpos="0" name="VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV"/>
<enum bitpos="1" name="VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV"/>
<enum bitpos="2" name="VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV"/>
+ <enum bitpos="3" name="VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_ERROR_REPORTING_BIT_NV"/>
</enums>
- <enums name="VkPipelineCreationFeedbackFlagBitsEXT" type="bitmask">
- <enum bitpos="0" name="VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT"/>
- <enum bitpos="1" name="VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT"/>
- <enum bitpos="2" name="VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT"/>
+ <enums name="VkPipelineCreationFeedbackFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT"/>
+ <enum name="VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT" alias="VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT"/>
+ <enum bitpos="1" name="VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT"/>
+ <enum name="VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT" alias="VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT"/>
+ <enum bitpos="2" name="VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT"/>
+ <enum name="VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT" alias="VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT"/>
</enums>
<enums name="VkFullScreenExclusiveEXT" type="enum">
<enum value="0" name="VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT"/>
@@ -6437,9 +8418,9 @@ typedef void <name>CAMetalLayer</name>;
<enum value="0" name="VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR"/>
<enum value="1" name="VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR"/>
<enum value="2" name="VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR"/>
- <enum name="VK_QUERY_SCOPE_COMMAND_BUFFER_KHR" alias="VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR"/>
- <enum name="VK_QUERY_SCOPE_RENDER_PASS_KHR" alias="VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR"/>
- <enum name="VK_QUERY_SCOPE_COMMAND_KHR" alias="VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR"/>
+ <enum name="VK_QUERY_SCOPE_COMMAND_BUFFER_KHR" alias="VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR" comment="Backwards-compatible alias containing a typo"/>
+ <enum name="VK_QUERY_SCOPE_RENDER_PASS_KHR" alias="VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR" comment="Backwards-compatible alias containing a typo"/>
+ <enum name="VK_QUERY_SCOPE_COMMAND_KHR" alias="VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_KHR" comment="Backwards-compatible alias containing a typo"/>
</enums>
<enums name="VkPerformanceCounterUnitKHR" type="enum">
<enum value="0" name="VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR"/>
@@ -6514,12 +8495,17 @@ typedef void <name>CAMetalLayer</name>;
</enums>
<enums name="VkPipelineCompilerControlFlagBitsAMD" type="bitmask">
</enums>
- <enums name="VkToolPurposeFlagBitsEXT" type="bitmask">
- <enum bitpos="0" name="VK_TOOL_PURPOSE_VALIDATION_BIT_EXT"/>
- <enum bitpos="1" name="VK_TOOL_PURPOSE_PROFILING_BIT_EXT"/>
- <enum bitpos="2" name="VK_TOOL_PURPOSE_TRACING_BIT_EXT"/>
- <enum bitpos="3" name="VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT"/>
- <enum bitpos="4" name="VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT"/>
+ <enums name="VkToolPurposeFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_TOOL_PURPOSE_VALIDATION_BIT"/>
+ <enum name="VK_TOOL_PURPOSE_VALIDATION_BIT_EXT" alias="VK_TOOL_PURPOSE_VALIDATION_BIT"/>
+ <enum bitpos="1" name="VK_TOOL_PURPOSE_PROFILING_BIT"/>
+ <enum name="VK_TOOL_PURPOSE_PROFILING_BIT_EXT" alias="VK_TOOL_PURPOSE_PROFILING_BIT"/>
+ <enum bitpos="2" name="VK_TOOL_PURPOSE_TRACING_BIT"/>
+ <enum name="VK_TOOL_PURPOSE_TRACING_BIT_EXT" alias="VK_TOOL_PURPOSE_TRACING_BIT"/>
+ <enum bitpos="3" name="VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT"/>
+ <enum name="VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT" alias="VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT"/>
+ <enum bitpos="4" name="VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT"/>
+ <enum name="VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT" alias="VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT"/>
</enums>
<enums name="VkFragmentShadingRateCombinerOpKHR" type="enum">
<enum value="0" name="VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR"/>
@@ -6546,7 +8532,443 @@ typedef void <name>CAMetalLayer</name>;
<enum value="0" name="VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV"/>
<enum value="1" name="VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV"/>
</enums>
+ <enums name="VkSubpassMergeStatusEXT" type="enum">
+ <enum value="0" name="VK_SUBPASS_MERGE_STATUS_MERGED_EXT"/>
+ <enum value="1" name="VK_SUBPASS_MERGE_STATUS_DISALLOWED_EXT"/>
+ <enum value="2" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SIDE_EFFECTS_EXT"/>
+ <enum value="3" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SAMPLES_MISMATCH_EXT"/>
+ <enum value="4" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_VIEWS_MISMATCH_EXT"/>
+ <enum value="5" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_ALIASING_EXT"/>
+ <enum value="6" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPENDENCIES_EXT"/>
+ <enum value="7" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INCOMPATIBLE_INPUT_ATTACHMENT_EXT"/>
+ <enum value="8" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_TOO_MANY_ATTACHMENTS_EXT"/>
+ <enum value="9" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_INSUFFICIENT_STORAGE_EXT"/>
+ <enum value="10" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_DEPTH_STENCIL_COUNT_EXT"/>
+ <enum value="11" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_RESOLVE_ATTACHMENT_REUSE_EXT"/>
+ <enum value="12" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_SINGLE_SUBPASS_EXT"/>
+ <enum value="13" name="VK_SUBPASS_MERGE_STATUS_NOT_MERGED_UNSPECIFIED_EXT"/>
+ </enums>
+ <enums name="VkAccessFlagBits2" type="bitmask" bitwidth="64">
+ <enum value="0" name="VK_ACCESS_2_NONE"/>
+ <enum name="VK_ACCESS_2_NONE_KHR" alias="VK_ACCESS_2_NONE"/>
+ <enum bitpos="0" name="VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT"/>
+ <enum name="VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR" alias="VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT"/>
+ <enum bitpos="1" name="VK_ACCESS_2_INDEX_READ_BIT"/>
+ <enum name="VK_ACCESS_2_INDEX_READ_BIT_KHR" alias="VK_ACCESS_2_INDEX_READ_BIT"/>
+ <enum bitpos="2" name="VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT"/>
+ <enum name="VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR" alias="VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT"/>
+ <enum bitpos="3" name="VK_ACCESS_2_UNIFORM_READ_BIT"/>
+ <enum name="VK_ACCESS_2_UNIFORM_READ_BIT_KHR" alias="VK_ACCESS_2_UNIFORM_READ_BIT"/>
+ <enum bitpos="4" name="VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT"/>
+ <enum name="VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR" alias="VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT"/>
+ <enum bitpos="5" name="VK_ACCESS_2_SHADER_READ_BIT"/>
+ <enum name="VK_ACCESS_2_SHADER_READ_BIT_KHR" alias="VK_ACCESS_2_SHADER_READ_BIT"/>
+ <enum bitpos="6" name="VK_ACCESS_2_SHADER_WRITE_BIT"/>
+ <enum name="VK_ACCESS_2_SHADER_WRITE_BIT_KHR" alias="VK_ACCESS_2_SHADER_WRITE_BIT"/>
+ <enum bitpos="7" name="VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT"/>
+ <enum name="VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR" alias="VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT"/>
+ <enum bitpos="8" name="VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT"/>
+ <enum name="VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR" alias="VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT"/>
+ <enum bitpos="9" name="VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT"/>
+ <enum name="VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR" alias="VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT"/>
+ <enum bitpos="10" name="VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT"/>
+ <enum name="VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR" alias="VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT"/>
+ <enum bitpos="11" name="VK_ACCESS_2_TRANSFER_READ_BIT"/>
+ <enum name="VK_ACCESS_2_TRANSFER_READ_BIT_KHR" alias="VK_ACCESS_2_TRANSFER_READ_BIT"/>
+ <enum bitpos="12" name="VK_ACCESS_2_TRANSFER_WRITE_BIT"/>
+ <enum name="VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR" alias="VK_ACCESS_2_TRANSFER_WRITE_BIT"/>
+ <enum bitpos="13" name="VK_ACCESS_2_HOST_READ_BIT"/>
+ <enum name="VK_ACCESS_2_HOST_READ_BIT_KHR" alias="VK_ACCESS_2_HOST_READ_BIT"/>
+ <enum bitpos="14" name="VK_ACCESS_2_HOST_WRITE_BIT"/>
+ <enum name="VK_ACCESS_2_HOST_WRITE_BIT_KHR" alias="VK_ACCESS_2_HOST_WRITE_BIT"/>
+ <enum bitpos="15" name="VK_ACCESS_2_MEMORY_READ_BIT"/>
+ <enum name="VK_ACCESS_2_MEMORY_READ_BIT_KHR" alias="VK_ACCESS_2_MEMORY_READ_BIT"/>
+ <enum bitpos="16" name="VK_ACCESS_2_MEMORY_WRITE_BIT"/>
+ <enum name="VK_ACCESS_2_MEMORY_WRITE_BIT_KHR" alias="VK_ACCESS_2_MEMORY_WRITE_BIT"/>
+ <comment>bitpos 17-31 are specified by extensions to the original VkAccessFlagBits enum</comment>
+ <enum bitpos="32" name="VK_ACCESS_2_SHADER_SAMPLED_READ_BIT"/>
+ <enum name="VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR" alias="VK_ACCESS_2_SHADER_SAMPLED_READ_BIT"/>
+ <enum bitpos="33" name="VK_ACCESS_2_SHADER_STORAGE_READ_BIT"/>
+ <enum name="VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR" alias="VK_ACCESS_2_SHADER_STORAGE_READ_BIT"/>
+ <enum bitpos="34" name="VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT"/>
+ <enum name="VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR" alias="VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT"/>
+ </enums>
+ <enums name="VkPipelineStageFlagBits2" type="bitmask" bitwidth="64">
+ <enum value="0" name="VK_PIPELINE_STAGE_2_NONE"/>
+ <enum name="VK_PIPELINE_STAGE_2_NONE_KHR" alias="VK_PIPELINE_STAGE_2_NONE"/>
+ <enum bitpos="0" name="VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR" alias="VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT"/>
+ <enum bitpos="1" name="VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR" alias="VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT"/>
+ <enum bitpos="2" name="VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR" alias="VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT"/>
+ <enum bitpos="3" name="VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR" alias="VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT"/>
+ <enum bitpos="4" name="VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR" alias="VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT"/>
+ <enum bitpos="5" name="VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR" alias="VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT"/>
+ <enum bitpos="6" name="VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR" alias="VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT"/>
+ <enum bitpos="7" name="VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR" alias="VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT"/>
+ <enum bitpos="8" name="VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR" alias="VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT"/>
+ <enum bitpos="9" name="VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR" alias="VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT"/>
+ <enum bitpos="10" name="VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR" alias="VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT"/>
+ <enum bitpos="11" name="VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR" alias="VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT"/>
+ <enum bitpos="12" name="VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR" alias="VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_TRANSFER_BIT" alias="VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR"/>
+ <enum name="VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR" alias="VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT"/>
+ <enum bitpos="13" name="VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR" alias="VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT"/>
+ <enum bitpos="14" name="VK_PIPELINE_STAGE_2_HOST_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_HOST_BIT_KHR" alias="VK_PIPELINE_STAGE_2_HOST_BIT"/>
+ <enum bitpos="15" name="VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR" alias="VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT"/>
+ <enum bitpos="16" name="VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR" alias="VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT"/>
+ <comment>bitpos 17-31 are specified by extensions to the original VkPipelineStageFlagBits enum</comment>
+ <enum bitpos="32" name="VK_PIPELINE_STAGE_2_COPY_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_COPY_BIT_KHR" alias="VK_PIPELINE_STAGE_2_COPY_BIT"/>
+ <enum bitpos="33" name="VK_PIPELINE_STAGE_2_RESOLVE_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR" alias="VK_PIPELINE_STAGE_2_RESOLVE_BIT"/>
+ <enum bitpos="34" name="VK_PIPELINE_STAGE_2_BLIT_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_BLIT_BIT_KHR" alias="VK_PIPELINE_STAGE_2_BLIT_BIT"/>
+ <enum bitpos="35" name="VK_PIPELINE_STAGE_2_CLEAR_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR" alias="VK_PIPELINE_STAGE_2_CLEAR_BIT"/>
+ <enum bitpos="36" name="VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR" alias="VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT"/>
+ <enum bitpos="37" name="VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR" alias="VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT"/>
+ <enum bitpos="38" name="VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT"/>
+ <enum name="VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR" alias="VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT"/>
+ </enums>
+ <enums name="VkSubmitFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_SUBMIT_PROTECTED_BIT"/>
+ <enum name="VK_SUBMIT_PROTECTED_BIT_KHR" alias="VK_SUBMIT_PROTECTED_BIT"/>
+ </enums>
+ <enums name="VkEventCreateFlagBits" type="bitmask">
+ </enums>
+ <enums name="VkPipelineLayoutCreateFlagBits" type="bitmask">
+ </enums>
+ <enums name="VkProvokingVertexModeEXT" type="enum">
+ <enum value="0" name="VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT"/>
+ <enum value="1" name="VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT"/>
+ </enums>
+ <enums name="VkAccelerationStructureMotionInstanceTypeNV" type="enum">
+ <enum value="0" name="VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_STATIC_NV"/>
+ <enum value="1" name="VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_MATRIX_MOTION_NV"/>
+ <enum value="2" name="VK_ACCELERATION_STRUCTURE_MOTION_INSTANCE_TYPE_SRT_MOTION_NV"/>
+ </enums>
+ <enums name="VkPipelineColorBlendStateCreateFlagBits" type="bitmask">
+ </enums>
+ <enums name="VkPipelineDepthStencilStateCreateFlagBits" type="bitmask">
+ </enums>
+ <enums name="VkGraphicsPipelineLibraryFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT"/>
+ <enum bitpos="1" name="VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT"/>
+ <enum bitpos="2" name="VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT"/>
+ <enum bitpos="3" name="VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT"/>
+ </enums>
+ <enums name="VkVideoCodecOperationFlagBitsKHR" type="bitmask">
+ <enum value="0" name="VK_VIDEO_CODEC_OPERATION_INVALID_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoChromaSubsamplingFlagBitsKHR" type="bitmask" comment="Vulkan video chroma subsampling definitions">
+ <enum value="0" name="VK_VIDEO_CHROMA_SUBSAMPLING_INVALID_BIT_KHR"/>
+ <enum bitpos="0" name="VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR"/>
+ <enum bitpos="1" name="VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR"/>
+ <enum bitpos="2" name="VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR"/>
+ <enum bitpos="3" name="VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoComponentBitDepthFlagBitsKHR" type="bitmask" comment="Vulkan video component bit depth definitions">
+ <enum value="0" name="VK_VIDEO_COMPONENT_BIT_DEPTH_INVALID_KHR"/>
+ <enum bitpos="0" name="VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR"/>
+ <enum bitpos="2" name="VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR"/>
+ <enum bitpos="4" name="VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoCapabilityFlagBitsKHR" type="bitmask">
+ <enum bitpos="0" name="VK_VIDEO_CAPABILITY_PROTECTED_CONTENT_BIT_KHR"/>
+ <enum bitpos="1" name="VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoSessionCreateFlagBitsKHR" type="bitmask">
+ <enum value="0" name="VK_VIDEO_SESSION_CREATE_DEFAULT_KHR"/>
+ <enum bitpos="0" name="VK_VIDEO_SESSION_CREATE_PROTECTED_CONTENT_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoCodingQualityPresetFlagBitsKHR" type="bitmask">
+ <enum bitpos="0" name="VK_VIDEO_CODING_QUALITY_PRESET_NORMAL_BIT_KHR"/>
+ <enum bitpos="1" name="VK_VIDEO_CODING_QUALITY_PRESET_POWER_BIT_KHR"/>
+ <enum bitpos="2" name="VK_VIDEO_CODING_QUALITY_PRESET_QUALITY_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoDecodeH264PictureLayoutFlagBitsEXT" type="bitmask">
+ <enum value="0" name="VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_EXT"/>
+ <enum bitpos="0" name="VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_INTERLEAVED_LINES_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_INTERLACED_SEPARATE_PLANES_BIT_EXT"/>
+ </enums>
+ <enums name="VkVideoCodingControlFlagBitsKHR" type="bitmask">
+ <enum value="0" name="VK_VIDEO_CODING_CONTROL_DEFAULT_KHR"/>
+ <enum bitpos="0" name="VK_VIDEO_CODING_CONTROL_RESET_BIT_KHR"/>
+ </enums>
+ <enums name="VkQueryResultStatusKHR" type="enum">
+ <enum value="-1" name="VK_QUERY_RESULT_STATUS_ERROR_KHR"/>
+ <enum value="0" name="VK_QUERY_RESULT_STATUS_NOT_READY_KHR"/>
+ <enum value="1" name="VK_QUERY_RESULT_STATUS_COMPLETE_KHR"/>
+ </enums>
+ <enums name="VkVideoDecodeCapabilityFlagBitsKHR" type="bitmask">
+ <enum value="0" name="VK_VIDEO_DECODE_CAPABILITY_DEFAULT_KHR"/>
+ <enum bitpos="0" name="VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR"/>
+ <enum bitpos="1" name="VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoDecodeFlagBitsKHR" type="bitmask">
+ <enum value="0" name="VK_VIDEO_DECODE_DEFAULT_KHR"/>
+ <enum bitpos="0" name="VK_VIDEO_DECODE_RESERVED_0_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoEncodeFlagBitsKHR" type="bitmask">
+ <enum value="0" name="VK_VIDEO_ENCODE_DEFAULT_KHR"/>
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_RESERVED_0_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoEncodeCapabilityFlagBitsKHR" type="bitmask">
+ <enum value="0" name="VK_VIDEO_ENCODE_CAPABILITY_DEFAULT_KHR"/>
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_CAPABILITY_PRECEDING_EXTERNALLY_ENCODED_BYTES_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoEncodeRateControlFlagBitsKHR" type="bitmask">
+ <enum value="0" name="VK_VIDEO_ENCODE_RATE_CONTROL_DEFAULT_KHR"/>
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_RATE_CONTROL_RESERVED_0_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoEncodeRateControlModeFlagBitsKHR" type="bitmask">
+ <enum value="0" name="VK_VIDEO_ENCODE_RATE_CONTROL_MODE_NONE_BIT_KHR"/>
+ <enum value="1" name="VK_VIDEO_ENCODE_RATE_CONTROL_MODE_CBR_BIT_KHR"/>
+ <enum value="2" name="VK_VIDEO_ENCODE_RATE_CONTROL_MODE_VBR_BIT_KHR"/>
+ </enums>
+ <enums name="VkVideoEncodeH264CapabilityFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_ENABLED_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_ENCODE_H264_CAPABILITY_DIRECT_8X8_INFERENCE_DISABLED_BIT_EXT"/>
+ <enum bitpos="2" name="VK_VIDEO_ENCODE_H264_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT"/>
+ <enum bitpos="3" name="VK_VIDEO_ENCODE_H264_CAPABILITY_QPPRIME_Y_ZERO_TRANSFORM_BYPASS_BIT_EXT"/>
+ <enum bitpos="4" name="VK_VIDEO_ENCODE_H264_CAPABILITY_SCALING_LISTS_BIT_EXT"/>
+ <enum bitpos="5" name="VK_VIDEO_ENCODE_H264_CAPABILITY_HRD_COMPLIANCE_BIT_EXT"/>
+ <enum bitpos="6" name="VK_VIDEO_ENCODE_H264_CAPABILITY_CHROMA_QP_OFFSET_BIT_EXT"/>
+ <enum bitpos="7" name="VK_VIDEO_ENCODE_H264_CAPABILITY_SECOND_CHROMA_QP_OFFSET_BIT_EXT"/>
+ <enum bitpos="8" name="VK_VIDEO_ENCODE_H264_CAPABILITY_PIC_INIT_QP_MINUS26_BIT_EXT"/>
+ <enum bitpos="9" name="VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_BIT_EXT"/>
+ <enum bitpos="10" name="VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_EXPLICIT_BIT_EXT"/>
+ <enum bitpos="11" name="VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_BIPRED_IMPLICIT_BIT_EXT"/>
+ <enum bitpos="12" name="VK_VIDEO_ENCODE_H264_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT"/>
+ <enum bitpos="13" name="VK_VIDEO_ENCODE_H264_CAPABILITY_TRANSFORM_8X8_BIT_EXT"/>
+ <enum bitpos="14" name="VK_VIDEO_ENCODE_H264_CAPABILITY_CABAC_BIT_EXT"/>
+ <enum bitpos="15" name="VK_VIDEO_ENCODE_H264_CAPABILITY_CAVLC_BIT_EXT"/>
+ <enum bitpos="16" name="VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_DISABLED_BIT_EXT"/>
+ <enum bitpos="17" name="VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_ENABLED_BIT_EXT"/>
+ <enum bitpos="18" name="VK_VIDEO_ENCODE_H264_CAPABILITY_DEBLOCKING_FILTER_PARTIAL_BIT_EXT"/>
+ <enum bitpos="19" name="VK_VIDEO_ENCODE_H264_CAPABILITY_DISABLE_DIRECT_SPATIAL_MV_PRED_BIT_EXT"/>
+ <enum bitpos="20" name="VK_VIDEO_ENCODE_H264_CAPABILITY_MULTIPLE_SLICE_PER_FRAME_BIT_EXT"/>
+ <enum bitpos="21" name="VK_VIDEO_ENCODE_H264_CAPABILITY_SLICE_MB_COUNT_BIT_EXT"/>
+ <enum bitpos="22" name="VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_EXT"/>
+ <enum bitpos="23" name="VK_VIDEO_ENCODE_H264_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT"/>
+ <enum bitpos="24" name="VK_VIDEO_ENCODE_H264_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT"/>
+ </enums>
+ <enums name="VkVideoEncodeH264InputModeFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_H264_INPUT_MODE_FRAME_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_ENCODE_H264_INPUT_MODE_SLICE_BIT_EXT"/>
+ <enum bitpos="2" name="VK_VIDEO_ENCODE_H264_INPUT_MODE_NON_VCL_BIT_EXT"/>
+ </enums>
+ <enums name="VkVideoEncodeH264OutputModeFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_H264_OUTPUT_MODE_FRAME_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_ENCODE_H264_OUTPUT_MODE_SLICE_BIT_EXT"/>
+ <enum bitpos="2" name="VK_VIDEO_ENCODE_H264_OUTPUT_MODE_NON_VCL_BIT_EXT"/>
+ </enums>
+ <enums name="VkVideoEncodeH264RateControlStructureFlagBitsEXT" type="bitmask">
+ <enum value="0" name="VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT"/>
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_FLAT_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_ENCODE_H264_RATE_CONTROL_STRUCTURE_DYADIC_BIT_EXT"/>
+ </enums>
+ <enums name="VkImageFormatConstraintsFlagBitsFUCHSIA" type="bitmask">
+ </enums>
+ <enums name="VkImageConstraintsInfoFlagBitsFUCHSIA" type="bitmask">
+ <enum bitpos="0" name="VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_RARELY_FUCHSIA"/>
+ <enum bitpos="1" name="VK_IMAGE_CONSTRAINTS_INFO_CPU_READ_OFTEN_FUCHSIA"/>
+ <enum bitpos="2" name="VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_RARELY_FUCHSIA"/>
+ <enum bitpos="3" name="VK_IMAGE_CONSTRAINTS_INFO_CPU_WRITE_OFTEN_FUCHSIA"/>
+ <enum bitpos="4" name="VK_IMAGE_CONSTRAINTS_INFO_PROTECTED_OPTIONAL_FUCHSIA"/>
+ </enums>
+ <enums name="VkFormatFeatureFlagBits2" type="bitmask" bitwidth="64">
+ <enum bitpos="0" name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR" alias="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT"/>
+ <enum bitpos="1" name="VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR" alias="VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT"/>
+ <enum bitpos="2" name="VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT_KHR" alias="VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT"/>
+ <enum bitpos="3" name="VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR" alias="VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT"/>
+ <enum bitpos="4" name="VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT_KHR" alias="VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT"/>
+ <enum bitpos="5" name="VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT_KHR" alias="VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT"/>
+ <enum bitpos="6" name="VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT_KHR" alias="VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT"/>
+ <enum bitpos="7" name="VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT_KHR" alias="VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT"/>
+ <enum bitpos="8" name="VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT_KHR" alias="VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT"/>
+ <enum bitpos="9" name="VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT_KHR" alias="VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT"/>
+ <enum bitpos="10" name="VK_FORMAT_FEATURE_2_BLIT_SRC_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_BLIT_SRC_BIT_KHR" alias="VK_FORMAT_FEATURE_2_BLIT_SRC_BIT"/>
+ <enum bitpos="11" name="VK_FORMAT_FEATURE_2_BLIT_DST_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_BLIT_DST_BIT_KHR" alias="VK_FORMAT_FEATURE_2_BLIT_DST_BIT"/>
+ <enum bitpos="12" name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT_KHR" alias="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT"/>
+ <enum bitpos="13" name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT" alias="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT"/>
+ <enum bitpos="14" name="VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT_KHR" alias="VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT"/>
+ <enum bitpos="15" name="VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT_KHR" alias="VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT"/>
+ <enum bitpos="16" name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT_KHR" alias="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT"/>
+ <enum bitpos="17" name="VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR" alias="VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT"/>
+ <enum bitpos="18" name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR" alias="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT"/>
+ <enum bitpos="19" name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR" alias="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT"/>
+ <enum bitpos="20" name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR" alias="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT"/>
+ <enum bitpos="21" name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR" alias="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT"/>
+ <enum bitpos="22" name="VK_FORMAT_FEATURE_2_DISJOINT_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_DISJOINT_BIT_KHR" alias="VK_FORMAT_FEATURE_2_DISJOINT_BIT"/>
+ <enum bitpos="23" name="VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT_KHR" alias="VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT"/>
+ <enum bitpos="31" name="VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR" alias="VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT"/>
+ <enum bitpos="32" name="VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR" alias="VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT"/>
+ <enum bitpos="33" name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT"/>
+ <enum name="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR" alias="VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT"/>
+ </enums>
+ <enums name="VkRenderingFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT"/>
+ <enum name="VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR" alias="VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT"/>
+ <enum bitpos="1" name="VK_RENDERING_SUSPENDING_BIT"/>
+ <enum name="VK_RENDERING_SUSPENDING_BIT_KHR" alias="VK_RENDERING_SUSPENDING_BIT"/>
+ <enum bitpos="2" name="VK_RENDERING_RESUMING_BIT"/>
+ <enum name="VK_RENDERING_RESUMING_BIT_KHR" alias="VK_RENDERING_RESUMING_BIT"/>
+ </enums>
+ <enums name="VkVideoEncodeH265CapabilityFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_H265_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_ENCODE_H265_CAPABILITY_SCALING_LISTS_BIT_EXT"/>
+ <enum bitpos="2" name="VK_VIDEO_ENCODE_H265_CAPABILITY_SAMPLE_ADAPTIVE_OFFSET_ENABLED_BIT_EXT"/>
+ <enum bitpos="3" name="VK_VIDEO_ENCODE_H265_CAPABILITY_PCM_ENABLE_BIT_EXT"/>
+ <enum bitpos="4" name="VK_VIDEO_ENCODE_H265_CAPABILITY_SPS_TEMPORAL_MVP_ENABLED_BIT_EXT"/>
+ <enum bitpos="5" name="VK_VIDEO_ENCODE_H265_CAPABILITY_HRD_COMPLIANCE_BIT_EXT"/>
+ <enum bitpos="6" name="VK_VIDEO_ENCODE_H265_CAPABILITY_INIT_QP_MINUS26_BIT_EXT"/>
+ <enum bitpos="7" name="VK_VIDEO_ENCODE_H265_CAPABILITY_LOG2_PARALLEL_MERGE_LEVEL_MINUS2_BIT_EXT"/>
+ <enum bitpos="8" name="VK_VIDEO_ENCODE_H265_CAPABILITY_SIGN_DATA_HIDING_ENABLED_BIT_EXT"/>
+ <enum bitpos="9" name="VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_ENABLED_BIT_EXT"/>
+ <enum bitpos="10" name="VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSFORM_SKIP_DISABLED_BIT_EXT"/>
+ <enum bitpos="11" name="VK_VIDEO_ENCODE_H265_CAPABILITY_PPS_SLICE_CHROMA_QP_OFFSETS_PRESENT_BIT_EXT"/>
+ <enum bitpos="12" name="VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_BIT_EXT"/>
+ <enum bitpos="13" name="VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_BIPRED_BIT_EXT"/>
+ <enum bitpos="14" name="VK_VIDEO_ENCODE_H265_CAPABILITY_WEIGHTED_PRED_NO_TABLE_BIT_EXT"/>
+ <enum bitpos="15" name="VK_VIDEO_ENCODE_H265_CAPABILITY_TRANSQUANT_BYPASS_ENABLED_BIT_EXT"/>
+ <enum bitpos="16" name="VK_VIDEO_ENCODE_H265_CAPABILITY_ENTROPY_CODING_SYNC_ENABLED_BIT_EXT"/>
+ <enum bitpos="17" name="VK_VIDEO_ENCODE_H265_CAPABILITY_DEBLOCKING_FILTER_OVERRIDE_ENABLED_BIT_EXT"/>
+ <enum bitpos="18" name="VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_FRAME_BIT_EXT"/>
+ <enum bitpos="19" name="VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_SLICE_PER_TILE_BIT_EXT"/>
+ <enum bitpos="20" name="VK_VIDEO_ENCODE_H265_CAPABILITY_MULTIPLE_TILE_PER_SLICE_BIT_EXT"/>
+ <enum bitpos="21" name="VK_VIDEO_ENCODE_H265_CAPABILITY_SLICE_SEGMENT_CTB_COUNT_BIT_EXT"/>
+ <enum bitpos="22" name="VK_VIDEO_ENCODE_H265_CAPABILITY_ROW_UNALIGNED_SLICE_SEGMENT_BIT_EXT"/>
+ <enum bitpos="23" name="VK_VIDEO_ENCODE_H265_CAPABILITY_DEPENDENT_SLICE_SEGMENT_BIT_EXT"/>
+ <enum bitpos="24" name="VK_VIDEO_ENCODE_H265_CAPABILITY_DIFFERENT_SLICE_TYPE_BIT_EXT"/>
+ <enum bitpos="25" name="VK_VIDEO_ENCODE_H265_CAPABILITY_B_FRAME_IN_L1_LIST_BIT_EXT"/>
+ </enums>
+ <enums name="VkVideoEncodeH265InputModeFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_H265_INPUT_MODE_FRAME_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_ENCODE_H265_INPUT_MODE_SLICE_SEGMENT_BIT_EXT"/>
+ <enum bitpos="2" name="VK_VIDEO_ENCODE_H265_INPUT_MODE_NON_VCL_BIT_EXT"/>
+ </enums>
+ <enums name="VkVideoEncodeH265OutputModeFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_H265_OUTPUT_MODE_FRAME_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_ENCODE_H265_OUTPUT_MODE_SLICE_SEGMENT_BIT_EXT"/>
+ <enum bitpos="2" name="VK_VIDEO_ENCODE_H265_OUTPUT_MODE_NON_VCL_BIT_EXT"/>
+ </enums>
+ <enums name="VkVideoEncodeH265RateControlStructureFlagBitsEXT" type="bitmask">
+ <enum value="0" name="VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_UNKNOWN_EXT"/>
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_FLAT_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_ENCODE_H265_RATE_CONTROL_STRUCTURE_DYADIC_BIT_EXT"/>
+ </enums>
+ <enums name="VkVideoEncodeH265CtbSizeFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_H265_CTB_SIZE_16_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_ENCODE_H265_CTB_SIZE_32_BIT_EXT"/>
+ <enum bitpos="2" name="VK_VIDEO_ENCODE_H265_CTB_SIZE_64_BIT_EXT"/>
+ </enums>
+ <enums name="VkVideoEncodeH265TransformBlockSizeFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_4_BIT_EXT"/>
+ <enum bitpos="1" name="VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_8_BIT_EXT"/>
+ <enum bitpos="2" name="VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_16_BIT_EXT"/>
+ <enum bitpos="3" name="VK_VIDEO_ENCODE_H265_TRANSFORM_BLOCK_SIZE_32_BIT_EXT"/>
+ </enums>
+ <enums name="VkExportMetalObjectTypeFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT"/>
+ <enum bitpos="1" name="VK_EXPORT_METAL_OBJECT_TYPE_METAL_COMMAND_QUEUE_BIT_EXT"/>
+ <enum bitpos="2" name="VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT"/>
+ <enum bitpos="3" name="VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT"/>
+ <enum bitpos="4" name="VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT"/>
+ <enum bitpos="5" name="VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT"/>
+ </enums>
+ <enums name="VkInstanceCreateFlagBits" type="bitmask">
+ </enums>
+ <enums name="VkImageCompressionFlagBitsEXT" type="bitmask">
+ <enum value="0" name="VK_IMAGE_COMPRESSION_DEFAULT_EXT"/>
+ <enum bitpos="0" name="VK_IMAGE_COMPRESSION_FIXED_RATE_DEFAULT_EXT"/>
+ <enum bitpos="1" name="VK_IMAGE_COMPRESSION_FIXED_RATE_EXPLICIT_EXT"/>
+ <enum bitpos="2" name="VK_IMAGE_COMPRESSION_DISABLED_EXT"/>
+ </enums>
+ <enums name="VkImageCompressionFixedRateFlagBitsEXT" type="bitmask">
+ <enum value="0" name="VK_IMAGE_COMPRESSION_FIXED_RATE_NONE_EXT"/>
+ <enum bitpos="0" name="VK_IMAGE_COMPRESSION_FIXED_RATE_1BPC_BIT_EXT"/>
+ <enum bitpos="1" name="VK_IMAGE_COMPRESSION_FIXED_RATE_2BPC_BIT_EXT"/>
+ <enum bitpos="2" name="VK_IMAGE_COMPRESSION_FIXED_RATE_3BPC_BIT_EXT"/>
+ <enum bitpos="3" name="VK_IMAGE_COMPRESSION_FIXED_RATE_4BPC_BIT_EXT"/>
+ <enum bitpos="4" name="VK_IMAGE_COMPRESSION_FIXED_RATE_5BPC_BIT_EXT"/>
+ <enum bitpos="5" name="VK_IMAGE_COMPRESSION_FIXED_RATE_6BPC_BIT_EXT"/>
+ <enum bitpos="6" name="VK_IMAGE_COMPRESSION_FIXED_RATE_7BPC_BIT_EXT"/>
+ <enum bitpos="7" name="VK_IMAGE_COMPRESSION_FIXED_RATE_8BPC_BIT_EXT"/>
+ <enum bitpos="8" name="VK_IMAGE_COMPRESSION_FIXED_RATE_9BPC_BIT_EXT"/>
+ <enum bitpos="9" name="VK_IMAGE_COMPRESSION_FIXED_RATE_10BPC_BIT_EXT"/>
+ <enum bitpos="10" name="VK_IMAGE_COMPRESSION_FIXED_RATE_11BPC_BIT_EXT"/>
+ <enum bitpos="11" name="VK_IMAGE_COMPRESSION_FIXED_RATE_12BPC_BIT_EXT"/>
+ <enum bitpos="12" name="VK_IMAGE_COMPRESSION_FIXED_RATE_13BPC_BIT_EXT"/>
+ <enum bitpos="13" name="VK_IMAGE_COMPRESSION_FIXED_RATE_14BPC_BIT_EXT"/>
+ <enum bitpos="14" name="VK_IMAGE_COMPRESSION_FIXED_RATE_15BPC_BIT_EXT"/>
+ <enum bitpos="15" name="VK_IMAGE_COMPRESSION_FIXED_RATE_16BPC_BIT_EXT"/>
+ <enum bitpos="16" name="VK_IMAGE_COMPRESSION_FIXED_RATE_17BPC_BIT_EXT"/>
+ <enum bitpos="17" name="VK_IMAGE_COMPRESSION_FIXED_RATE_18BPC_BIT_EXT"/>
+ <enum bitpos="18" name="VK_IMAGE_COMPRESSION_FIXED_RATE_19BPC_BIT_EXT"/>
+ <enum bitpos="19" name="VK_IMAGE_COMPRESSION_FIXED_RATE_20BPC_BIT_EXT"/>
+ <enum bitpos="20" name="VK_IMAGE_COMPRESSION_FIXED_RATE_21BPC_BIT_EXT"/>
+ <enum bitpos="21" name="VK_IMAGE_COMPRESSION_FIXED_RATE_22BPC_BIT_EXT"/>
+ <enum bitpos="22" name="VK_IMAGE_COMPRESSION_FIXED_RATE_23BPC_BIT_EXT"/>
+ <enum bitpos="23" name="VK_IMAGE_COMPRESSION_FIXED_RATE_24BPC_BIT_EXT"/>
+ </enums>
+ <enums name="VkPipelineRobustnessBufferBehaviorEXT" type="enum">
+ <enum value="0" name="VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DEVICE_DEFAULT_EXT" />
+ <enum value="1" name="VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_DISABLED_EXT" />
+ <enum value="2" name="VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_EXT" />
+ <enum value="3" name="VK_PIPELINE_ROBUSTNESS_BUFFER_BEHAVIOR_ROBUST_BUFFER_ACCESS_2_EXT" />
+ </enums>
+ <enums name="VkPipelineRobustnessImageBehaviorEXT" type="enum">
+ <enum value="0" name="VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DEVICE_DEFAULT_EXT" />
+ <enum value="1" name="VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_DISABLED_EXT" />
+ <enum value="2" name="VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_EXT" />
+ <enum value="3" name="VK_PIPELINE_ROBUSTNESS_IMAGE_BEHAVIOR_ROBUST_IMAGE_ACCESS_2_EXT" />
+ </enums>
<commands comment="Vulkan command definitions">
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_LAYER_NOT_PRESENT,VK_ERROR_EXTENSION_NOT_PRESENT,VK_ERROR_INCOMPATIBLE_DRIVER">
<proto><type>VkResult</type> <name>vkCreateInstance</name></proto>
@@ -6627,7 +9049,7 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true" externsync="true"><type>VkDevice</type> <name>device</name></param>
<param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
<implicitexternsyncparams>
- <param>all sname:VkQueue objects received from pname:device</param>
+ <param>all sname:VkQueue objects created from pname:device</param>
</implicitexternsyncparams>
</command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
@@ -6776,7 +9198,7 @@ typedef void <name>CAMetalLayer</name>;
<proto><type>VkResult</type> <name>vkQueueBindSparse</name></proto>
<param externsync="true"><type>VkQueue</type> <name>queue</name></param>
<param optional="true"><type>uint32_t</type> <name>bindInfoCount</name></param>
- <param len="bindInfoCount" externsync="pBindInfo[].pBufferBinds[].buffer,pBindInfo[].pImageOpaqueBinds[].image,pBindInfo[].pImageBinds[].image">const <type>VkBindSparseInfo</type>* <name>pBindInfo</name></param>
+ <param len="bindInfoCount">const <type>VkBindSparseInfo</type>* <name>pBindInfo</name></param>
<param optional="true" externsync="true"><type>VkFence</type> <name>fence</name></param>
</command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
@@ -6910,7 +9332,7 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true" externsync="true"><type>VkBufferView</type> <name>bufferView</name></param>
<param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
</command>
- <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_COMPRESSION_EXHAUSTED_EXT">
<proto><type>VkResult</type> <name>vkCreateImage</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param>const <type>VkImageCreateInfo</type>* <name>pCreateInfo</name></param>
@@ -7001,6 +9423,12 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
<param len="createInfoCount"><type>VkPipeline</type>* <name>pPipelines</name></param>
</command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
+ <proto><type>VkResult</type> <name>vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkRenderPass</type> <name>renderpass</name></param>
+ <param><type>VkExtent2D</type>* <name>pMaxWorkgroupSize</name></param>
+ </command>
<command>
<proto><type>void</type> <name>vkDestroyPipeline</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
@@ -7085,9 +9513,9 @@ typedef void <name>CAMetalLayer</name>;
<proto><type>void</type> <name>vkUpdateDescriptorSets</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param optional="true"><type>uint32_t</type> <name>descriptorWriteCount</name></param>
- <param len="descriptorWriteCount" externsync="pDescriptorWrites[].dstSet">const <type>VkWriteDescriptorSet</type>* <name>pDescriptorWrites</name></param>
+ <param len="descriptorWriteCount">const <type>VkWriteDescriptorSet</type>* <name>pDescriptorWrites</name></param>
<param optional="true"><type>uint32_t</type> <name>descriptorCopyCount</name></param>
- <param len="descriptorCopyCount" externsync="pDescriptorCopies[].dstSet">const <type>VkCopyDescriptorSet</type>* <name>pDescriptorCopies</name></param>
+ <param len="descriptorCopyCount">const <type>VkCopyDescriptorSet</type>* <name>pDescriptorCopies</name></param>
</command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
<proto><type>VkResult</type> <name>vkCreateFramebuffer</name></proto>
@@ -7172,6 +9600,9 @@ typedef void <name>CAMetalLayer</name>;
<proto><type>VkResult</type> <name>vkResetCommandBuffer</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param optional="true"><type>VkCommandBufferResetFlags</type> <name>flags</name></param>
+ <implicitexternsyncparams>
+ <param>the sname:VkCommandPool that pname:commandBuffer was allocated from</param>
+ </implicitexternsyncparams>
</command>
<command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdBindPipeline</name></proto>
@@ -7241,7 +9672,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkPipelineLayout</type> <name>layout</name></param>
<param><type>uint32_t</type> <name>firstSet</name></param>
<param><type>uint32_t</type> <name>descriptorSetCount</name></param>
- <param len="descriptorSetCount">const <type>VkDescriptorSet</type>* <name>pDescriptorSets</name></param>
+ <param len="descriptorSetCount" optional="false,true">const <type>VkDescriptorSet</type>* <name>pDescriptorSets</name></param>
<param optional="true"><type>uint32_t</type> <name>dynamicOffsetCount</name></param>
<param len="dynamicOffsetCount">const <type>uint32_t</type>* <name>pDynamicOffsets</name></param>
</command>
@@ -7260,7 +9691,7 @@ typedef void <name>CAMetalLayer</name>;
<param len="bindingCount" optional="false,true">const <type>VkBuffer</type>* <name>pBuffers</name></param>
<param len="bindingCount">const <type>VkDeviceSize</type>* <name>pOffsets</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDraw</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>vertexCount</name></param>
@@ -7268,7 +9699,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>firstVertex</name></param>
<param><type>uint32_t</type> <name>firstInstance</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDrawIndexed</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>indexCount</name></param>
@@ -7277,7 +9708,26 @@ typedef void <name>CAMetalLayer</name>;
<param><type>int32_t</type> <name>vertexOffset</name></param>
<param><type>uint32_t</type> <name>firstInstance</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdDrawMultiEXT</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param optional="true"><type>uint32_t</type> <name>drawCount</name></param>
+ <param noautovalidity="true" len="drawCount">const <type>VkMultiDrawInfoEXT</type>* <name>pVertexInfo</name></param>
+ <param><type>uint32_t</type> <name>instanceCount</name></param>
+ <param><type>uint32_t</type> <name>firstInstance</name></param>
+ <param><type>uint32_t</type> <name>stride</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdDrawMultiIndexedEXT</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param optional="true"><type>uint32_t</type> <name>drawCount</name></param>
+ <param noautovalidity="true" len="drawCount">const <type>VkMultiDrawIndexedInfoEXT</type>* <name>pIndexInfo</name></param>
+ <param><type>uint32_t</type> <name>instanceCount</name></param>
+ <param><type>uint32_t</type> <name>firstInstance</name></param>
+ <param><type>uint32_t</type> <name>stride</name></param>
+ <param optional="true">const <type>int32_t</type>* <name>pVertexOffset</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDrawIndirect</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>buffer</name></param>
@@ -7285,7 +9735,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>drawCount</name></param>
<param><type>uint32_t</type> <name>stride</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDrawIndexedIndirect</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>buffer</name></param>
@@ -7293,20 +9743,24 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>drawCount</name></param>
<param><type>uint32_t</type> <name>stride</name></param>
</command>
- <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="compute">
+ <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDispatch</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>groupCountX</name></param>
<param><type>uint32_t</type> <name>groupCountY</name></param>
<param><type>uint32_t</type> <name>groupCountZ</name></param>
</command>
- <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="compute">
+ <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDispatchIndirect</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>buffer</name></param>
<param><type>VkDeviceSize</type> <name>offset</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSubpassShadingHUAWEI</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ </command>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdCopyBuffer</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>srcBuffer</name></param>
@@ -7314,7 +9768,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>regionCount</name></param>
<param len="regionCount">const <type>VkBufferCopy</type>* <name>pRegions</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdCopyImage</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkImage</type> <name>srcImage</name></param>
@@ -7324,7 +9778,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>regionCount</name></param>
<param len="regionCount">const <type>VkImageCopy</type>* <name>pRegions</name></param>
</command>
- <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdBlitImage</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkImage</type> <name>srcImage</name></param>
@@ -7335,7 +9789,7 @@ typedef void <name>CAMetalLayer</name>;
<param len="regionCount">const <type>VkImageBlit</type>* <name>pRegions</name></param>
<param><type>VkFilter</type> <name>filter</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdCopyBufferToImage</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>srcBuffer</name></param>
@@ -7344,7 +9798,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>regionCount</name></param>
<param len="regionCount">const <type>VkBufferImageCopy</type>* <name>pRegions</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdCopyImageToBuffer</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkImage</type> <name>srcImage</name></param>
@@ -7353,7 +9807,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>regionCount</name></param>
<param len="regionCount">const <type>VkBufferImageCopy</type>* <name>pRegions</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdUpdateBuffer</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>dstBuffer</name></param>
@@ -7361,7 +9815,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkDeviceSize</type> <name>dataSize</name></param>
<param len="dataSize">const <type>void</type>* <name>pData</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer" comment="transfer support is only available when VK_KHR_maintenance1 is enabled, as documented in valid usage language in the specification">
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" comment="transfer support is only available when VK_KHR_maintenance1 is enabled, as documented in valid usage language in the specification">
<proto><type>void</type> <name>vkCmdFillBuffer</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>dstBuffer</name></param>
@@ -7369,16 +9823,16 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkDeviceSize</type> <name>size</name></param>
<param><type>uint32_t</type> <name>data</name></param>
</command>
- <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdClearColorImage</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkImage</type> <name>image</name></param>
<param><type>VkImageLayout</type> <name>imageLayout</name></param>
- <param>const <type>VkClearColorValue</type>* <name>pColor</name></param>
+ <param noautovalidity="true">const <type>VkClearColorValue</type>* <name>pColor</name></param>
<param><type>uint32_t</type> <name>rangeCount</name></param>
<param len="rangeCount">const <type>VkImageSubresourceRange</type>* <name>pRanges</name></param>
</command>
- <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdClearDepthStencilImage</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkImage</type> <name>image</name></param>
@@ -7387,7 +9841,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>rangeCount</name></param>
<param len="rangeCount">const <type>VkImageSubresourceRange</type>* <name>pRanges</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdClearAttachments</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>attachmentCount</name></param>
@@ -7395,7 +9849,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>rectCount</name></param>
<param len="rectCount">const <type>VkClearRect</type>* <name>pRects</name></param>
</command>
- <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdResolveImage</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkImage</type> <name>srcImage</name></param>
@@ -7405,25 +9859,25 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>regionCount</name></param>
<param len="regionCount">const <type>VkImageResolve</type>* <name>pRegions</name></param>
</command>
- <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <command queues="graphics,compute" renderpass="outside" videocoding="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdSetEvent</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkEvent</type> <name>event</name></param>
- <param><type>VkPipelineStageFlags</type> <name>stageMask</name></param>
+ <param optional="true"><type>VkPipelineStageFlags</type> <name>stageMask</name></param>
</command>
- <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <command queues="graphics,compute" renderpass="outside" videocoding="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdResetEvent</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkEvent</type> <name>event</name></param>
- <param><type>VkPipelineStageFlags</type> <name>stageMask</name></param>
+ <param optional="true"><type>VkPipelineStageFlags</type> <name>stageMask</name></param>
</command>
- <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <command queues="graphics,compute" renderpass="both" videocoding="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdWaitEvents</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>eventCount</name></param>
<param len="eventCount">const <type>VkEvent</type>* <name>pEvents</name></param>
- <param><type>VkPipelineStageFlags</type> <name>srcStageMask</name></param>
- <param><type>VkPipelineStageFlags</type> <name>dstStageMask</name></param>
+ <param optional="true"><type>VkPipelineStageFlags</type> <name>srcStageMask</name></param>
+ <param optional="true"><type>VkPipelineStageFlags</type> <name>dstStageMask</name></param>
<param optional="true"><type>uint32_t</type> <name>memoryBarrierCount</name></param>
<param len="memoryBarrierCount">const <type>VkMemoryBarrier</type>* <name>pMemoryBarriers</name></param>
<param optional="true"><type>uint32_t</type> <name>bufferMemoryBarrierCount</name></param>
@@ -7431,11 +9885,11 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true"><type>uint32_t</type> <name>imageMemoryBarrierCount</name></param>
<param len="imageMemoryBarrierCount">const <type>VkImageMemoryBarrier</type>* <name>pImageMemoryBarriers</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <command queues="transfer,graphics,compute" renderpass="both" videocoding="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdPipelineBarrier</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
- <param><type>VkPipelineStageFlags</type> <name>srcStageMask</name></param>
- <param><type>VkPipelineStageFlags</type> <name>dstStageMask</name></param>
+ <param optional="true"><type>VkPipelineStageFlags</type> <name>srcStageMask</name></param>
+ <param optional="true"><type>VkPipelineStageFlags</type> <name>dstStageMask</name></param>
<param optional="true"><type>VkDependencyFlags</type> <name>dependencyFlags</name></param>
<param optional="true"><type>uint32_t</type> <name>memoryBarrierCount</name></param>
<param len="memoryBarrierCount">const <type>VkMemoryBarrier</type>* <name>pMemoryBarriers</name></param>
@@ -7444,14 +9898,14 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true"><type>uint32_t</type> <name>imageMemoryBarrierCount</name></param>
<param len="imageMemoryBarrierCount">const <type>VkImageMemoryBarrier</type>* <name>pImageMemoryBarriers</name></param>
</command>
- <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <command queues="graphics,compute,decode,encode" renderpass="both" videocoding="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdBeginQuery</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkQueryPool</type> <name>queryPool</name></param>
<param><type>uint32_t</type> <name>query</name></param>
<param optional="true"><type>VkQueryControlFlags</type> <name>flags</name></param>
</command>
- <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <command queues="graphics,compute,decode,encode" renderpass="both" videocoding="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdEndQuery</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkQueryPool</type> <name>queryPool</name></param>
@@ -7466,21 +9920,21 @@ typedef void <name>CAMetalLayer</name>;
<proto><type>void</type> <name>vkCmdEndConditionalRenderingEXT</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
</command>
- <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <command queues="graphics,compute,decode,encode" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdResetQueryPool</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkQueryPool</type> <name>queryPool</name></param>
<param><type>uint32_t</type> <name>firstQuery</name></param>
<param><type>uint32_t</type> <name>queryCount</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="transfer,graphics,compute,decode,encode" renderpass="both" videocoding="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdWriteTimestamp</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkPipelineStageFlagBits</type> <name>pipelineStage</name></param>
<param><type>VkQueryPool</type> <name>queryPool</name></param>
<param><type>uint32_t</type> <name>query</name></param>
</command>
- <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdCopyQueryPoolResults</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkQueryPool</type> <name>queryPool</name></param>
@@ -7500,18 +9954,18 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>size</name></param>
<param len="size">const <type>void</type>* <name>pValues</name></param>
</command>
- <command queues="graphics" renderpass="outside" cmdbufferlevel="primary" pipeline="graphics">
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary">
<proto><type>void</type> <name>vkCmdBeginRenderPass</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param>const <type>VkRenderPassBeginInfo</type>* <name>pRenderPassBegin</name></param>
<param><type>VkSubpassContents</type> <name>contents</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary">
<proto><type>void</type> <name>vkCmdNextSubpass</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkSubpassContents</type> <name>contents</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary">
<proto><type>void</type> <name>vkCmdEndRenderPass</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
</command>
@@ -7606,18 +10060,18 @@ typedef void <name>CAMetalLayer</name>;
<command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
<proto><type>VkResult</type> <name>vkGetPhysicalDeviceSurfaceFormatsKHR</name></proto>
<param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
- <param><type>VkSurfaceKHR</type> <name>surface</name></param>
+ <param optional="true"><type>VkSurfaceKHR</type> <name>surface</name></param>
<param optional="false,true"><type>uint32_t</type>* <name>pSurfaceFormatCount</name></param>
<param optional="true" len="pSurfaceFormatCount"><type>VkSurfaceFormatKHR</type>* <name>pSurfaceFormats</name></param>
</command>
<command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
<proto><type>VkResult</type> <name>vkGetPhysicalDeviceSurfacePresentModesKHR</name></proto>
<param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
- <param><type>VkSurfaceKHR</type> <name>surface</name></param>
+ <param optional="true"><type>VkSurfaceKHR</type> <name>surface</name></param>
<param optional="false,true"><type>uint32_t</type>* <name>pPresentModeCount</name></param>
<param optional="true" len="pPresentModeCount"><type>VkPresentModeKHR</type>* <name>pPresentModes</name></param>
</command>
- <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_SURFACE_LOST_KHR,VK_ERROR_NATIVE_WINDOW_IN_USE_KHR,VK_ERROR_INITIALIZATION_FAILED">
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_SURFACE_LOST_KHR,VK_ERROR_NATIVE_WINDOW_IN_USE_KHR,VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_COMPRESSION_EXHAUSTED_EXT">
<proto><type>VkResult</type> <name>vkCreateSwapchainKHR</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param externsync="pCreateInfo-&gt;surface,pCreateInfo-&gt;oldSwapchain">const <type>VkSwapchainCreateInfoKHR</type>* <name>pCreateInfo</name></param>
@@ -7738,6 +10192,19 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
<param><type>VkSurfaceKHR</type>* <name>pSurface</name></param>
</command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateScreenSurfaceQNX</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param>const <type>VkScreenSurfaceCreateInfoQNX</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSurfaceKHR</type>* <name>pSurface</name></param>
+ </command>
+ <command>
+ <proto><type>VkBool32</type> <name>vkGetPhysicalDeviceScreenPresentationSupportQNX</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>uint32_t</type> <name>queueFamilyIndex</name></param>
+ <param>struct <type>_screen_window</type>* <name>window</name></param>
+ </command>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
<proto><type>VkResult</type> <name>vkCreateDebugReportCallbackEXT</name></proto>
<param><type>VkInstance</type> <name>instance</name></param>
@@ -7756,7 +10223,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkInstance</type> <name>instance</name></param>
<param><type>VkDebugReportFlagsEXT</type> <name>flags</name></param>
<param><type>VkDebugReportObjectTypeEXT</type> <name>objectType</name></param>
- <param><type>uint64_t</type> <name>object</name></param>
+ <param objecttype="objectType"><type>uint64_t</type> <name>object</name></param>
<param><type>size_t</type> <name>location</name></param>
<param><type>int32_t</type> <name>messageCode</name></param>
<param len="null-terminated">const <type>char</type>* <name>pLayerPrefix</name></param>
@@ -7860,7 +10327,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkFormatProperties2</type>* <name>pFormatProperties</name></param>
</command>
<command name="vkGetPhysicalDeviceFormatProperties2KHR" alias="vkGetPhysicalDeviceFormatProperties2"/>
- <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_FORMAT_NOT_SUPPORTED">
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_FORMAT_NOT_SUPPORTED,VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR">
<proto><type>VkResult</type> <name>vkGetPhysicalDeviceImageFormatProperties2</name></proto>
<param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
<param>const <type>VkPhysicalDeviceImageFormatInfo2</type>* <name>pImageFormatInfo</name></param>
@@ -7937,6 +10404,25 @@ typedef void <name>CAMetalLayer</name>;
<param><type>int</type> <name>fd</name></param>
<param><type>VkMemoryFdPropertiesKHR</type>* <name>pMemoryFdProperties</name></param>
</command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_TOO_MANY_OBJECTS,VK_ERROR_OUT_OF_HOST_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetMemoryZirconHandleFUCHSIA</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkMemoryGetZirconHandleInfoFUCHSIA</type>* <name>pGetZirconHandleInfo</name></param>
+ <param><type>zx_handle_t</type>* <name>pZirconHandle</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_INVALID_EXTERNAL_HANDLE">
+ <proto><type>VkResult</type> <name>vkGetMemoryZirconHandlePropertiesFUCHSIA</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkExternalMemoryHandleTypeFlagBits</type> <name>handleType</name></param>
+ <param><type>zx_handle_t</type> <name>zirconHandle</name></param>
+ <param><type>VkMemoryZirconHandlePropertiesFUCHSIA</type>* <name>pMemoryZirconHandleProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_INVALID_EXTERNAL_HANDLE">
+ <proto><type>VkResult</type> <name>vkGetMemoryRemoteAddressNV</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkMemoryGetRemoteAddressInfoNV</type>* <name>pMemoryGetRemoteAddressInfo</name></param>
+ <param><type>VkRemoteAddressNV</type>* <name>pAddress</name></param>
+ </command>
<command>
<proto><type>void</type> <name>vkGetPhysicalDeviceExternalSemaphoreProperties</name></proto>
<param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
@@ -7966,6 +10452,17 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkDevice</type> <name>device</name></param>
<param>const <type>VkImportSemaphoreFdInfoKHR</type>* <name>pImportSemaphoreFdInfo</name></param>
</command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_TOO_MANY_OBJECTS,VK_ERROR_OUT_OF_HOST_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetSemaphoreZirconHandleFUCHSIA</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkSemaphoreGetZirconHandleInfoFUCHSIA</type>* <name>pGetZirconHandleInfo</name></param>
+ <param><type>zx_handle_t</type>* <name>pZirconHandle</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_INVALID_EXTERNAL_HANDLE">
+ <proto><type>VkResult</type> <name>vkImportSemaphoreZirconHandleFUCHSIA</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkImportSemaphoreZirconHandleInfoFUCHSIA</type>* <name>pImportSemaphoreZirconHandleInfo</name></param>
+ </command>
<command>
<proto><type>void</type> <name>vkGetPhysicalDeviceExternalFenceProperties</name></proto>
<param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
@@ -8088,7 +10585,7 @@ typedef void <name>CAMetalLayer</name>;
<param len="bindInfoCount">const <type>VkBindImageMemoryInfo</type>* <name>pBindInfos</name></param>
</command>
<command name="vkBindImageMemory2KHR" alias="vkBindImageMemory2"/>
- <command queues="graphics,compute,transfer" renderpass="both" cmdbufferlevel="primary,secondary">
+ <command queues="graphics,compute,transfer" renderpass="both" videocoding="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdSetDeviceMask</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>deviceMask</name></param>
@@ -8147,7 +10644,7 @@ typedef void <name>CAMetalLayer</name>;
<command>
<proto><type>void</type> <name>vkUpdateDescriptorSetWithTemplate</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
- <param externsync="true"><type>VkDescriptorSet</type> <name>descriptorSet</name></param>
+ <param><type>VkDescriptorSet</type> <name>descriptorSet</name></param>
<param><type>VkDescriptorUpdateTemplate</type> <name>descriptorUpdateTemplate</name></param>
<param noautovalidity="true">const <type>void</type>* <name>pData</name></param>
</command>
@@ -8291,6 +10788,28 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true" len="pSparseMemoryRequirementCount"><type>VkSparseImageMemoryRequirements2</type>* <name>pSparseMemoryRequirements</name></param>
</command>
<command name="vkGetImageSparseMemoryRequirements2KHR" alias="vkGetImageSparseMemoryRequirements2"/>
+ <command>
+ <proto><type>void</type> <name>vkGetDeviceBufferMemoryRequirements</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkDeviceBufferMemoryRequirements</type>* <name>pInfo</name></param>
+ <param><type>VkMemoryRequirements2</type>* <name>pMemoryRequirements</name></param>
+ </command>
+ <command name="vkGetDeviceBufferMemoryRequirementsKHR" alias="vkGetDeviceBufferMemoryRequirements"/>
+ <command>
+ <proto><type>void</type> <name>vkGetDeviceImageMemoryRequirements</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkDeviceImageMemoryRequirements</type>* <name>pInfo</name></param>
+ <param><type>VkMemoryRequirements2</type>* <name>pMemoryRequirements</name></param>
+ </command>
+ <command name="vkGetDeviceImageMemoryRequirementsKHR" alias="vkGetDeviceImageMemoryRequirements"/>
+ <command>
+ <proto><type>void</type> <name>vkGetDeviceImageSparseMemoryRequirements</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkDeviceImageMemoryRequirements</type>* <name>pInfo</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pSparseMemoryRequirementCount</name></param>
+ <param optional="true" len="pSparseMemoryRequirementCount"><type>VkSparseImageMemoryRequirements2</type>* <name>pSparseMemoryRequirements</name></param>
+ </command>
+ <command name="vkGetDeviceImageSparseMemoryRequirementsKHR" alias="vkGetDeviceImageSparseMemoryRequirements"/>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
<proto><type>VkResult</type> <name>vkCreateSamplerYcbcrConversion</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
@@ -8472,10 +10991,10 @@ typedef void <name>CAMetalLayer</name>;
<param optional="false">const <type>void</type>* <name>pHostPointer</name></param>
<param><type>VkMemoryHostPointerPropertiesEXT</type>* <name>pMemoryHostPointerProperties</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <command queues="transfer,graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdWriteBufferMarkerAMD</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
- <param><type>VkPipelineStageFlagBits</type> <name>pipelineStage</name></param>
+ <param optional="true"><type>VkPipelineStageFlagBits</type> <name>pipelineStage</name></param>
<param><type>VkBuffer</type> <name>dstBuffer</name></param>
<param><type>VkDeviceSize</type> <name>dstOffset</name></param>
<param><type>uint32_t</type> <name>marker</name></param>
@@ -8488,21 +11007,21 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkRenderPass</type>* <name>pRenderPass</name></param>
</command>
<command name="vkCreateRenderPass2KHR" alias="vkCreateRenderPass2"/>
- <command queues="graphics" renderpass="outside" cmdbufferlevel="primary" pipeline="graphics">
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary">
<proto><type>void</type> <name>vkCmdBeginRenderPass2</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param>const <type>VkRenderPassBeginInfo</type>* <name>pRenderPassBegin</name></param>
<param>const <type>VkSubpassBeginInfo</type>* <name>pSubpassBeginInfo</name></param>
</command>
<command name="vkCmdBeginRenderPass2KHR" alias="vkCmdBeginRenderPass2"/>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary">
<proto><type>void</type> <name>vkCmdNextSubpass2</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param>const <type>VkSubpassBeginInfo</type>* <name>pSubpassBeginInfo</name></param>
<param>const <type>VkSubpassEndInfo</type>* <name>pSubpassEndInfo</name></param>
</command>
<command name="vkCmdNextSubpass2KHR" alias="vkCmdNextSubpass2"/>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary">
<proto><type>void</type> <name>vkCmdEndRenderPass2</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param>const <type>VkSubpassEndInfo</type>* <name>pSubpassEndInfo</name></param>
@@ -8540,7 +11059,7 @@ typedef void <name>CAMetalLayer</name>;
<param>const <type>VkMemoryGetAndroidHardwareBufferInfoANDROID</type>* <name>pInfo</name></param>
<param>struct <type>AHardwareBuffer</type>** <name>pBuffer</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDrawIndirectCount</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>buffer</name></param>
@@ -8552,7 +11071,7 @@ typedef void <name>CAMetalLayer</name>;
</command>
<command name="vkCmdDrawIndirectCountKHR" alias="vkCmdDrawIndirectCount"/>
<command name="vkCmdDrawIndirectCountAMD" alias="vkCmdDrawIndirectCount"/>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDrawIndexedIndirectCount</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>buffer</name></param>
@@ -8615,7 +11134,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>query</name></param>
<param><type>uint32_t</type> <name>index</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDrawIndirectByteCountEXT</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>instanceCount</name></param>
@@ -8652,13 +11171,13 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true"><type>uint32_t</type> <name>customSampleOrderCount</name></param>
<param len="customSampleOrderCount">const <type>VkCoarseSampleOrderCustomNV</type>* <name>pCustomSampleOrders</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDrawMeshTasksNV</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>taskCount</name></param>
<param><type>uint32_t</type> <name>firstTask</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDrawMeshTasksIndirectNV</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>buffer</name></param>
@@ -8666,7 +11185,7 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint32_t</type> <name>drawCount</name></param>
<param><type>uint32_t</type> <name>stride</name></param>
</command>
- <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdDrawMeshTasksIndirectCountNV</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBuffer</type> <name>buffer</name></param>
@@ -8689,6 +11208,12 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
<param><type>VkAccelerationStructureNV</type>* <name>pAccelerationStructure</name></param>
</command>
+ <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdBindInvocationMaskHUAWEI</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param optional="true"><type>VkImageView</type> <name>imageView</name></param>
+ <param><type>VkImageLayout</type> <name>imageLayout</name></param>
+ </command>
<command>
<proto><type>void</type> <name>vkDestroyAccelerationStructureKHR</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
@@ -8882,6 +11407,11 @@ typedef void <name>CAMetalLayer</name>;
<param>const <type>VkStridedDeviceAddressRegionKHR</type>* <name>pCallableShaderBindingTable</name></param>
<param><type>VkDeviceAddress</type> <name>indirectDeviceAddress</name></param>
</command>
+ <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdTraceRaysIndirect2KHR</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkDeviceAddress</type> <name>indirectDeviceAddress</name></param>
+ </command>
<command>
<proto><type>void</type> <name>vkGetDeviceAccelerationStructureCompatibilityKHR</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
@@ -9069,11 +11599,12 @@ typedef void <name>CAMetalLayer</name>;
<param><type>uint16_t</type> <name>lineStipplePattern</name></param>
</command>
<command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
- <proto><type>VkResult</type> <name>vkGetPhysicalDeviceToolPropertiesEXT</name></proto>
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceToolProperties</name></proto>
<param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
<param optional="false,true"><type>uint32_t</type>* <name>pToolCount</name></param>
- <param optional="true" len="pToolCount"><type>VkPhysicalDeviceToolPropertiesEXT</type>* <name>pToolProperties</name></param>
+ <param optional="true" len="pToolCount"><type>VkPhysicalDeviceToolProperties</type>* <name>pToolProperties</name></param>
</command>
+ <command name="vkGetPhysicalDeviceToolPropertiesEXT" alias="vkGetPhysicalDeviceToolProperties"/>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS_KHR">
<proto><type>VkResult</type> <name>vkCreateAccelerationStructureKHR</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
@@ -9123,84 +11654,95 @@ typedef void <name>CAMetalLayer</name>;
<param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
</command>
<command>
- <proto><type>uint32_t</type> <name>vkGetDeferredOperationMaxConcurrencyKHR</name></proto>
- <param><type>VkDevice</type> <name>device</name></param>
- <param><type>VkDeferredOperationKHR</type> <name>operation</name></param>
+ <proto><type>uint32_t</type> <name>vkGetDeferredOperationMaxConcurrencyKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkDeferredOperationKHR</type> <name>operation</name></param>
</command>
<command successcodes="VK_SUCCESS,VK_NOT_READY">
- <proto><type>VkResult</type> <name>vkGetDeferredOperationResultKHR</name></proto>
- <param><type>VkDevice</type> <name>device</name></param>
- <param><type>VkDeferredOperationKHR</type> <name>operation</name></param>
+ <proto><type>VkResult</type> <name>vkGetDeferredOperationResultKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkDeferredOperationKHR</type> <name>operation</name></param>
</command>
<command successcodes="VK_SUCCESS,VK_THREAD_DONE_KHR,VK_THREAD_IDLE_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
- <proto><type>VkResult</type> <name>vkDeferredOperationJoinKHR</name></proto>
- <param><type>VkDevice</type> <name>device</name></param>
- <param><type>VkDeferredOperationKHR</type> <name>operation</name></param>
+ <proto><type>VkResult</type> <name>vkDeferredOperationJoinKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkDeferredOperationKHR</type> <name>operation</name></param>
</command>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetCullModeEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetCullMode</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param optional="true"><type>VkCullModeFlags</type> <name>cullMode</name></param>
</command>
+ <command name="vkCmdSetCullModeEXT" alias="vkCmdSetCullMode"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetFrontFaceEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetFrontFace</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkFrontFace</type> <name>frontFace</name></param>
</command>
+ <command name="vkCmdSetFrontFaceEXT" alias="vkCmdSetFrontFace"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetPrimitiveTopologyEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetPrimitiveTopology</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkPrimitiveTopology</type> <name>primitiveTopology</name></param>
</command>
+ <command name="vkCmdSetPrimitiveTopologyEXT" alias="vkCmdSetPrimitiveTopology"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetViewportWithCountEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetViewportWithCount</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>viewportCount</name></param>
<param len="viewportCount">const <type>VkViewport</type>* <name>pViewports</name></param>
</command>
+ <command name="vkCmdSetViewportWithCountEXT" alias="vkCmdSetViewportWithCount"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetScissorWithCountEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetScissorWithCount</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>scissorCount</name></param>
<param len="scissorCount">const <type>VkRect2D</type>* <name>pScissors</name></param>
</command>
+ <command name="vkCmdSetScissorWithCountEXT" alias="vkCmdSetScissorWithCount"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdBindVertexBuffers2EXT</name></proto>
+ <proto><type>void</type> <name>vkCmdBindVertexBuffers2</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>uint32_t</type> <name>firstBinding</name></param>
<param><type>uint32_t</type> <name>bindingCount</name></param>
- <param len="bindingCount">const <type>VkBuffer</type>* <name>pBuffers</name></param>
+ <param len="bindingCount" optional="false,true">const <type>VkBuffer</type>* <name>pBuffers</name></param>
<param len="bindingCount">const <type>VkDeviceSize</type>* <name>pOffsets</name></param>
<param optional="true" len="bindingCount">const <type>VkDeviceSize</type>* <name>pSizes</name></param>
<param optional="true" len="bindingCount">const <type>VkDeviceSize</type>* <name>pStrides</name></param>
</command>
+ <command name="vkCmdBindVertexBuffers2EXT" alias="vkCmdBindVertexBuffers2"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetDepthTestEnableEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetDepthTestEnable</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBool32</type> <name>depthTestEnable</name></param>
</command>
+ <command name="vkCmdSetDepthTestEnableEXT" alias="vkCmdSetDepthTestEnable"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetDepthWriteEnableEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetDepthWriteEnable</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBool32</type> <name>depthWriteEnable</name></param>
</command>
+ <command name="vkCmdSetDepthWriteEnableEXT" alias="vkCmdSetDepthWriteEnable"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetDepthCompareOpEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetDepthCompareOp</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkCompareOp</type> <name>depthCompareOp</name></param>
</command>
+ <command name="vkCmdSetDepthCompareOpEXT" alias="vkCmdSetDepthCompareOp"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetDepthBoundsTestEnableEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetDepthBoundsTestEnable</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBool32</type> <name>depthBoundsTestEnable</name></param>
</command>
+ <command name="vkCmdSetDepthBoundsTestEnableEXT" alias="vkCmdSetDepthBoundsTestEnable"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetStencilTestEnableEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetStencilTestEnable</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkBool32</type> <name>stencilTestEnable</name></param>
</command>
+ <command name="vkCmdSetStencilTestEnableEXT" alias="vkCmdSetStencilTestEnable"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
- <proto><type>void</type> <name>vkCmdSetStencilOpEXT</name></proto>
+ <proto><type>void</type> <name>vkCmdSetStencilOp</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
<param><type>VkStencilFaceFlags</type> <name>faceMask</name></param>
<param><type>VkStencilOp</type> <name>failOp</name></param>
@@ -9208,65 +11750,104 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkStencilOp</type> <name>depthFailOp</name></param>
<param><type>VkCompareOp</type> <name>compareOp</name></param>
</command>
+ <command name="vkCmdSetStencilOpEXT" alias="vkCmdSetStencilOp"/>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetPatchControlPointsEXT</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>patchControlPoints</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetRasterizerDiscardEnable</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBool32</type> <name>rasterizerDiscardEnable</name></param>
+ </command>
+ <command name="vkCmdSetRasterizerDiscardEnableEXT" alias="vkCmdSetRasterizerDiscardEnable"/>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetDepthBiasEnable</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBool32</type> <name>depthBiasEnable</name></param>
+ </command>
+ <command name="vkCmdSetDepthBiasEnableEXT" alias="vkCmdSetDepthBiasEnable"/>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetLogicOpEXT</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkLogicOp</type> <name>logicOp</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetPrimitiveRestartEnable</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBool32</type> <name>primitiveRestartEnable</name></param>
+ </command>
+ <command name="vkCmdSetPrimitiveRestartEnableEXT" alias="vkCmdSetPrimitiveRestartEnable"/>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
- <proto><type>VkResult</type> <name>vkCreatePrivateDataSlotEXT</name></proto>
+ <proto><type>VkResult</type> <name>vkCreatePrivateDataSlot</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
- <param>const <type>VkPrivateDataSlotCreateInfoEXT</type>* <name>pCreateInfo</name></param>
+ <param>const <type>VkPrivateDataSlotCreateInfo</type>* <name>pCreateInfo</name></param>
<param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
- <param><type>VkPrivateDataSlotEXT</type>* <name>pPrivateDataSlot</name></param>
+ <param><type>VkPrivateDataSlot</type>* <name>pPrivateDataSlot</name></param>
</command>
+ <command name="vkCreatePrivateDataSlotEXT" alias="vkCreatePrivateDataSlot"/>
<command>
- <proto><type>void</type> <name>vkDestroyPrivateDataSlotEXT</name></proto>
+ <proto><type>void</type> <name>vkDestroyPrivateDataSlot</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
- <param optional="true" externsync="true"><type>VkPrivateDataSlotEXT</type> <name>privateDataSlot</name></param>
+ <param optional="true" externsync="true"><type>VkPrivateDataSlot</type> <name>privateDataSlot</name></param>
<param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
</command>
+ <command name="vkDestroyPrivateDataSlotEXT" alias="vkDestroyPrivateDataSlot"/>
<command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
- <proto><type>VkResult</type> <name>vkSetPrivateDataEXT</name></proto>
+ <proto><type>VkResult</type> <name>vkSetPrivateData</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param><type>VkObjectType</type> <name>objectType</name></param>
- <param><type>uint64_t</type> <name>objectHandle</name></param>
- <param><type>VkPrivateDataSlotEXT</type> <name>privateDataSlot</name></param>
+ <param objecttype="objectType"><type>uint64_t</type> <name>objectHandle</name></param>
+ <param><type>VkPrivateDataSlot</type> <name>privateDataSlot</name></param>
<param><type>uint64_t</type> <name>data</name></param>
</command>
+ <command name="vkSetPrivateDataEXT" alias="vkSetPrivateData"/>
<command>
- <proto><type>void</type> <name>vkGetPrivateDataEXT</name></proto>
+ <proto><type>void</type> <name>vkGetPrivateData</name></proto>
<param><type>VkDevice</type> <name>device</name></param>
<param><type>VkObjectType</type> <name>objectType</name></param>
- <param><type>uint64_t</type> <name>objectHandle</name></param>
- <param><type>VkPrivateDataSlotEXT</type> <name>privateDataSlot</name></param>
+ <param objecttype="objectType"><type>uint64_t</type> <name>objectHandle</name></param>
+ <param><type>VkPrivateDataSlot</type> <name>privateDataSlot</name></param>
<param><type>uint64_t</type>* <name>pData</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
- <proto><type>void</type> <name>vkCmdCopyBuffer2KHR</name></proto>
+ <command name="vkGetPrivateDataEXT" alias="vkGetPrivateData"/>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdCopyBuffer2</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
- <param>const <type>VkCopyBufferInfo2KHR</type>* <name>pCopyBufferInfo</name></param>
+ <param>const <type>VkCopyBufferInfo2</type>* <name>pCopyBufferInfo</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
- <proto><type>void</type> <name>vkCmdCopyImage2KHR</name></proto>
+ <command name="vkCmdCopyBuffer2KHR" alias="vkCmdCopyBuffer2"/>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdCopyImage2</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
- <param>const <type>VkCopyImageInfo2KHR</type>* <name>pCopyImageInfo</name></param>
+ <param>const <type>VkCopyImageInfo2</type>* <name>pCopyImageInfo</name></param>
</command>
- <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
- <proto><type>void</type> <name>vkCmdBlitImage2KHR</name></proto>
+ <command name="vkCmdCopyImage2KHR" alias="vkCmdCopyImage2"/>
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdBlitImage2</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
- <param>const <type>VkBlitImageInfo2KHR</type>* <name>pBlitImageInfo</name></param>
+ <param>const <type>VkBlitImageInfo2</type>* <name>pBlitImageInfo</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
- <proto><type>void</type> <name>vkCmdCopyBufferToImage2KHR</name></proto>
+ <command name="vkCmdBlitImage2KHR" alias="vkCmdBlitImage2"/>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdCopyBufferToImage2</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
- <param>const <type>VkCopyBufferToImageInfo2KHR</type>* <name>pCopyBufferToImageInfo</name></param>
+ <param>const <type>VkCopyBufferToImageInfo2</type>* <name>pCopyBufferToImageInfo</name></param>
</command>
- <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
- <proto><type>void</type> <name>vkCmdCopyImageToBuffer2KHR</name></proto>
+ <command name="vkCmdCopyBufferToImage2KHR" alias="vkCmdCopyBufferToImage2"/>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdCopyImageToBuffer2</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
- <param>const <type>VkCopyImageToBufferInfo2KHR</type>* <name>pCopyImageToBufferInfo</name></param>
+ <param>const <type>VkCopyImageToBufferInfo2</type>* <name>pCopyImageToBufferInfo</name></param>
</command>
- <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
- <proto><type>void</type> <name>vkCmdResolveImage2KHR</name></proto>
+ <command name="vkCmdCopyImageToBuffer2KHR" alias="vkCmdCopyImageToBuffer2"/>
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdResolveImage2</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
- <param>const <type>VkResolveImageInfo2KHR</type>* <name>pResolveImageInfo</name></param>
+ <param>const <type>VkResolveImageInfo2</type>* <name>pResolveImageInfo</name></param>
</command>
+ <command name="vkCmdResolveImage2KHR" alias="vkCmdResolveImage2"/>
<command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
<proto><type>void</type> <name>vkCmdSetFragmentShadingRateKHR</name></proto>
<param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
@@ -9290,16 +11871,328 @@ typedef void <name>CAMetalLayer</name>;
<param><type>VkDevice</type> <name>device</name></param>
<param><type>VkAccelerationStructureBuildTypeKHR</type> <name>buildType</name></param>
<param>const <type>VkAccelerationStructureBuildGeometryInfoKHR</type>* <name>pBuildInfo</name></param>
- <param len="pBuildInfo-&gt;geometryCount">const <type>uint32_t</type>* <name>pMaxPrimitiveCounts</name></param>
+ <param optional="true" len="pBuildInfo-&gt;geometryCount">const <type>uint32_t</type>* <name>pMaxPrimitiveCounts</name></param>
<param><type>VkAccelerationStructureBuildSizesInfoKHR</type>* <name>pSizeInfo</name></param>
</command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetVertexInputEXT</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param optional="true"><type>uint32_t</type> <name>vertexBindingDescriptionCount</name></param>
+ <param len="vertexBindingDescriptionCount">const <type>VkVertexInputBindingDescription2EXT</type>* <name>pVertexBindingDescriptions</name></param>
+ <param optional="true"><type>uint32_t</type> <name>vertexAttributeDescriptionCount</name></param>
+ <param len="vertexAttributeDescriptionCount">const <type>VkVertexInputAttributeDescription2EXT</type>* <name>pVertexAttributeDescriptions</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetColorWriteEnableEXT</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>attachmentCount</name></param>
+ <param len="attachmentCount">const <type>VkBool32</type>* <name>pColorWriteEnables</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="outside" videocoding="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetEvent2</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkEvent</type> <name>event</name></param>
+ <param>const <type>VkDependencyInfo</type>* <name>pDependencyInfo</name></param>
+ </command>
+ <command name="vkCmdSetEvent2KHR" alias="vkCmdSetEvent2"/>
+ <command queues="graphics,compute" renderpass="outside" videocoding="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdResetEvent2</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkEvent</type> <name>event</name></param>
+ <param optional="true"><type>VkPipelineStageFlags2</type> <name>stageMask</name></param>
+ </command>
+ <command name="vkCmdResetEvent2KHR" alias="vkCmdResetEvent2"/>
+ <command queues="graphics,compute" renderpass="both" videocoding="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdWaitEvents2</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>eventCount</name></param>
+ <param len="eventCount">const <type>VkEvent</type>* <name>pEvents</name></param>
+ <param len="eventCount">const <type>VkDependencyInfo</type>* <name>pDependencyInfos</name></param>
+ </command>
+ <command name="vkCmdWaitEvents2KHR" alias="vkCmdWaitEvents2"/>
+ <command queues="transfer,graphics,compute" renderpass="both" videocoding="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdPipelineBarrier2</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkDependencyInfo</type>* <name>pDependencyInfo</name></param>
+ </command>
+ <command name="vkCmdPipelineBarrier2KHR" alias="vkCmdPipelineBarrier2"/>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST">
+ <proto><type>VkResult</type> <name>vkQueueSubmit2</name></proto>
+ <param externsync="true"><type>VkQueue</type> <name>queue</name></param>
+ <param optional="true"><type>uint32_t</type> <name>submitCount</name></param>
+ <param len="submitCount">const <type>VkSubmitInfo2</type>* <name>pSubmits</name></param>
+ <param optional="true" externsync="true"><type>VkFence</type> <name>fence</name></param>
+ </command>
+ <command name="vkQueueSubmit2KHR" alias="vkQueueSubmit2"/>
+ <command queues="transfer,graphics,compute,decode,encode" renderpass="both" videocoding="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdWriteTimestamp2</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param optional="true"><type>VkPipelineStageFlags2</type> <name>stage</name></param>
+ <param><type>VkQueryPool</type> <name>queryPool</name></param>
+ <param><type>uint32_t</type> <name>query</name></param>
+ </command>
+ <command name="vkCmdWriteTimestamp2KHR" alias="vkCmdWriteTimestamp2"/>
+ <command queues="transfer,graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdWriteBufferMarker2AMD</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param optional="true"><type>VkPipelineStageFlags2</type> <name>stage</name></param>
+ <param><type>VkBuffer</type> <name>dstBuffer</name></param>
+ <param><type>VkDeviceSize</type> <name>dstOffset</name></param>
+ <param><type>uint32_t</type> <name>marker</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetQueueCheckpointData2NV</name></proto>
+ <param><type>VkQueue</type> <name>queue</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pCheckpointDataCount</name></param>
+ <param optional="true" len="pCheckpointDataCount"><type>VkCheckpointData2NV</type>* <name>pCheckpointData</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceVideoCapabilitiesKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param>const <type>VkVideoProfileKHR</type>* <name>pVideoProfile</name></param>
+ <param><type>VkVideoCapabilitiesKHR</type>* <name>pCapabilities</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR,VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceVideoFormatPropertiesKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param>const <type>VkPhysicalDeviceVideoFormatInfoKHR</type>* <name>pVideoFormatInfo</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pVideoFormatPropertyCount</name></param>
+ <param optional="true" len="pVideoFormatPropertyCount"><type>VkVideoFormatPropertiesKHR</type>* <name>pVideoFormatProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR">
+ <proto><type>VkResult</type> <name>vkCreateVideoSessionKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkVideoSessionCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkVideoSessionKHR</type>* <name>pVideoSession</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyVideoSessionKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkVideoSessionKHR</type> <name>videoSession</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_TOO_MANY_OBJECTS">
+ <proto><type>VkResult</type> <name>vkCreateVideoSessionParametersKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkVideoSessionParametersCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkVideoSessionParametersKHR</type>* <name>pVideoSessionParameters</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_TOO_MANY_OBJECTS">
+ <proto><type>VkResult</type> <name>vkUpdateVideoSessionParametersKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkVideoSessionParametersKHR</type> <name>videoSessionParameters</name></param>
+ <param>const <type>VkVideoSessionParametersUpdateInfoKHR</type>* <name>pUpdateInfo</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyVideoSessionParametersKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkVideoSessionParametersKHR</type> <name>videoSessionParameters</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_INITIALIZATION_FAILED">
+ <proto><type>VkResult</type> <name>vkGetVideoSessionMemoryRequirementsKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkVideoSessionKHR</type> <name>videoSession</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pVideoSessionMemoryRequirementsCount</name></param>
+ <param optional="true" len="pVideoSessionMemoryRequirementsCount"><type>VkVideoGetMemoryPropertiesKHR</type>* <name>pVideoSessionMemoryRequirements</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED">
+ <proto><type>VkResult</type> <name>vkBindVideoSessionMemoryKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkVideoSessionKHR</type> <name>videoSession</name></param>
+ <param><type>uint32_t</type> <name>videoSessionBindMemoryCount</name></param>
+ <param len="videoSessionBindMemoryCount">const <type>VkVideoBindMemoryKHR</type>* <name>pVideoSessionBindMemories</name></param>
+ </command>
+ <command queues="decode" renderpass="outside" videocoding="inside" cmdbufferlevel="primary">
+ <proto><type>void</type> <name>vkCmdDecodeVideoKHR</name></proto>
+ <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkVideoDecodeInfoKHR</type>* <name>pFrameInfo</name></param>
+ </command>
+ <command queues="decode,encode" renderpass="outside" videocoding="outside" cmdbufferlevel="primary">
+ <proto><type>void</type> <name>vkCmdBeginVideoCodingKHR</name></proto>
+ <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkVideoBeginCodingInfoKHR</type>* <name>pBeginInfo</name></param>
+ </command>
+ <command queues="decode,encode" renderpass="outside" videocoding="inside" cmdbufferlevel="primary">
+ <proto><type>void</type> <name>vkCmdControlVideoCodingKHR</name></proto>
+ <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkVideoCodingControlInfoKHR</type>* <name>pCodingControlInfo</name></param>
+ </command>
+ <command queues="decode,encode" renderpass="outside" videocoding="inside" cmdbufferlevel="primary">
+ <proto><type>void</type> <name>vkCmdEndVideoCodingKHR</name></proto>
+ <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkVideoEndCodingInfoKHR</type>* <name>pEndCodingInfo</name></param>
+ </command>
+ <command queues="encode" renderpass="outside" videocoding="inside" cmdbufferlevel="primary">
+ <proto><type>void</type> <name>vkCmdEncodeVideoKHR</name></proto>
+ <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkVideoEncodeInfoKHR</type>* <name>pEncodeInfo</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_INITIALIZATION_FAILED">
+ <proto><type>VkResult</type> <name>vkCreateCuModuleNVX</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkCuModuleCreateInfoNVX</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkCuModuleNVX</type>* <name>pModule</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_INITIALIZATION_FAILED">
+ <proto><type>VkResult</type> <name>vkCreateCuFunctionNVX</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkCuFunctionCreateInfoNVX</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkCuFunctionNVX</type>* <name>pFunction</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyCuModuleNVX</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkCuModuleNVX</type> <name>module</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyCuFunctionNVX</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkCuFunctionNVX</type> <name>function</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdCuLaunchKernelNVX</name></proto>
+ <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkCuLaunchInfoNVX</type>* <name>pLaunchInfo</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkSetDeviceMemoryPriorityEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkDeviceMemory</type> <name>memory</name></param>
+ <param><type>float</type> <name>priority</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_INITIALIZATION_FAILED">
+ <proto><type>VkResult</type> <name>vkAcquireDrmDisplayEXT</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>int32_t</type> <name>drmFd</name></param>
+ <param><type>VkDisplayKHR</type> <name>display</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_OUT_OF_HOST_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetDrmDisplayEXT</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>int32_t</type> <name>drmFd</name></param>
+ <param><type>uint32_t</type> <name>connectorId</name></param>
+ <param><type>VkDisplayKHR</type>* <name>display</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_TIMEOUT,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR,VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT">
+ <proto><type>VkResult</type> <name>vkWaitForPresentKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkSwapchainKHR</type> <name>swapchain</name></param>
+ <param><type>uint64_t</type> <name>presentId</name></param>
+ <param><type>uint64_t</type> <name>timeout</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_INVALID_EXTERNAL_HANDLE,VK_ERROR_INITIALIZATION_FAILED">
+ <proto><type>VkResult</type> <name>vkCreateBufferCollectionFUCHSIA</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkBufferCollectionCreateInfoFUCHSIA</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkBufferCollectionFUCHSIA</type>* <name>pCollection</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_FORMAT_NOT_SUPPORTED">
+ <proto><type>VkResult</type> <name>vkSetBufferCollectionBufferConstraintsFUCHSIA</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></param>
+ <param>const <type>VkBufferConstraintsInfoFUCHSIA</type>* <name>pBufferConstraintsInfo</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_FORMAT_NOT_SUPPORTED">
+ <proto><type>VkResult</type> <name>vkSetBufferCollectionImageConstraintsFUCHSIA</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></param>
+ <param>const <type>VkImageConstraintsInfoFUCHSIA</type>* <name>pImageConstraintsInfo</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyBufferCollectionFUCHSIA</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_INITIALIZATION_FAILED">
+ <proto><type>VkResult</type> <name>vkGetBufferCollectionPropertiesFUCHSIA</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkBufferCollectionFUCHSIA</type> <name>collection</name></param>
+ <param><type>VkBufferCollectionPropertiesFUCHSIA</type>* <name>pProperties</name></param>
+ </command>
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdBeginRendering</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkRenderingInfo</type>* <name>pRenderingInfo</name></param>
+ </command>
+ <command name="vkCmdBeginRenderingKHR" alias="vkCmdBeginRendering"/>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdEndRendering</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ </command>
+ <command name="vkCmdEndRenderingKHR" alias="vkCmdEndRendering"/>
+ <command>
+ <proto><type>void</type> <name>vkGetDescriptorSetLayoutHostMappingInfoVALVE</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkDescriptorSetBindingReferenceVALVE</type>* <name>pBindingReference</name></param>
+ <param><type>VkDescriptorSetLayoutHostMappingInfoVALVE</type>* <name>pHostMapping</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetDescriptorSetHostMappingVALVE</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkDescriptorSet</type> <name>descriptorSet</name></param>
+ <param><type>void</type>** <name>ppData</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetShaderModuleIdentifierEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkShaderModule</type> <name>shaderModule</name></param>
+ <param><type>VkShaderModuleIdentifierEXT</type>* <name>pIdentifier</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetShaderModuleCreateInfoIdentifierEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkShaderModuleCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param><type>VkShaderModuleIdentifierEXT</type>* <name>pIdentifier</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetImageSubresourceLayout2EXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkImage</type> <name>image</name></param>
+ <param>const <type>VkImageSubresource2EXT</type>* <name>pSubresource</name></param>
+ <param><type>VkSubresourceLayout2EXT</type>* <name>pLayout</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetPipelinePropertiesEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkPipelineInfoEXT</type>* <name>pPipelineInfo</name></param>
+ <param noautovalidity="true" validstructs="VkPipelinePropertiesIdentifierEXT"><type>VkBaseOutStructure</type>* <name>pPipelineProperties</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkExportMetalObjectsEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkExportMetalObjectsInfoEXT</type>* <name>pMetalObjectsInfo</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE">
+ <proto><type>VkResult</type> <name>vkGetFramebufferTilePropertiesQCOM</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkFramebuffer</type> <name>framebuffer</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPropertiesCount</name></param>
+ <param optional="true" len="pPropertiesCount"><type>VkTilePropertiesQCOM</type>* <name>pProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS">
+ <proto><type>VkResult</type> <name>vkGetDynamicRenderingTilePropertiesQCOM</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkRenderingInfo</type>* <name>pRenderingInfo</name></param>
+ <param><type>VkTilePropertiesQCOM</type>* <name>pProperties</name></param>
+ </command>
</commands>
<feature api="vulkan" name="VK_VERSION_1_0" number="1.0" comment="Vulkan core API interface definitions">
<require comment="Header boilerplate">
<type name="vk_platform"/>
<type name="VK_DEFINE_HANDLE"/>
+ <type name="VK_USE_64_BIT_PTR_DEFINES"/>
<type name="VK_DEFINE_NON_DISPATCHABLE_HANDLE"/>
+ <type name="VK_NULL_HANDLE"/>
</require>
<require comment="Fundamental types used by many commands and structures">
<type name="VkBool32"/>
@@ -9314,6 +12207,24 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkResult"/>
<type name="VkStructureType"/>
</require>
+ <require comment="API constants">
+ <enum name="VK_ATTACHMENT_UNUSED"/>
+ <enum name="VK_FALSE"/>
+ <enum name="VK_LOD_CLAMP_NONE"/>
+ <enum name="VK_QUEUE_FAMILY_IGNORED"/>
+ <enum name="VK_REMAINING_ARRAY_LAYERS"/>
+ <enum name="VK_REMAINING_MIP_LEVELS"/>
+ <enum name="VK_SUBPASS_EXTERNAL"/>
+ <enum name="VK_TRUE"/>
+ <enum name="VK_WHOLE_SIZE"/>
+ <enum name="VK_MAX_MEMORY_TYPES"/>
+ <enum name="VK_MAX_PHYSICAL_DEVICE_NAME_SIZE"/>
+ <enum name="VK_UUID_SIZE"/>
+ <enum name="VK_MAX_EXTENSION_NAME_SIZE"/>
+ <enum name="VK_MAX_DESCRIPTION_SIZE"/>
+ <enum name="VK_MAX_MEMORY_HEAPS"/>
+ <type name="VkPipelineCacheHeaderVersion"/>
+ </require>
<require comment="These types are part of the API, though not directly used in API commands or data structures">
<type name="VkBaseInStructure"/>
<type name="VkBaseOutStructure"/>
@@ -9324,6 +12235,7 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkImageMemoryBarrier"/>
<type name="VkMemoryBarrier"/>
<type name="VkObjectType"/>
+ <type name="VkPipelineCacheHeaderVersionOne"/>
<type name="VkVendorId"/>
</require>
<require comment="API version macros">
@@ -9335,19 +12247,11 @@ typedef void <name>CAMetalLayer</name>;
<type name="VK_VERSION_MAJOR"/>
<type name="VK_VERSION_MINOR"/>
<type name="VK_VERSION_PATCH"/>
- </require>
- <require comment="API constants">
- <enum name="VK_ATTACHMENT_UNUSED"/>
- <enum name="VK_FALSE"/>
- <enum name="VK_LOD_CLAMP_NONE"/>
- <enum name="VK_QUEUE_FAMILY_IGNORED"/>
- <enum name="VK_REMAINING_ARRAY_LAYERS"/>
- <enum name="VK_REMAINING_MIP_LEVELS"/>
- <enum name="VK_SUBPASS_EXTERNAL"/>
- <enum name="VK_TRUE"/>
- <enum name="VK_WHOLE_SIZE"/>
- <type name="VK_NULL_HANDLE"/>
- <type name="VkPipelineCacheHeaderVersion"/>
+ <type name="VK_MAKE_API_VERSION"/>
+ <type name="VK_API_VERSION_VARIANT"/>
+ <type name="VK_API_VERSION_MAJOR"/>
+ <type name="VK_API_VERSION_MINOR"/>
+ <type name="VK_API_VERSION_PATCH"/>
</require>
<require comment="Device initialization">
<type name="PFN_vkAllocationFunction"/>
@@ -9371,6 +12275,7 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkImageUsageFlags"/>
<type name="VkInstance"/>
<type name="VkInstanceCreateFlags"/>
+ <type name="VkInstanceCreateFlagBits"/>
<type name="VkInstanceCreateInfo"/>
<type name="VkInternalAllocationType"/>
<type name="VkMemoryHeap"/>
@@ -9391,7 +12296,6 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkQueueFlags"/>
<type name="VkSampleCountFlagBits"/>
<type name="VkSampleCountFlags"/>
- <type name="VkStructureType"/>
<type name="VkSystemAllocationScope"/>
<command name="vkCreateInstance"/>
<command name="vkDestroyInstance"/>
@@ -9407,10 +12311,9 @@ typedef void <name>CAMetalLayer</name>;
</require>
<require comment="Device commands">
<type name="VkDevice"/>
- <type name="VkDeviceCreateFlags"/>
+ <type name="VkDeviceCreateFlags" comment="Will add VkDeviceCreateFlagBits when bits are defined in the future"/>
<type name="VkDeviceCreateInfo"/>
- <type name="VkDeviceQueueCreateFlagBits"/>
- <type name="VkDeviceQueueCreateFlags"/>
+ <type name="VkDeviceQueueCreateFlags" comment="VkDeviceQueueCreateFlagBits was added later"/>
<type name="VkDeviceQueueCreateInfo"/>
<command name="vkCreateDevice"/>
<command name="vkDestroyDevice"/>
@@ -9488,7 +12391,7 @@ typedef void <name>CAMetalLayer</name>;
</require>
<require comment="Queue semaphore commands">
<type name="VkSemaphore"/>
- <type name="VkSemaphoreCreateFlags"/>
+ <type name="VkSemaphoreCreateFlags" comment="Will add VkSemaphoreCreateFlagBits when bits are defined in the future"/>
<type name="VkSemaphoreCreateInfo"/>
<command name="vkCreateSemaphore"/>
<command name="vkDestroySemaphore"/>
@@ -9496,6 +12399,7 @@ typedef void <name>CAMetalLayer</name>;
<require comment="Event commands">
<type name="VkEvent"/>
<type name="VkEventCreateFlags"/>
+ <type name="VkEventCreateFlagBits"/>
<type name="VkEventCreateInfo"/>
<command name="vkCreateEvent"/>
<command name="vkDestroyEvent"/>
@@ -9507,7 +12411,7 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkQueryPipelineStatisticFlagBits"/>
<type name="VkQueryPipelineStatisticFlags"/>
<type name="VkQueryPool"/>
- <type name="VkQueryPoolCreateFlags"/>
+ <type name="VkQueryPoolCreateFlags" comment="Will add VkQueryPoolCreateFlagBits when bits are defined in the future"/>
<type name="VkQueryPoolCreateInfo"/>
<type name="VkQueryResultFlagBits"/>
<type name="VkQueryResultFlags"/>
@@ -9529,7 +12433,7 @@ typedef void <name>CAMetalLayer</name>;
</require>
<require comment="Buffer view commands">
<type name="VkBufferView"/>
- <type name="VkBufferViewCreateFlags" comment="Will need FlagBits type eventually"/>
+ <type name="VkBufferViewCreateFlags" comment="Will add VkBufferViewFlagBits when bits are defined in the future"/>
<type name="VkBufferViewCreateInfo"/>
<command name="vkCreateBufferView"/>
<command name="vkDestroyBufferView"/>
@@ -9557,7 +12461,6 @@ typedef void <name>CAMetalLayer</name>;
</require>
<require comment="Shader commands">
<type name="VkShaderModule"/>
- <type name="VkShaderModuleCreateFlagBits"/>
<type name="VkShaderModuleCreateFlags"/>
<type name="VkShaderModuleCreateInfo"/>
<command name="vkCreateShaderModule"/>
@@ -9565,8 +12468,7 @@ typedef void <name>CAMetalLayer</name>;
</require>
<require comment="Pipeline Cache commands">
<type name="VkPipelineCache"/>
- <type name="VkPipelineCacheCreateFlagBits"/>
- <type name="VkPipelineCacheCreateFlags"/>
+ <type name="VkPipelineCacheCreateFlags" comment="VkPipelineCacheCreateFlagBits was added later"/>
<type name="VkPipelineCacheCreateInfo"/>
<command name="vkCreatePipelineCache"/>
<command name="vkDestroyPipelineCache"/>
@@ -9588,29 +12490,29 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkLogicOp"/>
<type name="VkPipeline"/>
<type name="VkPipelineColorBlendAttachmentState"/>
- <type name="VkPipelineColorBlendStateCreateFlags" comment="Will need FlagBits type eventually"/>
+ <type name="VkPipelineColorBlendStateCreateFlags" comment="Will add VkPipeline*StateFlagBits when bits are defined in the future"/>
<type name="VkPipelineColorBlendStateCreateInfo"/>
<type name="VkPipelineCreateFlagBits"/>
<type name="VkPipelineCreateFlags"/>
- <type name="VkPipelineDepthStencilStateCreateFlags" comment="Will need FlagBits type eventually"/>
+ <type name="VkPipelineDepthStencilStateCreateFlags" comment="Will add VkPipeline*StateFlagBits when bits are defined in the future"/>
<type name="VkPipelineDepthStencilStateCreateInfo"/>
- <type name="VkPipelineDynamicStateCreateFlags" comment="Will need FlagBits type eventually"/>
+ <type name="VkPipelineDynamicStateCreateFlags" comment="Will add VkPipeline*StateFlagBits when bits are defined in the future"/>
<type name="VkPipelineDynamicStateCreateInfo"/>
- <type name="VkPipelineInputAssemblyStateCreateFlags" comment="Will need FlagBits type eventually"/>
+ <type name="VkPipelineInputAssemblyStateCreateFlags" comment="Will add VkPipeline*StateFlagBits when bits are defined in the future"/>
<type name="VkPipelineInputAssemblyStateCreateInfo"/>
- <type name="VkPipelineLayoutCreateFlags" comment="Will need FlagBits type eventually"/>
- <type name="VkPipelineMultisampleStateCreateFlags" comment="Will need FlagBits type eventually"/>
+ <type name="VkPipelineLayoutCreateFlags" comment="Will add VkPipelineLayoutCreateFlagBits when bits are defined in the future"/>
+ <type name="VkPipelineMultisampleStateCreateFlags" comment="Will add VkPipelineMultisampleStateCreateFlagBits when bits are defined in the future"/>
<type name="VkPipelineMultisampleStateCreateInfo"/>
- <type name="VkPipelineRasterizationStateCreateFlags" comment="Will need FlagBits type eventually"/>
+ <type name="VkPipelineRasterizationStateCreateFlags" comment="Will add VkPipelineRasterizationStateCreateFlagBits when bits are defined in the future"/>
<type name="VkPipelineRasterizationStateCreateInfo"/>
<type name="VkPipelineShaderStageCreateFlagBits"/>
<type name="VkPipelineShaderStageCreateFlags"/>
<type name="VkPipelineShaderStageCreateInfo"/>
- <type name="VkPipelineTessellationStateCreateFlags" comment="Will need FlagBits type eventually"/>
+ <type name="VkPipelineTessellationStateCreateFlags" comment="Will add VkPipelineTessellationStateCreateFlagBits when bits are defined in the future"/>
<type name="VkPipelineTessellationStateCreateInfo"/>
- <type name="VkPipelineVertexInputStateCreateFlags" comment="Will need FlagBits type eventually"/>
+ <type name="VkPipelineVertexInputStateCreateFlags" comment="Will add VkPipelineVertexInputStateCreateFlagBits when bits are defined in the future"/>
<type name="VkPipelineVertexInputStateCreateInfo"/>
- <type name="VkPipelineViewportStateCreateFlags" comment="Will need FlagBits type eventually"/>
+ <type name="VkPipelineViewportStateCreateFlags" comment="Will add VkPipelineViewportStateCreateFlagBits when bits are defined in the future"/>
<type name="VkPipelineViewportStateCreateInfo"/>
<type name="VkPolygonMode"/>
<type name="VkPrimitiveTopology"/>
@@ -9956,13 +12858,14 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkPhysicalDeviceVariablePointerFeatures"/>
<type name="VkPhysicalDeviceVariablePointersFeatures"/>
</require>
- <require comment="Originally based on VK_KHR_protected_memory (extension 146), which was never published; thus the mystifying large value= numbers below. These are not aliased since they weren't actually promoted from an extension.">
+ <require comment="Originally based on VK_KHR_protected_memory (extension 146), which was never published; thus the mystifying large value= numbers below. These are not aliased since they were not actually promoted from an extension.">
<enum extends="VkStructureType" extnumber="146" offset="0" name="VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO"/>
<enum extends="VkStructureType" extnumber="146" offset="1" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES"/>
<enum extends="VkStructureType" extnumber="146" offset="2" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES"/>
<enum extends="VkStructureType" extnumber="146" offset="3" name="VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2"/>
<enum bitpos="4" extends="VkQueueFlagBits" name="VK_QUEUE_PROTECTED_BIT" comment="Queues may support protected operations"/>
<enum bitpos="0" extends="VkDeviceQueueCreateFlagBits" name="VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT" comment="Queue is a protected-capable device queue"/>
+ <type name="VkDeviceQueueCreateFlagBits" comment="This is a temporary workaround for processors not recognizing that VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT above also requires this type"/>
<enum bitpos="5" extends="VkMemoryPropertyFlagBits" name="VK_MEMORY_PROPERTY_PROTECTED_BIT" comment="Memory is protected"/>
<enum bitpos="3" extends="VkBufferCreateFlagBits" name="VK_BUFFER_CREATE_PROTECTED_BIT" comment="Buffer requires protected memory"/>
<enum bitpos="11" extends="VkImageCreateFlagBits" name="VK_IMAGE_CREATE_PROTECTED_BIT" comment="Image requires protected memory"/>
@@ -10245,7 +13148,6 @@ typedef void <name>CAMetalLayer</name>;
<enum offset="0" extends="VkStructureType" extnumber="212" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES"/>
<type name="VkPhysicalDeviceVulkanMemoryModelFeatures"/>
</require>
- <!-- Phase 2 features -->
<require comment="Promoted from VK_KHR_imageless_framebuffer (extension 109)">
<type name="VkPhysicalDeviceImagelessFramebufferFeatures"/>
<type name="VkFramebufferAttachmentsCreateInfo"/>
@@ -10325,6 +13227,270 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkGetDeviceMemoryOpaqueCaptureAddress"/>
</require>
</feature>
+ <feature api="vulkan" name="VK_VERSION_1_3" number="1.3" comment="Vulkan 1.3 core API interface definitions.">
+ <require>
+ <type name="VK_API_VERSION_1_3"/>
+ </require>
+ <require>
+ <type name="VkFlags64"/>
+ </require>
+ <require>
+ <enum extends="VkStructureType" value="53" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES"/>
+ <enum extends="VkStructureType" value="54" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES"/>
+ <type name="VkPhysicalDeviceVulkan13Features"/>
+ <type name="VkPhysicalDeviceVulkan13Properties"/>
+ </require>
+ <require comment="Promoted from VK_EXT_pipeline_creation_feedback (extension 193)">
+ <enum offset="0" extends="VkStructureType" extnumber="193" name="VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO"/>
+ <type name="VkPipelineCreationFeedbackFlagBits"/>
+ <type name="VkPipelineCreationFeedbackFlags"/>
+ <type name="VkPipelineCreationFeedbackCreateInfo"/>
+ <type name="VkPipelineCreationFeedback"/>
+ </require>
+ <require comment="Promoted from VK_KHR_shader_terminate_invocation (extension 216)">
+ <enum offset="0" extends="VkStructureType" extnumber="216" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES"/>
+ <type name="VkPhysicalDeviceShaderTerminateInvocationFeatures"/>
+ </require>
+ <require comment="Promoted from VK_EXT_tooling_info (extension 246)">
+ <enum offset="0" extends="VkStructureType" extnumber="246" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES"/>
+ <type name="VkToolPurposeFlagBits"/>
+ <type name="VkToolPurposeFlags"/>
+ <type name="VkPhysicalDeviceToolProperties"/>
+ <command name="vkGetPhysicalDeviceToolProperties"/>
+ </require>
+ <require comment="Promoted from VK_EXT_shader_demote_to_helper_invocation (extension 277)">
+ <enum offset="0" extends="VkStructureType" extnumber="277" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES"/>
+ <type name="VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures"/>
+ </require>
+ <require comment="Promoted from VK_KHR_shader_non_semantic_info (extension 294)">
+ </require>
+ <require comment="Promoted from VK_EXT_private_data (extension 296)">
+ <enum offset="0" extends="VkStructureType" extnumber="296" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES"/>
+ <enum offset="1" extends="VkStructureType" extnumber="296" name="VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO"/>
+ <enum offset="2" extends="VkStructureType" extnumber="296" name="VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO"/>
+ <enum offset="0" extends="VkObjectType" extnumber="296" name="VK_OBJECT_TYPE_PRIVATE_DATA_SLOT"/>
+ <type name="VkPhysicalDevicePrivateDataFeatures"/>
+ <type name="VkDevicePrivateDataCreateInfo"/>
+ <type name="VkPrivateDataSlotCreateInfo"/>
+ <type name="VkPrivateDataSlot"/>
+ <type name="VkPrivateDataSlotCreateFlags" comment="Will add VkPrivateDataSlotCreateFlagBits when bits are defined in the future"/>
+ <command name="vkCreatePrivateDataSlot"/>
+ <command name="vkDestroyPrivateDataSlot"/>
+ <command name="vkSetPrivateData"/>
+ <command name="vkGetPrivateData"/>
+ </require>
+ <require comment="Promoted from VK_EXT_pipeline_creation_cache_control (extension 298)">
+ <enum offset="0" extends="VkStructureType" extnumber="298" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES"/>
+ <type name="VkPhysicalDevicePipelineCreationCacheControlFeatures"/>
+ <enum bitpos="8" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT"/>
+ <enum bitpos="9" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT"/>
+ <enum offset="0" extends="VkResult" extnumber="298" name="VK_PIPELINE_COMPILE_REQUIRED"/>
+ <enum bitpos="0" extends="VkPipelineCacheCreateFlagBits" name="VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT"/>
+ </require>
+ <require comment="Promoted from VK_KHR_synchronization2 (extension 315)">
+ <enum offset="0" extends="VkStructureType" extnumber="315" name="VK_STRUCTURE_TYPE_MEMORY_BARRIER_2"/>
+ <enum offset="1" extends="VkStructureType" extnumber="315" name="VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2"/>
+ <enum offset="2" extends="VkStructureType" extnumber="315" name="VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2"/>
+ <enum offset="3" extends="VkStructureType" extnumber="315" name="VK_STRUCTURE_TYPE_DEPENDENCY_INFO"/>
+ <enum offset="4" extends="VkStructureType" extnumber="315" name="VK_STRUCTURE_TYPE_SUBMIT_INFO_2"/>
+ <enum offset="5" extends="VkStructureType" extnumber="315" name="VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO"/>
+ <enum offset="6" extends="VkStructureType" extnumber="315" name="VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO"/>
+ <enum offset="7" extends="VkStructureType" extnumber="315" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES"/>
+ <enum bitpos="0" extends="VkEventCreateFlagBits" name="VK_EVENT_CREATE_DEVICE_ONLY_BIT"/>
+ <enum offset="0" extends="VkImageLayout" extnumber="315" name="VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL"/>
+ <enum offset="1" extends="VkImageLayout" extnumber="315" name="VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL"/>
+ <enum value="0" extends="VkPipelineStageFlagBits" name="VK_PIPELINE_STAGE_NONE"/>
+ <enum value="0" extends="VkAccessFlagBits" name="VK_ACCESS_NONE"/>
+ <type name="VkPipelineStageFlags2"/>
+ <type name="VkPipelineStageFlagBits2"/>
+ <type name="VkAccessFlags2"/>
+ <type name="VkAccessFlagBits2"/>
+ <type name="VkMemoryBarrier2"/>
+ <type name="VkBufferMemoryBarrier2"/>
+ <type name="VkImageMemoryBarrier2"/>
+ <type name="VkDependencyInfo"/>
+ <type name="VkSubmitInfo2"/>
+ <type name="VkSemaphoreSubmitInfo"/>
+ <type name="VkCommandBufferSubmitInfo"/>
+ <type name="VkSubmitFlagBits"/>
+ <type name="VkSubmitFlags"/>
+ <type name="VkPhysicalDeviceSynchronization2Features"/>
+ <command name="vkCmdSetEvent2"/>
+ <command name="vkCmdResetEvent2"/>
+ <command name="vkCmdWaitEvents2"/>
+ <command name="vkCmdPipelineBarrier2"/>
+ <command name="vkCmdWriteTimestamp2"/>
+ <command name="vkQueueSubmit2"/>
+ </require>
+ <require comment="Promoted from VK_KHR_zero_initialize_workgroup_memory (extension 326)">
+ <enum offset="0" extends="VkStructureType" extnumber="326" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES"/>
+ <type name="VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures"/>
+ </require>
+ <require comment="Promoted from VK_EXT_image_robustness (extension 336)">
+ <enum offset="0" extends="VkStructureType" extnumber="336" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES"/>
+ <type name="VkPhysicalDeviceImageRobustnessFeatures"/>
+ </require>
+ <require comment="Promoted from VK_KHR_copy_commands2 (extension 338)">
+ <enum offset="0" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2"/>
+ <enum offset="1" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2"/>
+ <enum offset="2" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2"/>
+ <enum offset="3" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2"/>
+ <enum offset="4" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2"/>
+ <enum offset="5" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2"/>
+ <enum offset="6" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_BUFFER_COPY_2"/>
+ <enum offset="7" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_IMAGE_COPY_2"/>
+ <enum offset="8" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_IMAGE_BLIT_2"/>
+ <enum offset="9" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2"/>
+ <enum offset="10" extends="VkStructureType" extnumber="338" name="VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2"/>
+ <type name="VkCopyBufferInfo2"/>
+ <type name="VkCopyImageInfo2"/>
+ <type name="VkCopyBufferToImageInfo2"/>
+ <type name="VkCopyImageToBufferInfo2"/>
+ <type name="VkBlitImageInfo2"/>
+ <type name="VkResolveImageInfo2"/>
+ <type name="VkBufferCopy2"/>
+ <type name="VkImageCopy2"/>
+ <type name="VkImageBlit2"/>
+ <type name="VkBufferImageCopy2"/>
+ <type name="VkImageResolve2"/>
+ <command name="vkCmdCopyBuffer2"/>
+ <command name="vkCmdCopyImage2"/>
+ <command name="vkCmdCopyBufferToImage2"/>
+ <command name="vkCmdCopyImageToBuffer2"/>
+ <command name="vkCmdBlitImage2"/>
+ <command name="vkCmdResolveImage2"/>
+ </require>
+ <require comment="Promoted from VK_EXT_subgroup_size_control (STDPROMOTE/PROPLIMCHANGE) (extension 226)">
+ <type name="VkPhysicalDeviceSubgroupSizeControlFeatures"/>
+ <type name="VkPhysicalDeviceSubgroupSizeControlProperties"/>
+ <type name="VkPipelineShaderStageRequiredSubgroupSizeCreateInfo"/>
+ <enum offset="0" extends="VkStructureType" extnumber="226" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES"/>
+ <enum offset="1" extends="VkStructureType" extnumber="226" name="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO"/>
+ <enum offset="2" extends="VkStructureType" extnumber="226" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES"/>
+ <enum bitpos="0" extends="VkPipelineShaderStageCreateFlagBits" name="VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT"/>
+ <enum bitpos="1" extends="VkPipelineShaderStageCreateFlagBits" name="VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT"/>
+ </require>
+ <require comment="Promoted from VK_EXT_inline_uniform_block (STDPROMOTE/PROPLIMCHANGE) (extension 139)">
+ <enum offset="0" extends="VkDescriptorType" extnumber="139" name="VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK"/>
+ <enum offset="0" extends="VkStructureType" extnumber="139" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES"/>
+ <enum offset="1" extends="VkStructureType" extnumber="139" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES"/>
+ <enum offset="2" extends="VkStructureType" extnumber="139" name="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK"/>
+ <enum offset="3" extends="VkStructureType" extnumber="139" name="VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO"/>
+ <type name="VkPhysicalDeviceInlineUniformBlockFeatures"/>
+ <type name="VkPhysicalDeviceInlineUniformBlockProperties"/>
+ <type name="VkWriteDescriptorSetInlineUniformBlock"/>
+ <type name="VkDescriptorPoolInlineUniformBlockCreateInfo"/>
+ </require>
+ <require comment="Promoted from VK_EXT_ycbcr_2plane_444_formats (does not promote the Feature struct, just the formats) (extension 331)">
+ <enum offset="0" extends="VkFormat" extnumber="331" name="VK_FORMAT_G8_B8R8_2PLANE_444_UNORM"/>
+ <enum offset="1" extends="VkFormat" extnumber="331" name="VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16"/>
+ <enum offset="2" extends="VkFormat" extnumber="331" name="VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16"/>
+ <enum offset="3" extends="VkFormat" extnumber="331" name="VK_FORMAT_G16_B16R16_2PLANE_444_UNORM"/>
+ </require>
+ <require comment="Promoted from VK_EXT_4444_formats (does not promote the Feature struct, just the formats) (extension 341)">
+ <enum offset="0" extends="VkFormat" extnumber="341" name="VK_FORMAT_A4R4G4B4_UNORM_PACK16"/>
+ <enum offset="1" extends="VkFormat" extnumber="341" name="VK_FORMAT_A4B4G4R4_UNORM_PACK16"/>
+ </require>
+ <require comment="Promoted from VK_EXT_texture_compression_astc_hdr (Feature struct is promoted, but becomes optional) (extension 67)">
+ <enum offset="0" extends="VkStructureType" extnumber="67" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES"/>
+ <type name="VkPhysicalDeviceTextureCompressionASTCHDRFeatures"/>
+ <enum offset="0" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK"/>
+ <enum offset="1" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK"/>
+ <enum offset="2" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK"/>
+ <enum offset="3" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK"/>
+ <enum offset="4" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK"/>
+ <enum offset="5" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK"/>
+ <enum offset="6" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK"/>
+ <enum offset="7" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK"/>
+ <enum offset="8" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK"/>
+ <enum offset="9" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK"/>
+ <enum offset="10" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK"/>
+ <enum offset="11" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK"/>
+ <enum offset="12" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK"/>
+ <enum offset="13" extends="VkFormat" extnumber="67" name="VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK"/>
+ </require>
+ <require comment="Promoted from VK_KHR_dynamic_rendering (extension 45)">
+ <command name="vkCmdBeginRendering"/>
+ <command name="vkCmdEndRendering"/>
+ <enum offset="0" extends="VkStructureType" extnumber="45" name="VK_STRUCTURE_TYPE_RENDERING_INFO"/>
+ <enum offset="1" extends="VkStructureType" extnumber="45" name="VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO"/>
+ <enum offset="2" extends="VkStructureType" extnumber="45" name="VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO"/>
+ <enum offset="3" extends="VkStructureType" extnumber="45" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES"/>
+ <enum offset="4" extends="VkStructureType" extnumber="45" name="VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO"/>
+ <enum offset="0" extends="VkAttachmentStoreOp" extnumber="302" name="VK_ATTACHMENT_STORE_OP_NONE"/>
+ <type name="VkRenderingInfo"/>
+ <type name="VkRenderingAttachmentInfo"/>
+ <type name="VkPipelineRenderingCreateInfo"/>
+ <type name="VkPhysicalDeviceDynamicRenderingFeatures"/>
+ <type name="VkCommandBufferInheritanceRenderingInfo"/>
+ <type name="VkRenderingFlags"/>
+ <type name="VkRenderingFlagBits"/>
+ </require>
+ <require comment="Promoted from VK_EXT_extended_dynamic_state (Feature struct is not promoted) (extension 268)">
+ <enum offset="0" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_CULL_MODE"/>
+ <enum offset="1" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_FRONT_FACE"/>
+ <enum offset="2" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY"/>
+ <enum offset="3" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT"/>
+ <enum offset="4" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT"/>
+ <enum offset="5" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE"/>
+ <enum offset="6" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE"/>
+ <enum offset="7" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE"/>
+ <enum offset="8" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_DEPTH_COMPARE_OP"/>
+ <enum offset="9" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE"/>
+ <enum offset="10" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE"/>
+ <enum offset="11" extends="VkDynamicState" extnumber="268" name="VK_DYNAMIC_STATE_STENCIL_OP"/>
+ <command name="vkCmdSetCullMode"/>
+ <command name="vkCmdSetFrontFace"/>
+ <command name="vkCmdSetPrimitiveTopology"/>
+ <command name="vkCmdSetViewportWithCount"/>
+ <command name="vkCmdSetScissorWithCount"/>
+ <command name="vkCmdBindVertexBuffers2"/>
+ <command name="vkCmdSetDepthTestEnable"/>
+ <command name="vkCmdSetDepthWriteEnable"/>
+ <command name="vkCmdSetDepthCompareOp"/>
+ <command name="vkCmdSetDepthBoundsTestEnable"/>
+ <command name="vkCmdSetStencilTestEnable"/>
+ <command name="vkCmdSetStencilOp"/>
+ </require>
+ <require comment="Promoted from VK_KHR_shader_integer_dot_product (extension 281)">
+ <enum offset="0" extends="VkStructureType" extnumber="281" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES"/>
+ <enum offset="1" extends="VkStructureType" extnumber="281" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES"/>
+ <type name="VkPhysicalDeviceShaderIntegerDotProductFeatures"/>
+ <type name="VkPhysicalDeviceShaderIntegerDotProductProperties"/>
+ </require>
+ <require comment="Promoted from VK_EXT_texel_buffer_alignment (extension 282)">
+ <enum offset="1" extends="VkStructureType" extnumber="282" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES"/>
+ <type name="VkPhysicalDeviceTexelBufferAlignmentProperties"/>
+ </require>
+ <require comment="Promoted from VK_KHR_format_feature_flags2 (extension 361)">
+ <enum offset="0" extends="VkStructureType" extnumber="361" name="VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3"/>
+ <type name="VkFormatFeatureFlags2"/>
+ <type name="VkFormatFeatureFlagBits2"/>
+ <type name="VkFormatProperties3"/>
+ </require>
+ <require comment="Promoted from VK_EXT_extended_dynamic_state2 (Feature struct and optional state are not promoted) (extension 378)">
+ <enum offset="1" extends="VkDynamicState" extnumber="378" name="VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE"/>
+ <enum offset="2" extends="VkDynamicState" extnumber="378" name="VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE"/>
+ <enum offset="4" extends="VkDynamicState" extnumber="378" name="VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE"/>
+ <command name="vkCmdSetRasterizerDiscardEnable"/>
+ <command name="vkCmdSetDepthBiasEnable"/>
+ <command name="vkCmdSetPrimitiveRestartEnable"/>
+ </require>
+ <require comment="Promoted from VK_KHR_maintenance4 (extension 414)">
+ <enum offset="0" extends="VkStructureType" extnumber="414" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES"/>
+ <enum offset="1" extends="VkStructureType" extnumber="414" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES"/>
+ <enum offset="2" extends="VkStructureType" extnumber="414" name="VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS"/>
+ <enum offset="3" extends="VkStructureType" extnumber="414" name="VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS"/>
+ <enum value="0" extends="VkImageAspectFlagBits" name="VK_IMAGE_ASPECT_NONE"/>
+ <type name="VkPhysicalDeviceMaintenance4Features"/>
+ <type name="VkPhysicalDeviceMaintenance4Properties"/>
+ <type name="VkDeviceBufferMemoryRequirements"/>
+ <type name="VkDeviceImageMemoryRequirements"/>
+ <command name="vkGetDeviceBufferMemoryRequirements"/>
+ <command name="vkGetDeviceImageMemoryRequirements"/>
+ <command name="vkGetDeviceImageSparseMemoryRequirements"/>
+ </require>
+ </feature>
<extensions comment="Vulkan extension interface definitions">
<extension name="VK_KHR_surface" number="1" type="instance" author="KHR" contact="James Jones @cubanismo,Ian Elliott @ianelliottus" supported="vulkan">
@@ -10498,11 +13664,11 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_ANDROID_native_buffer" number="11" type="device" author="ANDROID" platform="android" contact="Jesse Hall @critsec" supported="disabled">
<require>
- <comment>VK_ANDROID_native_buffer is used between the Android Vulkan loader and drivers to implement the WSI extensions. It isn't exposed to applications and uses types that aren't part of Android's stable public API, so it is left disabled to keep it out of the standard Vulkan headers.</comment>
+ <comment>VK_ANDROID_native_buffer is used between the Android Vulkan loader and drivers to implement the WSI extensions. It is not exposed to applications and uses types that are not part of Android's stable public API, so it is left disabled to keep it out of the standard Vulkan headers.</comment>
<enum value="8" name="VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION"/>
<enum value="11" name="VK_ANDROID_NATIVE_BUFFER_NUMBER"/>
- <enum value="&quot;VK_ANDROID_native_buffer&quot;" name="VK_ANDROID_NATIVE_BUFFER_NAME"/>
- <enum name="VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME" alias="VK_ANDROID_NATIVE_BUFFER_NAME"/>
+ <enum value="&quot;VK_ANDROID_native_buffer&quot;" name="VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME"/>
+ <enum name="VK_ANDROID_NATIVE_BUFFER_NAME" alias="VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID"/>
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID"/>
<enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENTATION_PROPERTIES_ANDROID"/>
@@ -10520,7 +13686,7 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_EXT_debug_report" number="12" type="instance" author="GOOGLE" contact="Courtney Goeltzenleuchter @courtney-g" specialuse="debugging" supported="vulkan" deprecatedby="VK_EXT_debug_utils">
<require>
- <enum value="9" name="VK_EXT_DEBUG_REPORT_SPEC_VERSION"/>
+ <enum value="10" name="VK_EXT_DEBUG_REPORT_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_debug_report&quot;" name="VK_EXT_DEBUG_REPORT_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT"/>
<enum alias="VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT" comment="Backwards-compatible alias containing a typo"/>
@@ -10567,8 +13733,8 @@ typedef void <name>CAMetalLayer</name>;
<require>
<enum value="1" name="VK_IMG_FILTER_CUBIC_SPEC_VERSION"/>
<enum value="&quot;VK_IMG_filter_cubic&quot;" name="VK_IMG_FILTER_CUBIC_EXTENSION_NAME"/>
- <enum offset="0" extends="VkFilter" name="VK_FILTER_CUBIC_IMG"/>
- <enum bitpos="13" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG" comment="Format can be filtered with VK_FILTER_CUBIC_IMG when being sampled"/>
+ <enum extends="VkFilter" name="VK_FILTER_CUBIC_IMG" alias="VK_FILTER_CUBIC_EXT"/>
+ <enum extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG" alias="VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT" comment="Format can be filtered with VK_FILTER_CUBIC_IMG when being sampled"/>
</require>
</extension>
<extension name="VK_AMD_extension_17" number="17" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
@@ -10628,43 +13794,131 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkCmdDebugMarkerInsertEXT"/>
</require>
</extension>
- <extension name="VK_AMD_extension_24" number="24" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
- <require>
- <enum value="0" name="VK_AMD_EXTENSION_24_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_24&quot;" name="VK_AMD_EXTENSION_24_EXTENSION_NAME"/>
- <enum bitpos="6" extends="VkQueueFlagBits" name="VK_QUEUE_RESERVED_6_BIT_KHR"/>
- <enum bitpos="27" extends="VkPipelineStageFlagBits" name="VK_PIPELINE_STAGE_RESERVED_27_BIT_KHR"/>
- <enum bitpos="30" extends="VkAccessFlagBits" name="VK_ACCESS_RESERVED_30_BIT_KHR"/>
- <!-- Comment this out for now to avoid warning messages.
- The extension will probably change to avoid it.
- <enum bitpos="31" extends="VkAccessFlagBits" name="VK_ACCESS_RESERVED_31_BIT_KHR"/>
- -->
- <enum bitpos="15" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_RESERVED_15_BIT_KHR"/>
- <enum bitpos="16" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_RESERVED_16_BIT_KHR"/>
- <enum bitpos="13" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_RESERVED_13_BIT_KHR"/>
- <enum bitpos="14" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_RESERVED_14_BIT_KHR"/>
- <enum bitpos="15" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_RESERVED_15_BIT_KHR"/>
- <enum bitpos="27" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_RESERVED_27_BIT_KHR"/>
- <enum bitpos="28" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_RESERVED_28_BIT_KHR"/>
- <enum offset="8" extends="VkQueryType" name="VK_QUERY_TYPE_RESERVED_8"/>
- </require>
- </extension>
- <extension name="VK_AMD_extension_25" number="25" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
- <require>
- <enum value="0" name="VK_AMD_EXTENSION_25_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_25&quot;" name="VK_AMD_EXTENSION_25_EXTENSION_NAME"/>
- <enum bitpos="5" extends="VkQueueFlagBits" name="VK_QUEUE_RESERVED_5_BIT_KHR"/>
- <enum bitpos="26" extends="VkPipelineStageFlagBits" name="VK_PIPELINE_STAGE_RESERVED_26_BIT_KHR"/>
- <enum bitpos="28" extends="VkAccessFlagBits" name="VK_ACCESS_RESERVED_28_BIT_KHR"/>
- <enum bitpos="29" extends="VkAccessFlagBits" name="VK_ACCESS_RESERVED_29_BIT_KHR"/>
- <enum bitpos="13" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_RESERVED_13_BIT_KHR"/>
- <enum bitpos="14" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_RESERVED_14_BIT_KHR"/>
- <enum bitpos="10" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_RESERVED_10_BIT_KHR"/>
- <enum bitpos="11" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_RESERVED_11_BIT_KHR"/>
- <enum bitpos="12" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_RESERVED_12_BIT_KHR"/>
- <enum bitpos="25" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_RESERVED_25_BIT_KHR"/>
- <enum bitpos="26" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_RESERVED_26_BIT_KHR"/>
- <enum offset="4" extends="VkQueryType" name="VK_QUERY_TYPE_RESERVED_4"/>
+ <extension name="VK_KHR_video_queue" number="24" type="device" requires="VK_KHR_get_physical_device_properties2,VK_KHR_synchronization2" author="KHR" contact="Tony Zlatinski @tzlatinski" provisional="true" platform="provisional" supported="vulkan" requiresCore="1.1">
+ <require>
+ <enum value="4" name="VK_KHR_VIDEO_QUEUE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_video_queue&quot;" name="VK_KHR_VIDEO_QUEUE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_CAPABILITIES_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_PICTURE_RESOURCE_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_GET_MEMORY_PROPERTIES_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_BIND_MEMORY_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_SESSION_CREATE_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_CREATE_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="7" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_SESSION_PARAMETERS_UPDATE_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="8" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_BEGIN_CODING_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="9" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_END_CODING_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="10" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_CODING_CONTROL_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="11" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_REFERENCE_SLOT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="12" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_QUEUE_FAMILY_PROPERTIES_2_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="13" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="14" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_FORMAT_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="15" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="16" extends="VkStructureType" name="VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_2_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+
+ <enum offset="0" extends="VkObjectType" name="VK_OBJECT_TYPE_VIDEO_SESSION_KHR" comment="VkVideoSessionKHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkObjectType" name="VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR" comment="VkVideoSessionParametersKHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+
+ <enum offset="0" extends="VkQueryType" name="VK_QUERY_TYPE_RESULT_STATUS_ONLY_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="4" extends="VkQueryResultFlagBits" name="VK_QUERY_RESULT_WITH_STATUS_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+
+ <enum offset="0" extends="VkResult" dir="-" name="VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkResult" dir="-" name="VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="2" extends="VkResult" dir="-" name="VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="3" extends="VkResult" dir="-" name="VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="4" extends="VkResult" dir="-" name="VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="5" extends="VkResult" dir="-" name="VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+
+ <type name="VkVideoSessionKHR"/>
+ <type name="VkVideoSessionParametersKHR"/>
+
+ <type name="VkVideoCodecOperationFlagBitsKHR"/>
+ <type name="VkVideoCodecOperationFlagsKHR"/>
+ <type name="VkVideoChromaSubsamplingFlagBitsKHR"/>
+ <type name="VkVideoChromaSubsamplingFlagsKHR"/>
+ <type name="VkVideoComponentBitDepthFlagBitsKHR"/>
+ <type name="VkVideoComponentBitDepthFlagsKHR"/>
+ <type name="VkVideoCapabilityFlagBitsKHR"/>
+ <type name="VkVideoCapabilityFlagsKHR"/>
+ <type name="VkVideoSessionCreateFlagBitsKHR"/>
+ <type name="VkVideoSessionCreateFlagsKHR"/>
+ <type name="VkVideoBeginCodingFlagsKHR"/>
+ <type name="VkVideoEndCodingFlagsKHR"/>
+ <type name="VkVideoCodingControlFlagBitsKHR"/>
+ <type name="VkVideoCodingControlFlagsKHR"/>
+ <type name="VkVideoCodingQualityPresetFlagBitsKHR"/>
+ <type name="VkVideoCodingQualityPresetFlagsKHR"/>
+
+ <type name="VkQueueFamilyQueryResultStatusProperties2KHR"/>
+ <type name="VkQueryResultStatusKHR"/>
+
+ <type name="VkVideoQueueFamilyProperties2KHR"/>
+ <type name="VkVideoProfileKHR"/>
+ <type name="VkVideoProfilesKHR"/>
+ <type name="VkVideoCapabilitiesKHR"/>
+ <type name="VkPhysicalDeviceVideoFormatInfoKHR"/>
+ <type name="VkVideoFormatPropertiesKHR"/>
+ <type name="VkVideoPictureResourceKHR"/>
+ <type name="VkVideoReferenceSlotKHR"/>
+ <type name="VkVideoGetMemoryPropertiesKHR"/>
+ <type name="VkVideoBindMemoryKHR"/>
+ <type name="VkVideoSessionCreateInfoKHR"/>
+ <type name="VkVideoSessionParametersCreateInfoKHR"/>
+ <type name="VkVideoSessionParametersUpdateInfoKHR"/>
+ <type name="VkVideoBeginCodingInfoKHR"/>
+ <type name="VkVideoEndCodingInfoKHR"/>
+ <type name="VkVideoCodingControlInfoKHR"/>
+
+ <command name="vkGetPhysicalDeviceVideoCapabilitiesKHR"/>
+ <command name="vkGetPhysicalDeviceVideoFormatPropertiesKHR"/>
+
+ <command name="vkCreateVideoSessionKHR"/>
+ <command name="vkDestroyVideoSessionKHR"/>
+ <command name="vkGetVideoSessionMemoryRequirementsKHR"/>
+ <command name="vkBindVideoSessionMemoryKHR"/>
+ <command name="vkCreateVideoSessionParametersKHR"/>
+ <command name="vkUpdateVideoSessionParametersKHR"/>
+ <command name="vkDestroyVideoSessionParametersKHR"/>
+ <command name="vkCmdBeginVideoCodingKHR"/>
+ <command name="vkCmdEndVideoCodingKHR"/>
+ <command name="vkCmdControlVideoCodingKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_video_decode_queue" number="25" type="device" requires="VK_KHR_video_queue,VK_KHR_synchronization2" author="KHR" contact="jake.beju@amd.com" provisional="true" platform="provisional" supported="vulkan">
+ <require>
+ <enum value="4" name="VK_KHR_VIDEO_DECODE_QUEUE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_video_decode_queue&quot;" name="VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_CAPABILITIES_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="5" extends="VkQueueFlagBits" name="VK_QUEUE_VIDEO_DECODE_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <!-- VkPipelineStageFlagBits bitpos="26" is reserved by this extension, but not used -->
+ <enum bitpos="26" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_VIDEO_DECODE_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="35" extends="VkAccessFlagBits2" name="VK_ACCESS_2_VIDEO_DECODE_READ_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS" />
+ <enum bitpos="36" extends="VkAccessFlagBits2" name="VK_ACCESS_2_VIDEO_DECODE_WRITE_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="13" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="14" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="10" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="11" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="12" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="25" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_VIDEO_DECODE_OUTPUT_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="26" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_VIDEO_DECODE_DPB_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="0" extends="VkImageLayout" name="VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkImageLayout" name="VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="2" extends="VkImageLayout" name="VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+
+ <type name="VkVideoDecodeCapabilityFlagBitsKHR"/>
+ <type name="VkVideoDecodeCapabilityFlagsKHR"/>
+ <type name="VkVideoDecodeCapabilitiesKHR"/>
+
+ <type name="VkVideoDecodeFlagBitsKHR"/>
+ <type name="VkVideoDecodeFlagsKHR"/>
+
+ <type name="VkVideoDecodeInfoKHR"/>
+ <command name="vkCmdDecodeVideoKHR"/>
+ </require>
+ <require extension="VK_KHR_format_feature_flags2">
+ <enum bitpos="25" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_VIDEO_DECODE_OUTPUT_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="26" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_VIDEO_DECODE_DPB_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
</require>
</extension>
<extension name="VK_AMD_gcn_shader" number="26" type="device" author="AMD" contact="Dominik Witczak @dominikwitczakamd" supported="vulkan">
@@ -10688,7 +13942,7 @@ typedef void <name>CAMetalLayer</name>;
<extension name="VK_EXT_extension_28" number="28" author="NV" contact="Piers Daniell @pdaniell-nv" supported="disabled">
<require>
<enum value="0" name="VK_EXT_EXTENSION_28_SPEC_VERSION"/>
- <enum value="&quot;VK_NV_extension_28&quot;" name="VK_EXT_EXTENSION_28_EXTENSION_NAME"/>
+ <enum value="&quot;VK_EXT_extension_28&quot;" name="VK_EXT_EXTENSION_28_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_EXT_transform_feedback" number="29" type="device" author="NV" contact="Piers Daniell @pdaniell-nv" specialuse="glemulation,d3demulation,devtools" supported="vulkan" requires="VK_KHR_get_physical_device_properties2">
@@ -10708,8 +13962,8 @@ typedef void <name>CAMetalLayer</name>;
<enum offset="4" extends="VkQueryType" name="VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT"/>
- <enum bitpos="11" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT"/>
- <enum bitpos="12" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT"/>
+ <enum bitpos="11" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT"/>
+ <enum bitpos="12" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT"/>
<enum bitpos="25" extends="VkAccessFlagBits" name="VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT"/>
<enum bitpos="26" extends="VkAccessFlagBits" name="VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT"/>
@@ -10724,13 +13978,30 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkPipelineRasterizationStateStreamCreateFlagsEXT"/>
</require>
</extension>
- <extension name="VK_NVX_extension_30" number="30" author="NVX" contact="Jeff Juliano @jjulianoatnv" supported="disabled">
+ <extension name="VK_NVX_binary_import" number="30" type="device" author="NVX" contact="Eric Werness @ewerness-nv,Liam Middlebrook @liam-middlebrook" supported="vulkan">
<require>
- <enum value="0" name="VK_NVX_EXTENSION_30_SPEC_VERSION"/>
- <enum value="&quot;VK_NVX_extension_30&quot;" name="VK_NVX_EXTENSION_30_EXTENSION_NAME"/>
+ <enum value="1" name="VK_NVX_BINARY_IMPORT_SPEC_VERSION"/>
+ <enum value="&quot;VK_NVX_binary_import&quot;" name="VK_NVX_BINARY_IMPORT_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_CU_MODULE_CREATE_INFO_NVX"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_CU_FUNCTION_CREATE_INFO_NVX"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_CU_LAUNCH_INFO_NVX"/>
+ <enum offset="0" extends="VkObjectType" name="VK_OBJECT_TYPE_CU_MODULE_NVX"/>
+ <enum offset="1" extends="VkObjectType" name="VK_OBJECT_TYPE_CU_FUNCTION_NVX"/>
+ <enum offset="0" extends="VkDebugReportObjectTypeEXT" name="VK_DEBUG_REPORT_OBJECT_TYPE_CU_MODULE_NVX_EXT"/>
+ <enum offset="1" extends="VkDebugReportObjectTypeEXT" name="VK_DEBUG_REPORT_OBJECT_TYPE_CU_FUNCTION_NVX_EXT"/>
+ <type name="VkCuModuleNVX"/>
+ <type name="VkCuFunctionNVX"/>
+ <type name="VkCuModuleCreateInfoNVX"/>
+ <type name="VkCuFunctionCreateInfoNVX"/>
+ <type name="VkCuLaunchInfoNVX"/>
+ <command name="vkCreateCuModuleNVX"/>
+ <command name="vkCreateCuFunctionNVX"/>
+ <command name="vkDestroyCuModuleNVX"/>
+ <command name="vkDestroyCuFunctionNVX"/>
+ <command name="vkCmdCuLaunchKernelNVX"/>
</require>
</extension>
- <extension name="VK_NVX_image_view_handle" number="31" type="device" author="NVX" contact="Eric Werness @ewerness" supported="vulkan">
+ <extension name="VK_NVX_image_view_handle" number="31" type="device" author="NVX" contact="Eric Werness @ewerness-nv" supported="vulkan">
<require>
<enum value="2" name="VK_NVX_IMAGE_VIEW_HANDLE_SPEC_VERSION"/>
<enum value="&quot;VK_NVX_image_view_handle&quot;" name="VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME"/>
@@ -10786,22 +14057,112 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_AMD_shader_ballot&quot;" name="VK_AMD_SHADER_BALLOT_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_AMD_extension_39" number="39" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
- <require>
- <enum value="0" name="VK_AMD_EXTENSION_39_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_39&quot;" name="VK_AMD_EXTENSION_39_EXTENSION_NAME"/>
- </require>
- </extension>
- <extension name="VK_AMD_extension_40" number="40" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
- <require>
- <enum value="0" name="VK_AMD_EXTENSION_40_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_40&quot;" name="VK_AMD_EXTENSION_40_EXTENSION_NAME"/>
- </require>
- </extension>
- <extension name="VK_AMD_extension_41" number="41" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
- <require>
- <enum value="0" name="VK_AMD_EXTENSION_41_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_41&quot;" name="VK_AMD_EXTENSION_41_EXTENSION_NAME"/>
+ <extension name="VK_EXT_video_encode_h264" number="39" type="device" requires="VK_KHR_video_encode_queue" author="KHR" contact="Ahmed Abdelkhalek @aabdelkh" provisional="true" platform="provisional" supported="vulkan">
+ <require>
+ <enum value="7" name="VK_EXT_VIDEO_ENCODE_H264_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_video_encode_h264&quot;" name="VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_CAPABILITIES_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_VCL_FRAME_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_DPB_SLOT_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_NALU_SLICE_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_EMIT_PICTURE_PARAMETERS_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="7" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="8" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="9" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_RATE_CONTROL_LAYER_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="10" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_REFERENCE_LISTS_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="16" extends="VkVideoCodecOperationFlagBitsKHR" name="VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+
+ <type name="VkVideoEncodeH264CapabilityFlagBitsEXT"/>
+ <type name="VkVideoEncodeH264CapabilityFlagsEXT"/>
+ <type name="VkVideoEncodeH264InputModeFlagBitsEXT"/>
+ <type name="VkVideoEncodeH264InputModeFlagsEXT"/>
+ <type name="VkVideoEncodeH264OutputModeFlagBitsEXT"/>
+ <type name="VkVideoEncodeH264OutputModeFlagsEXT"/>
+ <type name="VkVideoEncodeH264CapabilitiesEXT"/>
+ <type name="VkVideoEncodeH264SessionParametersCreateInfoEXT"/>
+ <type name="VkVideoEncodeH264SessionParametersAddInfoEXT"/>
+ <type name="VkVideoEncodeH264VclFrameInfoEXT"/>
+ <type name="VkVideoEncodeH264ReferenceListsEXT"/>
+ <type name="VkVideoEncodeH264EmitPictureParametersEXT"/>
+ <type name="VkVideoEncodeH264DpbSlotInfoEXT"/>
+ <type name="VkVideoEncodeH264NaluSliceEXT"/>
+ <type name="VkVideoEncodeH264ProfileEXT"/>
+ <type name="VkVideoEncodeH264RateControlInfoEXT"/>
+ <type name="VkVideoEncodeH264RateControlStructureFlagBitsEXT"/>
+ <type name="VkVideoEncodeH264RateControlStructureFlagsEXT"/>
+ <type name="VkVideoEncodeH264RateControlLayerInfoEXT"/>
+ <type name="VkVideoEncodeH264QpEXT"/>
+ <type name="VkVideoEncodeH264FrameSizeEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_video_encode_h265" number="40" type="device" requires="VK_KHR_video_encode_queue" author="KHR" contact="Ahmed Abdelkhalek @aabdelkh" provisional="true" platform="provisional" supported="vulkan">
+ <require>
+ <enum value="7" name="VK_EXT_VIDEO_ENCODE_H265_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_video_encode_h265&quot;" name="VK_EXT_VIDEO_ENCODE_H265_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_CAPABILITIES_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_VCL_FRAME_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_DPB_SLOT_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_NALU_SLICE_SEGMENT_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_EMIT_PICTURE_PARAMETERS_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="7" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_PROFILE_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="8" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_REFERENCE_LISTS_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="9" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="10" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_H265_RATE_CONTROL_LAYER_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="17" extends="VkVideoCodecOperationFlagBitsKHR" name="VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+
+ <type name="VkVideoEncodeH265CapabilityFlagBitsEXT"/>
+ <type name="VkVideoEncodeH265CapabilityFlagsEXT"/>
+ <type name="VkVideoEncodeH265InputModeFlagBitsEXT"/>
+ <type name="VkVideoEncodeH265InputModeFlagsEXT"/>
+ <type name="VkVideoEncodeH265OutputModeFlagBitsEXT"/>
+ <type name="VkVideoEncodeH265OutputModeFlagsEXT"/>
+
+ <type name="VkVideoEncodeH265CtbSizeFlagBitsEXT"/>
+ <type name="VkVideoEncodeH265CtbSizeFlagsEXT"/>
+ <type name="VkVideoEncodeH265TransformBlockSizeFlagBitsEXT"/>
+ <type name="VkVideoEncodeH265TransformBlockSizeFlagsEXT"/>
+ <type name="VkVideoEncodeH265CapabilitiesEXT"/>
+ <type name="VkVideoEncodeH265SessionParametersCreateInfoEXT"/>
+ <type name="VkVideoEncodeH265SessionParametersAddInfoEXT"/>
+ <type name="VkVideoEncodeH265VclFrameInfoEXT"/>
+ <type name="VkVideoEncodeH265EmitPictureParametersEXT"/>
+ <type name="VkVideoEncodeH265DpbSlotInfoEXT"/>
+ <type name="VkVideoEncodeH265NaluSliceSegmentEXT"/>
+ <type name="VkVideoEncodeH265ProfileEXT"/>
+ <type name="VkVideoEncodeH265ReferenceListsEXT"/>
+ <type name="VkVideoEncodeH265RateControlInfoEXT"/>
+ <type name="VkVideoEncodeH265RateControlStructureFlagBitsEXT"/>
+ <type name="VkVideoEncodeH265RateControlStructureFlagsEXT"/>
+ <type name="VkVideoEncodeH265RateControlLayerInfoEXT"/>
+ <type name="VkVideoEncodeH265QpEXT"/>
+ <type name="VkVideoEncodeH265FrameSizeEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_video_decode_h264" number="41" type="device" requires="VK_KHR_video_decode_queue" author="KHR" contact="peter.fang@amd.com" provisional="true" platform="provisional" supported="vulkan">
+ <require>
+ <enum value="5" name="VK_EXT_VIDEO_DECODE_H264_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_video_decode_h264&quot;" name="VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_CAPABILITIES_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PICTURE_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_MVC_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_CREATE_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_SESSION_PARAMETERS_ADD_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_DPB_SLOT_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="0" extends="VkVideoCodecOperationFlagBitsKHR" name="VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <type name="VkVideoDecodeH264PictureLayoutFlagBitsEXT"/>
+ <type name="VkVideoDecodeH264PictureLayoutFlagsEXT"/>
+ <type name="VkVideoDecodeH264ProfileEXT"/>
+ <type name="VkVideoDecodeH264CapabilitiesEXT"/>
+ <type name="VkVideoDecodeH264SessionParametersCreateInfoEXT"/>
+ <type name="VkVideoDecodeH264SessionParametersAddInfoEXT"/>
+ <type name="VkVideoDecodeH264PictureInfoEXT"/>
+ <type name="VkVideoDecodeH264MvcEXT"/>
+ <type name="VkVideoDecodeH264DpbSlotInfoEXT"/>
</require>
</extension>
<extension name="VK_AMD_texture_gather_bias_lod" number="42" author="AMD" contact="Rex Xu @amdrexu" supported="vulkan" type="device" requires="VK_KHR_get_physical_device_properties2">
@@ -10828,10 +14189,49 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_AMD_extension_44&quot;" name="VK_AMD_EXTENSION_44_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_AMD_extension_45" number="45" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
- <require>
- <enum value="0" name="VK_AMD_EXTENSION_45_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_45&quot;" name="VK_AMD_EXTENSION_45_EXTENSION_NAME"/>
+ <extension name="VK_KHR_dynamic_rendering" number="45" author="KHR" type="device" requires="VK_KHR_depth_stencil_resolve,VK_KHR_get_physical_device_properties2" contact="Tobias Hector @tobski" supported="vulkan" promotedto="VK_VERSION_1_3">
+ <require>
+ <enum value="1" name="VK_KHR_DYNAMIC_RENDERING_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_dynamic_rendering&quot;" name="VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME"/>
+ <command name="vkCmdBeginRenderingKHR"/>
+ <command name="vkCmdEndRenderingKHR"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_RENDERING_INFO_KHR" alias="VK_STRUCTURE_TYPE_RENDERING_INFO"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR" alias="VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR" alias="VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR" alias="VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO"/>
+ <enum extends="VkAttachmentStoreOp" name="VK_ATTACHMENT_STORE_OP_NONE_KHR" alias="VK_ATTACHMENT_STORE_OP_NONE"/>
+ <type name="VkRenderingInfoKHR"/>
+ <type name="VkRenderingAttachmentInfoKHR"/>
+ <type name="VkPipelineRenderingCreateInfoKHR"/>
+ <type name="VkPhysicalDeviceDynamicRenderingFeaturesKHR"/>
+ <type name="VkCommandBufferInheritanceRenderingInfoKHR"/>
+ <type name="VkRenderingFlagsKHR"/>
+ <type name="VkRenderingFlagBitsKHR"/>
+ </require>
+ <require extension="VK_KHR_fragment_shading_rate">
+ <enum bitpos="21" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"/>
+ <enum alias="VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR" comment="Backwards-compatible alias containing a typo"/>
+ <enum offset="6" extends="VkStructureType" extnumber="45" name="VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR"/>
+ <type name="VkRenderingFragmentShadingRateAttachmentInfoKHR"/>
+ </require>
+ <require extension="VK_EXT_fragment_density_map">
+ <enum bitpos="22" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT"/>
+ <enum alias="VK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_RASTERIZATION_STATE_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT" comment="Backwards-compatible alias containing a typo"/>
+ <enum offset="7" extends="VkStructureType" extnumber="45" name="VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT"/>
+ <type name="VkRenderingFragmentDensityMapAttachmentInfoEXT"/>
+ </require>
+ <require extension="VK_AMD_mixed_attachment_samples">
+ <enum offset="8" extends="VkStructureType" extnumber="45" name="VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD"/>
+ <type name="VkAttachmentSampleCountInfoAMD"/>
+ </require>
+ <require extension="VK_NV_framebuffer_mixed_samples">
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_NV" alias="VK_STRUCTURE_TYPE_ATTACHMENT_SAMPLE_COUNT_INFO_AMD"/>
+ <type name="VkAttachmentSampleCountInfoNV"/>
+ </require>
+ <require extension="VK_NVX_multiview_per_view_attributes">
+ <enum offset="9" extends="VkStructureType" extnumber="45" name="VK_STRUCTURE_TYPE_MULTIVIEW_PER_VIEW_ATTRIBUTES_INFO_NVX"/>
+ <type name="VkMultiviewPerViewAttributesInfoNVX"/>
</require>
</extension>
<extension name="VK_AMD_extension_46" number="46" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
@@ -11088,48 +14488,58 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_EXT_shader_subgroup_vote&quot;" name="VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_EXT_texture_compression_astc_hdr" number="67" type="device" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" requires="VK_KHR_get_physical_device_properties2" supported="vulkan">
+ <extension name="VK_EXT_texture_compression_astc_hdr" number="67" type="device" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" requires="VK_KHR_get_physical_device_properties2" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
- <enum value="1" name="VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_texture_compression_astc_hdr&quot;" name="VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT"/>
+ <enum value="1" name="VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_texture_compression_astc_hdr&quot;" name="VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES"/>
<type name="VkPhysicalDeviceTextureCompressionASTCHDRFeaturesEXT"/>
- <enum extends="VkFormat" extnumber="67" offset="0" name="VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="1" name="VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="2" name="VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="3" name="VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="4" name="VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="5" name="VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="6" name="VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="7" name="VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="8" name="VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="9" name="VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="10" name="VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="11" name="VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="12" name="VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT"/>
- <enum extends="VkFormat" extnumber="67" offset="13" name="VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK"/>
+ <enum extends="VkFormat" name="VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT" alias="VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK"/>
</require>
</extension>
<extension name="VK_EXT_astc_decode_mode" number="68" type="device" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" requires="VK_KHR_get_physical_device_properties2" supported="vulkan">
<require>
- <enum value="1" name="VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_astc_decode_mode&quot;" name="VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT"/>
- <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT"/>
+ <enum value="1" name="VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_astc_decode_mode&quot;" name="VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT"/>
<type name="VkImageViewASTCDecodeModeEXT"/>
<type name="VkPhysicalDeviceASTCDecodeFeaturesEXT"/>
</require>
</extension>
- <extension name="VK_IMG_extension_69" number="69" type="device" author="IMG" contact="Tobias Hector @tobski" supported="disabled">
+ <extension name="VK_EXT_pipeline_robustness" requires="VK_KHR_get_physical_device_properties2" number="69" type="device" author="IMG" contact="Jarred Davies" supported="vulkan">
<require>
- <enum value="0" name="VK_IMG_EXTENSION_69_SPEC_VERSION"/>
- <enum value="&quot;VK_IMG_extension_69&quot;" name="VK_IMG_EXTENSION_69_EXTENSION_NAME"/>
+ <enum value="1" name="VK_EXT_PIPELINE_ROBUSTNESS_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_pipeline_robustness&quot;" name="VK_EXT_PIPELINE_ROBUSTNESS_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_ROBUSTNESS_CREATE_INFO_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_FEATURES_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES_EXT"/>
+ <type name="VkPhysicalDevicePipelineRobustnessFeaturesEXT"/>
+ <type name="VkPhysicalDevicePipelineRobustnessPropertiesEXT"/>
+ <type name="VkPipelineRobustnessCreateInfoEXT"/>
+ <type name="VkPipelineRobustnessBufferBehaviorEXT"/>
+ <type name="VkPipelineRobustnessImageBehaviorEXT"/>
</require>
</extension>
<extension name="VK_KHR_maintenance1" number="70" type="device" author="KHR" contact="Piers Daniell @pdaniell-nv" supported="vulkan" promotedto="VK_VERSION_1_1">
<require>
- <enum value="2" name="VK_KHR_MAINTENANCE1_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_maintenance1&quot;" name="VK_KHR_MAINTENANCE1_EXTENSION_NAME"/>
+ <enum value="2" name="VK_KHR_MAINTENANCE_1_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_maintenance1&quot;" name="VK_KHR_MAINTENANCE_1_EXTENSION_NAME"/>
+ <enum alias="VK_KHR_MAINTENANCE_1_SPEC_VERSION" name="VK_KHR_MAINTENANCE1_SPEC_VERSION" comment="Backwards-compatible alias containing a typo"/>
+ <enum alias="VK_KHR_MAINTENANCE_1_EXTENSION_NAME" name="VK_KHR_MAINTENANCE1_EXTENSION_NAME" comment="Backwards-compatible alias containing a typo"/>
<enum extends="VkResult" name="VK_ERROR_OUT_OF_POOL_MEMORY_KHR" alias="VK_ERROR_OUT_OF_POOL_MEMORY"/>
<enum extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR" alias="VK_FORMAT_FEATURE_TRANSFER_SRC_BIT"/>
<enum extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR" alias="VK_FORMAT_FEATURE_TRANSFER_DST_BIT"/>
@@ -11339,10 +14749,10 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_KHR_shader_float16_int8" number="83" type="device" requires="VK_KHR_get_physical_device_properties2" author="KHR" contact="Alexander Galazin @alegal-arm" supported="vulkan" promotedto="VK_VERSION_1_2">
<require>
- <enum value="1" name="VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_shader_float16_int8&quot;" name="VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME"/>
- <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES"/>
- <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES"/>
+ <enum value="1" name="VK_KHR_SHADER_FLOAT16_INT8_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_shader_float16_int8&quot;" name="VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES"/>
<type name="VkPhysicalDeviceShaderFloat16Int8FeaturesKHR"/>
<type name="VkPhysicalDeviceFloat16Int8FeaturesKHR"/>
</require>
@@ -11357,7 +14767,7 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_KHR_incremental_present" number="85" type="device" author="KHR" requires="VK_KHR_swapchain" contact="Ian Elliott @ianelliottus" supported="vulkan">
<require>
- <enum value="1" name="VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION"/>
+ <enum value="2" name="VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_incremental_present&quot;" name="VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR"/>
<type name="VkPresentRegionsKHR"/>
@@ -11467,7 +14877,11 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkGetPastPresentationTimingGOOGLE"/>
</require>
</extension>
- <extension name="RESERVED_DO_NOT_USE_94" number="94" supported="disabled" comment="Used for functionality subsumed into Vulkan 1.1 and not published as an extension">
+ <extension name="VK_RESERVED_do_not_use_94" number="94" supported="disabled" comment="Used for functionality subsumed into Vulkan 1.1 and not published as an extension">
+ <require>
+ <enum value="1" name="VK_RESERVED_DO_NOT_USE_94_SPEC_VERSION"/>
+ <enum value="&quot;VK_RESERVED_do_not_use_94&quot;" name="VK_RESERVED_DO_NOT_USE_94_EXTENSION_NAME"/>
+ </require>
</extension>
<extension name="VK_NV_sample_mask_override_coverage" number="95" type="device" author="NV" contact="Piers Daniell @pdaniell-nv" supported="vulkan">
<require>
@@ -11488,8 +14902,10 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_NV_viewport_array2" number="97" type="device" author="NV" contact="Daniel Koch @dgkoch" supported="vulkan">
<require>
- <enum value="1" name="VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION"/>
- <enum value="&quot;VK_NV_viewport_array2&quot;" name="VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME"/>
+ <enum value="1" name="VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_viewport_array2&quot;" name="VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME"/>
+ <enum alias="VK_NV_VIEWPORT_ARRAY_2_SPEC_VERSION" name="VK_NV_VIEWPORT_ARRAY2_SPEC_VERSION" comment="Backwards-compatible alias containing a typo"/>
+ <enum alias="VK_NV_VIEWPORT_ARRAY_2_EXTENSION_NAME" name="VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME" comment="Backwards-compatible alias containing a typo"/>
</require>
</extension>
<extension name="VK_NVX_multiview_per_view_attributes" number="98" type="device" requires="VK_KHR_multiview" author="NVX" contact="Jeff Bolz @jeffbolznv" supported="vulkan">
@@ -11580,7 +14996,7 @@ typedef void <name>CAMetalLayer</name>;
<enum offset="12" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT"/>
<enum offset="13" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_PASS_THROUGH_EXT"/>
<enum offset="14" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT"/>
- <enum extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_DCI_P3_LINEAR_EXT" alias="VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT" comment="Deprecated name for backwards compatibility"/>
+ <enum extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_DCI_P3_LINEAR_EXT" alias="VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT" comment="Backwards-compatible alias containing a typo"/>
</require>
</extension>
<extension name="VK_EXT_hdr_metadata" number="106" type="device" requires="VK_KHR_swapchain" author="GOOGLE" contact="Courtney Goeltzenleuchter @courtney-g" supported="vulkan">
@@ -11620,7 +15036,7 @@ typedef void <name>CAMetalLayer</name>;
<enum extends="VkFramebufferCreateFlagBits" name="VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR" alias="VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT"/>
</require>
</extension>
- <extension name="VK_KHR_create_renderpass2" requires="VK_KHR_multiview,VK_KHR_maintenance2" number="110" contact="Tobias Hector @tobias" type="device" supported="vulkan" promotedto="VK_VERSION_1_2">
+ <extension name="VK_KHR_create_renderpass2" requires="VK_KHR_multiview,VK_KHR_maintenance2" number="110" author="KHR" contact="Tobias Hector @tobias" type="device" supported="vulkan" promotedto="VK_VERSION_1_2">
<require>
<enum value="1" name="VK_KHR_CREATE_RENDERPASS_2_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_create_renderpass2&quot;" name="VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME"/>
@@ -11758,8 +15174,10 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_KHR_maintenance2" number="118" type="device" author="KHR" contact="Michael Worcester @michaelworcester" supported="vulkan" promotedto="VK_VERSION_1_1">
<require>
- <enum value="1" name="VK_KHR_MAINTENANCE2_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_maintenance2&quot;" name="VK_KHR_MAINTENANCE2_EXTENSION_NAME"/>
+ <enum value="1" name="VK_KHR_MAINTENANCE_2_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_maintenance2&quot;" name="VK_KHR_MAINTENANCE_2_EXTENSION_NAME"/>
+ <enum alias="VK_KHR_MAINTENANCE_2_SPEC_VERSION" name="VK_KHR_MAINTENANCE2_SPEC_VERSION" comment="Backwards-compatible alias containing a typo"/>
+ <enum alias="VK_KHR_MAINTENANCE_2_EXTENSION_NAME" name="VK_KHR_MAINTENANCE2_EXTENSION_NAME" comment="Backwards-compatible alias containing a typo"/>
<enum extends="VkImageCreateFlagBits" name="VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR" alias="VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT"/>
<enum extends="VkImageCreateFlagBits" name="VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR" alias="VK_IMAGE_CREATE_EXTENDED_USAGE_BIT"/>
<enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES"/>
@@ -11813,13 +15231,13 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_KHR_get_display_properties2" number="122" type="instance" requires="VK_KHR_display" author="KHR" contact="James Jones @cubanismo" supported="vulkan">
<require>
- <enum value="1" name="VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_get_display_properties2&quot;" name="VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR"/>
- <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR"/>
- <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR"/>
- <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR"/>
- <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR"/>
+ <enum value="1" name="VK_KHR_GET_DISPLAY_PROPERTIES_2_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_get_display_properties2&quot;" name="VK_KHR_GET_DISPLAY_PROPERTIES_2_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_PROPERTIES_2_KHR"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_PLANE_PROPERTIES_2_KHR"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_MODE_PROPERTIES_2_KHR"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_PLANE_INFO_2_KHR"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_PLANE_CAPABILITIES_2_KHR"/>
<type name="VkDisplayProperties2KHR"/>
<type name="VkDisplayPlaneProperties2KHR"/>
<type name="VkDisplayModeProperties2KHR"/>
@@ -11919,7 +15337,7 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_ANDROID_external_memory_android_hardware_buffer" number="130" type="device" author="ANDROID" requires="VK_KHR_sampler_ycbcr_conversion,VK_KHR_external_memory,VK_EXT_queue_family_foreign,VK_KHR_dedicated_allocation" platform="android" contact="Jesse Hall @critsec" supported="vulkan">
<require>
- <enum value="3" name="VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION"/>
+ <enum value="5" name="VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_SPEC_VERSION"/>
<enum value="&quot;VK_ANDROID_external_memory_android_hardware_buffer&quot;" name="VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME"/>
<enum bitpos="10" extends="VkExternalMemoryHandleTypeFlagBits" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID"/>
@@ -11938,6 +15356,10 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkGetMemoryAndroidHardwareBufferANDROID"/>
<type name="AHardwareBuffer"/>
</require>
+ <require extension="VK_KHR_format_feature_flags2">
+ <type name="VkAndroidHardwareBufferFormatProperties2ANDROID"/>
+ <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_2_ANDROID"/>
+ </require>
</extension>
<extension name="VK_EXT_sampler_filter_minmax" number="131" type="device" author="NV" requires="VK_KHR_get_physical_device_properties2" contact="Jeff Bolz @jeffbolznv" supported="vulkan" promotedto="VK_VERSION_1_2">
<require>
@@ -11976,6 +15398,7 @@ typedef void <name>CAMetalLayer</name>;
<require>
<enum value="0" name="VK_AMD_EXTENSION_135_SPEC_VERSION"/>
<enum value="&quot;VK_AMD_extension_135&quot;" name="VK_AMD_EXTENSION_135_EXTENSION_NAME"/>
+ <enum bitpos="25" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_RESERVED_25_BIT_AMD"/>
</require>
</extension>
<extension name="VK_AMD_extension_136" number="136" author="AMD" contact="Mais Alnasser @malnasse" supported="disabled">
@@ -11996,15 +15419,15 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_AMD_shader_fragment_mask&quot;" name="VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_EXT_inline_uniform_block" number="139" type="device" author="EXT" requires="VK_KHR_get_physical_device_properties2,VK_KHR_maintenance1" contact="Daniel Rakos @aqnuep" supported="vulkan">
+ <extension name="VK_EXT_inline_uniform_block" number="139" type="device" author="EXT" requires="VK_KHR_get_physical_device_properties2,VK_KHR_maintenance1" contact="Daniel Rakos @aqnuep" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
- <enum value="1" name="VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_inline_uniform_block&quot;" name="VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME"/>
- <enum offset="0" extends="VkDescriptorType" name="VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT"/>
- <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT"/>
- <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT"/>
- <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT"/>
+ <enum value="1" name="VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_inline_uniform_block&quot;" name="VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME"/>
+ <enum extends="VkDescriptorType" name="VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT" alias="VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT" alias="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT" alias="VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO"/>
<type name="VkPhysicalDeviceInlineUniformBlockFeaturesEXT"/>
<type name="VkPhysicalDeviceInlineUniformBlockPropertiesEXT"/>
<type name="VkWriteDescriptorSetInlineUniformBlockEXT"/>
@@ -12064,7 +15487,11 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_KHR_relaxed_block_layout&quot;" name="VK_KHR_RELAXED_BLOCK_LAYOUT_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="RESERVED_DO_NOT_USE_146" number="146" supported="disabled" comment="Used for functionality subsumed into Vulkan 1.1 and not published as an extension">
+ <extension name="VK_RESERVED_do_not_use_146" number="146" supported="disabled" comment="Used for functionality subsumed into Vulkan 1.1 and not published as an extension">
+ <require>
+ <enum value="1" name="VK_RESERVED_DO_NOT_USE_146_SPEC_VERSION"/>
+ <enum value="&quot;VK_RESERVED_do_not_use_146&quot;" name="VK_RESERVED_DO_NOT_USE_146_EXTENSION_NAME"/>
+ </require>
</extension>
<extension name="VK_KHR_get_memory_requirements2" number="147" type="device" author="KHR" contact="Jason Ekstrand @jekstrand" supported="vulkan" promotedto="VK_VERSION_1_1">
<require>
@@ -12093,7 +15520,7 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkImageFormatListCreateInfoKHR"/>
</require>
</extension>
- <extension name="VK_EXT_blend_operation_advanced" number="149" type="device" author="NV" contact="Jeff Bolz @jeffbolznv" supported="vulkan">
+ <extension name="VK_EXT_blend_operation_advanced" number="149" type="device" author="NV" contact="Jeff Bolz @jeffbolznv" supported="vulkan" requires="VK_KHR_get_physical_device_properties2">
<require>
<enum value="2" name="VK_EXT_BLEND_OPERATION_ADVANCED_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_blend_operation_advanced&quot;" name="VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME"/>
@@ -12164,7 +15591,7 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_KHR_acceleration_structure" number="151" type="device" requiresCore="1.1" requires="VK_EXT_descriptor_indexing,VK_KHR_buffer_device_address,VK_KHR_deferred_host_operations" author="KHR" contact="Daniel Koch @dgkoch" supported="vulkan" sortorder="1">
<require>
- <enum value="11" name="VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION"/>
+ <enum value="13" name="VK_KHR_ACCELERATION_STRUCTURE_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_acceleration_structure&quot;" name="VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME"/>
<enum offset="7" extends="VkStructureType" name="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR"/>
@@ -12247,6 +15674,9 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkGetDeviceAccelerationStructureCompatibilityKHR"/>
<command name="vkGetAccelerationStructureBuildSizesKHR"/>
</require>
+ <require extension="VK_KHR_format_feature_flags2">
+ <enum bitpos="29" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_ACCELERATION_STRUCTURE_VERTEX_BUFFER_BIT_KHR"/>
+ </require>
</extension>
<extension name="VK_KHR_ray_tracing_pipeline" number="348" type="device" requiresCore="1.1" requires="VK_KHR_spirv_1_4,VK_KHR_acceleration_structure" author="KHR" contact="Daniel Koch @dgkoch" supported="vulkan" sortorder="1">
<require>
@@ -12438,33 +15868,32 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_EXT_image_drm_format_modifier" number="159" type="device" requires="VK_KHR_bind_memory2,VK_KHR_get_physical_device_properties2,VK_KHR_image_format_list,VK_KHR_sampler_ycbcr_conversion" author="EXT" contact="Chad Versace @chadversary" supported="vulkan">
<require>
- <enum value="1" name="VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION"/>
+ <enum value="2" name="VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_image_drm_format_modifier&quot;" name="VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME"/>
-
- <enum offset="0" dir="-" extends="VkResult" name="VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"/>
-
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT"/>
- <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT"/>
- <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT"/>
- <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT"/>
- <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT"/>
-
- <enum offset="0" extends="VkImageTiling" name="VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT"/>
-
- <enum bitpos="7" extends="VkImageAspectFlagBits" name="VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT"/>
- <enum bitpos="8" extends="VkImageAspectFlagBits" name="VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT"/>
- <enum bitpos="9" extends="VkImageAspectFlagBits" name="VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT"/>
- <enum bitpos="10" extends="VkImageAspectFlagBits" name="VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT"/>
-
+ <enum offset="0" dir="-" extends="VkResult" name="VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT"/>
+ <enum offset="0" extends="VkImageTiling" name="VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT"/>
+ <enum bitpos="7" extends="VkImageAspectFlagBits" name="VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT"/>
+ <enum bitpos="8" extends="VkImageAspectFlagBits" name="VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT"/>
+ <enum bitpos="9" extends="VkImageAspectFlagBits" name="VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT"/>
+ <enum bitpos="10" extends="VkImageAspectFlagBits" name="VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT"/>
<type name="VkDrmFormatModifierPropertiesListEXT"/>
<type name="VkDrmFormatModifierPropertiesEXT"/>
<type name="VkPhysicalDeviceImageDrmFormatModifierInfoEXT"/>
<type name="VkImageDrmFormatModifierListCreateInfoEXT"/>
<type name="VkImageDrmFormatModifierExplicitCreateInfoEXT"/>
<type name="VkImageDrmFormatModifierPropertiesEXT"/>
-
<command name="vkGetImageDrmFormatModifierPropertiesEXT"/>
</require>
+ <require extension="VK_KHR_format_feature_flags2">
+ <type name="VkDrmFormatModifierPropertiesList2EXT"/>
+ <type name="VkDrmFormatModifierProperties2EXT"/>
+ <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_2_EXT"/>
+ </require>
</extension>
<extension name="VK_EXT_extension_160" number="160" author="EXT" contact="Mark Young @marky-lunarg" supported="disabled">
<require>
@@ -12525,8 +15954,8 @@ typedef void <name>CAMetalLayer</name>;
<require>
<enum value="1" name="VK_KHR_PORTABILITY_SUBSET_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_portability_subset&quot;" name="VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR"/>
- <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
<type name="VkPhysicalDevicePortabilitySubsetFeaturesKHR"/>
<type name="VkPhysicalDevicePortabilitySubsetPropertiesKHR"/>
</require>
@@ -12538,11 +15967,11 @@ typedef void <name>CAMetalLayer</name>;
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SHADING_RATE_IMAGE_STATE_CREATE_INFO_NV"/>
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV"/>
<enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_PROPERTIES_NV"/>
- <enum offset="3" extends="VkImageLayout" name="VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV"/>
+ <enum extends="VkImageLayout" name="VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV" alias="VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR"/>
<enum offset="4" extends="VkDynamicState" name="VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV"/>
- <enum bitpos="23" extends="VkAccessFlagBits" name="VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV"/>
- <enum bitpos="8" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV"/>
- <enum bitpos="22" extends="VkPipelineStageFlagBits" name="VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV"/>
+ <enum extends="VkAccessFlagBits" name="VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV" alias="VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"/>
+ <enum extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV" alias="VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"/>
+ <enum extends="VkPipelineStageFlagBits" name="VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV" alias="VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"/>
<enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_COARSE_SAMPLE_ORDER_STATE_CREATE_INFO_NV"/>
<enum offset="6" extends="VkDynamicState" name="VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV"/>
<type name="VkShadingRatePaletteEntryNV"/>
@@ -12559,7 +15988,7 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkCmdSetCoarseSampleOrderNV"/>
</require>
</extension>
- <extension name="VK_NV_ray_tracing" number="166" type="device" requires="VK_KHR_get_physical_device_properties2,VK_KHR_get_memory_requirements2" author="NV" contact="Eric Werness @ewerness" supported="vulkan">
+ <extension name="VK_NV_ray_tracing" number="166" type="device" requires="VK_KHR_get_physical_device_properties2,VK_KHR_get_memory_requirements2" author="NV" contact="Eric Werness @ewerness-nv" supported="vulkan">
<require>
<enum value="3" name="VK_NV_RAY_TRACING_SPEC_VERSION"/>
<enum value="&quot;VK_NV_ray_tracing&quot;" name="VK_NV_RAY_TRACING_EXTENSION_NAME"/>
@@ -12667,14 +16096,16 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_NV_extension_168" number="168" author="NV" contact="Daniel Koch @dgkoch" supported="disabled">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_168_SPEC_VERSION"/>
- <enum value="&quot;VK_NV_extension_168&quot;" name="VK_EXT_EXTENSION_168_EXTENSION_NAME"/>
+ <enum value="0" name="VK_NV_EXTENSION_168_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_168&quot;" name="VK_NV_EXTENSION_168_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_KHR_maintenance3" number="169" type="device" requires="VK_KHR_get_physical_device_properties2" author="KHR" contact="Jeff Bolz @jeffbolznv" supported="vulkan" promotedto="VK_VERSION_1_1">
<require>
- <enum value="1" name="VK_KHR_MAINTENANCE3_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_maintenance3&quot;" name="VK_KHR_MAINTENANCE3_EXTENSION_NAME"/>
+ <enum value="1" name="VK_KHR_MAINTENANCE_3_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_maintenance3&quot;" name="VK_KHR_MAINTENANCE_3_EXTENSION_NAME"/>
+ <enum alias="VK_KHR_MAINTENANCE_3_SPEC_VERSION" name="VK_KHR_MAINTENANCE3_SPEC_VERSION" comment="Backwards-compatible alias containing a typo"/>
+ <enum alias="VK_KHR_MAINTENANCE_3_EXTENSION_NAME" name="VK_KHR_MAINTENANCE3_EXTENSION_NAME" comment="Backwards-compatible alias containing a typo"/>
<enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES"/>
<enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT_KHR" alias="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT"/>
<type name="VkPhysicalDeviceMaintenance3PropertiesKHR"/>
@@ -12694,8 +16125,8 @@ typedef void <name>CAMetalLayer</name>;
<require>
<enum value="3" name="VK_EXT_FILTER_CUBIC_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_filter_cubic&quot;" name="VK_EXT_FILTER_CUBIC_EXTENSION_NAME"/>
- <enum extends="VkFilter" name="VK_FILTER_CUBIC_EXT" alias="VK_FILTER_CUBIC_IMG"/>
- <enum extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT" alias="VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG"/>
+ <enum offset="0" extends="VkFilter" extnumber="16" name="VK_FILTER_CUBIC_EXT"/>
+ <enum bitpos="13" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT"/>
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT"/>
<type name="VkPhysicalDeviceImageViewImageFormatInfoEXT"/>
@@ -12712,8 +16143,8 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_QCOM_extension_173" number="173" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="disabled">
<require>
- <enum value="0" name="VK_QCOM_extension_173_SPEC_VERSION"/>
- <enum value="&quot;VK_QCOM_extension_173&quot;" name="VK_QCOM_extension_173_EXTENSION_NAME"/>
+ <enum value="0" name="VK_QCOM_EXTENSION_173_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_extension_173&quot;" name="VK_QCOM_EXTENSION_173_EXTENSION_NAME"/>
<enum bitpos="18" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_RESERVED_18_BIT_QCOM"/>
<enum bitpos="16" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_RESERVED_16_BIT_QCOM"/>
<enum bitpos="17" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_RESERVED_17_BIT_QCOM"/>
@@ -12721,16 +16152,16 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_QCOM_extension_174" number="174" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="disabled">
<require>
- <enum value="0" name="VK_QCOM_extension_174_SPEC_VERSION"/>
- <enum value="&quot;VK_QCOM_extension_174&quot;" name="VK_QCOM_extension_174_EXTENSION_NAME"/>
+ <enum value="0" name="VK_QCOM_EXTENSION_174_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_extension_174&quot;" name="VK_QCOM_EXTENSION_174_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_EXT_global_priority" number="175" type="device" author="EXT" contact="Andres Rodriguez @lostgoat" supported="vulkan">
+ <extension name="VK_EXT_global_priority" number="175" type="device" author="EXT" contact="Andres Rodriguez @lostgoat" supported="vulkan" promotedto="VK_KHR_global_priority">
<require>
<enum value="2" name="VK_EXT_GLOBAL_PRIORITY_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_global_priority&quot;" name="VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT"/>
- <enum offset="1" dir="-" extends="VkResult" name="VK_ERROR_NOT_PERMITTED_EXT"/>
+ <enum extends="VkStructureType" alias="VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR" name="VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT"/>
+ <enum extends="VkResult" alias="VK_ERROR_NOT_PERMITTED_KHR" name="VK_ERROR_NOT_PERMITTED_EXT"/>
<type name="VkDeviceQueueGlobalPriorityCreateInfoEXT"/>
<type name="VkQueueGlobalPriorityEXT"/>
</require>
@@ -12745,8 +16176,8 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_EXT_extension_177" number="177" author="EXT" contact="Neil Henning @sheredom" supported="disabled">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_177_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_177&quot;" name="VK_KHR_EXTENSION_177_EXTENSION_NAME"/>
+ <enum value="0" name="VK_EXT_EXTENSION_177_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_177&quot;" name="VK_EXT_EXTENSION_177_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_KHR_8bit_storage" number="178" type="device" requires="VK_KHR_get_physical_device_properties2,VK_KHR_storage_buffer_storage_class" author="KHR" contact="Alexander Galazin @alegal-arm" supported="vulkan" promotedto="VK_VERSION_1_2">
@@ -12797,8 +16228,8 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_AMD_extension_183" number="183" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_183_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_183&quot;" name="VK_KHR_EXTENSION_183_EXTENSION_NAME"/>
+ <enum value="0" name="VK_AMD_EXTENSION_183_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_183&quot;" name="VK_AMD_EXTENSION_183_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_AMD_pipeline_compiler_control" number="184" type="device" author="AMD" contact="Matthaeus G. Chajdas @anteru" supported="vulkan">
@@ -12811,9 +16242,9 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkPipelineCompilerControlCreateInfoAMD"/>
</require>
</extension>
- <extension name="VK_EXT_calibrated_timestamps" number="185" type="device" author="EXT" contact="Daniel Rakos @drakos-amd" supported="vulkan">
+ <extension name="VK_EXT_calibrated_timestamps" number="185" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Daniel Rakos @drakos-amd" supported="vulkan">
<require>
- <enum value="1" name="VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION"/>
+ <enum value="2" name="VK_EXT_CALIBRATED_TIMESTAMPS_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_calibrated_timestamps&quot;" name="VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_CALIBRATED_TIMESTAMP_INFO_EXT"/>
<type name="VkTimeDomainEXT"/>
@@ -12832,20 +16263,44 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_AMD_extension_187" number="187" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_187_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_187&quot;" name="VK_KHR_EXTENSION_187_EXTENSION_NAME"/>
+ <enum value="0" name="VK_AMD_EXTENSION_187_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_187&quot;" name="VK_AMD_EXTENSION_187_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_AMD_extension_188" number="188" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
+ <extension name="VK_EXT_video_decode_h265" number="188" type="device" requires="VK_KHR_video_decode_queue" author="KHR" contact="peter.fang@amd.com" provisional="true" platform="provisional" supported="vulkan">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_188_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_188&quot;" name="VK_KHR_EXTENSION_188_EXTENSION_NAME"/>
+ <enum value="3" name="VK_EXT_VIDEO_DECODE_H265_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_video_decode_h265&quot;" name="VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_CAPABILITIES_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_CREATE_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_SESSION_PARAMETERS_ADD_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PROFILE_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_PICTURE_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_DECODE_H265_DPB_SLOT_INFO_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="1" extends="VkVideoCodecOperationFlagBitsKHR" name="VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_EXT" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+
+ <type name="VkVideoDecodeH265ProfileEXT"/>
+ <type name="VkVideoDecodeH265CapabilitiesEXT"/>
+
+ <type name="VkVideoDecodeH265SessionParametersCreateInfoEXT"/>
+ <type name="VkVideoDecodeH265SessionParametersAddInfoEXT"/>
+ <type name="VkVideoDecodeH265PictureInfoEXT"/>
+ <type name="VkVideoDecodeH265DpbSlotInfoEXT"/>
</require>
</extension>
- <extension name="VK_AMD_extension_189" number="189" author="AMD" contact="Daniel Rakos @drakos-amd" supported="disabled">
+ <extension name="VK_KHR_global_priority" number="189" type="device" author="KHR" contact="Tobias Hector @tobski" supported="vulkan">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_189_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_189&quot;" name="VK_KHR_EXTENSION_189_EXTENSION_NAME"/>
+ <enum value="1" name="VK_KHR_GLOBAL_PRIORITY_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_global_priority&quot;" name="VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" extnumber="175" name="VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR"/>
+ <enum offset="0" extends="VkStructureType" extnumber="389" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR"/>
+ <enum offset="1" extends="VkStructureType" extnumber="389" name="VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR"/>
+ <enum extends="VkResult" extnumber="175" offset="1" dir="-" name="VK_ERROR_NOT_PERMITTED_KHR"/>
+ <enum name="VK_MAX_GLOBAL_PRIORITY_SIZE_KHR"/>
+ <type name="VkDeviceQueueGlobalPriorityCreateInfoKHR"/>
+ <type name="VkQueueGlobalPriorityKHR"/>
+ <type name="VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR"/>
+ <type name="VkQueueFamilyGlobalPriorityPropertiesKHR"/>
</require>
</extension>
<extension name="VK_AMD_memory_overallocation_behavior" number="190" type="device" author="AMD" contact="Martin Dinkov @mdinkov" supported="vulkan">
@@ -12878,11 +16333,11 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkPresentFrameTokenGGP"/>
</require>
</extension>
- <extension name="VK_EXT_pipeline_creation_feedback" number="193" type="device" author="GOOGLE" contact="Jean-Francois Roy @jfroy" specialuse="devtools" supported="vulkan">
+ <extension name="VK_EXT_pipeline_creation_feedback" number="193" type="device" author="GOOGLE" contact="Jean-Francois Roy @jfroy" specialuse="devtools" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
- <enum value="1" name="VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION"/>
+ <enum value="1" name="VK_EXT_PIPELINE_CREATION_FEEDBACK_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_pipeline_creation_feedback&quot;" name="VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT" alias="VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO"/>
<type name="VkPipelineCreationFeedbackFlagBitsEXT"/>
<type name="VkPipelineCreationFeedbackFlagsEXT"/>
<type name="VkPipelineCreationFeedbackCreateInfoEXT"/>
@@ -13002,11 +16457,11 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkDrawMeshTasksIndirectCommandNV"/>
</require>
</extension>
- <extension name="VK_NV_fragment_shader_barycentric" number="204" type="device" requires="VK_KHR_get_physical_device_properties2" author="NV" contact="Pat Brown @nvpbrown" supported="vulkan">
+ <extension name="VK_NV_fragment_shader_barycentric" number="204" type="device" requires="VK_KHR_get_physical_device_properties2" author="NV" contact="Pat Brown @nvpbrown" supported="vulkan" promotedto="VK_KHR_fragment_shader_barycentric">
<require>
<enum value="1" name="VK_NV_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION"/>
<enum value="&quot;VK_NV_fragment_shader_barycentric&quot;" name="VK_NV_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_NV" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR"/>
<type name="VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV"/>
</require>
</extension>
@@ -13088,7 +16543,7 @@ typedef void <name>CAMetalLayer</name>;
<enum value="2" name="VK_INTEL_PERFORMANCE_QUERY_SPEC_VERSION"/>
<enum value="&quot;VK_INTEL_performance_query&quot;" name="VK_INTEL_PERFORMANCE_QUERY_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL"/>
- <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL" alias="VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL" comment="Backwards-compatible alias"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO_INTEL" alias="VK_STRUCTURE_TYPE_QUERY_POOL_PERFORMANCE_QUERY_CREATE_INFO_INTEL" comment="Backwards-compatible alias containing a typo"/>
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_INITIALIZE_PERFORMANCE_API_INFO_INTEL"/>
<enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PERFORMANCE_MARKER_INFO_INTEL"/>
<enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PERFORMANCE_STREAM_MARKER_INFO_INTEL"/>
@@ -13160,18 +16615,18 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkCreateImagePipeSurfaceFUCHSIA"/>
</require>
</extension>
- <extension name="VK_KHR_shader_terminate_invocation" number="216" type="device" author="KHR" requires="VK_KHR_get_physical_device_properties2" contact="Jesse Hall @critsec" supported="vulkan">
+ <extension name="VK_KHR_shader_terminate_invocation" number="216" type="device" author="KHR" requires="VK_KHR_get_physical_device_properties2" contact="Jesse Hall @critsec" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
<enum value="1" name="VK_KHR_SHADER_TERMINATE_INVOCATION_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_shader_terminate_invocation&quot;" name="VK_KHR_SHADER_TERMINATE_INVOCATION_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES"/>
<type name="VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR"/>
</require>
</extension>
<extension name="VK_GOOGLE_extension_217" number="217" author="GOOGLE" contact="Jesse Hall @critsec" supported="disabled">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_217_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_217&quot;" name="VK_KHR_EXTENSION_217_EXTENSION_NAME"/>
+ <enum value="0" name="VK_GOOGLE_EXTENSION_217_SPEC_VERSION"/>
+ <enum value="&quot;VK_GOOGLE_extension_217&quot;" name="VK_GOOGLE_EXTENSION_217_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_EXT_metal_surface" number="218" type="instance" requires="VK_KHR_surface" platform="metal" supported="vulkan" author="EXT" contact="Dzmitry Malyshau @kvark">
@@ -13187,7 +16642,7 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_EXT_fragment_density_map" number="219" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Matthew Netsch @mnetsch" supported="vulkan">
<require>
- <enum value="1" name="VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION"/>
+ <enum value="2" name="VK_EXT_FRAGMENT_DENSITY_MAP_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_fragment_density_map&quot;" name="VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT"/>
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT"/>
@@ -13205,6 +16660,9 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkPhysicalDeviceFragmentDensityMapPropertiesEXT"/>
<type name="VkRenderPassFragmentDensityMapCreateInfoEXT"/>
</require>
+ <require extension="VK_KHR_format_feature_flags2">
+ <enum bitpos="24" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_FRAGMENT_DENSITY_MAP_BIT_EXT"/>
+ </require>
</extension>
<extension name="VK_EXT_extension_220" number="220" author="EXT" contact="Dzmitry Malyshau @kvark" supported="disabled">
<require>
@@ -13235,8 +16693,10 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_GOOGLE_hlsl_functionality1" number="224" type="device" author="GOOGLE" contact="Hai Nguyen @chaoticbob" supported="vulkan">
<require>
- <enum value="1" name="VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION"/>
- <enum value="&quot;VK_GOOGLE_hlsl_functionality1&quot;" name="VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME"/>
+ <enum value="1" name="VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION"/>
+ <enum value="&quot;VK_GOOGLE_hlsl_functionality1&quot;" name="VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME"/>
+ <enum alias="VK_GOOGLE_HLSL_FUNCTIONALITY_1_SPEC_VERSION" name="VK_GOOGLE_HLSL_FUNCTIONALITY1_SPEC_VERSION" comment="Backwards-compatible alias containing a typo"/>
+ <enum alias="VK_GOOGLE_HLSL_FUNCTIONALITY_1_EXTENSION_NAME" name="VK_GOOGLE_HLSL_FUNCTIONALITY1_EXTENSION_NAME" comment="Backwards-compatible alias containing a typo"/>
</require>
</extension>
<extension name="VK_GOOGLE_decorate_string" number="225" type="device" author="GOOGLE" contact="Hai Nguyen @chaoticbob" supported="vulkan">
@@ -13245,23 +16705,23 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_GOOGLE_decorate_string&quot;" name="VK_GOOGLE_DECORATE_STRING_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_EXT_subgroup_size_control" number="226" type="device" requiresCore="1.1" author="EXT" contact="Neil Henning @sheredom" supported="vulkan">
+ <extension name="VK_EXT_subgroup_size_control" number="226" type="device" requiresCore="1.1" author="EXT" contact="Neil Henning @sheredom" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
- <enum value="2" name="VK_EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_subgroup_size_control&quot;" name="VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME"/>
- <type name="VkPhysicalDeviceSubgroupSizeControlFeaturesEXT"/>
- <type name="VkPhysicalDeviceSubgroupSizeControlPropertiesEXT"/>
- <type name="VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT"/>
- <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT"/>
- <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT"/>
- <enum bitpos="0" extends="VkPipelineShaderStageCreateFlagBits" name="VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT"/>
- <enum bitpos="1" extends="VkPipelineShaderStageCreateFlagBits" name="VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT"/>
+ <enum value="2" name="VK_EXT_SUBGROUP_SIZE_CONTROL_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_subgroup_size_control&quot;" name="VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME"/>
+ <type name="VkPhysicalDeviceSubgroupSizeControlFeaturesEXT"/>
+ <type name="VkPhysicalDeviceSubgroupSizeControlPropertiesEXT"/>
+ <type name="VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT" alias="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES"/>
+ <enum extends="VkPipelineShaderStageCreateFlagBits" name="VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT" alias="VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT"/>
+ <enum extends="VkPipelineShaderStageCreateFlagBits" name="VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT" alias="VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT"/>
</require>
</extension>
<extension name="VK_KHR_fragment_shading_rate" number="227" type="device" requires="VK_KHR_create_renderpass2,VK_KHR_get_physical_device_properties2" author="KHR" contact="Tobias Hector @tobski" supported="vulkan">
<require>
- <enum value="1" name="VK_KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION"/>
+ <enum value="2" name="VK_KHR_FRAGMENT_SHADING_RATE_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_fragment_shading_rate&quot;" name="VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME"/>
<type name="VkFragmentShadingRateCombinerOpKHR"/>
<type name="VkFragmentShadingRateAttachmentInfoKHR"/>
@@ -13271,17 +16731,20 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkPhysicalDeviceFragmentShadingRateKHR"/>
<command name="vkGetPhysicalDeviceFragmentShadingRatesKHR"/>
<command name="vkCmdSetFragmentShadingRateKHR"/>
- <enum extends="VkImageLayout" name="VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR" alias="VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV"/>
+ <enum offset="3" extends="VkImageLayout" extnumber="165" name="VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR"/>
<enum offset="0" extends="VkDynamicState" name="VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR"/>
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR"/>
<enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR"/>
<enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR"/>
<enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR"/>
- <enum extends="VkAccessFlagBits" name="VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR" alias="VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV"/>
- <enum extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR" alias="VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV"/>
- <enum extends="VkPipelineStageFlagBits" name="VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR" alias="VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV"/>
- <enum bitpos="30" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"/>
+ <enum bitpos="23" extends="VkAccessFlagBits" name="VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"/>
+ <enum bitpos="8" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"/>
+ <enum bitpos="22" extends="VkPipelineStageFlagBits" name="VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"/>
+ <enum bitpos="30" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"/>
+ </require>
+ <require extension="VK_KHR_format_feature_flags2">
+ <enum bitpos="30" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"/>
</require>
</extension>
<extension name="VK_AMD_shader_core_properties2" number="228" type="device" author="AMD" contact="Matthaeus G. Chajdas @anteru" supported="vulkan" requires="VK_AMD_shader_core_properties">
@@ -13434,25 +16897,25 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkGetBufferDeviceAddressEXT"/>
</require>
</extension>
- <extension name="VK_EXT_tooling_info" number="246" type="device" author="EXT" contact="Tobias Hector @tobski" supported="vulkan">
+ <extension name="VK_EXT_tooling_info" number="246" type="device" author="EXT" contact="Tobias Hector @tobski" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
<enum value="1" name="VK_EXT_TOOLING_INFO_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_tooling_info&quot;" name="VK_EXT_TOOLING_INFO_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES"/>
<type name="VkToolPurposeFlagBitsEXT"/>
<type name="VkToolPurposeFlagsEXT"/>
<type name="VkPhysicalDeviceToolPropertiesEXT"/>
<command name="vkGetPhysicalDeviceToolPropertiesEXT"/>
</require>
<require extension="VK_EXT_debug_report">
- <enum bitpos="5" extends="VkToolPurposeFlagBitsEXT" name="VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT"/>
+ <enum bitpos="5" extends="VkToolPurposeFlagBits" name="VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT"/>
</require>
<require extension="VK_EXT_debug_marker">
- <enum bitpos="6" extends="VkToolPurposeFlagBitsEXT" name="VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT"/>
+ <enum bitpos="6" extends="VkToolPurposeFlagBits" name="VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT"/>
</require>
<require extension="VK_EXT_debug_utils">
- <enum bitpos="5" extends="VkToolPurposeFlagBitsEXT" name="VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT"/>
- <enum bitpos="6" extends="VkToolPurposeFlagBitsEXT" name="VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT"/>
+ <enum bitpos="5" extends="VkToolPurposeFlagBits" name="VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT"/>
+ <enum bitpos="6" extends="VkToolPurposeFlagBits" name="VK_TOOL_PURPOSE_DEBUG_MARKERS_BIT_EXT"/>
</require>
</extension>
<extension name="VK_EXT_separate_stencil_usage" number="247" type="device" author="EXT" contact="Daniel Rakos @drakos-amd" supported="vulkan" promotedto="VK_VERSION_1_2">
@@ -13465,7 +16928,7 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_EXT_validation_features" number="248" type="instance" author="LUNARG" contact="Karl Schultz @karl-lunarg" specialuse="debugging" supported="vulkan">
<require>
- <enum value="4" name="VK_EXT_VALIDATION_FEATURES_SPEC_VERSION"/>
+ <enum value="5" name="VK_EXT_VALIDATION_FEATURES_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_validation_features&quot;" name="VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT"/>
<type name="VkValidationFeaturesEXT"/>
@@ -13473,10 +16936,13 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkValidationFeatureDisableEXT"/>
</require>
</extension>
- <extension name="VK_KHR_extension_249" number="249" author="KHR" contact="Keith Packard @keithp" supported="disabled">
+ <extension name="VK_KHR_present_wait" number="249" type="device" requires="VK_KHR_swapchain,VK_KHR_present_id" author="KHR" contact="Keith Packard @keithp" supported="vulkan">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_249_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_249&quot;" name="VK_KHR_EXTENSION_249_EXTENSION_NAME"/>
+ <enum value="1" name="VK_KHR_PRESENT_WAIT_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_present_wait&quot;" name="VK_KHR_PRESENT_WAIT_EXTENSION_NAME"/>
+ <command name="vkWaitForPresentKHR"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_WAIT_FEATURES_KHR"/>
+ <type name="VkPhysicalDevicePresentWaitFeaturesKHR"/>
</require>
</extension>
<extension name="VK_NV_cooperative_matrix" number="250" type="device" requires="VK_KHR_get_physical_device_properties2" author="NV" contact="Jeff Bolz @jeffbolznv" supported="vulkan">
@@ -13533,10 +16999,17 @@ typedef void <name>CAMetalLayer</name>;
<enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES"/>
</require>
</extension>
- <extension name="VK_EXT_extension_255" number="255" author="EXT" contact="Jesse Hall @jessehall" supported="disabled">
+ <extension name="VK_EXT_provoking_vertex" number="255" type="device" author="EXT" requires="VK_KHR_get_physical_device_properties2" contact="Jesse Hall @jessehall" specialuse="glemulation" supported="vulkan">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_255_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_255&quot;" name="VK_EXT_EXTENSION_255_EXTENSION_NAME"/>
+ <enum value="1" name="VK_EXT_PROVOKING_VERTEX_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_provoking_vertex&quot;" name="VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT"/>
+ <type name="VkPhysicalDeviceProvokingVertexFeaturesEXT"/>
+ <type name="VkPhysicalDeviceProvokingVertexPropertiesEXT"/>
+ <type name="VkPipelineRasterizationProvokingVertexStateCreateInfoEXT"/>
+ <type name="VkProvokingVertexModeEXT"/>
</require>
</extension>
<extension name="VK_EXT_full_screen_exclusive" number="256" type="device" author="EXT" requires="VK_KHR_get_physical_device_properties2,VK_KHR_surface,VK_KHR_get_surface_capabilities2,VK_KHR_swapchain" platform="win32" contact="James Jones @cubanismo" supported="vulkan">
@@ -13602,6 +17075,10 @@ typedef void <name>CAMetalLayer</name>;
<require>
<enum value="0" name="VK_EXT_EXTENSION_259_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_extension_259&quot;" name="VK_EXT_EXTENSION_259_EXTENSION_NAME"/>
+ <enum bitpos="9" extends="VkQueueFlagBits" name="VK_QUEUE_RESERVED_9_BIT_EXT"/>
+ <enum bitpos="44" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_RESERVED_44_BIT_EXT"/>
+ <enum bitpos="45" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_RESERVED_45_BIT_EXT"/>
+ <enum bitpos="19" extends="VkImageCreateFlagBits" name="VK_IMAGE_CREATE_RESERVED_19_BIT_EXT"/>
</require>
</extension>
<extension name="VK_EXT_line_rasterization" number="260" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Jeff Bolz @jeffbolznv" specialuse="cadsupport" supported="vulkan">
@@ -13638,8 +17115,8 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_GGP_extension_263" number="263" author="GGP" contact="Jean-Francois Roy @jfroy" supported="disabled">
<require>
- <enum value="0" name="VK_GOOGLE_EXTENSION_263_SPEC_VERSION"/>
- <enum value="&quot;VK_GGP_extension_263&quot;" name="VK_GOOGLE_EXTENSION_263_EXTENSION_NAME"/>
+ <enum value="0" name="VK_GGP_EXTENSION_263_SPEC_VERSION"/>
+ <enum value="&quot;VK_GGP_extension_263&quot;" name="VK_GGP_EXTENSION_263_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_BRCM_extension_264" number="264" author="BRCM" contact="Graeme Leese @gnl21" supported="disabled">
@@ -13666,27 +17143,27 @@ typedef void <name>CAMetalLayer</name>;
<extension name="VK_EXT_extension_267" number="267" type="device" author="EXT" contact="Piers Daniell @pdaniell-nv" supported="disabled">
<require>
<enum value="0" name="VK_EXT_EXTENSION_267_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_267&quot;" name="VK_EXT_extension_267"/>
+ <enum value="&quot;VK_EXT_extension_267&quot;" name="VK_EXT_EXTENSION_267_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_EXT_extended_dynamic_state" number="268" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Piers Daniell @pdaniell-nv" supported="vulkan">
+ <extension name="VK_EXT_extended_dynamic_state" number="268" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Piers Daniell @pdaniell-nv" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
<enum value="1" name="VK_EXT_EXTENDED_DYNAMIC_STATE_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_extended_dynamic_state&quot;" name="VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT"/>
- <enum offset="0" extends="VkDynamicState" name="VK_DYNAMIC_STATE_CULL_MODE_EXT"/>
- <enum offset="1" extends="VkDynamicState" name="VK_DYNAMIC_STATE_FRONT_FACE_EXT"/>
- <enum offset="2" extends="VkDynamicState" name="VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT"/>
- <enum offset="3" extends="VkDynamicState" name="VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT"/>
- <enum offset="4" extends="VkDynamicState" name="VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT"/>
- <enum offset="5" extends="VkDynamicState" name="VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT"/>
- <enum offset="6" extends="VkDynamicState" name="VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT"/>
- <enum offset="7" extends="VkDynamicState" name="VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT"/>
- <enum offset="8" extends="VkDynamicState" name="VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT"/>
- <enum offset="9" extends="VkDynamicState" name="VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT"/>
- <enum offset="10" extends="VkDynamicState" name="VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT"/>
- <enum offset="11" extends="VkDynamicState" name="VK_DYNAMIC_STATE_STENCIL_OP_EXT"/>
- <type name="VkPhysicalDeviceExtendedDynamicStateFeaturesEXT"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT" comment="Not promoted to 1.3"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_CULL_MODE_EXT" alias="VK_DYNAMIC_STATE_CULL_MODE"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_FRONT_FACE_EXT" alias="VK_DYNAMIC_STATE_FRONT_FACE"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT" alias="VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT" alias="VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT" alias="VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT" alias="VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT" alias="VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT" alias="VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT" alias="VK_DYNAMIC_STATE_DEPTH_COMPARE_OP"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT" alias="VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT" alias="VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_STENCIL_OP_EXT" alias="VK_DYNAMIC_STATE_STENCIL_OP"/>
+ <type name="VkPhysicalDeviceExtendedDynamicStateFeaturesEXT" comment="Not promoted to 1.3"/>
<command name="vkCmdSetCullModeEXT"/>
<command name="vkCmdSetFrontFaceEXT"/>
<command name="vkCmdSetPrimitiveTopologyEXT"/>
@@ -13699,8 +17176,8 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkCmdSetDepthBoundsTestEnableEXT"/>
<command name="vkCmdSetStencilTestEnableEXT"/>
<command name="vkCmdSetStencilOpEXT"/>
- </require>
- </extension>
+ </require>
+ </extension>
<extension name="VK_KHR_deferred_host_operations" number="269" type="device" author="KHR" contact="Josh Barczak @jbarczak" supported="vulkan">
<require>
<enum value="4" name="VK_KHR_DEFERRED_HOST_OPERATIONS_SPEC_VERSION"/>
@@ -13746,49 +17223,56 @@ typedef void <name>CAMetalLayer</name>;
<extension name="VK_INTEL_extension_271" number="271" type="device" author="INTEL" contact="Jason Ekstrand @jekstrand" supported="disabled">
<require>
<enum value="0" name="VK_INTEL_EXTENSION_271_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_271&quot;" name="VK_INTEL_extension_271"/>
+ <enum value="&quot;VK_INTEL_extension_271&quot;" name="VK_INTEL_EXTENSION_271_EXTENSION_NAME"/>
+ <enum bitpos="22" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_RESERVED_22_BIT_EXT"/>
</require>
</extension>
<extension name="VK_INTEL_extension_272" number="272" type="device" author="INTEL" contact="Jason Ekstrand @jekstrand" supported="disabled">
<require>
<enum value="0" name="VK_INTEL_EXTENSION_272_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_272&quot;" name="VK_INTEL_extension_272"/>
+ <enum value="&quot;VK_INTEL_extension_272&quot;" name="VK_INTEL_EXTENSION_272_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_INTEL_extension_273" number="273" type="device" author="INTEL" contact="Jason Ekstrand @jekstrand" supported="disabled">
<require>
<enum value="0" name="VK_INTEL_EXTENSION_273_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_273&quot;" name="VK_INTEL_extension_273"/>
+ <enum value="&quot;VK_INTEL_extension_273&quot;" name="VK_INTEL_EXTENSION_273_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_INTEL_extension_274" number="274" type="device" author="INTEL" contact="Jason Ekstrand @jekstrand" supported="disabled">
+ <extension name="VK_EXT_shader_atomic_float2" number="274" type="device" requires="VK_EXT_shader_atomic_float" author="EXT" contact="Jason Ekstrand @jekstrand" supported="vulkan">
<require>
- <enum value="0" name="VK_INTEL_EXTENSION_274_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_274&quot;" name="VK_INTEL_extension_274"/>
+ <enum value="1" name="VK_EXT_SHADER_ATOMIC_FLOAT_2_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_shader_atomic_float2&quot;" name="VK_EXT_SHADER_ATOMIC_FLOAT_2_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_2_FEATURES_EXT"/>
+ <type name="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT"/>
</require>
</extension>
<extension name="VK_KHR_extension_275" number="275" type="instance" author="KHR" contact="Lionel Landwerlin @llandwerlin" supported="disabled">
<require>
<enum value="0" name="VK_KHR_EXTENSION_275_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_275&quot;" name="VK_KHR_extension_275"/>
+ <enum value="&quot;VK_KHR_extension_275&quot;" name="VK_KHR_EXTENSION_275_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_KHR_extension_276" number="276" type="device" author="KHR" contact="James Jones @cubanismo" supported="disabled">
<require>
<enum value="0" name="VK_KHR_EXTENSION_276_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_276&quot;" name="VK_KHR_extension_276"/>
+ <enum value="&quot;VK_KHR_extension_276&quot;" name="VK_KHR_EXTENSION_276_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_EXT_shader_demote_to_helper_invocation" number="277" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Jeff Bolz @jeffbolznv" supported="vulkan">
+ <extension name="VK_EXT_shader_demote_to_helper_invocation" number="277" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Jeff Bolz @jeffbolznv" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
<enum value="1" name="VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_shader_demote_to_helper_invocation&quot;" name="VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES"/>
<type name="VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT"/>
</require>
</extension>
- <extension name="VK_NV_device_generated_commands" number="278" type="device" requiresCore="1.1" author="NV" contact="Christoph Kubisch @pixeljetstream" supported="vulkan">
+ <extension name="VK_NV_device_generated_commands" number="278" type="device" requiresCore="1.1" requires="VK_KHR_buffer_device_address" author="NV" contact="Christoph Kubisch @pixeljetstream" supported="vulkan">
<require>
+ <comment>
+ This extension requires buffer_device_address functionality.
+ VK_EXT_buffer_device_address is also acceptable, but since it is deprecated the KHR version is preferred.
+ </comment>
<enum value="3" name="VK_NV_DEVICE_GENERATED_COMMANDS_SPEC_VERSION"/>
<enum value="&quot;VK_NV_device_generated_commands&quot;" name="VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_NV"/>
@@ -13831,37 +17315,45 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkDestroyIndirectCommandsLayoutNV"/>
</require>
</extension>
- <extension name="VK_NV_extension_279" number="279" type="device" author="NV" contact="Christoph Kubisch @pixeljetstream" supported="disabled">
+ <extension name="VK_NV_inherited_viewport_scissor" number="279" type="device" author="NV" contact="David Zhao Akeley @akeley98" supported="vulkan">
<require>
- <enum value="0" name="VK_NV_EXTENSION_279_SPEC_VERSION"/>
- <enum value="&quot;VK_NV_extension_279&quot;" name="VK_NV_extension_279"/>
+ <enum value="1" name="VK_NV_INHERITED_VIEWPORT_SCISSOR_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_inherited_viewport_scissor&quot;" name="VK_NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INHERITED_VIEWPORT_SCISSOR_FEATURES_NV"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_VIEWPORT_SCISSOR_INFO_NV"/>
+ <type name="VkPhysicalDeviceInheritedViewportScissorFeaturesNV"/>
+ <type name="VkCommandBufferInheritanceViewportScissorInfoNV"/>
</require>
</extension>
<extension name="VK_KHR_extension_280" number="280" type="device" author="KHR" contact="Kevin Petit @kevinpetit" supported="disabled">
<require>
<enum value="0" name="VK_KHR_EXTENSION_280_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_280&quot;" name="VK_KHR_extension_280"/>
+ <enum value="&quot;VK_KHR_extension_280&quot;" name="VK_KHR_EXTENSION_280_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_ARM_extension_281" number="281" type="device" author="ARM" contact="Kevin Petit @kevinpetit" supported="disabled">
+ <extension name="VK_KHR_shader_integer_dot_product" number="281" type="device" author="KHR" requires="VK_KHR_get_physical_device_properties2" contact="Kevin Petit @kevinpetit" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
- <enum value="0" name="VK_ARM_EXTENSION_281_SPEC_VERSION"/>
- <enum value="&quot;VK_ARM_extension_281&quot;" name="VK_ARM_extension_281"/>
+ <enum value="1" name="VK_KHR_SHADER_INTEGER_DOT_PRODUCT_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_shader_integer_dot_product&quot;" name="VK_KHR_SHADER_INTEGER_DOT_PRODUCT_EXTENSION_NAME"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES"/>
+ <type name="VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR"/>
+ <type name="VkPhysicalDeviceShaderIntegerDotProductPropertiesKHR"/>
</require>
</extension>
- <extension name="VK_EXT_texel_buffer_alignment" number="282" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Jeff Bolz @jeffbolznv" supported="vulkan">
+ <extension name="VK_EXT_texel_buffer_alignment" number="282" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Jeff Bolz @jeffbolznv" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
<enum value="1" name="VK_EXT_TEXEL_BUFFER_ALIGNMENT_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_texel_buffer_alignment&quot;" name="VK_EXT_TEXEL_BUFFER_ALIGNMENT_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT"/>
- <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT"/>
- <type name="VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT" comment="Not promoted to 1.3"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES"/>
+ <type name="VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT" comment="Not promoted to 1.3"/>
<type name="VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT"/>
</require>
</extension>
<extension name="VK_QCOM_render_pass_transform" number="283" type="device" requires="VK_KHR_swapchain,VK_KHR_surface" author="QCOM" contact="Jeff Leger @jackohound" supported="vulkan">
<require>
- <enum value="1" name="VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION"/>
+ <enum value="3" name="VK_QCOM_RENDER_PASS_TRANSFORM_SPEC_VERSION"/>
<enum value="&quot;VK_QCOM_render_pass_transform&quot;" name="VK_QCOM_RENDER_PASS_TRANSFORM_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDER_PASS_TRANSFORM_INFO_QCOM"/>
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_RENDER_PASS_TRANSFORM_BEGIN_INFO_QCOM"/>
@@ -13873,12 +17365,12 @@ typedef void <name>CAMetalLayer</name>;
<extension name="VK_EXT_extension_284" number="284" type="device" author="EXT" contact="Samuel Pitoiset @hakzsam" supported="disabled">
<require>
<enum value="0" name="VK_EXT_EXTENSION_284_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_284&quot;" name="VK_EXT_extension_284"/>
+ <enum value="&quot;VK_EXT_extension_284&quot;" name="VK_EXT_EXTENSION_284_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_EXT_device_memory_report" number="285" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Yiwei Zhang @zhangyiwei" specialuse="devtools" supported="vulkan">
<require>
- <enum value="1" name="VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION"/>
+ <enum value="2" name="VK_EXT_DEVICE_MEMORY_REPORT_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_device_memory_report&quot;" name="VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_MEMORY_REPORT_FEATURES_EXT"/>
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_DEVICE_MEMORY_REPORT_CREATE_INFO_EXT"/>
@@ -13891,10 +17383,12 @@ typedef void <name>CAMetalLayer</name>;
<type name="PFN_vkDeviceMemoryReportCallbackEXT"/>
</require>
</extension>
- <extension name="VK_EXT_extension_286" number="286" type="instance" author="EXT" contact="Drew DeVault sir@cmpwn.com" supported="disabled">
+ <extension name="VK_EXT_acquire_drm_display" number="286" type="instance" requires="VK_EXT_direct_mode_display" author="EXT" contact="Drew DeVault sir@cmpwn.com" supported="vulkan">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_286_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_286&quot;" name="VK_EXT_extension_286"/>
+ <enum value="1" name="VK_EXT_ACQUIRE_DRM_DISPLAY_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_acquire_drm_display&quot;" name="VK_EXT_ACQUIRE_DRM_DISPLAY_EXTENSION_NAME"/>
+ <command name="vkAcquireDrmDisplayEXT"/>
+ <command name="vkGetDrmDisplayEXT"/>
</require>
</extension>
<extension name="VK_EXT_robustness2" number="287" type="device" author="EXT" contact="Liam Middlebrook @liam-middlebrook" supported="vulkan">
@@ -13907,7 +17401,7 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkPhysicalDeviceRobustness2PropertiesEXT"/>
</require>
</extension>
- <extension name="VK_EXT_custom_border_color" number="288" type="device" author="EXT" contact="Liam Middlebrook @liam-middlebrook" supported="vulkan">
+ <extension name="VK_EXT_custom_border_color" number="288" type="device" author="EXT" contact="Liam Middlebrook @liam-middlebrook" specialuse="glemulation,d3demulation" supported="vulkan">
<require>
<enum value="12" name="VK_EXT_CUSTOM_BORDER_COLOR_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_custom_border_color&quot;" name="VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME"/>
@@ -13989,32 +17483,35 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_NV_extension_293&quot;" name="VK_NV_EXTENSION_293_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_KHR_shader_non_semantic_info" number="294" type="device" author="KHR" contact="Baldur Karlsson @baldurk" supported="vulkan">
+ <extension name="VK_KHR_shader_non_semantic_info" number="294" type="device" author="KHR" contact="Baldur Karlsson @baldurk" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
<enum value="1" name="VK_KHR_SHADER_NON_SEMANTIC_INFO_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_shader_non_semantic_info&quot;" name="VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_KHR_extension_295" number="295" author="KHR" contact="Keith Packard @keithp" supported="disabled">
+ <extension name="VK_KHR_present_id" number="295" type="device" requires="VK_KHR_swapchain" author="KHR" contact="Keith Packard @keithp" supported="vulkan">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_295_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_295&quot;" name="VK_KHR_EXTENSION_295_EXTENSION_NAME"/>
+ <enum value="1" name="VK_KHR_PRESENT_ID_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_present_id&quot;" name="VK_KHR_PRESENT_ID_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PRESENT_ID_KHR"/>
+ <type name="VkPresentIdKHR"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR"/>
+ <type name="VkPhysicalDevicePresentIdFeaturesKHR"/>
</require>
</extension>
- <extension name="VK_EXT_private_data" number="296" type="device" author="NV" contact="Matthew Rusch @mattruschnv" supported="vulkan">
+ <extension name="VK_EXT_private_data" number="296" type="device" author="NV" contact="Matthew Rusch @mattruschnv" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
<enum value="1" name="VK_EXT_PRIVATE_DATA_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_private_data&quot;" name="VK_EXT_PRIVATE_DATA_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT"/>
- <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT"/>
- <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT"/>
- <enum offset="0" extends="VkObjectType" name="VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT" alias="VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT" alias="VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO"/>
+ <enum extends="VkObjectType" name="VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT" alias="VK_OBJECT_TYPE_PRIVATE_DATA_SLOT"/>
<type name="VkPhysicalDevicePrivateDataFeaturesEXT"/>
<type name="VkDevicePrivateDataCreateInfoEXT"/>
<type name="VkPrivateDataSlotCreateInfoEXT"/>
<type name="VkPrivateDataSlotEXT"/>
- <type name="VkPrivateDataSlotCreateFlagsEXT"/>
- <type name="VkPrivateDataSlotCreateFlagBitsEXT"/>
+ <type name="VkPrivateDataSlotCreateFlagsEXT" comment="Will add VkPrivateDataSlotCreateFlagBits when bits are defined in the future"/>
<command name="vkCreatePrivateDataSlotEXT"/>
<command name="vkDestroyPrivateDataSlotEXT"/>
<command name="vkSetPrivateDataEXT"/>
@@ -14028,39 +17525,79 @@ typedef void <name>CAMetalLayer</name>;
<enum bitpos="3" extends="VkPipelineShaderStageCreateFlagBits" name="VK_PIPELINE_SHADER_STAGE_CREATE_RESERVED_3_BIT_KHR"/>
</require>
</extension>
- <extension name="VK_EXT_pipeline_creation_cache_control" number="298" type="device" author="AMD" contact="Gregory Grebe @grgrebe_amd" supported="vulkan">
+ <extension name="VK_EXT_pipeline_creation_cache_control" number="298" type="device" author="AMD" contact="Gregory Grebe @grgrebe_amd" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
- <enum value="3" name="VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_pipeline_creation_cache_control&quot;"
- name="VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType"
- name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT"/>
+ <enum value="3" name="VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_pipeline_creation_cache_control&quot;" name="VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES"/>
<type name="VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT"/>
- <enum bitpos="8" extends="VkPipelineCreateFlagBits"
- name="VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT"/>
- <enum bitpos="9" extends="VkPipelineCreateFlagBits"
- name="VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT"/>
- <enum extends="VkResult" offset="0" name="VK_PIPELINE_COMPILE_REQUIRED_EXT"/>
- <enum extends="VkResult" name="VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT" alias="VK_PIPELINE_COMPILE_REQUIRED_EXT"/>
- <enum bitpos="0" extends="VkPipelineCacheCreateFlagBits"
- name="VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT"/>
+ <enum extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT_EXT" alias="VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT"/>
+ <enum extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT_EXT" alias="VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT"/>
+ <enum extends="VkResult" name="VK_PIPELINE_COMPILE_REQUIRED_EXT" alias="VK_PIPELINE_COMPILE_REQUIRED"/>
+ <enum extends="VkResult" name="VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT" alias="VK_PIPELINE_COMPILE_REQUIRED"/>
+ <enum extends="VkPipelineCacheCreateFlagBits" name="VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT" alias="VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT"/>
+ <type name="VkPipelineCacheCreateFlagBits" comment="This is a temporary workaround for processors not recognizing that VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT_EXT above also requires this type"/>
</require>
</extension>
<extension name="VK_KHR_extension_299" number="299" author="KHR" contact="Mark Bellamy @mark.bellamy_arm" supported="disabled">
<require>
<enum value="0" name="VK_KHR_EXTENSION_299_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_extension_299&quot;" name="VK_KHR_EXTENSION_299_EXTENSION_NAME"/>
+ <enum bitpos="2" extends="VkMemoryHeapFlagBits" name="VK_MEMORY_HEAP_RESERVED_2_BIT_KHR"/>
+ <enum extends="VkPipelineCacheCreateFlagBits" name="VK_PIPELINE_CACHE_CREATE_RESERVED_1_BIT_KHR" alias="VK_PIPELINE_CACHE_CREATE_RESERVED_1_BIT_EXT"/>
+ <enum bitpos="2" extends="VkPipelineCacheCreateFlagBits" name="VK_PIPELINE_CACHE_CREATE_RESERVED_2_BIT_KHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_video_encode_queue" number="300" type="device" requires="VK_KHR_video_queue,VK_KHR_synchronization2" author="KHR" contact="Ahmed Abdelkhalek @aabdelkh" provisional="true" platform="provisional" supported="vulkan">
+ <require>
+ <enum value="5" name="VK_KHR_VIDEO_ENCODE_QUEUE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_video_encode_queue&quot;" name="VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME"/>
+ <!-- VkPipelineStageFlagBits bitpos="27" is reserved by this extension, but not used -->
+ <enum bitpos="27" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_VIDEO_ENCODE_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS" />
+ <enum bitpos="37" extends="VkAccessFlagBits2" name="VK_ACCESS_2_VIDEO_ENCODE_READ_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS" />
+ <enum bitpos="38" extends="VkAccessFlagBits2" name="VK_ACCESS_2_VIDEO_ENCODE_WRITE_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_RATE_CONTROL_LAYER_INFO_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VIDEO_ENCODE_CAPABILITIES_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="6" extends="VkQueueFlagBits" name="VK_QUEUE_VIDEO_ENCODE_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="15" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="16" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="13" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="14" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="15" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="27" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_VIDEO_ENCODE_INPUT_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="28" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_VIDEO_ENCODE_DPB_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="0" extends="VkImageLayout" name="VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="1" extends="VkImageLayout" name="VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="2" extends="VkImageLayout" name="VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum offset="0" extends="VkQueryType" name="VK_QUERY_TYPE_VIDEO_ENCODE_BITSTREAM_BUFFER_RANGE_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+
+ <type name="VkVideoEncodeFlagBitsKHR"/>
+ <type name="VkVideoEncodeFlagsKHR"/>
+ <type name="VkVideoEncodeInfoKHR"/>
+
+ <type name="VkVideoEncodeCapabilityFlagBitsKHR"/>
+ <type name="VkVideoEncodeCapabilityFlagsKHR"/>
+ <type name="VkVideoEncodeCapabilitiesKHR"/>
+
+ <type name="VkVideoEncodeRateControlFlagBitsKHR"/>
+ <type name="VkVideoEncodeRateControlFlagsKHR"/>
+ <type name="VkVideoEncodeRateControlModeFlagBitsKHR"/>
+ <type name="VkVideoEncodeRateControlModeFlagsKHR"/>
+ <type name="VkVideoEncodeRateControlInfoKHR"/>
+ <type name="VkVideoEncodeRateControlLayerInfoKHR"/>
+
+ <command name="vkCmdEncodeVideoKHR"/>
</require>
- </extension>
- <extension name="VK_KHR_extension_300" number="300" author="KHR" contact="Aidan Fabius @afabius" supported="disabled">
- <require>
- <enum value="0" name="VK_KHR_EXTENSION_300_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_300&quot;" name="VK_KHR_EXTENSION_300_EXTENSION_NAME"/>
+ <require extension="VK_KHR_format_feature_flags2">
+ <enum bitpos="27" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_VIDEO_ENCODE_INPUT_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
+ <enum bitpos="28" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_VIDEO_ENCODE_DPB_BIT_KHR" protect="VK_ENABLE_BETA_EXTENSIONS"/>
</require>
</extension>
<extension name="VK_NV_device_diagnostics_config" number="301" type="device" requires="VK_KHR_get_physical_device_properties2" author="NV" contact="Kedarnath Thangudu @kthangudu" supported="vulkan">
<require>
- <enum value="1" name="VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION"/>
+ <enum value="2" name="VK_NV_DEVICE_DIAGNOSTICS_CONFIG_SPEC_VERSION"/>
<enum value="&quot;VK_NV_device_diagnostics_config&quot;" name="VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DIAGNOSTICS_CONFIG_FEATURES_NV"/>
<enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV"/>
@@ -14072,39 +17609,39 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_QCOM_render_pass_store_ops" number="302" type="device" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="vulkan">
<require>
- <enum value="2" name="VK_QCOM_render_pass_store_ops_SPEC_VERSION"/>
- <enum value="&quot;VK_QCOM_render_pass_store_ops&quot;" name="VK_QCOM_render_pass_store_ops_EXTENSION_NAME"/>
- <enum offset="0" extends="VkAttachmentStoreOp" name="VK_ATTACHMENT_STORE_OP_NONE_QCOM"/>
+ <enum value="2" name="VK_QCOM_RENDER_PASS_STORE_OPS_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_render_pass_store_ops&quot;" name="VK_QCOM_RENDER_PASS_STORE_OPS_EXTENSION_NAME"/>
+ <enum extends="VkAttachmentStoreOp" name="VK_ATTACHMENT_STORE_OP_NONE_QCOM" alias="VK_ATTACHMENT_STORE_OP_NONE"/>
</require>
</extension>
<extension name="VK_QCOM_extension_303" number="303" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="disabled">
<require>
- <enum value="0" name="VK_QCOM_extension_303_SPEC_VERSION"/>
- <enum value="&quot;VK_QCOM_extension_303&quot;" name="VK_QCOM_extension_303_EXTENSION_NAME"/>
+ <enum value="0" name="VK_QCOM_EXTENSION_303_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_extension_303&quot;" name="VK_QCOM_EXTENSION_303_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_QCOM_extension_304" number="304" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="disabled">
<require>
- <enum value="0" name="VK_QCOM_extension_304_SPEC_VERSION"/>
- <enum value="&quot;VK_QCOM_extension_304&quot;" name="VK_QCOM_extension_304_EXTENSION_NAME"/>
+ <enum value="0" name="VK_QCOM_EXTENSION_304_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_extension_304&quot;" name="VK_QCOM_EXTENSION_304_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_QCOM_extension_305" number="305" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="disabled">
<require>
- <enum value="0" name="VK_QCOM_extension_305_SPEC_VERSION"/>
- <enum value="&quot;VK_QCOM_extension_305&quot;" name="VK_QCOM_extension_305_EXTENSION_NAME"/>
+ <enum value="0" name="VK_QCOM_EXTENSION_305_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_extension_305&quot;" name="VK_QCOM_EXTENSION_305_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_QCOM_extension_306" number="306" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="disabled">
<require>
- <enum value="0" name="VK_QCOM_extension_306_SPEC_VERSION"/>
- <enum value="&quot;VK_QCOM_extension_306&quot;" name="VK_QCOM_extension_306_EXTENSION_NAME"/>
+ <enum value="0" name="VK_QCOM_EXTENSION_306_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_extension_306&quot;" name="VK_QCOM_EXTENSION_306_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_QCOM_extension_307" number="307" author="QCOM" contact="Bill Licea-Kane @wwlk" supported="disabled">
<require>
- <enum value="0" name="VK_QCOM_extension_307_SPEC_VERSION"/>
- <enum value="&quot;VK_QCOM_extension_307&quot;" name="VK_QCOM_extension_307_EXTENSION_NAME"/>
+ <enum value="0" name="VK_QCOM_EXTENSION_307_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_extension_307&quot;" name="VK_QCOM_EXTENSION_307_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_NV_extension_308" number="308" type="device" author="NV" contact="Tristan Lorach @tlorach" supported="disabled">
@@ -14117,13 +17654,12 @@ typedef void <name>CAMetalLayer</name>;
<require>
<enum value="0" name="VK_KHR_EXTENSION_309_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_extension_309&quot;" name="VK_KHR_EXTENSION_309_EXTENSION_NAME"/>
- <enum bitpos="2" extends="VkMemoryHeapFlagBits" name="VK_MEMORY_HEAP_RESERVED_2_BIT_KHR"/>
</require>
</extension>
<extension name="VK_QCOM_extension_310" number="310" author="QCOM" contact="Jeff Leger @jackohound" supported="disabled">
<require>
- <enum value="0" name="VK_QCOM_extension_310_SPEC_VERSION"/>
- <enum value="&quot;VK_QCOM_extension_310&quot;" name="VK_QCOM_extension_310_EXTENSION_NAME"/>
+ <enum value="0" name="VK_QCOM_EXTENSION_310_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_extension_310&quot;" name="VK_QCOM_EXTENSION_310_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_RESERVED_QCOM"/>
</require>
</extension>
@@ -14133,10 +17669,43 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_NV_extension_311&quot;" name="VK_NV_EXTENSION_311_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_EXT_extension_312" number="312" author="MVK" contact="Bill Hollings @billhollings" supported="disabled">
- <require>
- <enum value="0" name="VK_EXT_EXTENSION_312_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_312&quot;" name="VK_EXT_EXTENSION_312_EXTENSION_NAME"/>
+ <extension name="VK_EXT_metal_objects" number="312" type="device" platform="metal" supported="vulkan" author="EXT" contact="Bill Hollings @billhollings">
+ <require>
+ <enum value="1" name="VK_EXT_METAL_OBJECTS_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_metal_objects&quot;" name="VK_EXT_METAL_OBJECTS_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT"/>
+ <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT"/>
+ <enum offset="7" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT"/>
+ <enum offset="8" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT"/>
+ <enum offset="9" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMPORT_METAL_IO_SURFACE_INFO_EXT"/>
+ <enum offset="10" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT"/>
+ <enum offset="11" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT"/>
+ <type name="VkExportMetalObjectTypeFlagBitsEXT"/>
+ <type name="VkExportMetalObjectTypeFlagsEXT"/>
+ <type name="VkExportMetalObjectCreateInfoEXT"/>
+ <type name="VkExportMetalObjectsInfoEXT"/>
+ <type name="VkExportMetalDeviceInfoEXT"/>
+ <type name="VkExportMetalCommandQueueInfoEXT"/>
+ <type name="VkExportMetalBufferInfoEXT"/>
+ <type name="VkImportMetalBufferInfoEXT"/>
+ <type name="VkExportMetalTextureInfoEXT"/>
+ <type name="VkImportMetalTextureInfoEXT"/>
+ <type name="VkExportMetalIOSurfaceInfoEXT"/>
+ <type name="VkImportMetalIOSurfaceInfoEXT"/>
+ <type name="VkExportMetalSharedEventInfoEXT"/>
+ <type name="VkImportMetalSharedEventInfoEXT"/>
+ <type name="MTLDevice_id"/>
+ <type name="MTLCommandQueue_id"/>
+ <type name="MTLBuffer_id"/>
+ <type name="MTLTexture_id"/>
+ <type name="MTLSharedEvent_id"/>
+ <type name="IOSurfaceRef"/>
+ <command name="vkExportMetalObjectsEXT"/>
</require>
</extension>
<extension name="VK_EXT_extension_313" number="313" author="MVK" contact="Bill Hollings @billhollings" supported="disabled">
@@ -14151,10 +17720,102 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_AMD_extension_314&quot;" name="VK_AMD_EXTENSION_314_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_AMD_extension_315" number="315" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
- <require>
- <enum value="0" name="VK_AMD_EXTENSION_315_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_315&quot;" name="VK_AMD_EXTENSION_315_EXTENSION_NAME"/>
+ <extension name="VK_KHR_synchronization2" number="315" type="device" author="KHR" requires="VK_KHR_get_physical_device_properties2" contact="Tobias Hector @tobski" supported="vulkan" promotedto="VK_VERSION_1_3">
+ <require>
+ <enum value="1" name="VK_KHR_SYNCHRONIZATION_2_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_synchronization2&quot;" name="VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR" alias="VK_STRUCTURE_TYPE_MEMORY_BARRIER_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2_KHR" alias="VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2_KHR" alias="VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR" alias="VK_STRUCTURE_TYPE_DEPENDENCY_INFO"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR" alias="VK_STRUCTURE_TYPE_SUBMIT_INFO_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR" alias="VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR" alias="VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES"/>
+ <enum extends="VkEventCreateFlagBits" name="VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR" alias="VK_EVENT_CREATE_DEVICE_ONLY_BIT"/>
+ <enum extends="VkImageLayout" name="VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL_KHR" alias="VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL"/>
+ <enum extends="VkImageLayout" name="VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR" alias="VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL"/>
+ <enum extends="VkPipelineStageFlagBits" name="VK_PIPELINE_STAGE_NONE_KHR" alias="VK_PIPELINE_STAGE_NONE"/>
+ <enum extends="VkAccessFlagBits" name="VK_ACCESS_NONE_KHR" alias="VK_ACCESS_NONE"/>
+ <type name="VkFlags64"/>
+ <type name="VkPipelineStageFlags2KHR"/>
+ <type name="VkPipelineStageFlagBits2KHR"/>
+ <type name="VkAccessFlags2KHR"/>
+ <type name="VkAccessFlagBits2KHR"/>
+ <type name="VkMemoryBarrier2KHR"/>
+ <type name="VkBufferMemoryBarrier2KHR"/>
+ <type name="VkImageMemoryBarrier2KHR"/>
+ <type name="VkDependencyInfoKHR"/>
+ <type name="VkSubmitInfo2KHR"/>
+ <type name="VkSemaphoreSubmitInfoKHR"/>
+ <type name="VkCommandBufferSubmitInfoKHR"/>
+ <type name="VkSubmitFlagBitsKHR"/>
+ <type name="VkSubmitFlagsKHR"/>
+ <type name="VkPhysicalDeviceSynchronization2FeaturesKHR"/>
+ <command name="vkCmdSetEvent2KHR"/>
+ <command name="vkCmdResetEvent2KHR"/>
+ <command name="vkCmdWaitEvents2KHR"/>
+ <command name="vkCmdPipelineBarrier2KHR"/>
+ <command name="vkCmdWriteTimestamp2KHR"/>
+ <command name="vkQueueSubmit2KHR"/>
+ </require>
+ <require extension="VK_EXT_transform_feedback">
+ <enum bitpos="24" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_TRANSFORM_FEEDBACK_BIT_EXT"/>
+ <enum bitpos="25" extends="VkAccessFlagBits2" name="VK_ACCESS_2_TRANSFORM_FEEDBACK_WRITE_BIT_EXT"/>
+ <enum bitpos="26" extends="VkAccessFlagBits2" name="VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT"/>
+ <enum bitpos="27" extends="VkAccessFlagBits2" name="VK_ACCESS_2_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT"/>
+ </require>
+ <require extension="VK_EXT_conditional_rendering">
+ <enum bitpos="18" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_CONDITIONAL_RENDERING_BIT_EXT" comment="A pipeline stage for conditional rendering predicate fetch"/>
+ <enum bitpos="20" extends="VkAccessFlagBits2" name="VK_ACCESS_2_CONDITIONAL_RENDERING_READ_BIT_EXT" comment="read access flag for reading conditional rendering predicate"/>
+ </require>
+ <require extension="VK_NV_device_generated_commands">
+ <enum bitpos="17" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_COMMAND_PREPROCESS_BIT_NV"/>
+ <enum bitpos="17" extends="VkAccessFlagBits2" name="VK_ACCESS_2_COMMAND_PREPROCESS_READ_BIT_NV"/>
+ <enum bitpos="18" extends="VkAccessFlagBits2" name="VK_ACCESS_2_COMMAND_PREPROCESS_WRITE_BIT_NV"/>
+ </require>
+ <require extension="VK_KHR_fragment_shading_rate">
+ <enum bitpos="22" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"/>
+ <enum bitpos="23" extends="VkAccessFlagBits2" name="VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"/>
+ </require>
+ <require extension="VK_NV_shading_rate_image">
+ <enum extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_SHADING_RATE_IMAGE_BIT_NV" alias="VK_PIPELINE_STAGE_2_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR"/>
+ <enum extends="VkAccessFlagBits2" name="VK_ACCESS_2_SHADING_RATE_IMAGE_READ_BIT_NV" alias="VK_ACCESS_2_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR"/>
+ </require>
+ <require extension="VK_KHR_acceleration_structure">
+ <enum bitpos="25" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"/>
+ <enum bitpos="21" extends="VkAccessFlagBits2" name="VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR"/>
+ <enum bitpos="22" extends="VkAccessFlagBits2" name="VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"/>
+ </require>
+ <require extension="VK_KHR_ray_tracing_pipeline">
+ <enum bitpos="21" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR"/>
+ </require>
+ <require extension="VK_NV_ray_tracing">
+ <enum extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_NV" alias="VK_PIPELINE_STAGE_2_RAY_TRACING_SHADER_BIT_KHR"/>
+ <enum extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_NV" alias="VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR"/>
+ <enum extends="VkAccessFlagBits2" name="VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_NV" alias="VK_ACCESS_2_ACCELERATION_STRUCTURE_READ_BIT_KHR"/>
+ <enum extends="VkAccessFlagBits2" name="VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_NV" alias="VK_ACCESS_2_ACCELERATION_STRUCTURE_WRITE_BIT_KHR"/>
+ </require>
+ <require extension="VK_EXT_fragment_density_map">
+ <enum bitpos="23" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_FRAGMENT_DENSITY_PROCESS_BIT_EXT"/>
+ <enum bitpos="24" extends="VkAccessFlagBits2" name="VK_ACCESS_2_FRAGMENT_DENSITY_MAP_READ_BIT_EXT"/>
+ </require>
+ <require extension="VK_EXT_blend_operation_advanced">
+ <enum bitpos="19" extends="VkAccessFlagBits2" name="VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT"/>
+ </require>
+ <require extension="VK_NV_mesh_shader">
+ <enum bitpos="19" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_TASK_SHADER_BIT_NV"/>
+ <enum bitpos="20" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_MESH_SHADER_BIT_NV"/>
+ </require>
+ <require extension="VK_AMD_buffer_marker">
+ <command name="vkCmdWriteBufferMarker2AMD"/>
+ </require>
+ <require extension="VK_NV_device_diagnostic_checkpoints">
+ <type name="VkQueueFamilyCheckpointProperties2NV"/>
+ <type name="VkCheckpointData2NV"/>
+ <command name="vkGetQueueCheckpointData2NV"/>
+ <enum offset="8" extends="VkStructureType" name="VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_2_NV"/>
+ <enum offset="9" extends="VkStructureType" name="VK_STRUCTURE_TYPE_CHECKPOINT_DATA_2_NV"/>
</require>
</extension>
<extension name="VK_AMD_extension_316" number="316" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
@@ -14167,6 +17828,16 @@ typedef void <name>CAMetalLayer</name>;
<require>
<enum value="0" name="VK_AMD_EXTENSION_317_SPEC_VERSION"/>
<enum value="&quot;VK_AMD_extension_317&quot;" name="VK_AMD_EXTENSION_317_EXTENSION_NAME"/>
+ <enum bitpos="4" extends="VkDescriptorSetLayoutCreateFlagBits" name="VK_DESCRIPTOR_SET_LAYOUT_CREATE_RESERVED_4_BIT_AMD"/>
+ <enum bitpos="5" extends="VkDescriptorSetLayoutCreateFlagBits" name="VK_DESCRIPTOR_SET_LAYOUT_CREATE_RESERVED_5_BIT_AMD"/>
+ <enum bitpos="21" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_RESERVED_21_BIT_AMD"/>
+ <enum bitpos="22" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_RESERVED_22_BIT_AMD"/>
+ <enum bitpos="5" extends="VkBufferCreateFlagBits" name="VK_BUFFER_CREATE_RESERVED_5_BIT_AMD"/>
+ <enum bitpos="16" extends="VkImageCreateFlagBits" name="VK_IMAGE_CREATE_RESERVED_16_BIT_AMD"/>
+ <enum bitpos="3" extends="VkSamplerCreateFlagBits" name="VK_SAMPLER_CREATE_RESERVED_3_BIT_AMD"/>
+ <enum bitpos="41" extends="VkAccessFlagBits2" name="VK_ACCESS_2_RESERVED_41_BIT_AMD"/>
+ <enum bitpos="2" extends="VkImageViewCreateFlagBits" name="VK_IMAGE_VIEW_CREATE_RESERVED_2_BIT_AMD"/>
+ <enum bitpos="3" extends="VkAccelerationStructureCreateFlagBitsKHR" name="VK_ACCELERATION_STRUCTURE_CREATE_RESERVED_3_BIT_AMD"/>
</require>
</extension>
<extension name="VK_AMD_extension_318" number="318" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
@@ -14179,6 +17850,8 @@ typedef void <name>CAMetalLayer</name>;
<require>
<enum value="0" name="VK_AMD_EXTENSION_319_SPEC_VERSION"/>
<enum value="&quot;VK_AMD_extension_319&quot;" name="VK_AMD_EXTENSION_319_EXTENSION_NAME"/>
+ <enum bitpos="3" extends="VkDescriptorSetLayoutCreateFlagBits" name="VK_DESCRIPTOR_SET_LAYOUT_CREATE_RESERVED_3_BIT_AMD"/>
+ <enum bitpos="0" extends="VkPipelineLayoutCreateFlagBits" name="VK_PIPELINE_LAYOUT_CREATE_RESERVED_0_BIT_AMD"/>
</require>
</extension>
<extension name="VK_AMD_extension_320" number="320" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
@@ -14187,28 +17860,48 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_AMD_extension_320&quot;" name="VK_AMD_EXTENSION_320_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_AMD_extension_321" number="321" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+ <extension name="VK_EXT_graphics_pipeline_library" number="321" type="device" requires="VK_KHR_get_physical_device_properties2,VK_KHR_pipeline_library" author="AMD" contact="Tobias Hector @tobski" supported="vulkan">
<require>
- <enum value="0" name="VK_AMD_EXTENSION_321_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_321&quot;" name="VK_AMD_EXTENSION_321_EXTENSION_NAME"/>
+ <enum value="1" name="VK_EXT_GRAPHICS_PIPELINE_LIBRARY_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_graphics_pipeline_library&quot;" name="VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME"/>
+ <type name="VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT"/>
+ <type name="VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT"/>
+ <type name="VkGraphicsPipelineLibraryCreateInfoEXT"/>
+ <type name="VkGraphicsPipelineLibraryFlagBitsEXT"/>
+ <type name="VkGraphicsPipelineLibraryFlagsEXT"/>
+ <type name="VkPipelineLayoutCreateFlagBits"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_LIBRARY_CREATE_INFO_EXT"/>
+ <enum bitpos="23" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT"/>
+ <enum bitpos="10" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT"/>
+ <enum bitpos="1" extends="VkPipelineLayoutCreateFlagBits" name="VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT"/>
</require>
</extension>
- <extension name="VK_AMD_extension_322" number="322" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+ <extension name="VK_AMD_shader_early_and_late_fragment_tests" number="322" author="EXT" contact="Tobias Hector @tobski" type="device" supported="vulkan">
<require>
- <enum value="0" name="VK_AMD_EXTENSION_322_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_322&quot;" name="VK_AMD_EXTENSION_322_EXTENSION_NAME"/>
+ <enum value="1" name="VK_AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_shader_early_and_late_fragment_tests&quot;" name="VK_AMD_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_EXTENSION_NAME"/>
+ <type name="VkPhysicalDeviceShaderEarlyAndLateFragmentTestsFeaturesAMD"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EARLY_AND_LATE_FRAGMENT_TESTS_FEATURES_AMD"/>
</require>
</extension>
- <extension name="VK_AMD_extension_323" number="323" author="AMD" contact="Martin Dinkov @mdinkov" supported="disabled">
+ <extension name="VK_KHR_fragment_shader_barycentric" number="323" type="device" requires="VK_KHR_get_physical_device_properties2" author="KHR" contact="Stu Smith" supported="vulkan">
<require>
- <enum value="0" name="VK_AMD_EXTENSION_323_SPEC_VERSION"/>
- <enum value="&quot;VK_AMD_extension_323&quot;" name="VK_AMD_EXTENSION_323_EXTENSION_NAME"/>
+ <enum value="1" name="VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_fragment_shader_barycentric&quot;" name="VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" extnumber="204" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR"/>
+ <type name="VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR"/>
+ <type name="VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR"/>
</require>
</extension>
- <extension name="VK_KHR_extension_324" number="324" author="KHR" contact="Alan Baker @alan-baker" supported="disabled">
+ <extension name="VK_KHR_shader_subgroup_uniform_control_flow" number="324" type="device" requiresCore="1.1" author="KHR" contact="Alan Baker @alan-baker" supported="vulkan">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_324_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_324&quot;" name="VK_KHR_EXTENSION_324_EXTENSION_NAME"/>
+ <enum value="1" name="VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_shader_subgroup_uniform_control_flow&quot;" name="VK_KHR_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_UNIFORM_CONTROL_FLOW_FEATURES_KHR"/>
+ <type name="VkPhysicalDeviceShaderSubgroupUniformControlFlowFeaturesKHR"/>
</require>
</extension>
<extension name="VK_KHR_extension_325" number="325" author="KHR" contact="Ralph Potter gitlab:@r_potter" supported="disabled">
@@ -14217,10 +17910,12 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_KHR_extension_325&quot;" name="VK_KHR_EXTENSION_325_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_KHR_extension_326" number="326" author="KHR" contact="Alan Baker @alan-baker" supported="disabled">
+ <extension name="VK_KHR_zero_initialize_workgroup_memory" number="326" type="device" requires="VK_KHR_get_physical_device_properties2" author="KHR" contact="Alan Baker @alan-baker" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_326_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_326&quot;" name="VK_KHR_EXTENSION_326_EXTENSION_NAME"/>
+ <enum value="1" name="VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_zero_initialize_workgroup_memory&quot;" name="VK_KHR_ZERO_INITIALIZE_WORKGROUP_MEMORY_EXTENSION_NAME"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES"/>
+ <type name="VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeaturesKHR"/>
</require>
</extension>
<extension name="VK_NV_fragment_shading_rate_enums" number="327" type="device" requires="VK_KHR_fragment_shading_rate" author="NV" contact="Pat Brown @nvpbrown" supported="vulkan">
@@ -14238,10 +17933,27 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkCmdSetFragmentShadingRateEnumNV"/>
</require>
</extension>
- <extension name="VK_NV_extension_328" number="328" author="NV" contact="Pat Brown @nvpbrown" supported="disabled">
- <require>
- <enum value="0" name="VK_NV_EXTENSION_328_SPEC_VERSION"/>
- <enum value="&quot;VK_NV_extension_328&quot;" name="VK_NV_EXTENSION_328_EXTENSION_NAME"/>
+ <extension name="VK_NV_ray_tracing_motion_blur" number="328" type="device" requires="VK_KHR_ray_tracing_pipeline" author="NV" contact="Eric Werness" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_NV_RAY_TRACING_MOTION_BLUR_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_ray_tracing_motion_blur&quot;" name="VK_NV_RAY_TRACING_MOTION_BLUR_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_MOTION_TRIANGLES_DATA_NV"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MOTION_BLUR_FEATURES_NV"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MOTION_INFO_NV"/>
+ <enum bitpos="5" extends="VkBuildAccelerationStructureFlagBitsKHR" name="VK_BUILD_ACCELERATION_STRUCTURE_MOTION_BIT_NV"/>
+ <enum bitpos="2" extends="VkAccelerationStructureCreateFlagBitsKHR" name="VK_ACCELERATION_STRUCTURE_CREATE_MOTION_BIT_NV"/>
+ <enum bitpos="20" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV"/>
+ <type name="VkAccelerationStructureGeometryMotionTrianglesDataNV"/>
+ <type name="VkAccelerationStructureMotionInfoNV"/>
+ <type name="VkAccelerationStructureMotionInstanceNV"/>
+ <type name="VkAccelerationStructureMotionInstanceDataNV"/>
+ <type name="VkAccelerationStructureMatrixMotionInstanceNV"/>
+ <type name="VkAccelerationStructureSRTMotionInstanceNV"/>
+ <type name="VkSRTDataNV"/>
+ <type name="VkAccelerationStructureMotionInstanceTypeNV"/>
+ <type name="VkPhysicalDeviceRayTracingMotionBlurFeaturesNV"/>
+ <type name="VkAccelerationStructureMotionInfoFlagsNV"/>
+ <type name="VkAccelerationStructureMotionInstanceFlagsNV"/>
</require>
</extension>
<extension name="VK_NV_extension_329" number="329" author="NV" contact="Pat Brown @nvpbrown" supported="disabled">
@@ -14256,10 +17968,21 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_NV_extension_330&quot;" name="VK_NV_EXTENSION_330_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_NV_extension_331" number="331" author="NV" contact="Tony Zlatinski @tzlatinski" supported="disabled">
+ <extension name="VK_EXT_ycbcr_2plane_444_formats" number="331" type="device" requires="VK_KHR_sampler_ycbcr_conversion" author="EXT" contact="Tony Zlatinski @tzlatinski" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
- <enum value="0" name="VK_NV_EXTENSION_331_SPEC_VERSION"/>
- <enum value="&quot;VK_NV_extension_331&quot;" name="VK_NV_EXTENSION_331_EXTENSION_NAME"/>
+ <comment>
+ VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT and
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT
+ were not promoted to Vulkan 1.3.
+ </comment>
+ <enum value="1" name="VK_EXT_YCBCR_2PLANE_444_FORMATS_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_ycbcr_2plane_444_formats&quot;" name="VK_EXT_YCBCR_2PLANE_444_FORMATS_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_2_PLANE_444_FORMATS_FEATURES_EXT"/>
+ <enum extends="VkFormat" name="VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT" alias="VK_FORMAT_G8_B8R8_2PLANE_444_UNORM"/>
+ <enum extends="VkFormat" name="VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT" alias="VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16"/>
+ <enum extends="VkFormat" name="VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT" alias="VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16"/>
+ <enum extends="VkFormat" name="VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT" alias="VK_FORMAT_G16_B16R16_2PLANE_444_UNORM"/>
+ <type name="VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT"/>
</require>
</extension>
<extension name="VK_NV_extension_332" number="332" author="NV" contact="Tony Zlatinski @tzlatinski" supported="disabled">
@@ -14281,8 +18004,8 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_QCOM_rotated_copy_commands" number="334" type="device" requires="VK_KHR_swapchain,VK_KHR_copy_commands2" author="QCOM" contact="Jeff Leger @jackohound" supported="vulkan">
<require>
- <enum value="0" name="VK_QCOM_rotated_copy_commands_SPEC_VERSION"/>
- <enum value="&quot;VK_QCOM_rotated_copy_commands&quot;" name="VK_QCOM_rotated_copy_commands_EXTENSION_NAME"/>
+ <enum value="1" name="VK_QCOM_ROTATED_COPY_COMMANDS_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_rotated_copy_commands&quot;" name="VK_QCOM_ROTATED_COPY_COMMANDS_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_COPY_COMMAND_TRANSFORM_INFO_QCOM"/>
<type name="VkCopyCommandTransformInfoQCOM"/>
</require>
@@ -14293,35 +18016,37 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_KHR_extension_335&quot;" name="VK_KHR_EXTENSION_335_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_EXT_image_robustness" number="336" type="device" author="EXT" contact="Graeme Leese @gnl21" supported="vulkan" requires="VK_KHR_get_physical_device_properties2">
+ <extension name="VK_EXT_image_robustness" number="336" type="device" author="EXT" contact="Graeme Leese @gnl21" supported="vulkan" requires="VK_KHR_get_physical_device_properties2" promotedto="VK_VERSION_1_3">
<require>
<enum value="1" name="VK_EXT_IMAGE_ROBUSTNESS_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_image_robustness&quot;" name="VK_EXT_IMAGE_ROBUSTNESS_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES"/>
<type name="VkPhysicalDeviceImageRobustnessFeaturesEXT"/>
</require>
</extension>
- <extension name="VK_KHR_extension_337" number="337" type="device" author="KHR" contact="Caio Marcelo de Oliveira Filho @cmarcelo" supported="disabled">
+ <extension name="VK_KHR_workgroup_memory_explicit_layout" number="337" type="device" requires="VK_KHR_get_physical_device_properties2" author="KHR" contact="Caio Marcelo de Oliveira Filho @cmarcelo" supported="vulkan">
<require>
- <enum value="0" name="VK_KHR_EXTENSION_337_SPEC_VERSION"/>
- <enum value="&quot;VK_KHR_extension_337&quot;" name="VK_KHR_EXTENSION_337_EXTENSION_NAME"/>
+ <enum value="1" name="VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_workgroup_memory_explicit_layout&quot;" name="VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR"/>
+ <type name="VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR"/>
</require>
</extension>
- <extension name="VK_KHR_copy_commands2" number="338" author="KHR" type="device" contact="Jeff Leger @jackohound" supported="vulkan">
+ <extension name="VK_KHR_copy_commands2" number="338" author="KHR" type="device" contact="Jeff Leger @jackohound" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
<enum value="1" name="VK_KHR_COPY_COMMANDS_2_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_copy_commands2&quot;" name="VK_KHR_COPY_COMMANDS_2_EXTENSION_NAME"/>
- <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR"/>
- <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR"/>
- <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR"/>
- <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR"/>
- <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR"/>
- <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR"/>
- <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR"/>
- <enum offset="7" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR"/>
- <enum offset="8" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR"/>
- <enum offset="9" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR"/>
- <enum offset="10" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2_KHR" alias="VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR" alias="VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2_KHR" alias="VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2_KHR" alias="VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2_KHR" alias="VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2_KHR" alias="VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_COPY_2_KHR" alias="VK_STRUCTURE_TYPE_BUFFER_COPY_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_COPY_2_KHR" alias="VK_STRUCTURE_TYPE_IMAGE_COPY_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_BLIT_2_KHR" alias="VK_STRUCTURE_TYPE_IMAGE_BLIT_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2_KHR" alias="VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2_KHR" alias="VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2"/>
<type name="VkCopyBufferInfo2KHR"/>
<type name="VkCopyImageInfo2KHR"/>
<type name="VkCopyBufferToImageInfo2KHR"/>
@@ -14341,25 +18066,50 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkCmdResolveImage2KHR"/>
</require>
</extension>
- <extension name="VK_ARM_extension_339" number="339" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="disabled">
- <require>
- <enum value="0" name="VK_ARM_EXTENSION_339_SPEC_VERSION"/>
- <enum value="&quot;VK_ARM_extension_339&quot;" name="VK_ARM_EXTENSION_339_EXTENSION_NAME"/>
+ <extension name="VK_EXT_image_compression_control" number="339" type="device" author="EXT" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_IMAGE_COMPRESSION_CONTROL_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_image_compression_control&quot;" name="VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT"/>
+ <type name="VkPhysicalDeviceImageCompressionControlFeaturesEXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT"/>
+ <type name="VkImageCompressionControlEXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SUBRESOURCE_LAYOUT_2_EXT"/>
+ <type name="VkSubresourceLayout2EXT"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_SUBRESOURCE_2_EXT"/>
+ <type name="VkImageSubresource2EXT"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT"/>
+ <type name="VkImageCompressionPropertiesEXT"/>
+ <type name="VkImageCompressionFlagBitsEXT"/>
+ <type name="VkImageCompressionFlagsEXT"/>
+ <type name="VkImageCompressionFixedRateFlagBitsEXT"/>
+ <type name="VkImageCompressionFixedRateFlagsEXT"/>
+ <enum offset="0" dir="-" extends="VkResult" name="VK_ERROR_COMPRESSION_EXHAUSTED_EXT"/>
+ <command name="vkGetImageSubresourceLayout2EXT"/>
</require>
</extension>
<extension name="VK_EXT_extension_340" number="340" author="EXT" contact="Joshua Ashton @Joshua-Ashton" supported="disabled">
<require>
<enum value="0" name="VK_EXT_EXTENSION_340_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_extension_340&quot;" name="VK_EXT_EXTENSION_340_EXTENSION_NAME"/>
+ <enum bitpos="19" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_RESERVED_19_BIT_EXT"/>
+ <enum bitpos="25" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_RESERVED_25_BIT_EXT"/>
+ <enum bitpos="26" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_RESERVED_26_BIT_EXT"/>
+ <enum bitpos="3" extends="VkDependencyFlagBits" name="VK_DEPENDENCY_RESERVED_3_BIT_EXT"/>
</require>
</extension>
- <extension name="VK_EXT_4444_formats" number="341" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Joshua Ashton @Joshua-Ashton" supported="vulkan">
+ <extension name="VK_EXT_4444_formats" number="341" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Joshua Ashton @Joshua-Ashton" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
+ <comment>
+ VkPhysicalDevice4444FormatsFeaturesEXT and
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT
+ were not promoted to Vulkan 1.3.
+ </comment>
<enum value="1" name="VK_EXT_4444_FORMATS_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_4444_formats&quot;" name="VK_EXT_4444_FORMATS_EXTENSION_NAME"/>
<enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT"/>
- <enum offset="0" extends="VkFormat" name="VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT"/>
- <enum offset="1" extends="VkFormat" name="VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT"/>
+ <enum extends="VkFormat" name="VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT" alias="VK_FORMAT_A4R4G4B4_UNORM_PACK16"/>
+ <enum extends="VkFormat" name="VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT" alias="VK_FORMAT_A4B4G4R4_UNORM_PACK16"/>
<type name="VkPhysicalDevice4444FormatsFeaturesEXT"/>
</require>
</extension>
@@ -14369,10 +18119,20 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_EXT_extension_342&quot;" name="VK_EXT_EXTENSION_342_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_ARM_extension_343" number="343" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="disabled">
+ <extension name="VK_ARM_rasterization_order_attachment_access" number="343" type="device" requires="VK_KHR_get_physical_device_properties2" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="vulkan">
<require>
- <enum value="0" name="VK_ARM_EXTENSION_343_SPEC_VERSION"/>
- <enum value="&quot;VK_ARM_extension_343&quot;" name="VK_ARM_EXTENSION_343_EXTENSION_NAME"/>
+ <enum value="1" name="VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_SPEC_VERSION"/>
+ <enum value="&quot;VK_ARM_rasterization_order_attachment_access&quot;" name="VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM"/>
+ <type name="VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM"/>
+ <type name="VkPipelineColorBlendStateCreateFlagBits"/>
+ <type name="VkPipelineDepthStencilStateCreateFlagBits"/>
+ <enum bitpos="0" extends="VkPipelineColorBlendStateCreateFlagBits" name="VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM"/>
+ <enum bitpos="0" extends="VkPipelineDepthStencilStateCreateFlagBits" name="VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM"/>
+ <enum bitpos="1" extends="VkPipelineDepthStencilStateCreateFlagBits" name="VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM"/>
+ <enum bitpos="4" extends="VkSubpassDescriptionFlagBits" name="VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_ARM"/>
+ <enum bitpos="5" extends="VkSubpassDescriptionFlagBits" name="VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM"/>
+ <enum bitpos="6" extends="VkSubpassDescriptionFlagBits" name="VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM"/>
</require>
</extension>
<extension name="VK_ARM_extension_344" number="344" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="disabled">
@@ -14381,10 +18141,12 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_ARM_extension_344&quot;" name="VK_ARM_EXTENSION_344_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_ARM_extension_345" number="345" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="disabled">
- <require>
- <enum value="0" name="VK_ARM_EXTENSION_345_SPEC_VERSION"/>
- <enum value="&quot;VK_ARM_extension_345&quot;" name="VK_ARM_EXTENSION_345_EXTENSION_NAME"/>
+ <extension name="VK_EXT_rgba10x6_formats" number="345" type="device" requires="VK_KHR_sampler_ycbcr_conversion" author="EXT" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_RGBA10X6_FORMATS_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_rgba10x6_formats&quot;" name="VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT"/>
+ <type name="VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT"/>
</require>
</extension>
<extension name="VK_NV_acquire_winrt_display" number="346" type="device" requires="VK_EXT_direct_mode_display" author="NV" contact="Jeff Juliano @jjuliano" platform="win32" supported="vulkan">
@@ -14410,7 +18172,6 @@ typedef void <name>CAMetalLayer</name>;
<require>
<enum value="0" name="VK_KHR_EXTENSION_350_SPEC_VERSION"/>
<enum value="&quot;VK_KHR_extension_350&quot;" name="VK_KHR_EXTENSION_350_EXTENSION_NAME"/>
- <enum bitpos="2" extends="VkPipelineCacheCreateFlagBits" name="VK_PIPELINE_CACHE_CREATE_RESERVED_2_BIT_EXT"/>
</require>
</extension>
<extension name="VK_NV_extension_351" number="351" author="NV" contact="Liam Middlebrook @liam-middlebrook" supported="disabled">
@@ -14433,16 +18194,28 @@ typedef void <name>CAMetalLayer</name>;
<type name="VkMutableDescriptorTypeCreateInfoVALVE"/>
</require>
</extension>
- <extension name="VK_EXT_extension_353" number="353" author="EXT" contact="Piers Daniell @pdaniell-nv" supported="disabled">
+ <extension name="VK_EXT_vertex_input_dynamic_state" number="353" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Piers Daniell @pdaniell-nv" supported="vulkan">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_353_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_353&quot;" name="VK_EXT_EXTENSION_353_EXTENSION_NAME"/>
+ <enum value="2" name="VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_vertex_input_dynamic_state&quot;" name="VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT"/>
+ <enum offset="0" extends="VkDynamicState" name="VK_DYNAMIC_STATE_VERTEX_INPUT_EXT"/>
+ <type name="VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT"/>
+ <type name="VkVertexInputBindingDescription2EXT"/>
+ <type name="VkVertexInputAttributeDescription2EXT"/>
+ <command name="vkCmdSetVertexInputEXT"/>
</require>
</extension>
- <extension name="VK_EXT_extension_354" number="354" author="EXT" contact="Simon Ser @emersion" supported="disabled">
+ <extension name="VK_EXT_physical_device_drm" number="354" author="EXT" type="device" contact="Simon Ser @emersion" supported="vulkan" requires="VK_KHR_get_physical_device_properties2">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_354_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_354&quot;" name="VK_EXT_EXTENSION_354_EXTENSION_NAME"/>
+ <enum value="1" name="VK_EXT_PHYSICAL_DEVICE_DRM_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_physical_device_drm&quot;" name="VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME"/>
+
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT"/>
+
+ <type name="VkPhysicalDeviceDrmPropertiesEXT"/>
</require>
</extension>
<extension name="VK_EXT_extension_355" number="355" author="EXT" contact="Ralph Potter gitlab:@r_potter" supported="disabled">
@@ -14451,16 +18224,22 @@ typedef void <name>CAMetalLayer</name>;
<enum value="&quot;VK_EXT_extension_355&quot;" name="VK_EXT_EXTENSION_355_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_EXT_vertex_attribute_aliasing" number="356" type="device" author="EXT" contact="Shahbaz Youssefi @syoussefi" supported="disabled" specialuse="glemulation">
+ <extension name="VK_EXT_depth_clip_control" number="356" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Shahbaz Youssefi @syoussefi" supported="vulkan" specialuse="glemulation">
<require>
- <enum value="0" name="VK_EXT_VERTEX_ATTRIBUTE_ALIASING_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_vertex_attribute_aliasing&quot;" name="VK_EXT_VERTEX_ATTRIBUTE_ALIASING_EXTENSION_NAME"/>
+ <enum value="1" name="VK_EXT_DEPTH_CLIP_CONTROL_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_depth_clip_control&quot;" name="VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_CONTROL_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT"/>
+ <type name="VkPhysicalDeviceDepthClipControlFeaturesEXT"/>
+ <type name="VkPipelineViewportDepthClipControlCreateInfoEXT"/>
</require>
</extension>
- <extension name="VK_EXT_extension_357" number="357" author="EXT" contact="Courtney Goeltzenleuchter @courtney-g" supported="disabled" specialuse="glemulation">
+ <extension name="VK_EXT_primitive_topology_list_restart" number="357" type="device" author="EXT" contact="Shahbaz Youssefi @syoussefi" supported="vulkan" specialuse="glemulation">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_357"/>
- <enum value="&quot;VK_EXT_extension_357&quot;" name="VK_EXT_EXTENSION_357"/>
+ <enum value="1" name="VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_primitive_topology_list_restart&quot;" name="VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT"/>
+ <type name="VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT"/>
</require>
</extension>
<extension name="VK_KHR_extension_358" number="358" author="KHR" contact="Jeff Bolz @jeffbolznv" supported="disabled">
@@ -14471,20 +18250,24 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_EXT_extension_359" number="359" author="EXT" contact="Bill Hollings @billhollings" supported="disabled" specialuse="glemulation">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_359"/>
- <enum value="&quot;VK_EXT_extension_359&quot;" name="VK_EXT_EXTENSION_359"/>
+ <enum value="0" name="VK_EXT_EXTENSION_359_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_359&quot;" name="VK_EXT_EXTENSION_359_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_EXT_extension_360" number="360" author="EXT" contact="Bill Hollings @billhollings" supported="disabled" specialuse="glemulation">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_360"/>
- <enum value="&quot;VK_EXT_extension_360&quot;" name="VK_EXT_EXTENSION_360"/>
+ <enum value="0" name="VK_EXT_EXTENSION_360_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_360&quot;" name="VK_EXT_EXTENSION_360_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_KHR_extension_361" number="361" author="KHR" contact="Lionel Landwerlin @llandwerlin" supported="disabled">
+ <extension name="VK_KHR_format_feature_flags2" number="361" author="KHR" type="device" requires="VK_KHR_get_physical_device_properties2" contact="Lionel Landwerlin @llandwerlin" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_361"/>
- <enum value="&quot;VK_EXT_extension_361&quot;" name="VK_EXT_EXTENSION_361"/>
+ <enum value="1" name="VK_KHR_FORMAT_FEATURE_FLAGS_2_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_format_feature_flags2&quot;" name="VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3_KHR" alias="VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3"/>
+ <type name="VkFormatFeatureFlags2KHR"/>
+ <type name="VkFormatFeatureFlagBits2KHR"/>
+ <type name="VkFormatProperties3KHR"/>
</require>
</extension>
<extension name="VK_EXT_extension_362" number="362" author="EXT" contact="Lionel Duc @nvlduc" supported="disabled">
@@ -14501,32 +18284,79 @@ typedef void <name>CAMetalLayer</name>;
</extension>
<extension name="VK_FUCHSIA_extension_364" number="364" author="FUCHSIA" contact="Craig Stout @cdotstout" supported="disabled">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_364_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_364&quot;" name="VK_EXT_EXTENSION_364_EXTENSION_NAME"/>
- </require>
- </extension>
- <extension name="VK_FUCHSIA_extension_365" number="365" author="FUCHSIA" contact="Craig Stout @cdotstout" supported="disabled">
- <require>
- <enum value="0" name="VK_EXT_EXTENSION_365_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_365&quot;" name="VK_EXT_EXTENSION_365_EXTENSION_NAME"/>
- </require>
- </extension>
- <extension name="VK_FUCHSIA_extension_366" number="366" author="FUCHSIA" contact="Craig Stout @cdotstout" supported="disabled">
- <require>
- <enum value="0" name="VK_EXT_EXTENSION_366_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_366&quot;" name="VK_EXT_EXTENSION_366_EXTENSION_NAME"/>
- </require>
- </extension>
- <extension name="VK_FUCHSIA_extension_367" number="367" author="FUCHSIA" contact="Craig Stout @cdotstout" supported="disabled">
- <require>
- <enum value="0" name="VK_EXT_EXTENSION_367_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_367&quot;" name="VK_EXT_EXTENSION_367_EXTENSION_NAME"/>
+ <enum value="0" name="VK_FUCHSIA_EXTENSION_364_SPEC_VERSION"/>
+ <enum value="&quot;VK_FUCHSIA_extension_364&quot;" name="VK_FUCHSIA_EXTENSION_364_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_FUCHSIA_external_memory" number="365" type="device" requires="VK_KHR_external_memory_capabilities,VK_KHR_external_memory" author="FUCHSIA" contact="John Rosasco @rosasco" platform="fuchsia" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION"/>
+ <enum value="&quot;VK_FUCHSIA_external_memory&quot;" name="VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA"/>
+ <enum bitpos="11" extends="VkExternalMemoryHandleTypeFlagBits" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA"/>
+ <type name="VkImportMemoryZirconHandleInfoFUCHSIA"/>
+ <type name="VkMemoryZirconHandlePropertiesFUCHSIA"/>
+ <type name="VkMemoryGetZirconHandleInfoFUCHSIA"/>
+ <command name="vkGetMemoryZirconHandleFUCHSIA"/>
+ <command name="vkGetMemoryZirconHandlePropertiesFUCHSIA"/>
+ </require>
+ </extension>
+ <extension name="VK_FUCHSIA_external_semaphore" number="366" type="device" requires="VK_KHR_external_semaphore_capabilities,VK_KHR_external_semaphore" author="FUCHSIA" contact="John Rosasco @rosasco" platform="fuchsia" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION"/>
+ <enum value="&quot;VK_FUCHSIA_external_semaphore&quot;" name="VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA"/>
+ <enum bitpos="7" extends="VkExternalSemaphoreHandleTypeFlagBits" name="VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA"/>
+ <type name="VkImportSemaphoreZirconHandleInfoFUCHSIA"/>
+ <type name="VkSemaphoreGetZirconHandleInfoFUCHSIA"/>
+ <command name="vkImportSemaphoreZirconHandleFUCHSIA"/>
+ <command name="vkGetSemaphoreZirconHandleFUCHSIA"/>
+ </require>
+ </extension>
+ <extension name="VK_FUCHSIA_buffer_collection" number="367" type="device" requires="VK_FUCHSIA_external_memory,VK_KHR_sampler_ycbcr_conversion" author="FUCHSIA" contact="John Rosasco @rosasco" supported="vulkan" platform="fuchsia">
+ <require>
+ <enum value="2" name="VK_FUCHSIA_BUFFER_COLLECTION_SPEC_VERSION"/>
+ <enum value="&quot;VK_FUCHSIA_buffer_collection&quot;" name="VK_FUCHSIA_BUFFER_COLLECTION_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CREATE_INFO_FUCHSIA"/>
+ <enum offset="0" extends="VkObjectType" name="VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA" comment="VkBufferCollectionFUCHSIA"/>
+ <enum offset="0" extends="VkDebugReportObjectTypeEXT" name="VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMPORT_MEMORY_BUFFER_COLLECTION_FUCHSIA"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_IMAGE_CREATE_INFO_FUCHSIA"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_PROPERTIES_FUCHSIA"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_CONSTRAINTS_INFO_FUCHSIA"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_BUFFER_CREATE_INFO_FUCHSIA"/>
+ <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_CONSTRAINTS_INFO_FUCHSIA"/>
+ <enum offset="7" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_FORMAT_CONSTRAINTS_INFO_FUCHSIA"/>
+ <enum offset="8" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SYSMEM_COLOR_SPACE_FUCHSIA"/>
+ <enum offset="9" extends="VkStructureType" name="VK_STRUCTURE_TYPE_BUFFER_COLLECTION_CONSTRAINTS_INFO_FUCHSIA"/>
+ <type name="VkBufferCollectionFUCHSIA"/>
+ <type name="VkBufferCollectionCreateInfoFUCHSIA"/>
+ <type name="VkImportMemoryBufferCollectionFUCHSIA"/>
+ <type name="VkBufferCollectionImageCreateInfoFUCHSIA"/>
+ <type name="VkBufferConstraintsInfoFUCHSIA"/>
+ <type name="VkBufferCollectionBufferCreateInfoFUCHSIA"/>
+ <type name="VkBufferCollectionPropertiesFUCHSIA"/>
+ <type name="VkImageFormatConstraintsFlagsFUCHSIA" comment="Will add VkImageFormatConstraintsFlagBitsFUCHSIA when bits are defined in the future"/>
+ <type name="VkSysmemColorSpaceFUCHSIA"/>
+ <type name="VkImageConstraintsInfoFlagBitsFUCHSIA"/>
+ <type name="VkImageConstraintsInfoFlagsFUCHSIA"/>
+ <type name="VkImageConstraintsInfoFUCHSIA"/>
+ <type name="VkImageFormatConstraintsInfoFUCHSIA"/>
+ <type name="VkBufferCollectionConstraintsInfoFUCHSIA"/>
+ <command name="vkCreateBufferCollectionFUCHSIA"/>
+ <command name="vkSetBufferCollectionImageConstraintsFUCHSIA"/>
+ <command name="vkSetBufferCollectionBufferConstraintsFUCHSIA"/>
+ <command name="vkDestroyBufferCollectionFUCHSIA"/>
+ <command name="vkGetBufferCollectionPropertiesFUCHSIA"/>
</require>
</extension>
<extension name="VK_FUCHSIA_extension_368" number="368" author="FUCHSIA" contact="Craig Stout @cdotstout" supported="disabled">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_368_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_368&quot;" name="VK_EXT_EXTENSION_368_EXTENSION_NAME"/>
+ <enum value="0" name="VK_FUCHSIA_EXTENSION_368_SPEC_VERSION"/>
+ <enum value="&quot;VK_FUCHSIA_extension_368&quot;" name="VK_FUCHSIA_EXTENSION_368_EXTENSION_NAME"/>
</require>
</extension>
<extension name="VK_QCOM_extension_369" number="369" author="QCOM" contact="Matthew Netsch @mnetsch" supported="disabled">
@@ -14536,63 +18366,116 @@ typedef void <name>CAMetalLayer</name>;
<enum bitpos="4" extends="VkDescriptorBindingFlagBits" name="VK_DESCRIPTOR_BINDING_RESERVED_4_BIT_QCOM"/>
</require>
</extension>
- <extension name="VK_HUAWEI_extension_370" number="370" author="HUAWEI" contact="Hueilong Wang @wyvernathuawei" supported="disabled">
+ <extension name="VK_HUAWEI_subpass_shading" number="370" type="device" author="HUAWEI" contact="Pan Gao @PanGao-h" requires="VK_KHR_create_renderpass2,VK_KHR_synchronization2" supported="vulkan">
<require>
- <enum value="0" name="VK_HUAWEI_EXTENSION_370_SPEC_VERSION"/>
- <enum value="&quot;VK_HUAWEI_extension_370&quot;" name="VK_HUAWEI_EXTENSION_370_EXTENSION_NAME"/>
+ <enum value="2" name="VK_HUAWEI_SUBPASS_SHADING_SPEC_VERSION"/>
+ <enum value="&quot;VK_HUAWEI_subpass_shading&quot;" name="VK_HUAWEI_SUBPASS_SHADING_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SUBPASS_SHADING_PIPELINE_CREATE_INFO_HUAWEI"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_FEATURES_HUAWEI"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_SHADING_PROPERTIES_HUAWEI"/>
+ <enum offset="3" extends="VkPipelineBindPoint" extnumber="370" name="VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI"/>
+ <enum bitpos="39" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_SUBPASS_SHADING_BIT_HUAWEI"/>
+ <enum bitpos="14" extends="VkShaderStageFlagBits" name="VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI"/>
+ <type name="VkSubpassShadingPipelineCreateInfoHUAWEI"/>
+ <type name="VkPhysicalDeviceSubpassShadingFeaturesHUAWEI"/>
+ <type name="VkPhysicalDeviceSubpassShadingPropertiesHUAWEI"/>
+ <command name="vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEI"/>
+ <command name="vkCmdSubpassShadingHUAWEI"/>
</require>
</extension>
- <extension name="VK_HUAWEI_extension_371" number="371" author="HUAWEI" contact="Hueilong Wang @wyvernathuawei" supported="disabled">
+ <extension name="VK_HUAWEI_invocation_mask" number="371" type="device" requires="VK_KHR_ray_tracing_pipeline,VK_KHR_synchronization2" author="Huawei" contact="Pan Gao @PanGao-h" supported="vulkan">
<require>
- <enum value="0" name="VK_HUAWEI_EXTENSION_371_SPEC_VERSION"/>
- <enum value="&quot;VK_HUAWEI_extension_371&quot;" name="VK_HUAWEI_EXTENSION_371_EXTENSION_NAME"/>
+ <enum value="1" name="VK_HUAWEI_INVOCATION_MASK_SPEC_VERSION"/>
+ <enum value="&quot;VK_HUAWEI_invocation_mask&quot;" name="VK_HUAWEI_INVOCATION_MASK_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INVOCATION_MASK_FEATURES_HUAWEI"/>
+ <enum bitpos="39" extends="VkAccessFlagBits2" name="VK_ACCESS_2_INVOCATION_MASK_READ_BIT_HUAWEI"/>
+ <enum bitpos="18" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI"/>
+ <enum bitpos="40" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_INVOCATION_MASK_BIT_HUAWEI"/>
+ <type name="VkPhysicalDeviceInvocationMaskFeaturesHUAWEI"/>
+ <command name="vkCmdBindInvocationMaskHUAWEI"/>
</require>
</extension>
- <extension name="VK_NV_extension_372" number="372" author="NV" contact="Carsten Rohde @crohde" supported="disabled">
+ <extension name="VK_NV_external_memory_rdma" number="372" type="device" requires="VK_KHR_external_memory" author="NV" contact="Carsten Rohde @crohde" supported="vulkan">
<require>
- <enum value="0" name="VK_NV_EXTENSION_372_SPEC_VERSION"/>
- <enum value="&quot;VK_NV_extension_372&quot;" name="VK_NV_EXTENSION_372_EXTENSION_NAME"/>
- <enum bitpos="5" extends="VkBufferCreateFlagBits" name="VK_BUFFER_CREATE_RESERVED_5_BIT_NV"/>
- <enum bitpos="15" extends="VkImageCreateFlagBits" name="VK_IMAGE_CREATE_RESERVED_15_BIT_NV"/>
+ <enum value="1" name="VK_NV_EXTERNAL_MEMORY_RDMA_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_external_memory_rdma&quot;" name="VK_NV_EXTERNAL_MEMORY_RDMA_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_MEMORY_GET_REMOTE_ADDRESS_INFO_NV"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_RDMA_FEATURES_NV"/>
+ <enum bitpos="8" extends="VkMemoryPropertyFlagBits" name="VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV"/>
+ <enum bitpos="12" extends="VkExternalMemoryHandleTypeFlagBits" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV"/>
+ <type name="VkRemoteAddressNV"/>
+ <type name="VkMemoryGetRemoteAddressInfoNV"/>
+ <type name="VkPhysicalDeviceExternalMemoryRDMAFeaturesNV"/>
+ <command name="vkGetMemoryRemoteAddressNV"/>
</require>
</extension>
- <extension name="VK_NV_extension_373" number="373" author="NV" contact="Daniel Koch @dgkoch" supported="disabled">
+ <extension name="VK_EXT_pipeline_properties" number="373" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Mukund Keshava @mkeshavanv" supported="vulkan">
<require>
- <enum value="0" name="VK_NV_EXTENSION_373_SPEC_VERSION"/>
- <enum value="&quot;VK_NV_extension_373&quot;" name="VK_NV_EXTENSION_373_EXTENSION_NAME"/>
+ <enum value="1" name="VK_EXT_PIPELINE_PROPERTIES_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_pipeline_properties&quot;" name="VK_EXT_PIPELINE_PROPERTIES_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_PROPERTIES_IDENTIFIER_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_INFO_EXT" alias="VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR"/>
+ <type name="VkPipelineInfoEXT"/>
+ <type name="VkPipelinePropertiesIdentifierEXT"/>
+ <type name="VkPhysicalDevicePipelinePropertiesFeaturesEXT"/>
+ <command name="vkGetPipelinePropertiesEXT"/>
</require>
</extension>
<extension name="VK_NV_extension_374" number="374" author="NV" contact="Daniel Koch @dgkoch" supported="disabled">
<require>
<enum value="0" name="VK_NV_EXTENSION_374_SPEC_VERSION"/>
<enum value="&quot;VK_NV_extension_374&quot;" name="VK_NV_EXTENSION_374_EXTENSION_NAME"/>
+ <enum bitpos="4" extends="VkExternalFenceHandleTypeFlagBits" name="VK_EXTERNAL_FENCE_HANDLE_TYPE_RESERVED_4_BIT_NV"/>
+ <enum bitpos="5" extends="VkExternalFenceHandleTypeFlagBits" name="VK_EXTERNAL_FENCE_HANDLE_TYPE_RESERVED_5_BIT_NV"/>
+ <enum bitpos="5" extends="VkExternalSemaphoreHandleTypeFlagBits" name="VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_RESERVED_5_BIT_NV"/>
</require>
</extension>
<extension name="VK_NV_extension_375" number="375" author="NV" contact="Daniel Koch @dgkoch" supported="disabled">
<require>
<enum value="0" name="VK_NV_EXTENSION_375_SPEC_VERSION"/>
<enum value="&quot;VK_NV_extension_375&quot;" name="VK_NV_EXTENSION_375_EXTENSION_NAME"/>
+ <enum bitpos="13" extends="VkExternalMemoryHandleTypeFlagBits" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_RESERVED_13_BIT_NV"/>
</require>
</extension>
- <extension name="VK_EXT_extension_376" number="376" author="EXT" contact="Shahbaz Youssefi @syoussefi" supported="disabled">
+ <extension name="VK_EXT_extension_376" number="376" author="EXT" contact="Melih Yasin Yalcin @yalcinmelihyasin" supported="disabled">
<require>
<enum value="0" name="VK_EXT_EXTENSION_376_SPEC_VERSION"/>
<enum value="&quot;VK_EXT_extension_376&quot;" name="VK_EXT_EXTENSION_376_EXTENSION_NAME"/>
</require>
</extension>
- <extension name="VK_EXT_extension_377" number="377" author="EXT" contact="Hugues Evrard @hevrard" supported="disabled">
+ <extension name="VK_EXT_multisampled_render_to_single_sampled" number="377" type="device" requires="VK_KHR_create_renderpass2,VK_KHR_depth_stencil_resolve" author="EXT" contact="Shahbaz Youssefi @syoussefi" supported="vulkan">
<require>
- <enum value="0" name="VK_EXT_EXTENSION_377_SPEC_VERSION"/>
- <enum value="&quot;VK_EXT_extension_377&quot;" name="VK_EXT_EXTENSION_377_EXTENSION_NAME"/>
+ <enum value="1" name="VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_multisampled_render_to_single_sampled&quot;" name="VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SUBPASS_RESOLVE_PERFORMANCE_QUERY_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_EXT"/>
+ <enum bitpos="18" extends="VkImageCreateFlagBits" name="VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT"/>
+ <type name="VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesEXT"/>
+ <type name="VkSubpassResolvePerformanceQueryEXT"/>
+ <type name="VkMultisampledRenderToSingleSampledInfoEXT"/>
</require>
</extension>
- <extension name="VK_NV_extension_378" number="378" author="NV" contact="Vikram Kushwaha @vkushwaha-nv" supported="disabled">
+ <extension name="VK_EXT_extended_dynamic_state2" number="378" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Vikram Kushwaha @vkushwaha-nv" supported="vulkan" promotedto="VK_VERSION_1_3">
<require>
- <enum value="0" name="VK_NV_EXTENSION_378_SPEC_VERSION"/>
- <enum value="&quot;VK_NV_extension_378&quot;" name="VK_NV_EXTENSION_378_EXTENSION_NAME"/>
+ <enum value="1" name="VK_EXT_EXTENDED_DYNAMIC_STATE_2_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extended_dynamic_state2&quot;" name="VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT" comment="Not promoted to 1.3"/>
+ <enum offset="0" extends="VkDynamicState" name="VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT" comment="Not promoted to 1.3"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT" alias="VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT" alias="VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE"/>
+ <enum offset="3" extends="VkDynamicState" name="VK_DYNAMIC_STATE_LOGIC_OP_EXT" comment="Not promoted to 1.3"/>
+ <enum extends="VkDynamicState" name="VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT" alias="VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE"/>
+ <type name="VkPhysicalDeviceExtendedDynamicState2FeaturesEXT" comment="Not promoted to 1.3"/>
+ <command name="vkCmdSetPatchControlPointsEXT" comment="Not promoted to 1.3"/>
+ <command name="vkCmdSetRasterizerDiscardEnableEXT"/>
+ <command name="vkCmdSetDepthBiasEnableEXT"/>
+ <command name="vkCmdSetLogicOpEXT" comment="Not promoted to 1.3"/>
+ <command name="vkCmdSetPrimitiveRestartEnableEXT"/>
</require>
</extension>
- <extension name="VK_QNX_screen_surface" number="379" type="instance" requires="VK_KHR_surface" platform="screen" author="QNX" contact="Mike Gorchak @mgorchak-blackberry" supported="disabled">
+ <extension name="VK_QNX_screen_surface" number="379" type="instance" requires="VK_KHR_surface" platform="screen" author="QNX" contact="Mike Gorchak @mgorchak-blackberry" supported="vulkan">
<require>
<enum value="1" name="VK_QNX_SCREEN_SURFACE_SPEC_VERSION"/>
<enum value="&quot;VK_QNX_screen_surface&quot;" name="VK_QNX_SCREEN_SURFACE_EXTENSION_NAME"/>
@@ -14603,10 +18486,2180 @@ typedef void <name>CAMetalLayer</name>;
<command name="vkGetPhysicalDeviceScreenPresentationSupportQNX"/>
</require>
</extension>
+ <extension name="VK_KHR_extension_380" number="380" author="KHR" contact="James Jones @cubanismo" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_380_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_380&quot;" name="VK_KHR_EXTENSION_380_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_381" number="381" author="KHR" contact="James Jones @cubanismo" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_381_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_381&quot;" name="VK_KHR_EXTENSION_381_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_color_write_enable" number="382" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Sharif Elcott @selcott" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_COLOR_WRITE_ENABLE_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_color_write_enable&quot;" name="VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT"/>
+ <enum offset="0" extends="VkDynamicState" name="VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT"/>
+ <type name="VkPhysicalDeviceColorWriteEnableFeaturesEXT"/>
+ <type name="VkPipelineColorWriteCreateInfoEXT"/>
+ <command name="vkCmdSetColorWriteEnableEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_primitives_generated_query" number="383" type="device" requires="VK_EXT_transform_feedback" author="EXT" contact="Shahbaz Youssefi @syoussefi" supported="vulkan" specialuse="glemulation">
+ <require>
+ <enum value="1" name="VK_EXT_PRIMITIVES_GENERATED_QUERY_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_primitives_generated_query&quot;" name="VK_EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVES_GENERATED_QUERY_FEATURES_EXT"/>
+ <enum offset="0" extends="VkQueryType" name="VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT"/>
+ <type name="VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_384" number="384" type="instance" author="EXT" contact="Chia-I Wu @olvaffe1" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_384_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_384&quot;" name="VK_EXT_EXTENSION_384_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_MESA_extension_385" number="385" type="instance" author="MESA" contact="Chia-I Wu @olvaffe1" supported="disabled">
+ <require>
+ <enum value="0" name="VK_MESA_EXTENSION_385_SPEC_VERSION"/>
+ <enum value="&quot;VK_MESA_extension_385&quot;" name="VK_MESA_EXTENSION_385_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GOOGLE_extension_386" number="386" author="GOOGLE" contact="Chia-I Wu @olvaffe1" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GOOGLE_EXTENSION_386_SPEC_VERSION"/>
+ <enum value="&quot;VK_GOOGLE_extension_386&quot;" name="VK_GOOGLE_EXTENSION_386_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_ray_tracing_maintenance1" number="387" type="device" requiresCore="1.1" requires="VK_KHR_acceleration_structure" author="KHR" contact="Daniel Koch @dgkoch" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_KHR_RAY_TRACING_MAINTENANCE_1_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_ray_tracing_maintenance1&quot;" name="VK_KHR_RAY_TRACING_MAINTENANCE_1_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_MAINTENANCE_1_FEATURES_KHR"/>
+ <enum offset="0" extends="VkQueryType" name="VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_BOTTOM_LEVEL_POINTERS_KHR"/>
+ <enum offset="1" extends="VkQueryType" name="VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SIZE_KHR"/>
+ <type name="VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR"/>
+ </require>
+ <require extension="VK_KHR_synchronization2">
+ <!-- VkPipelineStageFlagBits bitpos="28" is reserved by this extension, but not used -->
+ <enum bitpos="28" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_COPY_BIT_KHR"/>
+ </require>
+ <require extension="VK_KHR_synchronization2,VK_KHR_ray_tracing_pipeline">
+ <enum bitpos="40" extends="VkAccessFlagBits2" name="VK_ACCESS_2_SHADER_BINDING_TABLE_READ_BIT_KHR"/>
+ </require>
+ <require extension="VK_KHR_ray_tracing_pipeline">
+ <type name="VkTraceRaysIndirectCommand2KHR"/>
+ <command name="vkCmdTraceRaysIndirect2KHR"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_388" number="388" author="EXT" contact="Alan Baker @alan-baker" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_388_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_388&quot;" name="VK_EXT_EXTENSION_388_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_global_priority_query" number="389" type="device" requires="VK_EXT_global_priority,VK_KHR_get_physical_device_properties2" author="EXT" contact="Yiwei Zhang @zhangyiwei" supported="vulkan" promotedto="VK_KHR_global_priority">
+ <require>
+ <enum value="1" name="VK_EXT_GLOBAL_PRIORITY_QUERY_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_global_priority_query&quot;" name="VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME"/>
+ <enum extends="VkStructureType" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT"/>
+ <enum extends="VkStructureType" alias="VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR" name="VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT"/>
+ <enum name="VK_MAX_GLOBAL_PRIORITY_SIZE_EXT"/>
+ <type name="VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT"/>
+ <type name="VkQueueFamilyGlobalPriorityPropertiesEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_390" number="390" author="EXT" contact="Joshua Ashton @Joshua-Ashton" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_390_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_390&quot;" name="VK_EXT_EXTENSION_390_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_391" number="391" author="EXT" contact="Joshua Ashton @Joshua-Ashton" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_391_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_391&quot;" name="VK_EXT_EXTENSION_391_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_image_view_min_lod" number="392" type="device" requires="VK_KHR_get_physical_device_properties2" author="EXT" contact="Joshua Ashton @Joshua-Ashton" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_IMAGE_VIEW_MIN_LOD_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_image_view_min_lod&quot;" name="VK_EXT_IMAGE_VIEW_MIN_LOD_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT"/>
+ <type name="VkPhysicalDeviceImageViewMinLodFeaturesEXT"/>
+ <type name="VkImageViewMinLodCreateInfoEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_multi_draw" number="393" author="EXT" contact="Mike Blumenkrantz @zmike" type="device" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_MULTI_DRAW_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_multi_draw&quot;" name="VK_EXT_MULTI_DRAW_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT"/>
+ <type name="VkPhysicalDeviceMultiDrawFeaturesEXT"/>
+ <type name="VkPhysicalDeviceMultiDrawPropertiesEXT"/>
+ <command name="vkCmdDrawMultiEXT"/>
+ <command name="vkCmdDrawMultiIndexedEXT"/>
+ <type name="VkMultiDrawInfoEXT"/>
+ <type name="VkMultiDrawIndexedInfoEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_image_2d_view_of_3d" number="394" requires="VK_KHR_maintenance1,VK_KHR_get_physical_device_properties2" author="EXT" contact="Mike Blumenkrantz @zmike" specialuse="glemulation" type="device" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_IMAGE_2D_VIEW_OF_3D_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_image_2d_view_of_3d&quot;" name="VK_EXT_IMAGE_2D_VIEW_OF_3D_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_2D_VIEW_OF_3D_FEATURES_EXT"/>
+ <type name="VkPhysicalDeviceImage2DViewOf3DFeaturesEXT"/>
+ <enum extends="VkImageCreateFlagBits" bitpos="17" name="VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT" comment="Image is created with a layout where individual slices are capable of being used as 2D images"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_portability_enumeration" number="395" author="KHR" contact="Charles Giessen @charles-lunarg" type="instance" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_KHR_PORTABILITY_ENUMERATION_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_portability_enumeration&quot;" name="VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME"/>
+ <enum bitpos="0" extends="VkInstanceCreateFlagBits" name="VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_396" number="396" author="EXT" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_396_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_396&quot;" name="VK_KHR_EXTENSION_396_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_397" number="397" author="NV" contact="Christoph Kubisch @pixeljetstream" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_397_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_397&quot;" name="VK_NV_EXTENSION_397_EXTENSION_NAME"/>
+ <enum bitpos="30" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_RESERVED_30_BIT_NV"/>
+ <enum bitpos="44" extends="VkAccessFlagBits2" name="VK_ACCESS_2_RESERVED_44_BIT_NV"/>
+ <enum bitpos="45" extends="VkAccessFlagBits2" name="VK_ACCESS_2_RESERVED_45_BIT_NV"/>
+ <enum bitpos="23" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_RESERVED_23_BIT_NV"/>
+ <enum bitpos="24" extends="VkBufferUsageFlagBits" name="VK_BUFFER_USAGE_RESERVED_24_BIT_NV"/>
+ <enum bitpos="24" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_RESERVED_24_BIT_NV"/>
+ <enum bitpos="4" extends="VkGeometryInstanceFlagBitsKHR" name="VK_GEOMETRY_INSTANCE_RESERVED_4_BIT_NV"/>
+ <enum bitpos="5" extends="VkGeometryInstanceFlagBitsKHR" name="VK_GEOMETRY_INSTANCE_RESERVED_5_BIT_NV"/>
+ <enum bitpos="6" extends="VkBuildAccelerationStructureFlagBitsKHR" name="VK_BUILD_ACCELERATION_STRUCTURE_RESERVED_6_BIT_NV"/>
+ <enum bitpos="7" extends="VkBuildAccelerationStructureFlagBitsKHR" name="VK_BUILD_ACCELERATION_STRUCTURE_RESERVED_7_BIT_NV"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_398" number="398" author="NV" contact="Christoph Kubisch @pixeljetstream" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_398_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_398&quot;" name="VK_NV_EXTENSION_398_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_JUICE_extension_399" number="399" author="JUICE" contact="Dean Beeler @canadacow" supported="disabled">
+ <require>
+ <enum value="0" name="VK_JUICE_EXTENSION_399_SPEC_VERSION"/>
+ <enum value="&quot;VK_JUICE_extension_399&quot;" name="VK_JUICE_EXTENSION_399_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_JUICE_extension_400" number="400" author="JUICE" contact="David McCloskey @damcclos" supported="disabled">
+ <require>
+ <enum value="0" name="VK_JUICE_EXTENSION_400_SPEC_VERSION"/>
+ <enum value="&quot;VK_JUICE_extension_400&quot;" name="VK_JUICE_EXTENSION_400_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_load_store_op_none" number="401" author="EXT" type="device" contact="Shahbaz Youssefi @syoussefi" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_LOAD_STORE_OP_NONE_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_load_store_op_none&quot;" name="VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkAttachmentLoadOp" name="VK_ATTACHMENT_LOAD_OP_NONE_EXT"/>
+ <enum extends="VkAttachmentStoreOp" name="VK_ATTACHMENT_STORE_OP_NONE_EXT" alias="VK_ATTACHMENT_STORE_OP_NONE"/>
+ </require>
+ </extension>
+ <extension name="VK_FB_extension_402" number="402" author="FB" contact="Artem Bolgar @artyom17" supported="disabled">
+ <require>
+ <enum value="0" name="VK_FB_EXTENSION_402_SPEC_VERSION"/>
+ <enum value="&quot;VK_FB_extension_402&quot;" name="VK_FB_EXTENSION_402_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_FB_extension_403" number="403" author="FB" contact="Artem Bolgar @artyom17" supported="disabled">
+ <require>
+ <enum value="0" name="VK_FB_EXTENSION_403_SPEC_VERSION"/>
+ <enum value="&quot;VK_FB_extension_403&quot;" name="VK_FB_EXTENSION_403_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_FB_extension_404" number="404" author="FB" contact="Artem Bolgar @artyom17" supported="disabled">
+ <require>
+ <enum value="0" name="VK_FB_EXTENSION_404_SPEC_VERSION"/>
+ <enum value="&quot;VK_FB_extension_404&quot;" name="VK_FB_EXTENSION_404_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_HUAWEI_extension_405" number="405" author="HUAWEI" contact="Hueilong Wang @wyvernathuawei" supported="disabled">
+ <require>
+ <enum value="0" name="VK_HUAWEI_EXTENSION_405_SPEC_VERSION"/>
+ <enum value="&quot;VK_HUAWEI_extension_405&quot;" name="VK_HUAWEI_EXTENSION_405_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_HUAWEI_extension_406" number="406" author="HUAWEI" contact="Hueilong Wang @wyvernathuawei" supported="disabled">
+ <require>
+ <enum value="0" name="VK_HUAWEI_EXTENSION_406_SPEC_VERSION"/>
+ <enum value="&quot;VK_HUAWEI_extension_406&quot;" name="VK_HUAWEI_EXTENSION_406_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GGP_extension_407" number="407" author="GGP" contact="J.D. Rouan @jdrouan" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GGP_EXTENSION_407_SPEC_VERSION"/>
+ <enum value="&quot;VK_GGP_extension_407&quot;" name="VK_GGP_EXTENSION_407_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GGP_extension_408" number="408" author="GGP" contact="J.D. Rouan @jdrouan" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GGP_EXTENSION_408_SPEC_VERSION"/>
+ <enum value="&quot;VK_GGP_extension_408&quot;" name="VK_GGP_EXTENSION_408_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GGP_extension_409" number="409" author="GGP" contact="J.D. Rouan @jdrouan" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GGP_EXTENSION_409_SPEC_VERSION"/>
+ <enum value="&quot;VK_GGP_extension_409&quot;" name="VK_GGP_EXTENSION_409_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GGP_extension_410" number="410" author="GGP" contact="J.D. Rouan @jdrouan" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GGP_EXTENSION_410_SPEC_VERSION"/>
+ <enum value="&quot;VK_GGP_extension_410&quot;" name="VK_GGP_EXTENSION_410_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GGP_extension_411" number="411" author="GGP" contact="J.D. Rouan @jdrouan" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GGP_EXTENSION_411_SPEC_VERSION"/>
+ <enum value="&quot;VK_GGP_extension_411&quot;" name="VK_GGP_EXTENSION_411_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_border_color_swizzle" number="412" type="device" author="EXT" contact="Piers Daniell @pdaniell-nv" supported="vulkan" requires="VK_EXT_custom_border_color" specialuse="glemulation,d3demulation">
+ <require>
+ <enum value="1" name="VK_EXT_BORDER_COLOR_SWIZZLE_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_border_color_swizzle&quot;" name="VK_EXT_BORDER_COLOR_SWIZZLE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BORDER_COLOR_SWIZZLE_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT"/>
+ <type name="VkPhysicalDeviceBorderColorSwizzleFeaturesEXT"/>
+ <type name="VkSamplerBorderColorComponentMappingCreateInfoEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_pageable_device_local_memory" number="413" author="EXT" contact="Piers Daniell @pdaniell-nv" type="device" requires="VK_EXT_memory_priority" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_pageable_device_local_memory&quot;" name="VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT"/>
+ <type name="VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT"/>
+ <command name="vkSetDeviceMemoryPriorityEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_maintenance4" number="414" type="device" requiresCore="1.1" author="KHR" contact="Piers Daniell @pdaniell-nv" supported="vulkan" promotedto="VK_VERSION_1_3">
+ <require>
+ <enum value="2" name="VK_KHR_MAINTENANCE_4_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_maintenance4&quot;" name="VK_KHR_MAINTENANCE_4_EXTENSION_NAME"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR" alias="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR" alias="VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS"/>
+ <enum extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR" alias="VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS"/>
+ <enum extends="VkImageAspectFlagBits" name="VK_IMAGE_ASPECT_NONE_KHR" alias="VK_IMAGE_ASPECT_NONE"/>
+ <type name="VkPhysicalDeviceMaintenance4FeaturesKHR"/>
+ <type name="VkPhysicalDeviceMaintenance4PropertiesKHR"/>
+ <type name="VkDeviceBufferMemoryRequirementsKHR"/>
+ <type name="VkDeviceImageMemoryRequirementsKHR"/>
+ <command name="vkGetDeviceBufferMemoryRequirementsKHR"/>
+ <command name="vkGetDeviceImageMemoryRequirementsKHR"/>
+ <command name="vkGetDeviceImageSparseMemoryRequirementsKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_HUAWEI_extension_415" number="415" author="HUAWEI" contact="Hueilong Wang @wyvernathuawei" supported="disabled">
+ <require>
+ <enum value="0" name="VK_HUAWEI_EXTENSION_415_SPEC_VERSION"/>
+ <enum value="&quot;VK_HUAWEI_extension_415&quot;" name="VK_HUAWEI_EXTENSION_415_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_ARM_extension_416" number="416" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="disabled">
+ <require>
+ <enum value="0" name="VK_ARM_EXTENSION_416_SPEC_VERSION"/>
+ <enum value="&quot;VK_ARM_extension_416&quot;" name="VK_ARM_EXTENSION_416_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_417" number="417" author="KHR" contact="Kevin Petit @kevinpetit" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_417_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_417&quot;" name="VK_KHR_EXTENSION_417_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_ARM_extension_418" number="418" author="ARM" contact="Kevin Petit @kevinpetit" supported="disabled">
+ <require>
+ <enum value="0" name="VK_ARM_EXTENSION_418_SPEC_VERSION"/>
+ <enum value="&quot;VK_ARM_extension_418&quot;" name="VK_ARM_EXTENSION_418_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_419" number="419" author="EXT" contact="Mike Blumenkrantz @zmike" type="device" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_419_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_419&quot;" name="VK_EXT_EXTENSION_419_EXTENSION_NAME"/>
+ <enum bitpos="3" extends="VkImageViewCreateFlagBits" name="VK_IMAGE_VIEW_CREATE_RESERVED_3_BIT_EXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_420" number="420" author="EXT" contact="Mike Blumenkrantz @zmike" type="device" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_420_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_420&quot;" name="VK_EXT_EXTENSION_420_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_VALVE_descriptor_set_host_mapping" number="421" type="device" author="VALVE" contact="Hans-Kristian Arntzen @HansKristian-Work" specialuse="d3demulation" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_SPEC_VERSION"/>
+ <enum value="&quot;VK_VALVE_descriptor_set_host_mapping&quot;" name="VK_VALVE_DESCRIPTOR_SET_HOST_MAPPING_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_SET_HOST_MAPPING_FEATURES_VALVE"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_BINDING_REFERENCE_VALVE"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_HOST_MAPPING_INFO_VALVE"/>
+ <type name="VkPhysicalDeviceDescriptorSetHostMappingFeaturesVALVE"/>
+ <type name="VkDescriptorSetBindingReferenceVALVE"/>
+ <type name="VkDescriptorSetLayoutHostMappingInfoVALVE"/>
+ <command name="vkGetDescriptorSetLayoutHostMappingInfoVALVE"/>
+ <command name="vkGetDescriptorSetHostMappingVALVE"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_422" number="422" author="EXT" contact="Graeme Leese @gnl21" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_422_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_422&quot;" name="VK_EXT_EXTENSION_422_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_non_seamless_cube_map" number="423" author="EXT" type="device" contact="Georg Lehmann @DadSchoorse" specialuse="d3demulation,glemulation" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_NON_SEAMLESS_CUBE_MAP_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_non_seamless_cube_map&quot;" name="VK_EXT_NON_SEAMLESS_CUBE_MAP_EXTENSION_NAME"/>
+ <enum bitpos="2" extends="VkSamplerCreateFlagBits" name="VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NON_SEAMLESS_CUBE_MAP_FEATURES_EXT"/>
+ <type name="VkPhysicalDeviceNonSeamlessCubeMapFeaturesEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_ARM_extension_424" number="424" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="disabled">
+ <require>
+ <enum value="0" name="VK_ARM_EXTENSION_424_SPEC_VERSION"/>
+ <enum value="&quot;VK_ARM_extension_424&quot;" name="VK_ARM_EXTENSION_424_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_ARM_extension_425" number="425" author="ARM" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="disabled">
+ <require>
+ <enum value="0" name="VK_ARM_EXTENSION_425_SPEC_VERSION"/>
+ <enum value="&quot;VK_ARM_extension_425&quot;" name="VK_ARM_EXTENSION_425_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_QCOM_fragment_density_map_offset" number="426" type="device" requires="VK_KHR_get_physical_device_properties2,VK_EXT_fragment_density_map" author="QCOM" contact="Matthew Netsch @mnetsch" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_fragment_density_map_offset&quot;" name="VK_QCOM_FRAGMENT_DENSITY_MAP_OFFSET_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_FEATURES_QCOM"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_QCOM"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SUBPASS_FRAGMENT_DENSITY_MAP_OFFSET_END_INFO_QCOM"/>
+ <enum bitpos="15" extends="VkImageCreateFlagBits" name="VK_IMAGE_CREATE_FRAGMENT_DENSITY_MAP_OFFSET_BIT_QCOM"/>
+ <type name="VkPhysicalDeviceFragmentDensityMapOffsetFeaturesQCOM"/>
+ <type name="VkPhysicalDeviceFragmentDensityMapOffsetPropertiesQCOM"/>
+ <type name="VkSubpassFragmentDensityMapOffsetEndInfoQCOM"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_427" number="427" author="NV" contact="Vikram Kushwaha @vkushwaha-nv" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_427_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_427&quot;" name="VK_NV_EXTENSION_427_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_428" number="428" author="NV" contact="Vikram Kushwaha @vkushwaha-nv" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_428_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_428&quot;" name="VK_NV_EXTENSION_428_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_429" number="429" author="NV" contact="Vikram Kushwaha @vkushwaha-nv" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_429_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_429&quot;" name="VK_NV_EXTENSION_429_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_430" number="430" author="NV" contact="Vikram Kushwaha @vkushwaha-nv" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_430_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_430&quot;" name="VK_NV_EXTENSION_430_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_linear_color_attachment" number="431" type="device" author="NVIDIA" contact="sourav parmar @souravpNV" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_NV_LINEAR_COLOR_ATTACHMENT_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_linear_color_attachment&quot;" name="VK_NV_LINEAR_COLOR_ATTACHMENT_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINEAR_COLOR_ATTACHMENT_FEATURES_NV"/>
+ <type name="VkPhysicalDeviceLinearColorAttachmentFeaturesNV"/>
+ </require>
+ <require extension="VK_KHR_format_feature_flags2">
+ <enum bitpos="38" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_LINEAR_COLOR_ATTACHMENT_BIT_NV" comment="Format support linear image as render target, it cannot be mixed with non linear attachment"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_432" number="432" author="NV" contact="Sourav Parmar @souravpNV" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_432_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_432&quot;" name="VK_NV_EXTENSION_432_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_433" number="433" author="NV" contact="Sourav Parmar @souravpNV" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_433_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_433&quot;" name="VK_NV_EXTENSION_433_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GOOGLE_surfaceless_query" number="434" type="instance" requires="VK_KHR_surface" author="GOOGLE" contact="Shahbaz Youssefi @syoussefi" specialuse="glemulation" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_GOOGLE_SURFACELESS_QUERY_SPEC_VERSION"/>
+ <enum value="&quot;VK_GOOGLE_surfaceless_query&quot;" name="VK_GOOGLE_SURFACELESS_QUERY_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_435" number="435" author="KHR" contact="Alan Baker @alan-baker" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_435_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_435&quot;" name="VK_KHR_EXTENSION_435_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_436" number="436" author="NV" contact="Daniel Koch @dgkoch" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_436_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_436&quot;" name="VK_NV_EXTENSION_436_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_437" number="437" author="EXT" contact="Jonathan Weinstein @Jonathan-Weinstein" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_437_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_437&quot;" name="VK_EXT_EXTENSION_437_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_image_compression_control_swapchain" number="438" type="device" requires="VK_EXT_image_compression_control" author="EXT" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_image_compression_control_swapchain&quot;" name="VK_EXT_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT"/>
+ <type name="VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_SEC_extension_439" number="439" author="SEC" contact="Ralph Potter gitlab:@r_potter" supported="disabled">
+ <require>
+ <enum value="0" name="VK_SEC_EXTENSION_439_SPEC_VERSION"/>
+ <enum value="&quot;VK_SEC_extension_439&quot;" name="VK_SEC_EXTENSION_439_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_QCOM_extension_440" number="440" author="QCOM" contact="Jeff Leger @jackohound" supported="disabled">
+ <require>
+ <enum value="0" name="VK_QCOM_EXTENSION_440_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_extension_440&quot;" name="VK_QCOM_EXTENSION_440_EXTENSION_NAME"/>
+ <enum bitpos="7" extends="VkQueueFlagBits" name="VK_QUEUE_RESERVED_7_BIT_QCOM"/>
+ <enum bitpos="1" extends="VkDeviceQueueCreateFlagBits" name="VK_DEVICE_QUEUE_CREATE_RESERVED_1_BIT_QCOM"/>
+ </require>
+ </extension>
+ <extension name="VK_QCOM_image_processing" number="441" type="device" requires="VK_KHR_format_feature_flags2" author="QCOM" contact="Jeff Leger @jackohound" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_QCOM_IMAGE_PROCESSING_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_image_processing&quot;" name="VK_QCOM_IMAGE_PROCESSING_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_FEATURES_QCOM"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_PROCESSING_PROPERTIES_QCOM"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_VIEW_SAMPLE_WEIGHT_CREATE_INFO_QCOM"/>
+ <enum bitpos="4" extends="VkSamplerCreateFlagBits" name="VK_SAMPLER_CREATE_IMAGE_PROCESSING_BIT_QCOM"/>
+ <enum bitpos="20" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM"/>
+ <enum bitpos="21" extends="VkImageUsageFlagBits" name="VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM"/>
+ <enum offset="0" extends="VkDescriptorType" name="VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM"/>
+ <enum offset="1" extends="VkDescriptorType" name="VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM"/>
+ <type name="VkImageViewSampleWeightCreateInfoQCOM"/>
+ <type name="VkPhysicalDeviceImageProcessingFeaturesQCOM"/>
+ <type name="VkPhysicalDeviceImageProcessingPropertiesQCOM"/>
+ </require>
+ <require extension="VK_KHR_format_feature_flags2">
+ <enum bitpos="34" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_WEIGHT_IMAGE_BIT_QCOM"/>
+ <enum bitpos="35" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_WEIGHT_SAMPLED_IMAGE_BIT_QCOM"/>
+ <enum bitpos="36" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_BLOCK_MATCHING_BIT_QCOM"/>
+ <enum bitpos="37" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_BOX_FILTER_SAMPLED_BIT_QCOM"/>
+ </require>
+ </extension>
+ <extension name="VK_COREAVI_extension_442" number="442" author="COREAVI" contact="Aidan Fabius @afabius" supported="disabled">
+ <require>
+ <enum value="0" name="VK_COREAVI_EXTENSION_442_SPEC_VERSION"/>
+ <enum value="&quot;VK_COREAVI_extension_442&quot;" name="VK_COREAVI_EXTENSION_442_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_COREAVI_extension_443" number="443" author="COREAVI" contact="Aidan Fabius @afabius" supported="disabled">
+ <require>
+ <enum value="0" name="VK_COREAVI_EXTENSION_443_SPEC_VERSION"/>
+ <enum value="&quot;VK_COREAVI_extension_443&quot;" name="VK_COREAVI_EXTENSION_443_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_COREAVI_extension_444" number="444" author="COREAVI" contact="Aidan Fabius @afabius" supported="disabled">
+ <require>
+ <enum value="0" name="VK_COREAVI_EXTENSION_444_SPEC_VERSION"/>
+ <enum value="&quot;VK_COREAVI_extension_444&quot;" name="VK_COREAVI_EXTENSION_444_EXTENSION_NAME"/>
+ <enum extends="VkCommandPoolResetFlagBits" bitpos="1" name="VK_COMMAND_POOL_RESET_RESERVED_1_BIT_COREAVI"/>
+ </require>
+ </extension>
+ <extension name="VK_COREAVI_extension_445" number="445" author="COREAVI" contact="Aidan Fabius @afabius" supported="disabled">
+ <require>
+ <enum value="0" name="VK_COREAVI_EXTENSION_445_SPEC_VERSION"/>
+ <enum value="&quot;VK_COREAVI_extension_445&quot;" name="VK_COREAVI_EXTENSION_445_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_COREAVI_extension_446" number="446" author="COREAVI" contact="Aidan Fabius @afabius" supported="disabled">
+ <require>
+ <enum value="0" name="VK_COREAVI_EXTENSION_446_SPEC_VERSION"/>
+ <enum value="&quot;VK_COREAVI_extension_446&quot;" name="VK_COREAVI_EXTENSION_446_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_COREAVI_extension_447" number="447" author="COREAVI" contact="Aidan Fabius @afabius" supported="disabled">
+ <require>
+ <enum value="0" name="VK_COREAVI_EXTENSION_447_SPEC_VERSION"/>
+ <enum value="&quot;VK_COREAVI_extension_447&quot;" name="VK_COREAVI_EXTENSION_447_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_SEC_extension_448" number="448" author="SEC" contact="Ralph Potter gitlab:@r_potter" supported="disabled">
+ <require>
+ <enum value="0" name="VK_SEC_EXTENSION_448_SPEC_VERSION"/>
+ <enum value="&quot;VK_SEC_extension_448&quot;" name="VK_SEC_EXTENSION_448_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_SEC_extension_449" number="449" author="SEC" contact="Ralph Potter gitlab:@r_potter" supported="disabled">
+ <require>
+ <enum value="0" name="VK_SEC_EXTENSION_449_SPEC_VERSION"/>
+ <enum value="&quot;VK_SEC_extension_449&quot;" name="VK_SEC_EXTENSION_449_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_SEC_extension_450" number="450" author="SEC" contact="Ralph Potter gitlab:@r_potter" supported="disabled">
+ <require>
+ <enum value="0" name="VK_SEC_EXTENSION_450_SPEC_VERSION"/>
+ <enum value="&quot;VK_SEC_extension_450&quot;" name="VK_SEC_EXTENSION_450_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_SEC_extension_451" number="451" author="SEC" contact="Ralph Potter gitlab:@r_potter" supported="disabled">
+ <require>
+ <enum value="0" name="VK_SEC_EXTENSION_451_SPEC_VERSION"/>
+ <enum value="&quot;VK_SEC_extension_451&quot;" name="VK_SEC_EXTENSION_451_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_452" number="452" author="NV" contact="Piers Daniell @pdaniell-nv" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_452_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_452&quot;" name="VK_NV_EXTENSION_452_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_ARM_extension_453" number="453" author="Arm" contact="Kevin Petit @kevinpetit" supported="disabled">
+ <require>
+ <enum value="0" name="VK_ARM_EXTENSION_453_SPEC_VERSION"/>
+ <enum value="&quot;VK_ARM_extension_453&quot;" name="VK_ARM_EXTENSION_453_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GOOGLE_extension_454" number="454" author="GOOGLE" contact="Chad Versace @chadversary" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GOOGLE_EXTENSION_454_SPEC_VERSION"/>
+ <enum value="&quot;VK_GOOGLE_extension_454&quot;" name="VK_GOOGLE_EXTENSION_454_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GOOGLE_extension_455" number="455" author="GOOGLE" contact="Chad Versace @chadversary" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GOOGLE_EXTENSION_455_SPEC_VERSION"/>
+ <enum value="&quot;VK_GOOGLE_extension_455&quot;" name="VK_GOOGLE_EXTENSION_455_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_456" number="456" author="NV" contact="Piers Daniell @pdaniell-nv" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_456_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_456&quot;" name="VK_NV_EXTENSION_456_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_457" number="457" author="RASTERGRID" contact="Daniel Rakos @aqnuep1" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_457_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_457&quot;" name="VK_EXT_EXTENSION_457_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_458" number="458" author="RASTERGRID" contact="Daniel Rakos @aqnuep1" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_458_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_458&quot;" name="VK_EXT_EXTENSION_458_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_subpass_merge_feedback" number="459" type="device" author="EXT" contact="Ting Wei @catweiting" supported="vulkan">
+ <require>
+ <enum value="2" name="VK_EXT_SUBPASS_MERGE_FEEDBACK_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_subpass_merge_feedback&quot;" name="VK_EXT_SUBPASS_MERGE_FEEDBACK_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBPASS_MERGE_FEEDBACK_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_CONTROL_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_RENDER_PASS_CREATION_FEEDBACK_CREATE_INFO_EXT"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_RENDER_PASS_SUBPASS_FEEDBACK_CREATE_INFO_EXT"/>
+ <type name="VkPhysicalDeviceSubpassMergeFeedbackFeaturesEXT"/>
+ <type name="VkRenderPassCreationControlEXT"/>
+ <type name="VkRenderPassCreationFeedbackInfoEXT"/>
+ <type name="VkRenderPassCreationFeedbackCreateInfoEXT"/>
+ <type name="VkRenderPassSubpassFeedbackInfoEXT"/>
+ <type name="VkRenderPassSubpassFeedbackCreateInfoEXT"/>
+ <type name="VkSubpassMergeStatusEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_460" number="460" author="EXT" contact="Charles Giessen @charles-lunarg" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_460_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_460&quot;" name="VK_EXT_EXTENSION_460_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_461" number="461" author="EXT" contact="Kevin Petit @kevinpetit" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_461_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_461&quot;" name="VK_EXT_EXTENSION_461_EXTENSION_NAME"/>
+ <enum bitpos="39" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_RESERVED_39_BIT_EXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_462" number="462" author="EXT" contact="Joshua Ashton @Joshua-Ashton,Liam Middlebrook @liam-middlebrook" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_462_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_462&quot;" name="VK_EXT_EXTENSION_462_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_shader_module_identifier" number="463" type="device" requires="VK_KHR_get_physical_device_properties2,VK_EXT_pipeline_creation_cache_control" author="EXT" contact="Hans-Kristian Arntzen @HansKristian-Work" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_SHADER_MODULE_IDENTIFIER_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_shader_module_identifier&quot;" name="VK_EXT_SHADER_MODULE_IDENTIFIER_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SHADER_MODULE_IDENTIFIER_EXT"/>
+ <enum name="VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT"/>
+ <type name="VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT"/>
+ <type name="VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT"/>
+ <type name="VkPipelineShaderStageModuleIdentifierCreateInfoEXT"/>
+ <type name="VkShaderModuleIdentifierEXT"/>
+ <command name="vkGetShaderModuleIdentifierEXT"/>
+ <command name="vkGetShaderModuleCreateInfoIdentifierEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_464" number="464" author="EXT" contact="Jan-Harald Fredriksen @janharaldfredriksen-arm" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_464_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_464&quot;" name="VK_EXT_EXTENSION_464_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_465" number="465" author="NV" contact="Carsten Rohde @crohde" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_465_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_465&quot;" name="VK_NV_EXTENSION_465_EXTENSION_NAME"/>
+ <enum bitpos="8" extends="VkQueueFlagBits" name="VK_QUEUE_RESERVED_8_BIT_NV"/>
+ <enum bitpos="29" extends="VkPipelineStageFlagBits2" name="VK_PIPELINE_STAGE_2_RESERVED_29_BIT_NV"/>
+ <enum bitpos="42" extends="VkAccessFlagBits2" name="VK_ACCESS_2_RESERVED_42_BIT_NV"/>
+ <enum bitpos="43" extends="VkAccessFlagBits2" name="VK_ACCESS_2_RESERVED_43_BIT_NV"/>
+ <enum bitpos="40" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_RESERVED_40_BIT_NV"/>
+ <enum bitpos="41" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_RESERVED_41_BIT_NV"/>
+ <enum bitpos="42" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_RESERVED_42_BIT_NV"/>
+ <enum bitpos="43" extends="VkFormatFeatureFlagBits2" name="VK_FORMAT_FEATURE_2_RESERVED_43_BIT_NV"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_466" number="466" author="EXT" contact="Shahbaz Youssefi @syoussefi" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_466_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_466&quot;" name="VK_EXT_EXTENSION_466_EXTENSION_NAME"/>
+ <enum bitpos="7" extends="VkSubpassDescriptionFlagBits" name="VK_SUBPASS_DESCRIPTION_RESERVED_7_BIT_EXT"/>
+ <enum bitpos="3" extends="VkRenderingFlagBits" name="VK_RENDERING_RESERVED_3_BIT_EXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_467" number="467" author="EXT" contact="Shahbaz Youssefi @syoussefi" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_467_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_467&quot;" name="VK_EXT_EXTENSION_467_EXTENSION_NAME"/>
+ <enum bitpos="27" extends="VkPipelineCreateFlagBits" name="VK_PIPELINE_CREATE_RESERVED_27_BIT_EXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_468" number="468" author="EXT" contact="Shahbaz Youssefi @syoussefi" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_468_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_468&quot;" name="VK_EXT_EXTENSION_468_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_ANDROID_extension_469" number="469" type="device" platform="android" author="ANDROID" contact="Chris Forbes @chrisforbes" supported="disabled">
+ <require>
+ <enum value="0" name="VK_ANDROID_EXTENSION_469_SPEC_VERSION"/>
+ <enum value="&quot;VK_ANDROID_extension_469&quot;" name="VK_ANDROID_EXTENSION_469_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_470" number="470" author="AMD" contact="Stu Smith" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_470_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_470&quot;" name="VK_AMD_EXTENSION_470_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_471" number="471" author="AMD" contact="Stu Smith" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_471_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_471&quot;" name="VK_AMD_EXTENSION_471_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_472" number="472" author="AMD" contact="Stu Smith" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_472_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_472&quot;" name="VK_AMD_EXTENSION_472_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_473" number="473" author="AMD" contact="Stu Smith" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_473_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_473&quot;" name="VK_AMD_EXTENSION_473_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_474" number="474" author="AMD" contact="Stu Smith" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_474_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_474&quot;" name="VK_AMD_EXTENSION_474_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_475" number="475" author="AMD" contact="Stu Smith" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_475_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_475&quot;" name="VK_AMD_EXTENSION_475_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_476" number="476" author="AMD" contact="Stu Smith" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_476_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_476&quot;" name="VK_AMD_EXTENSION_476_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_477" number="477" author="AMD" contact="Stu Smith" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_477_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_477&quot;" name="VK_AMD_EXTENSION_477_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_478" number="478" author="AMD" contact="Stu Smith" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_478_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_478&quot;" name="VK_AMD_EXTENSION_478_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_479" number="479" author="AMD" contact="Stu Smith" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_479_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_479&quot;" name="VK_AMD_EXTENSION_479_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_480" number="480" author="EXT" contact="Daniel Stone" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_480_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_480&quot;" name="VK_EXT_EXTENSION_480_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_481" number="481" author="EXT" contact="Daniel Stone" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_481_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_481&quot;" name="VK_EXT_EXTENSION_481_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_482" number="482" author="KHR" contact="Eric Werness" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_482_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_482&quot;" name="VK_EXT_EXTENSION_482_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_483" number="483" author="EXT" contact="Piers Daniell" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_483_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_483&quot;" name="VK_EXT_EXTENSION_483_EXTENSION_NAME"/>
+ <enum bitpos="15" extends="VkShaderStageFlagBits" name="VK_SHADER_STAGE_EXT_483_RESERVE_15"/>
+ <enum bitpos="16" extends="VkShaderStageFlagBits" name="VK_SHADER_STAGE_EXT_483_RESERVE_16"/>
+ <enum bitpos="17" extends="VkShaderStageFlagBits" name="VK_SHADER_STAGE_EXT_483_RESERVE_17"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_484" number="484" author="KHR" contact="Chris Glover @cdglove" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_484_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_484&quot;" name="VK_EXT_EXTENSION_484_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_QCOM_tile_properties" number="485" type="device" requires="VK_KHR_get_physical_device_properties2" author="QCOM" contact="Jeff Leger @jackohound" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_QCOM_TILE_PROPERTIES_SPEC_VERSION"/>
+ <enum value="&quot;VK_QCOM_tile_properties&quot;" name="VK_QCOM_TILE_PROPERTIES_EXTENSION_NAME"/>
+ <command name="vkGetFramebufferTilePropertiesQCOM"/>
+ <command name="vkGetDynamicRenderingTilePropertiesQCOM"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TILE_PROPERTIES_FEATURES_QCOM"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_TILE_PROPERTIES_QCOM"/>
+ <type name="VkPhysicalDeviceTilePropertiesFeaturesQCOM"/>
+ <type name="VkTilePropertiesQCOM"/>
+ <type name="VkRenderingInfoKHR"/>
+ </require>
+ </extension>
</extensions>
+ <formats>
+ <format name="VK_FORMAT_R4G4_UNORM_PACK8" class="8-bit" blockSize="1" texelsPerBlock="1" packed="8">
+ <component name="R" bits="4" numericFormat="UNORM"/>
+ <component name="G" bits="4" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R4G4B4A4_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="R" bits="4" numericFormat="UNORM"/>
+ <component name="G" bits="4" numericFormat="UNORM"/>
+ <component name="B" bits="4" numericFormat="UNORM"/>
+ <component name="A" bits="4" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_B4G4R4A4_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="B" bits="4" numericFormat="UNORM"/>
+ <component name="G" bits="4" numericFormat="UNORM"/>
+ <component name="R" bits="4" numericFormat="UNORM"/>
+ <component name="A" bits="4" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R5G6B5_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="R" bits="5" numericFormat="UNORM"/>
+ <component name="G" bits="6" numericFormat="UNORM"/>
+ <component name="B" bits="5" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_B5G6R5_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="B" bits="5" numericFormat="UNORM"/>
+ <component name="G" bits="6" numericFormat="UNORM"/>
+ <component name="R" bits="5" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R5G5B5A1_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="R" bits="5" numericFormat="UNORM"/>
+ <component name="G" bits="5" numericFormat="UNORM"/>
+ <component name="B" bits="5" numericFormat="UNORM"/>
+ <component name="A" bits="1" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_B5G5R5A1_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="B" bits="5" numericFormat="UNORM"/>
+ <component name="R" bits="5" numericFormat="UNORM"/>
+ <component name="G" bits="5" numericFormat="UNORM"/>
+ <component name="A" bits="1" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_A1R5G5B5_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="A" bits="1" numericFormat="UNORM"/>
+ <component name="R" bits="5" numericFormat="UNORM"/>
+ <component name="G" bits="5" numericFormat="UNORM"/>
+ <component name="B" bits="5" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R8_UNORM" class="8-bit" blockSize="1" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="UNORM"/>
+ <spirvimageformat name="R8"/>
+ </format>
+ <format name="VK_FORMAT_R8_SNORM" class="8-bit" blockSize="1" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SNORM"/>
+ <spirvimageformat name="R8Snorm"/>
+ </format>
+ <format name="VK_FORMAT_R8_USCALED" class="8-bit" blockSize="1" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_R8_SSCALED" class="8-bit" blockSize="1" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_R8_UINT" class="8-bit" blockSize="1" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="UINT"/>
+ <spirvimageformat name="R8ui"/>
+ </format>
+ <format name="VK_FORMAT_R8_SINT" class="8-bit" blockSize="1" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SINT"/>
+ <spirvimageformat name="R8i"/>
+ </format>
+ <format name="VK_FORMAT_R8_SRGB" class="8-bit" blockSize="1" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_R8G8_UNORM" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="UNORM"/>
+ <component name="G" bits="8" numericFormat="UNORM"/>
+ <spirvimageformat name="Rg8"/>
+ </format>
+ <format name="VK_FORMAT_R8G8_SNORM" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SNORM"/>
+ <component name="G" bits="8" numericFormat="SNORM"/>
+ <spirvimageformat name="Rg8Snorm"/>
+ </format>
+ <format name="VK_FORMAT_R8G8_USCALED" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="USCALED"/>
+ <component name="G" bits="8" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_R8G8_SSCALED" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SSCALED"/>
+ <component name="G" bits="8" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_R8G8_UINT" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="UINT"/>
+ <component name="G" bits="8" numericFormat="UINT"/>
+ <spirvimageformat name="Rg8ui"/>
+ </format>
+ <format name="VK_FORMAT_R8G8_SINT" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SINT"/>
+ <component name="G" bits="8" numericFormat="SINT"/>
+ <spirvimageformat name="Rg8i"/>
+ </format>
+ <format name="VK_FORMAT_R8G8_SRGB" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SRGB"/>
+ <component name="G" bits="8" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8_UNORM" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="UNORM"/>
+ <component name="G" bits="8" numericFormat="UNORM"/>
+ <component name="B" bits="8" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8_SNORM" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SNORM"/>
+ <component name="G" bits="8" numericFormat="SNORM"/>
+ <component name="B" bits="8" numericFormat="SNORM"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8_USCALED" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="USCALED"/>
+ <component name="G" bits="8" numericFormat="USCALED"/>
+ <component name="B" bits="8" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8_SSCALED" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SSCALED"/>
+ <component name="G" bits="8" numericFormat="SSCALED"/>
+ <component name="B" bits="8" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8_UINT" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="UINT"/>
+ <component name="G" bits="8" numericFormat="UINT"/>
+ <component name="B" bits="8" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8_SINT" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SINT"/>
+ <component name="G" bits="8" numericFormat="SINT"/>
+ <component name="B" bits="8" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8_SRGB" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SRGB"/>
+ <component name="G" bits="8" numericFormat="SRGB"/>
+ <component name="B" bits="8" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8_UNORM" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="UNORM"/>
+ <component name="G" bits="8" numericFormat="UNORM"/>
+ <component name="R" bits="8" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8_SNORM" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="SNORM"/>
+ <component name="G" bits="8" numericFormat="SNORM"/>
+ <component name="R" bits="8" numericFormat="SNORM"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8_USCALED" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="USCALED"/>
+ <component name="G" bits="8" numericFormat="USCALED"/>
+ <component name="R" bits="8" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8_SSCALED" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="SSCALED"/>
+ <component name="G" bits="8" numericFormat="SSCALED"/>
+ <component name="R" bits="8" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8_UINT" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="UINT"/>
+ <component name="G" bits="8" numericFormat="UINT"/>
+ <component name="R" bits="8" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8_SINT" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="SINT"/>
+ <component name="G" bits="8" numericFormat="SINT"/>
+ <component name="R" bits="8" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8_SRGB" class="24-bit" blockSize="3" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="SRGB"/>
+ <component name="G" bits="8" numericFormat="SRGB"/>
+ <component name="R" bits="8" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8A8_UNORM" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="UNORM"/>
+ <component name="G" bits="8" numericFormat="UNORM"/>
+ <component name="B" bits="8" numericFormat="UNORM"/>
+ <component name="A" bits="8" numericFormat="UNORM"/>
+ <spirvimageformat name="Rgba8"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8A8_SNORM" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SNORM"/>
+ <component name="G" bits="8" numericFormat="SNORM"/>
+ <component name="B" bits="8" numericFormat="SNORM"/>
+ <component name="A" bits="8" numericFormat="SNORM"/>
+ <spirvimageformat name="Rgba8Snorm"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8A8_USCALED" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="USCALED"/>
+ <component name="G" bits="8" numericFormat="USCALED"/>
+ <component name="B" bits="8" numericFormat="USCALED"/>
+ <component name="A" bits="8" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8A8_SSCALED" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SSCALED"/>
+ <component name="G" bits="8" numericFormat="SSCALED"/>
+ <component name="B" bits="8" numericFormat="SSCALED"/>
+ <component name="A" bits="8" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8A8_UINT" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="UINT"/>
+ <component name="G" bits="8" numericFormat="UINT"/>
+ <component name="B" bits="8" numericFormat="UINT"/>
+ <component name="A" bits="8" numericFormat="UINT"/>
+ <spirvimageformat name="Rgba8ui"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8A8_SINT" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SINT"/>
+ <component name="G" bits="8" numericFormat="SINT"/>
+ <component name="B" bits="8" numericFormat="SINT"/>
+ <component name="A" bits="8" numericFormat="SINT"/>
+ <spirvimageformat name="Rgba8i"/>
+ </format>
+ <format name="VK_FORMAT_R8G8B8A8_SRGB" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="8" numericFormat="SRGB"/>
+ <component name="G" bits="8" numericFormat="SRGB"/>
+ <component name="B" bits="8" numericFormat="SRGB"/>
+ <component name="A" bits="8" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8A8_UNORM" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="UNORM"/>
+ <component name="G" bits="8" numericFormat="UNORM"/>
+ <component name="R" bits="8" numericFormat="UNORM"/>
+ <component name="A" bits="8" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8A8_SNORM" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="SNORM"/>
+ <component name="G" bits="8" numericFormat="SNORM"/>
+ <component name="R" bits="8" numericFormat="SNORM"/>
+ <component name="A" bits="8" numericFormat="SNORM"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8A8_USCALED" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="USCALED"/>
+ <component name="G" bits="8" numericFormat="USCALED"/>
+ <component name="R" bits="8" numericFormat="USCALED"/>
+ <component name="A" bits="8" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8A8_SSCALED" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="SSCALED"/>
+ <component name="G" bits="8" numericFormat="SSCALED"/>
+ <component name="R" bits="8" numericFormat="SSCALED"/>
+ <component name="A" bits="8" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8A8_UINT" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="UINT"/>
+ <component name="G" bits="8" numericFormat="UINT"/>
+ <component name="R" bits="8" numericFormat="UINT"/>
+ <component name="A" bits="8" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8A8_SINT" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="SINT"/>
+ <component name="G" bits="8" numericFormat="SINT"/>
+ <component name="R" bits="8" numericFormat="SINT"/>
+ <component name="A" bits="8" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8A8_SRGB" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="B" bits="8" numericFormat="SRGB"/>
+ <component name="G" bits="8" numericFormat="SRGB"/>
+ <component name="R" bits="8" numericFormat="SRGB"/>
+ <component name="A" bits="8" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_A8B8G8R8_UNORM_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="8" numericFormat="UNORM"/>
+ <component name="B" bits="8" numericFormat="UNORM"/>
+ <component name="G" bits="8" numericFormat="UNORM"/>
+ <component name="R" bits="8" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_A8B8G8R8_SNORM_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="8" numericFormat="SNORM"/>
+ <component name="B" bits="8" numericFormat="SNORM"/>
+ <component name="G" bits="8" numericFormat="SNORM"/>
+ <component name="R" bits="8" numericFormat="SNORM"/>
+ </format>
+ <format name="VK_FORMAT_A8B8G8R8_USCALED_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="8" numericFormat="USCALED"/>
+ <component name="B" bits="8" numericFormat="USCALED"/>
+ <component name="G" bits="8" numericFormat="USCALED"/>
+ <component name="R" bits="8" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_A8B8G8R8_SSCALED_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="8" numericFormat="SSCALED"/>
+ <component name="B" bits="8" numericFormat="SSCALED"/>
+ <component name="G" bits="8" numericFormat="SSCALED"/>
+ <component name="R" bits="8" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_A8B8G8R8_UINT_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="8" numericFormat="UINT"/>
+ <component name="B" bits="8" numericFormat="UINT"/>
+ <component name="G" bits="8" numericFormat="UINT"/>
+ <component name="R" bits="8" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_A8B8G8R8_SINT_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="8" numericFormat="SINT"/>
+ <component name="B" bits="8" numericFormat="SINT"/>
+ <component name="G" bits="8" numericFormat="SINT"/>
+ <component name="R" bits="8" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_A8B8G8R8_SRGB_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="8" numericFormat="SRGB"/>
+ <component name="B" bits="8" numericFormat="SRGB"/>
+ <component name="G" bits="8" numericFormat="SRGB"/>
+ <component name="R" bits="8" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_A2R10G10B10_UNORM_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="UNORM"/>
+ <component name="R" bits="10" numericFormat="UNORM"/>
+ <component name="G" bits="10" numericFormat="UNORM"/>
+ <component name="B" bits="10" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_A2R10G10B10_SNORM_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="SNORM"/>
+ <component name="R" bits="10" numericFormat="SNORM"/>
+ <component name="G" bits="10" numericFormat="SNORM"/>
+ <component name="B" bits="10" numericFormat="SNORM"/>
+ </format>
+ <format name="VK_FORMAT_A2R10G10B10_USCALED_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="USCALED"/>
+ <component name="R" bits="10" numericFormat="USCALED"/>
+ <component name="G" bits="10" numericFormat="USCALED"/>
+ <component name="B" bits="10" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_A2R10G10B10_SSCALED_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="SSCALED"/>
+ <component name="R" bits="10" numericFormat="SSCALED"/>
+ <component name="G" bits="10" numericFormat="SSCALED"/>
+ <component name="B" bits="10" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_A2R10G10B10_UINT_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="UINT"/>
+ <component name="R" bits="10" numericFormat="UINT"/>
+ <component name="G" bits="10" numericFormat="UINT"/>
+ <component name="B" bits="10" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_A2R10G10B10_SINT_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="SINT"/>
+ <component name="R" bits="10" numericFormat="SINT"/>
+ <component name="G" bits="10" numericFormat="SINT"/>
+ <component name="B" bits="10" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_A2B10G10R10_UNORM_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="UNORM"/>
+ <component name="B" bits="10" numericFormat="UNORM"/>
+ <component name="G" bits="10" numericFormat="UNORM"/>
+ <component name="R" bits="10" numericFormat="UNORM"/>
+ <spirvimageformat name="Rgb10A2"/>
+ </format>
+ <format name="VK_FORMAT_A2B10G10R10_SNORM_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="SNORM"/>
+ <component name="B" bits="10" numericFormat="SNORM"/>
+ <component name="G" bits="10" numericFormat="SNORM"/>
+ <component name="R" bits="10" numericFormat="SNORM"/>
+ </format>
+ <format name="VK_FORMAT_A2B10G10R10_USCALED_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="USCALED"/>
+ <component name="B" bits="10" numericFormat="USCALED"/>
+ <component name="G" bits="10" numericFormat="USCALED"/>
+ <component name="R" bits="10" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_A2B10G10R10_SSCALED_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="SSCALED"/>
+ <component name="B" bits="10" numericFormat="SSCALED"/>
+ <component name="G" bits="10" numericFormat="SSCALED"/>
+ <component name="R" bits="10" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_A2B10G10R10_UINT_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="UINT"/>
+ <component name="B" bits="10" numericFormat="UINT"/>
+ <component name="G" bits="10" numericFormat="UINT"/>
+ <component name="R" bits="10" numericFormat="UINT"/>
+ <spirvimageformat name="Rgb10a2ui"/>
+ </format>
+ <format name="VK_FORMAT_A2B10G10R10_SINT_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="A" bits="2" numericFormat="SINT"/>
+ <component name="B" bits="10" numericFormat="SINT"/>
+ <component name="G" bits="10" numericFormat="SINT"/>
+ <component name="R" bits="10" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_R16_UNORM" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="UNORM"/>
+ <spirvimageformat name="R16"/>
+ </format>
+ <format name="VK_FORMAT_R16_SNORM" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SNORM"/>
+ <spirvimageformat name="R16Snorm"/>
+ </format>
+ <format name="VK_FORMAT_R16_USCALED" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_R16_SSCALED" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_R16_UINT" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="UINT"/>
+ <spirvimageformat name="R16ui"/>
+ </format>
+ <format name="VK_FORMAT_R16_SINT" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SINT"/>
+ <spirvimageformat name="R16i"/>
+ </format>
+ <format name="VK_FORMAT_R16_SFLOAT" class="16-bit" blockSize="2" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SFLOAT"/>
+ <spirvimageformat name="R16f"/>
+ </format>
+ <format name="VK_FORMAT_R16G16_UNORM" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="UNORM"/>
+ <component name="G" bits="16" numericFormat="UNORM"/>
+ <spirvimageformat name="Rg16"/>
+ </format>
+ <format name="VK_FORMAT_R16G16_SNORM" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SNORM"/>
+ <component name="G" bits="16" numericFormat="SNORM"/>
+ <spirvimageformat name="Rg16Snorm"/>
+ </format>
+ <format name="VK_FORMAT_R16G16_USCALED" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="USCALED"/>
+ <component name="G" bits="16" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_R16G16_SSCALED" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SSCALED"/>
+ <component name="G" bits="16" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_R16G16_UINT" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="UINT"/>
+ <component name="G" bits="16" numericFormat="UINT"/>
+ <spirvimageformat name="Rg16ui"/>
+ </format>
+ <format name="VK_FORMAT_R16G16_SINT" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SINT"/>
+ <component name="G" bits="16" numericFormat="SINT"/>
+ <spirvimageformat name="Rg16i"/>
+ </format>
+ <format name="VK_FORMAT_R16G16_SFLOAT" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SFLOAT"/>
+ <component name="G" bits="16" numericFormat="SFLOAT"/>
+ <spirvimageformat name="Rg16f"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16_UNORM" class="48-bit" blockSize="6" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="UNORM"/>
+ <component name="G" bits="16" numericFormat="UNORM"/>
+ <component name="B" bits="16" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16_SNORM" class="48-bit" blockSize="6" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SNORM"/>
+ <component name="G" bits="16" numericFormat="SNORM"/>
+ <component name="B" bits="16" numericFormat="SNORM"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16_USCALED" class="48-bit" blockSize="6" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="USCALED"/>
+ <component name="G" bits="16" numericFormat="USCALED"/>
+ <component name="B" bits="16" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16_SSCALED" class="48-bit" blockSize="6" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SSCALED"/>
+ <component name="G" bits="16" numericFormat="SSCALED"/>
+ <component name="B" bits="16" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16_UINT" class="48-bit" blockSize="6" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="UINT"/>
+ <component name="G" bits="16" numericFormat="UINT"/>
+ <component name="B" bits="16" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16_SINT" class="48-bit" blockSize="6" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SINT"/>
+ <component name="G" bits="16" numericFormat="SINT"/>
+ <component name="B" bits="16" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16_SFLOAT" class="48-bit" blockSize="6" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SFLOAT"/>
+ <component name="G" bits="16" numericFormat="SFLOAT"/>
+ <component name="B" bits="16" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16A16_UNORM" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="UNORM"/>
+ <component name="G" bits="16" numericFormat="UNORM"/>
+ <component name="B" bits="16" numericFormat="UNORM"/>
+ <component name="A" bits="16" numericFormat="UNORM"/>
+ <spirvimageformat name="Rgba16"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16A16_SNORM" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SNORM"/>
+ <component name="G" bits="16" numericFormat="SNORM"/>
+ <component name="B" bits="16" numericFormat="SNORM"/>
+ <component name="A" bits="16" numericFormat="SNORM"/>
+ <spirvimageformat name="Rgba16Snorm"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16A16_USCALED" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="USCALED"/>
+ <component name="G" bits="16" numericFormat="USCALED"/>
+ <component name="B" bits="16" numericFormat="USCALED"/>
+ <component name="A" bits="16" numericFormat="USCALED"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16A16_SSCALED" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SSCALED"/>
+ <component name="G" bits="16" numericFormat="SSCALED"/>
+ <component name="B" bits="16" numericFormat="SSCALED"/>
+ <component name="A" bits="16" numericFormat="SSCALED"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16A16_UINT" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="UINT"/>
+ <component name="G" bits="16" numericFormat="UINT"/>
+ <component name="B" bits="16" numericFormat="UINT"/>
+ <component name="A" bits="16" numericFormat="UINT"/>
+ <spirvimageformat name="Rgba16ui"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16A16_SINT" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SINT"/>
+ <component name="G" bits="16" numericFormat="SINT"/>
+ <component name="B" bits="16" numericFormat="SINT"/>
+ <component name="A" bits="16" numericFormat="SINT"/>
+ <spirvimageformat name="Rgba16i"/>
+ </format>
+ <format name="VK_FORMAT_R16G16B16A16_SFLOAT" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="16" numericFormat="SFLOAT"/>
+ <component name="G" bits="16" numericFormat="SFLOAT"/>
+ <component name="B" bits="16" numericFormat="SFLOAT"/>
+ <component name="A" bits="16" numericFormat="SFLOAT"/>
+ <spirvimageformat name="Rgba16f"/>
+ </format>
+ <format name="VK_FORMAT_R32_UINT" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="UINT"/>
+ <spirvimageformat name="R32ui"/>
+ </format>
+ <format name="VK_FORMAT_R32_SINT" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="SINT"/>
+ <spirvimageformat name="R32i"/>
+ </format>
+ <format name="VK_FORMAT_R32_SFLOAT" class="32-bit" blockSize="4" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="SFLOAT"/>
+ <spirvimageformat name="R32f"/>
+ </format>
+ <format name="VK_FORMAT_R32G32_UINT" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="UINT"/>
+ <component name="G" bits="32" numericFormat="UINT"/>
+ <spirvimageformat name="Rg32ui"/>
+ </format>
+ <format name="VK_FORMAT_R32G32_SINT" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="SINT"/>
+ <component name="G" bits="32" numericFormat="SINT"/>
+ <spirvimageformat name="Rg32i"/>
+ </format>
+ <format name="VK_FORMAT_R32G32_SFLOAT" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="SFLOAT"/>
+ <component name="G" bits="32" numericFormat="SFLOAT"/>
+ <spirvimageformat name="Rg32f"/>
+ </format>
+ <format name="VK_FORMAT_R32G32B32_UINT" class="96-bit" blockSize="12" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="UINT"/>
+ <component name="G" bits="32" numericFormat="UINT"/>
+ <component name="B" bits="32" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_R32G32B32_SINT" class="96-bit" blockSize="12" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="SINT"/>
+ <component name="G" bits="32" numericFormat="SINT"/>
+ <component name="B" bits="32" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_R32G32B32_SFLOAT" class="96-bit" blockSize="12" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="SFLOAT"/>
+ <component name="G" bits="32" numericFormat="SFLOAT"/>
+ <component name="B" bits="32" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_R32G32B32A32_UINT" class="128-bit" blockSize="16" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="UINT"/>
+ <component name="G" bits="32" numericFormat="UINT"/>
+ <component name="B" bits="32" numericFormat="UINT"/>
+ <component name="A" bits="32" numericFormat="UINT"/>
+ <spirvimageformat name="Rgba32ui"/>
+ </format>
+ <format name="VK_FORMAT_R32G32B32A32_SINT" class="128-bit" blockSize="16" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="SINT"/>
+ <component name="G" bits="32" numericFormat="SINT"/>
+ <component name="B" bits="32" numericFormat="SINT"/>
+ <component name="A" bits="32" numericFormat="SINT"/>
+ <spirvimageformat name="Rgba32i"/>
+ </format>
+ <format name="VK_FORMAT_R32G32B32A32_SFLOAT" class="128-bit" blockSize="16" texelsPerBlock="1">
+ <component name="R" bits="32" numericFormat="SFLOAT"/>
+ <component name="G" bits="32" numericFormat="SFLOAT"/>
+ <component name="B" bits="32" numericFormat="SFLOAT"/>
+ <component name="A" bits="32" numericFormat="SFLOAT"/>
+ <spirvimageformat name="Rgba32f"/>
+ </format>
+ <format name="VK_FORMAT_R64_UINT" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="UINT"/>
+ <spirvimageformat name="R64ui"/>
+ </format>
+ <format name="VK_FORMAT_R64_SINT" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="SINT"/>
+ <spirvimageformat name="R64i"/>
+ </format>
+ <format name="VK_FORMAT_R64_SFLOAT" class="64-bit" blockSize="8" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_R64G64_UINT" class="128-bit" blockSize="16" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="UINT"/>
+ <component name="B" bits="64" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_R64G64_SINT" class="128-bit" blockSize="16" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="SINT"/>
+ <component name="B" bits="64" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_R64G64_SFLOAT" class="128-bit" blockSize="16" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="SFLOAT"/>
+ <component name="B" bits="64" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_R64G64B64_UINT" class="192-bit" blockSize="24" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="UINT"/>
+ <component name="G" bits="64" numericFormat="UINT"/>
+ <component name="B" bits="64" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_R64G64B64_SINT" class="192-bit" blockSize="24" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="SINT"/>
+ <component name="G" bits="64" numericFormat="SINT"/>
+ <component name="B" bits="64" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_R64G64B64_SFLOAT" class="192-bit" blockSize="24" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="SFLOAT"/>
+ <component name="G" bits="64" numericFormat="SFLOAT"/>
+ <component name="B" bits="64" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_R64G64B64A64_UINT" class="256-bit" blockSize="32" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="UINT"/>
+ <component name="G" bits="64" numericFormat="UINT"/>
+ <component name="B" bits="64" numericFormat="UINT"/>
+ <component name="A" bits="64" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_R64G64B64A64_SINT" class="256-bit" blockSize="32" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="SINT"/>
+ <component name="G" bits="64" numericFormat="SINT"/>
+ <component name="B" bits="64" numericFormat="SINT"/>
+ <component name="A" bits="64" numericFormat="SINT"/>
+ </format>
+ <format name="VK_FORMAT_R64G64B64A64_SFLOAT" class="256-bit" blockSize="32" texelsPerBlock="1">
+ <component name="R" bits="64" numericFormat="SFLOAT"/>
+ <component name="G" bits="64" numericFormat="SFLOAT"/>
+ <component name="B" bits="64" numericFormat="SFLOAT"/>
+ <component name="A" bits="64" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_B10G11R11_UFLOAT_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="B" bits="10" numericFormat="UFLOAT"/>
+ <component name="G" bits="11" numericFormat="UFLOAT"/>
+ <component name="R" bits="10" numericFormat="UFLOAT"/>
+ <spirvimageformat name="R11fG11fB10f"/>
+ </format>
+ <format name="VK_FORMAT_E5B9G9R9_UFLOAT_PACK32" class="32-bit" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="B" bits="9" numericFormat="UFLOAT"/>
+ <component name="G" bits="9" numericFormat="UFLOAT"/>
+ <component name="R" bits="9" numericFormat="UFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_D16_UNORM" class="D16" blockSize="2" texelsPerBlock="1">
+ <component name="D" bits="16" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_X8_D24_UNORM_PACK32" class="D24" blockSize="4" texelsPerBlock="1" packed="32">
+ <component name="D" bits="24" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_D32_SFLOAT" class="D32" blockSize="4" texelsPerBlock="1">
+ <component name="D" bits="32" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_S8_UINT" class="S8" blockSize="1" texelsPerBlock="1">
+ <component name="S" bits="8" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_D16_UNORM_S8_UINT" class="D16S8" blockSize="3" texelsPerBlock="1">
+ <component name="D" bits="16" numericFormat="UNORM"/>
+ <component name="S" bits="8" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_D24_UNORM_S8_UINT" class="D24S8" blockSize="4" texelsPerBlock="1">
+ <component name="D" bits="24" numericFormat="UNORM"/>
+ <component name="S" bits="8" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_D32_SFLOAT_S8_UINT" class="D32S8" blockSize="5" texelsPerBlock="1">
+ <component name="D" bits="32" numericFormat="SFLOAT"/>
+ <component name="S" bits="8" numericFormat="UINT"/>
+ </format>
+ <format name="VK_FORMAT_BC1_RGB_UNORM_BLOCK" class="BC1_RGB" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_BC1_RGB_SRGB_BLOCK" class="BC1_RGB" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_BC1_RGBA_UNORM_BLOCK" class="BC1_RGBA" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_BC1_RGBA_SRGB_BLOCK" class="BC1_RGBA" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_BC2_UNORM_BLOCK" class="BC2" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_BC2_SRGB_BLOCK" class="BC2" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_BC3_UNORM_BLOCK" class="BC3" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_BC3_SRGB_BLOCK" class="BC3" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_BC4_UNORM_BLOCK" class="BC4" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_BC4_SNORM_BLOCK" class="BC4" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_BC5_UNORM_BLOCK" class="BC5" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_BC5_SNORM_BLOCK" class="BC5" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_BC6H_UFLOAT_BLOCK" class="BC6H" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="UFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="UFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="UFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_BC6H_SFLOAT_BLOCK" class="BC6H" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_BC7_UNORM_BLOCK" class="BC7" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_BC7_SRGB_BLOCK" class="BC7" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="BC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK" class="ETC2_RGB" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="ETC2">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK" class="ETC2_RGB" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="ETC2">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK" class="ETC2_RGBA" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="ETC2">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK" class="ETC2_RGBA" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="ETC2">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK" class="ETC2_EAC_RGBA" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="ETC2">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK" class="ETC2_EAC_RGBA" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="ETC2">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_EAC_R11_UNORM_BLOCK" class="EAC_R" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="EAC">
+ <component name="R" bits="11" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_EAC_R11_SNORM_BLOCK" class="EAC_R" blockSize="8" texelsPerBlock="16" blockExtent="4,4,1" compressed="EAC">
+ <component name="R" bits="11" numericFormat="SNORM"/>
+ </format>
+ <format name="VK_FORMAT_EAC_R11G11_UNORM_BLOCK" class="EAC_RG" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="EAC">
+ <component name="R" bits="11" numericFormat="UNORM"/>
+ <component name="G" bits="11" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_EAC_R11G11_SNORM_BLOCK" class="EAC_RG" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="EAC">
+ <component name="R" bits="11" numericFormat="SNORM"/>
+ <component name="G" bits="11" numericFormat="SNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_4x4_UNORM_BLOCK" class="ASTC_4x4" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_4x4_SRGB_BLOCK" class="ASTC_4x4" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_5x4_UNORM_BLOCK" class="ASTC_5x4" blockSize="16" texelsPerBlock="20" blockExtent="5,4,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_5x4_SRGB_BLOCK" class="ASTC_5x4" blockSize="16" texelsPerBlock="20" blockExtent="5,4,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_5x5_UNORM_BLOCK" class="ASTC_5x5" blockSize="16" texelsPerBlock="25" blockExtent="5,5,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_5x5_SRGB_BLOCK" class="ASTC_5x5" blockSize="16" texelsPerBlock="25" blockExtent="5,5,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_6x5_UNORM_BLOCK" class="ASTC_6x5" blockSize="16" texelsPerBlock="30" blockExtent="6,5,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_6x5_SRGB_BLOCK" class="ASTC_6x5" blockSize="16" texelsPerBlock="30" blockExtent="6,5,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_6x6_UNORM_BLOCK" class="ASTC_6x6" blockSize="16" texelsPerBlock="36" blockExtent="6,6,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_6x6_SRGB_BLOCK" class="ASTC_6x6" blockSize="16" texelsPerBlock="36" blockExtent="6,6,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_8x5_UNORM_BLOCK" class="ASTC_8x5" blockSize="16" texelsPerBlock="40" blockExtent="8,5,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_8x5_SRGB_BLOCK" class="ASTC_8x5" blockSize="16" texelsPerBlock="40" blockExtent="8,5,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_8x6_UNORM_BLOCK" class="ASTC_8x6" blockSize="16" texelsPerBlock="48" blockExtent="8,6,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_8x6_SRGB_BLOCK" class="ASTC_8x6" blockSize="16" texelsPerBlock="48" blockExtent="8,6,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_8x8_UNORM_BLOCK" class="ASTC_8x8" blockSize="16" texelsPerBlock="64" blockExtent="8,8,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_8x8_SRGB_BLOCK" class="ASTC_8x8" blockSize="16" texelsPerBlock="64" blockExtent="8,8,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x5_UNORM_BLOCK" class="ASTC_10x5" blockSize="16" texelsPerBlock="50" blockExtent="10,5,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x5_SRGB_BLOCK" class="ASTC_10x5" blockSize="16" texelsPerBlock="50" blockExtent="10,5,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x6_UNORM_BLOCK" class="ASTC_10x6" blockSize="16" texelsPerBlock="60" blockExtent="10,6,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x6_SRGB_BLOCK" class="ASTC_10x6" blockSize="16" texelsPerBlock="60" blockExtent="10,6,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x8_UNORM_BLOCK" class="ASTC_10x8" blockSize="16" texelsPerBlock="80" blockExtent="10,8,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x8_SRGB_BLOCK" class="ASTC_10x8" blockSize="16" texelsPerBlock="80" blockExtent="10,8,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x10_UNORM_BLOCK" class="ASTC_10x10" blockSize="16" texelsPerBlock="100" blockExtent="10,10,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x10_SRGB_BLOCK" class="ASTC_10x10" blockSize="16" texelsPerBlock="100" blockExtent="10,10,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_12x10_UNORM_BLOCK" class="ASTC_12x10" blockSize="16" texelsPerBlock="120" blockExtent="12,10,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_12x10_SRGB_BLOCK" class="ASTC_12x10" blockSize="16" texelsPerBlock="120" blockExtent="12,10,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_12x12_UNORM_BLOCK" class="ASTC_12x12" blockSize="16" texelsPerBlock="144" blockExtent="12,12,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_12x12_SRGB_BLOCK" class="ASTC_12x12" blockSize="16" texelsPerBlock="144" blockExtent="12,12,1" compressed="ASTC LDR">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_G8B8G8R8_422_UNORM" class="32-bit G8B8G8R8" blockSize="4" texelsPerBlock="1" blockExtent="2,1,1" chroma="422">
+ <component name="G" bits="8" numericFormat="UNORM"/>
+ <component name="B" bits="8" numericFormat="UNORM"/>
+ <component name="G" bits="8" numericFormat="UNORM"/>
+ <component name="R" bits="8" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_B8G8R8G8_422_UNORM" class="32-bit B8G8R8G8" blockSize="4" texelsPerBlock="1" blockExtent="2,1,1" chroma="422">
+ <component name="B" bits="8" numericFormat="UNORM"/>
+ <component name="G" bits="8" numericFormat="UNORM"/>
+ <component name="R" bits="8" numericFormat="UNORM"/>
+ <component name="G" bits="8" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM" class="8-bit 3-plane 420" blockSize="3" texelsPerBlock="1" chroma="420">
+ <component name="G" bits="8" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="8" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="8" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R8_UNORM"/>
+ <plane index="1" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R8_UNORM"/>
+ <plane index="2" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R8_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G8_B8R8_2PLANE_420_UNORM" class="8-bit 2-plane 420" blockSize="3" texelsPerBlock="1" chroma="420">
+ <component name="G" bits="8" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="8" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="8" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R8_UNORM"/>
+ <plane index="1" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R8G8_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM" class="8-bit 3-plane 422" blockSize="3" texelsPerBlock="1" chroma="422">
+ <component name="G" bits="8" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="8" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="8" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R8_UNORM"/>
+ <plane index="1" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R8_UNORM"/>
+ <plane index="2" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R8_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G8_B8R8_2PLANE_422_UNORM" class="8-bit 2-plane 422" blockSize="3" texelsPerBlock="1" chroma="422">
+ <component name="G" bits="8" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="8" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="8" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R8_UNORM"/>
+ <plane index="1" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R8G8_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM" class="8-bit 3-plane 444" blockSize="3" texelsPerBlock="1" chroma="444">
+ <component name="G" bits="8" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="8" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="8" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R8_UNORM"/>
+ <plane index="1" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R8_UNORM"/>
+ <plane index="2" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R8_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R10X6_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="R" bits="10" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R10X6G10X6_UNORM_2PACK16" class="32-bit" blockSize="4" texelsPerBlock="1" packed="16">
+ <component name="R" bits="10" numericFormat="UNORM"/>
+ <component name="G" bits="10" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16" class="64-bit R10G10B10A10" blockSize="8" texelsPerBlock="1" packed="16" chroma="444">
+ <component name="R" bits="10" numericFormat="UNORM"/>
+ <component name="G" bits="10" numericFormat="UNORM"/>
+ <component name="B" bits="10" numericFormat="UNORM"/>
+ <component name="A" bits="10" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16" class="64-bit G10B10G10R10" blockSize="8" texelsPerBlock="1" blockExtent="2,1,1" packed="16" chroma="422">
+ <component name="G" bits="10" numericFormat="UNORM"/>
+ <component name="B" bits="10" numericFormat="UNORM"/>
+ <component name="G" bits="10" numericFormat="UNORM"/>
+ <component name="R" bits="10" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16" class="64-bit B10G10R10G10" blockSize="8" texelsPerBlock="1" blockExtent="2,1,1" packed="16" chroma="422">
+ <component name="B" bits="10" numericFormat="UNORM"/>
+ <component name="G" bits="10" numericFormat="UNORM"/>
+ <component name="R" bits="10" numericFormat="UNORM"/>
+ <component name="G" bits="10" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16" class="10-bit 3-plane 420" blockSize="6" texelsPerBlock="1" packed="16" chroma="420">
+ <component name="G" bits="10" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="10" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="10" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ <plane index="2" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16" class="10-bit 2-plane 420" blockSize="6" texelsPerBlock="1" packed="16" chroma="420">
+ <component name="G" bits="10" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="10" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="10" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R10X6G10X6_UNORM_2PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16" class="10-bit 3-plane 422" blockSize="6" texelsPerBlock="1" packed="16" chroma="422">
+ <component name="G" bits="10" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="10" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="10" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ <plane index="2" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16" class="10-bit 2-plane 422" blockSize="6" texelsPerBlock="1" packed="16" chroma="422">
+ <component name="G" bits="10" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="10" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="10" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R10X6G10X6_UNORM_2PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16" class="10-bit 3-plane 444" blockSize="6" texelsPerBlock="1" packed="16" chroma="444">
+ <component name="G" bits="10" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="10" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="10" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ <plane index="2" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ </format>
+ <format name="VK_FORMAT_R12X4_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="R" bits="12" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R12X4G12X4_UNORM_2PACK16" class="32-bit" blockSize="4" texelsPerBlock="1" packed="16">
+ <component name="R" bits="12" numericFormat="UNORM"/>
+ <component name="G" bits="12" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16" class="64-bit R12G12B12A12" blockSize="8" texelsPerBlock="1" packed="16" chroma="444">
+ <component name="R" bits="12" numericFormat="UNORM"/>
+ <component name="G" bits="12" numericFormat="UNORM"/>
+ <component name="B" bits="12" numericFormat="UNORM"/>
+ <component name="A" bits="12" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16" class="64-bit G12B12G12R12" blockSize="8" texelsPerBlock="1" blockExtent="2,1,1" packed="16" chroma="422">
+ <component name="G" bits="12" numericFormat="UNORM"/>
+ <component name="B" bits="12" numericFormat="UNORM"/>
+ <component name="G" bits="12" numericFormat="UNORM"/>
+ <component name="R" bits="12" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16" class="64-bit B12G12R12G12" blockSize="8" texelsPerBlock="1" blockExtent="2,1,1" packed="16" chroma="422">
+ <component name="B" bits="12" numericFormat="UNORM"/>
+ <component name="G" bits="12" numericFormat="UNORM"/>
+ <component name="R" bits="12" numericFormat="UNORM"/>
+ <component name="G" bits="12" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16" class="12-bit 3-plane 420" blockSize="6" texelsPerBlock="1" packed="16" chroma="420">
+ <component name="G" bits="12" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="12" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="12" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ <plane index="2" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16" class="12-bit 2-plane 420" blockSize="6" texelsPerBlock="1" packed="16" chroma="420">
+ <component name="G" bits="12" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="12" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="12" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R12X4G12X4_UNORM_2PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16" class="12-bit 3-plane 422" blockSize="6" texelsPerBlock="1" packed="16" chroma="422">
+ <component name="G" bits="12" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="12" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="12" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ <plane index="2" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16" class="12-bit 2-plane 422" blockSize="6" texelsPerBlock="1" packed="16" chroma="422">
+ <component name="G" bits="12" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="12" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="12" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R12X4G12X4_UNORM_2PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16" class="12-bit 3-plane 444" blockSize="6" texelsPerBlock="1" packed="16" chroma="444">
+ <component name="G" bits="12" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="12" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="12" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ <plane index="2" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G16B16G16R16_422_UNORM" class="64-bit G16B16G16R16" blockSize="8" texelsPerBlock="1" blockExtent="2,1,1" chroma="422">
+ <component name="G" bits="16" numericFormat="UNORM"/>
+ <component name="B" bits="16" numericFormat="UNORM"/>
+ <component name="G" bits="16" numericFormat="UNORM"/>
+ <component name="R" bits="16" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_B16G16R16G16_422_UNORM" class="64-bit B16G16R16G16" blockSize="8" texelsPerBlock="1" blockExtent="2,1,1" chroma="422">
+ <component name="B" bits="16" numericFormat="UNORM"/>
+ <component name="G" bits="16" numericFormat="UNORM"/>
+ <component name="R" bits="16" numericFormat="UNORM"/>
+ <component name="G" bits="16" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM" class="16-bit 3-plane 420" blockSize="6" texelsPerBlock="1" chroma="420">
+ <component name="G" bits="16" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="16" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="16" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R16_UNORM"/>
+ <plane index="1" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R16_UNORM"/>
+ <plane index="2" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R16_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G16_B16R16_2PLANE_420_UNORM" class="16-bit 2-plane 420" blockSize="6" texelsPerBlock="1" chroma="420">
+ <component name="G" bits="16" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="16" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="16" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R16_UNORM"/>
+ <plane index="1" widthDivisor="2" heightDivisor="2" compatible="VK_FORMAT_R16G16_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM" class="16-bit 3-plane 422" blockSize="6" texelsPerBlock="1" chroma="422">
+ <component name="G" bits="16" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="16" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="16" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R16_UNORM"/>
+ <plane index="1" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R16_UNORM"/>
+ <plane index="2" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R16_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G16_B16R16_2PLANE_422_UNORM" class="16-bit 2-plane 422" blockSize="6" texelsPerBlock="1" chroma="422">
+ <component name="G" bits="16" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="16" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="16" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R16_UNORM"/>
+ <plane index="1" widthDivisor="2" heightDivisor="1" compatible="VK_FORMAT_R16G16_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM" class="16-bit 3-plane 444" blockSize="6" texelsPerBlock="1" chroma="444">
+ <component name="G" bits="16" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="16" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="16" numericFormat="UNORM" planeIndex="2"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R16_UNORM"/>
+ <plane index="1" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R16_UNORM"/>
+ <plane index="2" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R16_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG" class="PVRTC1_2BPP" blockSize="8" texelsPerBlock="1" blockExtent="8,4,1" compressed="PVRTC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG" class="PVRTC1_4BPP" blockSize="8" texelsPerBlock="1" blockExtent="4,4,1" compressed="PVRTC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG" class="PVRTC2_2BPP" blockSize="8" texelsPerBlock="1" blockExtent="8,4,1" compressed="PVRTC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG" class="PVRTC2_4BPP" blockSize="8" texelsPerBlock="1" blockExtent="4,4,1" compressed="PVRTC">
+ <component name="R" bits="compressed" numericFormat="UNORM"/>
+ <component name="G" bits="compressed" numericFormat="UNORM"/>
+ <component name="B" bits="compressed" numericFormat="UNORM"/>
+ <component name="A" bits="compressed" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG" class="PVRTC1_2BPP" blockSize="8" texelsPerBlock="1" blockExtent="8,4,1" compressed="PVRTC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG" class="PVRTC1_4BPP" blockSize="8" texelsPerBlock="1" blockExtent="4,4,1" compressed="PVRTC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG" class="PVRTC2_2BPP" blockSize="8" texelsPerBlock="1" blockExtent="8,4,1" compressed="PVRTC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG" class="PVRTC2_4BPP" blockSize="8" texelsPerBlock="1" blockExtent="4,4,1" compressed="PVRTC">
+ <component name="R" bits="compressed" numericFormat="SRGB"/>
+ <component name="G" bits="compressed" numericFormat="SRGB"/>
+ <component name="B" bits="compressed" numericFormat="SRGB"/>
+ <component name="A" bits="compressed" numericFormat="SRGB"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK" class="ASTC_4x4" blockSize="16" texelsPerBlock="16" blockExtent="4,4,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK" class="ASTC_5x4" blockSize="16" texelsPerBlock="20" blockExtent="5,4,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK" class="ASTC_5x5" blockSize="16" texelsPerBlock="25" blockExtent="5,5,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK" class="ASTC_6x5" blockSize="16" texelsPerBlock="30" blockExtent="6,5,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK" class="ASTC_6x6" blockSize="16" texelsPerBlock="36" blockExtent="6,6,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK" class="ASTC_8x5" blockSize="16" texelsPerBlock="40" blockExtent="8,5,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK" class="ASTC_8x6" blockSize="16" texelsPerBlock="48" blockExtent="8,6,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK" class="ASTC_8x8" blockSize="16" texelsPerBlock="64" blockExtent="8,8,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK" class="ASTC_10x5" blockSize="16" texelsPerBlock="50" blockExtent="10,5,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK" class="ASTC_10x6" blockSize="16" texelsPerBlock="60" blockExtent="10,6,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK" class="ASTC_10x8" blockSize="16" texelsPerBlock="80" blockExtent="10,8,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK" class="ASTC_10x10" blockSize="16" texelsPerBlock="100" blockExtent="10,10,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK" class="ASTC_12x10" blockSize="16" texelsPerBlock="120" blockExtent="12,10,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK" class="ASTC_12x12" blockSize="16" texelsPerBlock="144" blockExtent="12,12,1" compressed="ASTC HDR">
+ <component name="R" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="G" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="B" bits="compressed" numericFormat="SFLOAT"/>
+ <component name="A" bits="compressed" numericFormat="SFLOAT"/>
+ </format>
+ <format name="VK_FORMAT_G8_B8R8_2PLANE_444_UNORM" class="8-bit 2-plane 444" blockSize="3" texelsPerBlock="1" chroma="444">
+ <component name="G" bits="8" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="8" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="8" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R8_UNORM"/>
+ <plane index="1" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R8G8_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16" class="10-bit 2-plane 444" blockSize="6" texelsPerBlock="1" packed="16" chroma="444">
+ <component name="G" bits="10" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="10" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="10" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R10X6_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R10X6G10X6_UNORM_2PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16" class="12-bit 2-plane 444" blockSize="6" texelsPerBlock="1" packed="16" chroma="444">
+ <component name="G" bits="12" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="12" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="12" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R12X4_UNORM_PACK16"/>
+ <plane index="1" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R12X4G12X4_UNORM_2PACK16"/>
+ </format>
+ <format name="VK_FORMAT_G16_B16R16_2PLANE_444_UNORM" class="16-bit 2-plane 444" blockSize="6" texelsPerBlock="1" chroma="444">
+ <component name="G" bits="16" numericFormat="UNORM" planeIndex="0"/>
+ <component name="B" bits="16" numericFormat="UNORM" planeIndex="1"/>
+ <component name="R" bits="16" numericFormat="UNORM" planeIndex="1"/>
+ <plane index="0" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R16_UNORM"/>
+ <plane index="1" widthDivisor="1" heightDivisor="1" compatible="VK_FORMAT_R16G16_UNORM"/>
+ </format>
+ <format name="VK_FORMAT_A4R4G4B4_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="A" bits="4" numericFormat="UNORM"/>
+ <component name="R" bits="4" numericFormat="UNORM"/>
+ <component name="G" bits="4" numericFormat="UNORM"/>
+ <component name="B" bits="4" numericFormat="UNORM"/>
+ </format>
+ <format name="VK_FORMAT_A4B4G4R4_UNORM_PACK16" class="16-bit" blockSize="2" texelsPerBlock="1" packed="16">
+ <component name="A" bits="4" numericFormat="UNORM"/>
+ <component name="B" bits="4" numericFormat="UNORM"/>
+ <component name="G" bits="4" numericFormat="UNORM"/>
+ <component name="R" bits="4" numericFormat="UNORM"/>
+ </format>
+ </formats>
<spirvextensions comment="SPIR-V Extensions allowed in Vulkan and what is required to use it">
<spirvextension name="SPV_KHR_variable_pointers">
- <enable version="VK_API_VERSION_1_1"/>
+ <enable version="VK_VERSION_1_1"/>
<enable extension="VK_KHR_variable_pointers"/>
</spirvextension>
<spirvextension name="SPV_AMD_shader_explicit_vertex_parameter">
@@ -14637,26 +20690,26 @@ typedef void <name>CAMetalLayer</name>;
<enable extension="VK_AMD_texture_gather_bias_lod"/>
</spirvextension>
<spirvextension name="SPV_KHR_shader_draw_parameters">
- <enable version="VK_API_VERSION_1_1"/>
+ <enable version="VK_VERSION_1_1"/>
<enable extension="VK_KHR_shader_draw_parameters"/>
</spirvextension>
<spirvextension name="SPV_KHR_8bit_storage">
- <enable version="VK_API_VERSION_1_2"/>
+ <enable version="VK_VERSION_1_2"/>
<enable extension="VK_KHR_8bit_storage"/>
</spirvextension>
<spirvextension name="SPV_KHR_16bit_storage">
- <enable version="VK_API_VERSION_1_1"/>
+ <enable version="VK_VERSION_1_1"/>
<enable extension="VK_KHR_16bit_storage"/>
</spirvextension>
<spirvextension name="SPV_KHR_shader_clock">
<enable extension="VK_KHR_shader_clock"/>
</spirvextension>
<spirvextension name="SPV_KHR_float_controls">
- <enable version="VK_API_VERSION_1_2"/>
+ <enable version="VK_VERSION_1_2"/>
<enable extension="VK_KHR_shader_float_controls"/>
</spirvextension>
<spirvextension name="SPV_KHR_storage_buffer_storage_class">
- <enable version="VK_API_VERSION_1_1"/>
+ <enable version="VK_VERSION_1_1"/>
<enable extension="VK_KHR_storage_buffer_storage_class"/>
</spirvextension>
<spirvextension name="SPV_KHR_post_depth_coverage">
@@ -14687,18 +20740,18 @@ typedef void <name>CAMetalLayer</name>;
<enable extension="VK_NV_shader_subgroup_partitioned"/>
</spirvextension>
<spirvextension name="SPV_EXT_shader_viewport_index_layer">
- <enable version="VK_API_VERSION_1_2"/>
+ <enable version="VK_VERSION_1_2"/>
<enable extension="VK_EXT_shader_viewport_index_layer"/>
</spirvextension>
<spirvextension name="SPV_NVX_multiview_per_view_attributes">
<enable extension="VK_NVX_multiview_per_view_attributes"/>
</spirvextension>
<spirvextension name="SPV_EXT_descriptor_indexing">
- <enable version="VK_API_VERSION_1_2"/>
+ <enable version="VK_VERSION_1_2"/>
<enable extension="VK_EXT_descriptor_indexing"/>
</spirvextension>
<spirvextension name="SPV_KHR_vulkan_memory_model">
- <enable version="VK_API_VERSION_1_2"/>
+ <enable version="VK_VERSION_1_2"/>
<enable extension="VK_KHR_vulkan_memory_model"/>
</spirvextension>
<spirvextension name="SPV_NV_compute_shader_derivatives">
@@ -14722,6 +20775,9 @@ typedef void <name>CAMetalLayer</name>;
<spirvextension name="SPV_KHR_ray_query">
<enable extension="VK_KHR_ray_query"/>
</spirvextension>
+ <spirvextension name="SPV_KHR_ray_cull_mask">
+ <enable extension="VK_KHR_ray_tracing_maintenance1"/>
+ </spirvextension>
<spirvextension name="SPV_GOOGLE_hlsl_functionality1">
<enable extension="VK_GOOGLE_hlsl_functionality1"/>
</spirvextension>
@@ -14735,7 +20791,7 @@ typedef void <name>CAMetalLayer</name>;
<enable extension="VK_EXT_fragment_density_map"/>
</spirvextension>
<spirvextension name="SPV_KHR_physical_storage_buffer">
- <enable version="VK_API_VERSION_1_2"/>
+ <enable version="VK_VERSION_1_2"/>
<enable extension="VK_KHR_buffer_device_address"/>
</spirvextension>
<spirvextension name="SPV_EXT_physical_storage_buffer">
@@ -14751,160 +20807,225 @@ typedef void <name>CAMetalLayer</name>;
<enable extension="VK_EXT_fragment_shader_interlock"/>
</spirvextension>
<spirvextension name="SPV_EXT_demote_to_helper_invocation">
+ <enable version="VK_API_VERSION_1_3"/>
<enable extension="VK_EXT_shader_demote_to_helper_invocation"/>
</spirvextension>
<spirvextension name="SPV_KHR_fragment_shading_rate">
<enable extension="VK_KHR_fragment_shading_rate"/>
</spirvextension>
<spirvextension name="SPV_KHR_non_semantic_info">
+ <enable version="VK_API_VERSION_1_3"/>
<enable extension="VK_KHR_shader_non_semantic_info"/>
</spirvextension>
<spirvextension name="SPV_EXT_shader_image_int64">
<enable extension="VK_EXT_shader_image_atomic_int64"/>
</spirvextension>
<spirvextension name="SPV_KHR_terminate_invocation">
+ <enable version="VK_API_VERSION_1_3"/>
<enable extension="VK_KHR_shader_terminate_invocation"/>
</spirvextension>
+ <spirvextension name="SPV_KHR_multiview">
+ <enable version="VK_VERSION_1_1"/>
+ <enable extension="VK_KHR_multiview"/>
+ </spirvextension>
+ <spirvextension name="SPV_KHR_workgroup_memory_explicit_layout">
+ <enable extension="VK_KHR_workgroup_memory_explicit_layout"/>
+ </spirvextension>
+ <spirvextension name="SPV_EXT_shader_atomic_float_add">
+ <enable extension="VK_EXT_shader_atomic_float"/>
+ </spirvextension>
+ <spirvextension name="SPV_KHR_fragment_shader_barycentric">
+ <enable extension="VK_KHR_fragment_shader_barycentric"/>
+ </spirvextension>
+ <spirvextension name="SPV_KHR_subgroup_uniform_control_flow">
+ <enable version="VK_API_VERSION_1_3"/>
+ <enable extension="VK_KHR_shader_subgroup_uniform_control_flow"/>
+ </spirvextension>
+ <spirvextension name="SPV_EXT_shader_atomic_float_min_max">
+ <enable extension="VK_EXT_shader_atomic_float2"/>
+ </spirvextension>
+ <spirvextension name="SPV_EXT_shader_atomic_float16_add">
+ <enable extension="VK_EXT_shader_atomic_float2"/>
+ </spirvextension>
+ <spirvextension name="SPV_KHR_integer_dot_product">
+ <enable version="VK_API_VERSION_1_3"/>
+ <enable extension="VK_KHR_shader_integer_dot_product"/>
+ </spirvextension>
+ <spirvextension name="SPV_INTEL_shader_integer_functions">
+ <enable extension="VK_INTEL_shader_integer_functions2"/>
+ </spirvextension>
+ <spirvextension name="SPV_KHR_device_group">
+ <enable version="VK_API_VERSION_1_1"/>
+ <enable extension="VK_KHR_device_group"/>
+ </spirvextension>
+ <spirvextension name="SPV_QCOM_image_processing">
+ <enable extension="VK_QCOM_image_processing"/>
+ </spirvextension>
</spirvextensions>
<spirvcapabilities comment="SPIR-V Capabilities allowed in Vulkan and what is required to use it">
<spirvcapability name="Matrix">
- <enable version="VK_API_VERSION_1_0"/>
+ <enable version="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="Shader">
- <enable version="VK_API_VERSION_1_0"/>
+ <enable version="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="InputAttachment">
- <enable version="VK_API_VERSION_1_0"/>
+ <enable version="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="Sampled1D">
- <enable version="VK_API_VERSION_1_0"/>
+ <enable version="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="Image1D">
- <enable version="VK_API_VERSION_1_0"/>
+ <enable version="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="SampledBuffer">
- <enable version="VK_API_VERSION_1_0"/>
+ <enable version="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="ImageBuffer">
- <enable version="VK_API_VERSION_1_0"/>
+ <enable version="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="ImageQuery">
- <enable version="VK_API_VERSION_1_0"/>
+ <enable version="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="DerivativeControl">
- <enable version="VK_API_VERSION_1_0"/>
+ <enable version="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="Geometry">
- <enable struct="VkPhysicalDeviceFeatures" feature="geometryShader"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="geometryShader" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="Tessellation">
- <enable struct="VkPhysicalDeviceFeatures" feature="tessellationShader"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="tessellationShader" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="Float64">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderFloat64"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderFloat64" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="Int64">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderInt64"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderInt64" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="Int64Atomics">
<enable struct="VkPhysicalDeviceVulkan12Features" feature="shaderBufferInt64Atomics" requires="VK_VERSION_1_2,VK_KHR_shader_atomic_int64"/>
<enable struct="VkPhysicalDeviceVulkan12Features" feature="shaderSharedInt64Atomics" requires="VK_VERSION_1_2,VK_KHR_shader_atomic_int64"/>
+ <enable struct="VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT" feature="shaderImageInt64Atomics" requires="VK_EXT_shader_image_atomic_int64"/>
+ </spirvcapability>
+ <spirvcapability name="AtomicFloat16AddEXT">
+ <enable struct="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT" feature="shaderBufferFloat16AtomicAdd" requires="VK_EXT_shader_atomic_float2"/>
+ <enable struct="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT" feature="shaderSharedFloat16AtomicAdd" requires="VK_EXT_shader_atomic_float2"/>
</spirvcapability>
<spirvcapability name="AtomicFloat32AddEXT">
<enable struct="VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" feature="shaderBufferFloat32AtomicAdd" requires="VK_EXT_shader_atomic_float"/>
<enable struct="VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" feature="shaderSharedFloat32AtomicAdd" requires="VK_EXT_shader_atomic_float"/>
<enable struct="VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" feature="shaderImageFloat32AtomicAdd" requires="VK_EXT_shader_atomic_float"/>
- <enable struct="VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" feature="sparseImageFloat32AtomicAdd" requires="VK_EXT_shader_atomic_float"/>
</spirvcapability>
<spirvcapability name="AtomicFloat64AddEXT">
<enable struct="VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" feature="shaderBufferFloat64AtomicAdd" requires="VK_EXT_shader_atomic_float"/>
<enable struct="VkPhysicalDeviceShaderAtomicFloatFeaturesEXT" feature="shaderSharedFloat64AtomicAdd" requires="VK_EXT_shader_atomic_float"/>
</spirvcapability>
+ <spirvcapability name="AtomicFloat16MinMaxEXT">
+ <enable struct="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT" feature="shaderBufferFloat16AtomicMinMax" requires="VK_EXT_shader_atomic_float2"/>
+ <enable struct="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT" feature="shaderSharedFloat16AtomicMinMax" requires="VK_EXT_shader_atomic_float2"/>
+ </spirvcapability>
+ <spirvcapability name="AtomicFloat32MinMaxEXT">
+ <enable struct="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT" feature="shaderBufferFloat32AtomicMinMax" requires="VK_EXT_shader_atomic_float2"/>
+ <enable struct="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT" feature="shaderSharedFloat32AtomicMinMax" requires="VK_EXT_shader_atomic_float2"/>
+ <enable struct="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT" feature="shaderImageFloat32AtomicMinMax" requires="VK_EXT_shader_atomic_float2"/>
+ </spirvcapability>
+ <spirvcapability name="AtomicFloat64MinMaxEXT">
+ <enable struct="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT" feature="shaderBufferFloat64AtomicMinMax" requires="VK_EXT_shader_atomic_float2"/>
+ <enable struct="VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT" feature="shaderSharedFloat64AtomicMinMax" requires="VK_EXT_shader_atomic_float2"/>
+ </spirvcapability>
<spirvcapability name="Int64ImageEXT">
<enable struct="VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT" feature="shaderImageInt64Atomics" requires="VK_EXT_shader_image_atomic_int64"/>
</spirvcapability>
<spirvcapability name="Int16">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderInt16"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderInt16" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="TessellationPointSize">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderTessellationAndGeometryPointSize"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderTessellationAndGeometryPointSize" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="GeometryPointSize">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderTessellationAndGeometryPointSize"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderTessellationAndGeometryPointSize" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="ImageGatherExtended">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderImageGatherExtended"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderImageGatherExtended" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="StorageImageMultisample">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageImageMultisample"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageImageMultisample" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="UniformBufferArrayDynamicIndexing">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderUniformBufferArrayDynamicIndexing"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderUniformBufferArrayDynamicIndexing" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="SampledImageArrayDynamicIndexing">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderSampledImageArrayDynamicIndexing"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderSampledImageArrayDynamicIndexing" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="StorageBufferArrayDynamicIndexing">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageBufferArrayDynamicIndexing"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageBufferArrayDynamicIndexing" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="StorageImageArrayDynamicIndexing">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageImageArrayDynamicIndexing"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageImageArrayDynamicIndexing" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="ClipDistance">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderClipDistance"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderClipDistance" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="CullDistance">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderCullDistance"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderCullDistance" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="ImageCubeArray">
- <enable struct="VkPhysicalDeviceFeatures" feature="imageCubeArray"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="imageCubeArray" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="SampleRateShading">
- <enable struct="VkPhysicalDeviceFeatures" feature="sampleRateShading"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="sampleRateShading" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="SparseResidency">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderResourceResidency"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderResourceResidency" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="MinLod">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderResourceMinLod"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderResourceMinLod" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="SampledCubeArray">
- <enable struct="VkPhysicalDeviceFeatures" feature="imageCubeArray"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="imageCubeArray" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="ImageMSArray">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageImageMultisample"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageImageMultisample" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="StorageImageExtendedFormats">
- <enable version="VK_API_VERSION_1_0"/>
+ <enable version="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="InterpolationFunction">
- <enable struct="VkPhysicalDeviceFeatures" feature="sampleRateShading"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="sampleRateShading" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="StorageImageReadWithoutFormat">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageImageReadWithoutFormat"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageImageReadWithoutFormat" requires="VK_VERSION_1_0"/>
+ <enable version="VK_API_VERSION_1_3"/>
+ <enable extension="VK_KHR_format_feature_flags2"/>
</spirvcapability>
<spirvcapability name="StorageImageWriteWithoutFormat">
- <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageImageWriteWithoutFormat"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="shaderStorageImageWriteWithoutFormat" requires="VK_VERSION_1_0"/>
+ <enable version="VK_API_VERSION_1_3"/>
+ <enable extension="VK_KHR_format_feature_flags2"/>
</spirvcapability>
<spirvcapability name="MultiViewport">
- <enable struct="VkPhysicalDeviceFeatures" feature="multiViewport"/>
+ <enable struct="VkPhysicalDeviceFeatures" feature="multiViewport" requires="VK_VERSION_1_0"/>
</spirvcapability>
<spirvcapability name="DrawParameters">
- <enable struct="VkPhysicalDeviceVulkan11Features" feature="shaderDrawParameters" requires="VK_VERSION_1_1"/>
+ <enable struct="VkPhysicalDeviceVulkan11Features" feature="shaderDrawParameters" requires="VK_VERSION_1_2"/>
+ <enable struct="VkPhysicalDeviceShaderDrawParametersFeatures" feature="shaderDrawParameters" requires="VK_VERSION_1_1"/>
<enable extension="VK_KHR_shader_draw_parameters"/>
</spirvcapability>
<spirvcapability name="MultiView">
- <enable struct="VkPhysicalDeviceVulkan11Features" feature="multiview" requires="VK_VERSION_1_1,VK_KHR_multiview"/>
+ <enable struct="VkPhysicalDeviceVulkan11Features" feature="multiview" requires="VK_VERSION_1_2"/>
+ <enable struct="VkPhysicalDeviceMultiviewFeatures" feature="multiview" requires="VK_KHR_multiview"/>
</spirvcapability>
<spirvcapability name="DeviceGroup">
- <enable version="VK_API_VERSION_1_1"/>
+ <enable version="VK_VERSION_1_1"/>
<enable extension="VK_KHR_device_group"/>
</spirvcapability>
<spirvcapability name="VariablePointersStorageBuffer">
- <enable struct="VkPhysicalDeviceVulkan11Features" feature="variablePointersStorageBuffer" requires="VK_VERSION_1_1,VK_KHR_variable_pointers"/>
+ <enable struct="VkPhysicalDeviceVulkan11Features" feature="variablePointersStorageBuffer" requires="VK_VERSION_1_2"/>
+ <enable struct="VkPhysicalDeviceVariablePointersFeatures" feature="variablePointersStorageBuffer" requires="VK_KHR_variable_pointers"/>
</spirvcapability>
<spirvcapability name="VariablePointers">
- <enable struct="VkPhysicalDeviceVulkan11Features" feature="variablePointers" requires="VK_VERSION_1_1,VK_KHR_variable_pointers"/>
+ <enable struct="VkPhysicalDeviceVulkan11Features" feature="variablePointers" requires="VK_VERSION_1_2"/>
+ <enable struct="VkPhysicalDeviceVariablePointersFeatures" feature="variablePointers" requires="VK_KHR_variable_pointers"/>
</spirvcapability>
<spirvcapability name="ShaderClockKHR">
<enable extension="VK_KHR_shader_clock"/>
@@ -14952,16 +21073,20 @@ typedef void <name>CAMetalLayer</name>;
<enable extension="VK_NVX_multiview_per_view_attributes"/>
</spirvcapability>
<spirvcapability name="StorageBuffer16BitAccess">
- <enable struct="VkPhysicalDeviceVulkan11Features" feature="storageBuffer16BitAccess" requires="VK_VERSION_1_1,VK_KHR_16bit_storage"/>
+ <enable struct="VkPhysicalDeviceVulkan11Features" feature="storageBuffer16BitAccess" requires="VK_VERSION_1_2"/>
+ <enable struct="VkPhysicalDevice16BitStorageFeatures" feature="storageBuffer16BitAccess" requires="VK_KHR_16bit_storage"/>
</spirvcapability>
<spirvcapability name="UniformAndStorageBuffer16BitAccess">
- <enable struct="VkPhysicalDeviceVulkan11Features" feature="uniformAndStorageBuffer16BitAccess" requires="VK_VERSION_1_1,VK_KHR_16bit_storage"/>
+ <enable struct="VkPhysicalDeviceVulkan11Features" feature="uniformAndStorageBuffer16BitAccess" requires="VK_VERSION_1_2"/>
+ <enable struct="VkPhysicalDevice16BitStorageFeatures" feature="uniformAndStorageBuffer16BitAccess" requires="VK_KHR_16bit_storage"/>
</spirvcapability>
<spirvcapability name="StoragePushConstant16">
- <enable struct="VkPhysicalDeviceVulkan11Features" feature="storagePushConstant16" requires="VK_VERSION_1_1,VK_KHR_16bit_storage"/>
+ <enable struct="VkPhysicalDeviceVulkan11Features" feature="storagePushConstant16" requires="VK_VERSION_1_2"/>
+ <enable struct="VkPhysicalDevice16BitStorageFeatures" feature="storagePushConstant16" requires="VK_KHR_16bit_storage"/>
</spirvcapability>
<spirvcapability name="StorageInputOutput16">
- <enable struct="VkPhysicalDeviceVulkan11Features" feature="storageInputOutput16" requires="VK_VERSION_1_1,VK_KHR_16bit_storage"/>
+ <enable struct="VkPhysicalDeviceVulkan11Features" feature="storageInputOutput16" requires="VK_VERSION_1_2"/>
+ <enable struct="VkPhysicalDevice16BitStorageFeatures" feature="storageInputOutput16" requires="VK_KHR_16bit_storage"/>
</spirvcapability>
<spirvcapability name="GroupNonUniform">
<enable property="VkPhysicalDeviceVulkan11Properties" member="subgroupSupportedOperations" value="VK_SUBGROUP_FEATURE_BASIC_BIT" requires="VK_VERSION_1_1"/>
@@ -14994,7 +21119,7 @@ typedef void <name>CAMetalLayer</name>;
<enable extension="VK_EXT_post_depth_coverage"/>
</spirvcapability>
<spirvcapability name="ShaderNonUniform">
- <enable version="VK_API_VERSION_1_2"/>
+ <enable version="VK_VERSION_1_2"/>
<enable extension="VK_EXT_descriptor_indexing"/>
</spirvcapability>
<spirvcapability name="RuntimeDescriptorArray">
@@ -15103,10 +21228,17 @@ typedef void <name>CAMetalLayer</name>;
</spirvcapability>
<spirvcapability name="RayTraversalPrimitiveCullingKHR">
<enable struct="VkPhysicalDeviceRayTracingPipelineFeaturesKHR" feature="rayTraversalPrimitiveCulling" requires="VK_KHR_ray_tracing_pipeline"/>
+ <enable struct="VkPhysicalDeviceRayQueryFeaturesKHR" feature="rayQuery" requires="VK_KHR_ray_query"/>
+ </spirvcapability>
+ <spirvcapability name="RayCullMaskKHR">
+ <enable struct="VkPhysicalDeviceRayTracingMaintenance1FeaturesKHR" feature="rayTracingMaintenance1" requires="VK_KHR_ray_tracing_maintenance1"/>
</spirvcapability>
<spirvcapability name="RayTracingNV">
<enable extension="VK_NV_ray_tracing"/>
</spirvcapability>
+ <spirvcapability name="RayTracingMotionBlurNV">
+ <enable struct="VkPhysicalDeviceRayTracingMotionBlurFeaturesNV" feature="rayTracingMotionBlur" requires="VK_NV_ray_tracing_motion_blur"/>
+ </spirvcapability>
<spirvcapability name="TransformFeedback">
<enable struct="VkPhysicalDeviceTransformFeedbackFeaturesEXT" feature="transformFeedback" requires="VK_EXT_transform_feedback"/>
</spirvcapability>
@@ -15140,6 +21272,7 @@ typedef void <name>CAMetalLayer</name>;
<enable struct="VkPhysicalDeviceShadingRateImageFeaturesNV" feature="shadingRateImage" requires="VK_NV_shading_rate_image"/>
</spirvcapability>
<spirvcapability name="DemoteToHelperInvocationEXT">
+ <enable struct="VkPhysicalDeviceVulkan13Features" feature="shaderDemoteToHelperInvocation" requires="VK_VERSION_1_3,VK_EXT_shader_demote_to_helper_invocation"/>
<enable struct="VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT" feature="shaderDemoteToHelperInvocation" requires="VK_EXT_shader_demote_to_helper_invocation"/>
</spirvcapability>
<spirvcapability name="FragmentShadingRateKHR">
@@ -15147,5 +21280,42 @@ typedef void <name>CAMetalLayer</name>;
<enable struct="VkPhysicalDeviceFragmentShadingRateFeaturesKHR" feature="primitiveFragmentShadingRate" requires="VK_KHR_fragment_shading_rate"/>
<enable struct="VkPhysicalDeviceFragmentShadingRateFeaturesKHR" feature="attachmentFragmentShadingRate" requires="VK_KHR_fragment_shading_rate"/>
</spirvcapability>
+ <spirvcapability name="WorkgroupMemoryExplicitLayoutKHR">
+ <enable struct="VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR" feature="workgroupMemoryExplicitLayout" requires="VK_KHR_workgroup_memory_explicit_layout"/>
+ </spirvcapability>
+ <spirvcapability name="WorkgroupMemoryExplicitLayout8BitAccessKHR">
+ <enable struct="VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR" feature="workgroupMemoryExplicitLayout8BitAccess" requires="VK_KHR_workgroup_memory_explicit_layout"/>
+ </spirvcapability>
+ <spirvcapability name="WorkgroupMemoryExplicitLayout16BitAccessKHR">
+ <enable struct="VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR" feature="workgroupMemoryExplicitLayout16BitAccess" requires="VK_KHR_workgroup_memory_explicit_layout"/>
+ </spirvcapability>
+ <spirvcapability name="DotProductInputAllKHR">
+ <enable struct="VkPhysicalDeviceVulkan13Features" feature="shaderIntegerDotProduct" requires="VK_VERSION_1_3,VK_KHR_shader_integer_dot_product"/>
+ <enable struct="VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR" feature="shaderIntegerDotProduct" requires="VK_KHR_shader_integer_dot_product"/>
+ </spirvcapability>
+ <spirvcapability name="DotProductInput4x8BitKHR">
+ <enable struct="VkPhysicalDeviceVulkan13Features" feature="shaderIntegerDotProduct" requires="VK_VERSION_1_3,VK_KHR_shader_integer_dot_product"/>
+ <enable struct="VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR" feature="shaderIntegerDotProduct" requires="VK_KHR_shader_integer_dot_product"/>
+ </spirvcapability>
+ <spirvcapability name="DotProductInput4x8BitPackedKHR">
+ <enable struct="VkPhysicalDeviceVulkan13Features" feature="shaderIntegerDotProduct" requires="VK_VERSION_1_3,VK_KHR_shader_integer_dot_product"/>
+ <enable struct="VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR" feature="shaderIntegerDotProduct" requires="VK_KHR_shader_integer_dot_product"/>
+ </spirvcapability>
+ <spirvcapability name="DotProductKHR">
+ <enable struct="VkPhysicalDeviceVulkan13Features" feature="shaderIntegerDotProduct" requires="VK_VERSION_1_3,VK_KHR_shader_integer_dot_product"/>
+ <enable struct="VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR" feature="shaderIntegerDotProduct" requires="VK_KHR_shader_integer_dot_product"/>
+ </spirvcapability>
+ <spirvcapability name="FragmentBarycentricKHR">
+ <enable struct="VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR" feature="fragmentShaderBarycentric" requires="VK_KHR_fragment_shader_barycentric"/>
+ </spirvcapability>
+ <spirvcapability name="TextureSampleWeightedQCOM">
+ <enable struct="VkPhysicalDeviceImageProcessingFeaturesQCOM" feature="textureSampleWeighted" requires="VK_QCOM_image_processing"/>
+ </spirvcapability>
+ <spirvcapability name="TextureBoxFilterQCOM">
+ <enable struct="VkPhysicalDeviceImageProcessingFeaturesQCOM" feature="textureBoxFilter" requires="VK_QCOM_image_processing"/>
+ </spirvcapability>
+ <spirvcapability name="TextureBlockMatchQCOM">
+ <enable struct="VkPhysicalDeviceImageProcessingFeaturesQCOM" feature="textureBlockMatch" requires="VK_QCOM_image_processing"/>
+ </spirvcapability>
</spirvcapabilities>
</registry>